You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdebase/kcontrol/kfontinst/kcmfontinst/KFileFontView.cpp

646 lines
17 KiB

////////////////////////////////////////////////////////////////////////////////
//
// Class Name : CKFileFontView
// Author : Craig Drummond
// Project : K Font Installer
// Creation Date : 31/05/2003
// Version : $Revision$ $Date$
//
////////////////////////////////////////////////////////////////////////////////
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
////////////////////////////////////////////////////////////////////////////////
// (C) Craig Drummond, 2003
////////////////////////////////////////////////////////////////////////////////
//
// NOTE: HEAVILY copied from kfiledetailview.cpp...
//
// Copyright (C) 1997 Stephan Kulow <coolo@kde.org>
// 2000, 2001 Carsten Pfeiffer <pfeiffer@kde.org>
//
#include <qevent.h>
#include <qkeycode.h>
#include <qheader.h>
#include <qpainter.h>
#include <qpixmap.h>
#include <kapplication.h>
#include <kfileitem.h>
#include <kglobal.h>
#include <kglobalsettings.h>
#include <kicontheme.h>
#include <klocale.h>
#include <kiconloader.h>
#include <kdebug.h>
#include <kurldrag.h>
#include "KFileFontView.h"
#define COL_NAME 0
#define COL_SIZE 1
#define COL_TYPE 2
class CKFileFontView::CKFileFontViewPrivate
{
public:
CKFileFontViewPrivate() : itsDropItem(0) {}
CFontListViewItem *itsDropItem;
QTimer itsAutoOpenTimer;
};
CKFileFontView::CKFileFontView(QWidget *parent, const char *name)
: KListView(parent, name),
KFileView(),
d(new CKFileFontViewPrivate())
{
itsSortingCol = COL_NAME;
itsBlockSortingSignal = false;
setViewName(i18n("Detailed View"));
addColumn(i18n("Name"));
addColumn(i18n("Size"));
addColumn(i18n("Type"));
setShowSortIndicator(true);
setAllColumnsShowFocus(true);
setDragEnabled(false);
connect(header(), SIGNAL(sectionClicked(int)), SLOT(slotSortingChanged(int)));
connect(this, SIGNAL(returnPressed(QListViewItem *)), SLOT(slotActivate(QListViewItem *)));
connect(this, SIGNAL(clicked(QListViewItem *, const QPoint&, int)), SLOT(selected( QListViewItem *)));
connect(this, SIGNAL(doubleClicked(QListViewItem *, const QPoint &, int)), SLOT(slotActivate(QListViewItem *)));
connect(this, SIGNAL(contextMenuRequested(QListViewItem *, const QPoint &, int)),
this, SLOT(slotActivateMenu(QListViewItem *, const QPoint &)));
// DND
connect(&(d->itsAutoOpenTimer), SIGNAL(timeout()), this, SLOT(slotAutoOpen()));
setSelectionMode(KFileView::selectionMode());
itsResolver = new KMimeTypeResolver<CFontListViewItem, CKFileFontView>(this);
}
CKFileFontView::~CKFileFontView()
{
delete itsResolver;
delete d;
}
void CKFileFontView::setSelected(const KFileItem *info, bool enable)
{
if (info)
{
// we can only hope that this casts works
CFontListViewItem *item = (CFontListViewItem*)info->extraData(this);
if (item)
KListView::setSelected(item, enable);
}
}
void CKFileFontView::setCurrentItem(const KFileItem *item)
{
if (item)
{
CFontListViewItem *it = (CFontListViewItem*) item->extraData(this);
if (it)
KListView::setCurrentItem(it);
}
}
KFileItem * CKFileFontView::currentFileItem() const
{
CFontListViewItem *current = static_cast<CFontListViewItem*>(currentItem());
return current ? current->fileInfo() : NULL;
}
void CKFileFontView::clearSelection()
{
KListView::clearSelection();
}
void CKFileFontView::selectAll()
{
if (KFile::NoSelection!=KFileView::selectionMode() && KFile::Single!=KFileView::selectionMode())
KListView::selectAll(true);
}
void CKFileFontView::invertSelection()
{
KListView::invertSelection();
}
void CKFileFontView::slotActivateMenu(QListViewItem *item,const QPoint& pos)
{
if (!item)
sig->activateMenu(0, pos);
else
{
CFontListViewItem *i = (CFontListViewItem*) item;
sig->activateMenu(i->fileInfo(), pos);
}
}
void CKFileFontView::clearView()
{
itsResolver->m_lstPendingMimeIconItems.clear();
KListView::clear();
}
void CKFileFontView::insertItem(KFileItem *i)
{
KFileView::insertItem(i);
CFontListViewItem *item = new CFontListViewItem((QListView*) this, i);
setSortingKey(item, i);
i->setExtraData(this, item);
if (!i->isMimeTypeKnown())
itsResolver->m_lstPendingMimeIconItems.append(item);
}
void CKFileFontView::slotActivate(QListViewItem *item)
{
if (item)
{
const KFileItem *fi = ((CFontListViewItem*)item)->fileInfo();
if (fi)
sig->activate(fi);
}
}
void CKFileFontView::selected(QListViewItem *item)
{
if (item && !(KApplication::keyboardMouseState() & (ShiftButton|ControlButton)) &&
KGlobalSettings::singleClick())
{
const KFileItem *fi = ((CFontListViewItem*)item)->fileInfo();
if (fi && (fi->isDir() || !onlyDoubleClickSelectsFiles()))
sig->activate(fi);
}
}
void CKFileFontView::highlighted( QListViewItem *item )
{
if (item)
{
const KFileItem *fi = ((CFontListViewItem*)item)->fileInfo();
if (fi)
sig->highlightFile(fi);
}
}
void CKFileFontView::setSelectionMode(KFile::SelectionMode sm)
{
disconnect(SIGNAL(selectionChanged()), this);
disconnect(SIGNAL(selectionChanged(QListViewItem *)), this);
switch (sm)
{
case KFile::Multi:
QListView::setSelectionMode(QListView::Multi);
break;
case KFile::Extended:
QListView::setSelectionMode(QListView::Extended);
break;
case KFile::NoSelection:
QListView::setSelectionMode(QListView::NoSelection);
break;
default: // fall through
case KFile::Single:
QListView::setSelectionMode(QListView::Single);
break;
}
// for highlighting
if (KFile::Multi==sm || KFile::Extended==sm)
connect(this, SIGNAL(selectionChanged()), SLOT(slotSelectionChanged()));
else
connect(this, SIGNAL(selectionChanged(QListViewItem *)), SLOT(highlighted(QListViewItem * )));
}
bool CKFileFontView::isSelected(const KFileItem *i) const
{
if (!i)
return false;
else
{
CFontListViewItem *item = (CFontListViewItem*) i->extraData(this);
return (item && item->isSelected());
}
}
void CKFileFontView::updateView(bool b)
{
if (b)
{
QListViewItemIterator it((QListView*)this);
for (; it.current(); ++it)
{
CFontListViewItem *item=static_cast<CFontListViewItem *>(it.current());
item->setPixmap(0, item->fileInfo()->pixmap(KIcon::SizeSmall));
}
}
}
void CKFileFontView::updateView(const KFileItem *i)
{
if (i)
{
CFontListViewItem *item = (CFontListViewItem*) i->extraData(this);
if (item)
{
item->init();
setSortingKey(item, i);
}
}
}
void CKFileFontView::setSortingKey(CFontListViewItem *item, const KFileItem *i)
{
QDir::SortSpec spec = KFileView::sorting();
if (spec&QDir::Size)
item->setKey(sortingKey(i->size(), i->isDir(), spec));
else
item->setKey(sortingKey(i->text(), i->isDir(), spec));
}
void CKFileFontView::removeItem(const KFileItem *i)
{
if (i)
{
CFontListViewItem *item = (CFontListViewItem*) i->extraData(this);
itsResolver->m_lstPendingMimeIconItems.remove(item);
delete item;
KFileView::removeItem(i);
}
}
void CKFileFontView::slotSortingChanged(int col)
{
QDir::SortSpec sort = sorting();
int sortSpec = -1;
bool reversed = col == itsSortingCol && (sort & QDir::Reversed) == 0;
itsSortingCol = col;
switch(col)
{
case COL_NAME:
sortSpec = (sort & ~QDir::SortByMask | QDir::Name);
break;
case COL_SIZE:
sortSpec = (sort & ~QDir::SortByMask | QDir::Size);
break;
// the following columns have no equivalent in QDir, so we set it
// to QDir::Unsorted and remember the column (itsSortingCol)
case COL_TYPE:
sortSpec = (sort & ~QDir::SortByMask | QDir::Time);
break;
default:
break;
}
if (reversed)
sortSpec|=QDir::Reversed;
else
sortSpec&=~QDir::Reversed;
if (sort & QDir::IgnoreCase)
sortSpec|=QDir::IgnoreCase;
else
sortSpec&=~QDir::IgnoreCase;
KFileView::setSorting(static_cast<QDir::SortSpec>(sortSpec));
KFileItem *item;
KFileItemListIterator it(*items());
if ( sortSpec & QDir::Size )
{
for (; (item = it.current()); ++it )
{
CFontListViewItem *i = viewItem(item);
i->setKey(sortingKey(item->size(), item->isDir(), sortSpec));
}
}
else
for (; (item = it.current()); ++it )
{
CFontListViewItem *i = viewItem(item);
i->setKey(sortingKey(i->text(itsSortingCol), item->isDir(), sortSpec));
}
KListView::setSorting(itsSortingCol, !reversed);
KListView::sort();
if (!itsBlockSortingSignal)
sig->changeSorting( static_cast<QDir::SortSpec>( sortSpec ) );
}
void CKFileFontView::setSorting(QDir::SortSpec spec)
{
if (spec & QDir::Size)
itsSortingCol=COL_SIZE;
else
itsSortingCol=COL_NAME;
// inversed, because slotSortingChanged will reverse it
if (spec & QDir::Reversed)
spec = (QDir::SortSpec) (spec & ~QDir::Reversed);
else
spec = (QDir::SortSpec) (spec | QDir::Reversed);
KFileView::setSorting((QDir::SortSpec) spec);
// don't emit sortingChanged() when called via setSorting()
itsBlockSortingSignal = true; // can't use blockSignals()
slotSortingChanged(itsSortingCol);
itsBlockSortingSignal = false;
}
void CKFileFontView::ensureItemVisible(const KFileItem *i)
{
if (i)
{
CFontListViewItem *item = (CFontListViewItem*) i->extraData(this);
if ( item )
KListView::ensureItemVisible(item);
}
}
// we're in multiselection mode
void CKFileFontView::slotSelectionChanged()
{
sig->highlightFile(NULL);
}
KFileItem * CKFileFontView::firstFileItem() const
{
CFontListViewItem *item = static_cast<CFontListViewItem*>(firstChild());
return item ? item->fileInfo() : NULL;
}
KFileItem * CKFileFontView::nextItem(const KFileItem *fileItem) const
{
if (fileItem)
{
CFontListViewItem *item = viewItem(fileItem);
return item && item->itemBelow() ? ((CFontListViewItem*) item->itemBelow())->fileInfo() : NULL;
}
return firstFileItem();
}
KFileItem * CKFileFontView::prevItem(const KFileItem *fileItem) const
{
if (fileItem)
{
CFontListViewItem *item = viewItem(fileItem);
return item && item->itemAbove() ? ((CFontListViewItem*) item->itemAbove())->fileInfo() : NULL;
}
return firstFileItem();
}
void CKFileFontView::keyPressEvent(QKeyEvent *e)
{
KListView::keyPressEvent(e);
if (Key_Return==e->key() || Key_Enter==e->key())
if (e->state() & ControlButton)
e->ignore();
else
e->accept();
}
//
// mimetype determination on demand
//
void CKFileFontView::mimeTypeDeterminationFinished()
{
// anything to do?
}
void CKFileFontView::determineIcon(CFontListViewItem *item)
{
item->fileInfo()->determineMimeType();
updateView(item->fileInfo());
}
void CKFileFontView::listingCompleted()
{
itsResolver->start();
}
QDragObject *CKFileFontView::dragObject()
{
// create a list of the URL:s that we want to drag
KURL::List urls;
KFileItemListIterator it(* KFileView::selectedItems());
QPixmap pixmap;
QPoint hotspot;
for ( ; it.current(); ++it )
urls.append( (*it)->url() );
if(urls.count()> 1)
pixmap = DesktopIcon("kmultiple", KIcon::SizeSmall);
if(pixmap.isNull())
pixmap = currentFileItem()->pixmap(KIcon::SizeSmall);
hotspot.setX(pixmap.width() / 2);
hotspot.setY(pixmap.height() / 2);
QDragObject *dragObject=new KURLDrag(urls, widget());
if(dragObject)
dragObject->setPixmap(pixmap, hotspot);
return dragObject;
}
void CKFileFontView::slotAutoOpen()
{
d->itsAutoOpenTimer.stop();
if(d->itsDropItem)
{
KFileItem *fileItem = d->itsDropItem->fileInfo();
if (fileItem && !fileItem->isFile() && (fileItem->isDir() || fileItem->isLink()))
sig->activate(fileItem);
}
}
bool CKFileFontView::acceptDrag(QDropEvent *e) const
{
#if 0 // Following doesn't seem to work, why???
bool ok=false;
KURL::List urls;
if((e->source()!=const_cast<CKFileFontView *>(this)) &&
(QDropEvent::Copy==e->action() || QDropEvent::Move==e->action()) &&
KURLDrag::decode(e, urls) && !urls.isEmpty())
{
KURL::List::Iterator it;
ok=true;
for(it=urls.begin(); ok && it!=urls.end(); ++it)
if(!CFontEngine::isAFontOrAfm(QFile::encodeName((*it).path())))
ok=false;
}
return ok;
#endif
return KURLDrag::canDecode(e) && (e->source()!= const_cast<CKFileFontView*>(this)) &&
(QDropEvent::Copy==e->action() || QDropEvent::Move==e->action());
}
void CKFileFontView::contentsDragEnterEvent(QDragEnterEvent *e)
{
if (!acceptDrag(e)) // can we decode this ?
e->ignore(); // No
else
{
e->acceptAction(); // Yes
if((dropOptions() & AutoOpenDirs))
{
CFontListViewItem *item = dynamic_cast<CFontListViewItem*>(itemAt(contentsToViewport(e->pos())));
if (item) // are we over an item ?
{
d->itsDropItem = item;
d->itsAutoOpenTimer.start(autoOpenDelay()); // restart timer
}
else
{
d->itsDropItem = 0;
d->itsAutoOpenTimer.stop();
}
}
}
}
void CKFileFontView::contentsDragMoveEvent(QDragMoveEvent *e)
{
if (!acceptDrag(e)) // can we decode this ?
e->ignore(); // No
else
{
e->acceptAction(); // Yes
if ((dropOptions() & AutoOpenDirs))
{
CFontListViewItem *item = dynamic_cast<CFontListViewItem*>(itemAt(contentsToViewport(e->pos())));
if (item) // are we over an item ?
{
if (d->itsDropItem != item)
{
d->itsDropItem = item;
d->itsAutoOpenTimer.start(autoOpenDelay()); // restart timer
}
}
else
{
d->itsDropItem = 0;
d->itsAutoOpenTimer.stop();
}
}
}
}
void CKFileFontView::contentsDragLeaveEvent(QDragLeaveEvent *)
{
d->itsDropItem = 0;
d->itsAutoOpenTimer.stop();
}
void CKFileFontView::contentsDropEvent(QDropEvent *e)
{
d->itsDropItem = 0;
d->itsAutoOpenTimer.stop();
if (!acceptDrag(e)) // can we decode this ?
e->ignore(); // No
else
{
e->acceptAction(); // Yes
CFontListViewItem *item = dynamic_cast<CFontListViewItem*>(itemAt(contentsToViewport(e->pos())));
KFileItem *fileItem = item ? item->fileInfo() : 0;
KURL::List urls;
emit dropped(e, fileItem);
if(KURLDrag::decode(e, urls) && !urls.isEmpty())
{
emit dropped(e, urls, fileItem ? fileItem->url() : KURL());
sig->dropURLs(fileItem, e, urls);
}
}
}
void CKFileFontView::readConfig(KConfig *kc, const QString &group)
{
restoreLayout(kc, group.isEmpty() ? QString("CFileFontView") : group);
slotSortingChanged(sortColumn());
}
void CKFileFontView::writeConfig(KConfig *kc, const QString &group)
{
saveLayout(kc, group.isEmpty() ? QString("CFileFontView") : group);
}
/////////////////////////////////////////////////////////////////
void CFontListViewItem::init()
{
CFontListViewItem::setPixmap(COL_NAME, itsInf->pixmap(KIcon::SizeSmall));
setText(COL_NAME, itsInf->text());
setText(COL_SIZE, itsInf->isDir() ? "" : KGlobal::locale()->formatNumber(itsInf->size(), 0));
setText(COL_TYPE, itsInf->mimeComment());
}
void CKFileFontView::virtual_hook(int id, void *data)
{
KListView::virtual_hook(id, data);
KFileView::virtual_hook(id, data);
}
#include "KFileFontView.moc"