summaryrefslogtreecommitdiffstats
path: root/src/gvcore/filedetailview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gvcore/filedetailview.cpp')
-rw-r--r--src/gvcore/filedetailview.cpp552
1 files changed, 552 insertions, 0 deletions
diff --git a/src/gvcore/filedetailview.cpp b/src/gvcore/filedetailview.cpp
new file mode 100644
index 0000000..b36a1dd
--- /dev/null
+++ b/src/gvcore/filedetailview.cpp
@@ -0,0 +1,552 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab
+/* This file is based on kfiledetailview.cpp v1.43 from the KDE libs. Original
+ copyright follows.
+*/
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Stephan Kulow <coolo@kde.org>
+ 2000, 2001 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+// Qt
+#include <qbitmap.h>
+#include <qevent.h>
+#include <qheader.h>
+#include <qkeycode.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+
+// KDE
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kfileitem.h>
+#include <kglobalsettings.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kurldrag.h>
+#include <kwordwrap.h>
+
+// Local
+#include "archive.h"
+#include "dragpixmapgenerator.h"
+#include "filedetailviewitem.h"
+#include "filedetailview.moc"
+#include "timeutils.h"
+namespace Gwenview {
+
+
+static QPixmap createShownItemPixmap(int size, const QColor& color) {
+ QPixmap pix(size, size);
+ pix.fill(Qt::red);
+ QPainter painter(&pix);
+ int margin = 2;
+
+ QPointArray pa(3);
+ int arrowSize = size/2 - margin;
+ int center = size/2 - 1;
+ pa[0] = QPoint((size - arrowSize) / 2, center - arrowSize);
+ pa[1] = QPoint((size + arrowSize) / 2, center);
+ pa[2] = QPoint(pa[0].x(), center + arrowSize);
+
+ painter.setBrush(color);
+ painter.setPen(color);
+ painter.drawPolygon(pa);
+ painter.end();
+
+ pix.setMask(pix.createHeuristicMask());
+
+ return pix;
+}
+
+
+FileDetailView::FileDetailView(QWidget *parent, const char *name)
+ : KListView(parent, name), FileViewBase()
+{
+ mSortingCol = COL_NAME;
+ mBlockSortingSignal = false;
+
+ addColumn( i18n( "Name" ) );
+ addColumn( i18n( "Size" ) );
+ addColumn( i18n( "Date" ) );
+ addColumn( i18n( "Permissions" ) );
+ addColumn( i18n( "Owner" ) );
+ addColumn( i18n( "Group" ) );
+ setShowSortIndicator( TRUE );
+ setAllColumnsShowFocus( TRUE );
+
+ 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& )));
+
+ QListView::setSelectionMode( QListView::Extended );
+ connect( this, SIGNAL( selectionChanged() ),
+ SLOT( slotSelectionChanged() ));
+
+ // FileViewStack need to be aware of sort changes, to update the sort menu
+ connect( sig, SIGNAL(sortingChanged(QDir::SortSpec)),
+ this, SIGNAL(sortingChanged(QDir::SortSpec)) );
+
+ setSorting( sorting() );
+
+
+ mResolver =
+ new KMimeTypeResolver<FileDetailViewItem,FileDetailView>( this );
+
+ setDragEnabled(true);
+
+ setAcceptDrops(true);
+ setDropVisualizer(false);
+ setDropHighlighter(false);
+
+ int size = IconSize(KIcon::Small);
+ mShownItemUnselectedPixmap = createShownItemPixmap(size, colorGroup().highlight());
+ mShownItemSelectedPixmap = createShownItemPixmap(size, colorGroup().highlightedText());
+}
+
+
+FileDetailView::~FileDetailView()
+{
+ delete mResolver;
+}
+
+
+void FileDetailView::setSelected( const KFileItem *info, bool enable )
+{
+ if (!info) return;
+ FileDetailViewItem *item = viewItem(info);
+ if (item) KListView::setSelected(item, enable);
+}
+
+void FileDetailView::setCurrentItem( const KFileItem *item )
+{
+ if (!item) return;
+ FileDetailViewItem *listItem = viewItem(item);
+ if (listItem) KListView::setCurrentItem(listItem);
+}
+
+KFileItem * FileDetailView::currentFileItem() const
+{
+ FileDetailViewItem *current = static_cast<FileDetailViewItem*>( currentItem() );
+ if ( current ) return current->fileInfo();
+
+ return 0L;
+}
+
+void FileDetailView::clearSelection()
+{
+ KListView::clearSelection();
+}
+
+void FileDetailView::selectAll()
+{
+ KListView::selectAll( true );
+}
+
+void FileDetailView::invertSelection()
+{
+ KListView::invertSelection();
+}
+
+void FileDetailView::slotActivateMenu (QListViewItem *item,const QPoint& pos )
+{
+ if ( !item ) {
+ sig->activateMenu( 0, pos );
+ return;
+ }
+ FileDetailViewItem *i = (FileDetailViewItem*) item;
+ sig->activateMenu( i->fileInfo(), pos );
+}
+
+void FileDetailView::clearView()
+{
+ mResolver->m_lstPendingMimeIconItems.clear();
+ mShownFileItem=0L;
+ KListView::clear();
+}
+
+void FileDetailView::insertItem( KFileItem *i )
+{
+ KFileView::insertItem( i );
+
+ FileDetailViewItem *item = new FileDetailViewItem( (QListView*) this, i );
+
+ setSortingKey( item, i );
+
+ i->setExtraData( this, item );
+
+ if ( !i->isMimeTypeKnown() )
+ mResolver->m_lstPendingMimeIconItems.append( item );
+}
+
+void FileDetailView::slotActivate( QListViewItem *item )
+{
+ if ( !item ) return;
+
+ const KFileItem *fi = ( (FileDetailViewItem*)item )->fileInfo();
+ if ( fi ) sig->activate( fi );
+}
+
+void FileDetailView::selected( QListViewItem *item )
+{
+ if ( !item ) return;
+
+ if ( KGlobalSettings::singleClick() ) {
+ const KFileItem *fi = ( (FileDetailViewItem*)item )->fileInfo();
+ if ( fi && (fi->isDir() || !onlyDoubleClickSelectsFiles()) )
+ sig->activate( fi );
+ }
+}
+
+void FileDetailView::highlighted( QListViewItem *item )
+{
+ if ( !item ) return;
+
+ const KFileItem *fi = ( (FileDetailViewItem*)item )->fileInfo();
+ if ( fi ) sig->highlightFile( fi );
+}
+
+
+bool FileDetailView::isSelected(const KFileItem* fileItem) const
+{
+ if (!fileItem) return false;
+
+ FileDetailViewItem *item = viewItem(fileItem);
+ return item && item->isSelected();
+}
+
+
+void FileDetailView::updateView( bool b )
+{
+ if ( !b ) return;
+
+ QListViewItemIterator it( (QListView*)this );
+ for ( ; it.current(); ++it ) {
+ FileDetailViewItem *item=static_cast<FileDetailViewItem *>(it.current());
+ item->setPixmap( 0, item->fileInfo()->pixmap(KIcon::SizeSmall) );
+ }
+}
+
+void FileDetailView::updateView( const KFileItem *i )
+{
+ if ( !i ) return;
+
+ FileDetailViewItem *item = viewItem(i);
+ if ( !item ) return;
+
+ item->init();
+ setSortingKey( item, i );
+}
+
+
+void FileDetailView::setSortingKey( FileDetailViewItem *dvItem, const KFileItem *item)
+{
+ QDir::SortSpec spec = KFileView::sorting();
+ bool isDirOrArchive=item->isDir() || Archive::fileItemIsArchive(item);
+
+ QString key;
+ if ( spec & QDir::Time ) {
+ time_t time = TimeUtils::getTime(item);
+ key=sortingKey(time, isDirOrArchive, spec);
+
+ } else if ( spec & QDir::Size ) {
+ key=sortingKey( item->size(), isDirOrArchive, spec );
+
+ } else {
+ // Name or Unsorted
+ key=sortingKey( item->text(), isDirOrArchive, spec );
+ }
+
+ dvItem->setKey(key);
+}
+
+
+void FileDetailView::removeItem( const KFileItem *i )
+{
+ if ( !i ) return;
+
+ FileDetailViewItem *item = viewItem(i);
+ mResolver->m_lstPendingMimeIconItems.remove( item );
+ if(mShownFileItem==i) mShownFileItem=0L;
+ delete item;
+
+ KFileView::removeItem( i );
+}
+
+void FileDetailView::slotSortingChanged( int col )
+{
+ QDir::SortSpec sort = sorting();
+ int sortSpec = -1;
+ bool reversed = col == mSortingCol && (sort & QDir::Reversed) == 0;
+ mSortingCol = col;
+
+ switch( col ) {
+ case COL_NAME:
+ sortSpec = (sort & ~QDir::SortByMask | QDir::Name);
+ break;
+ case COL_SIZE:
+ sortSpec = (sort & ~QDir::SortByMask | QDir::Size);
+ break;
+ case COL_DATE:
+ sortSpec = (sort & ~QDir::SortByMask | QDir::Time);
+ break;
+
+ // the following columns have no equivalent in QDir, so we set it
+ // to QDir::Unsorted and remember the column (mSortingCol)
+ case COL_OWNER:
+ case COL_GROUP:
+ case COL_PERM:
+ // grmbl, QDir::Unsorted == SortByMask.
+ sortSpec = (sort & ~QDir::SortByMask);// | QDir::Unsorted;
+ 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() );
+
+ for ( ; (item = it.current() ); ++it ) {
+ FileDetailViewItem* thumbItem=viewItem( item );
+ if (thumbItem) setSortingKey(thumbItem,item);
+ }
+
+ KListView::setSorting( mSortingCol, !reversed );
+ KListView::sort();
+
+ if (!mBlockSortingSignal) sig->changeSorting( static_cast<QDir::SortSpec>( sortSpec ) );
+}
+
+
+void FileDetailView::setSorting( QDir::SortSpec spec )
+{
+ int col = 0;
+ if ( spec & QDir::Time )
+ col = COL_DATE;
+ else if ( spec & QDir::Size )
+ col = COL_SIZE;
+ else if ( spec & QDir::Unsorted )
+ col = mSortingCol;
+ else
+ col = 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);
+
+ mSortingCol = col;
+ KFileView::setSorting( (QDir::SortSpec) spec );
+
+
+ // don't emit sortingChanged() when called via setSorting()
+ mBlockSortingSignal = true; // can't use blockSignals()
+ slotSortingChanged( col );
+ mBlockSortingSignal = false;
+}
+
+void FileDetailView::ensureItemVisible( const KFileItem *i )
+{
+ if ( !i ) return;
+
+ FileDetailViewItem *item = viewItem(i);
+
+ if ( item ) KListView::ensureItemVisible( item );
+}
+
+// we're in multiselection mode
+void FileDetailView::slotSelectionChanged()
+{
+ sig->highlightFile( 0L );
+}
+
+KFileItem * FileDetailView::firstFileItem() const
+{
+ FileDetailViewItem *item = static_cast<FileDetailViewItem*>( firstChild() );
+ if ( item ) return item->fileInfo();
+ return 0L;
+}
+
+KFileItem * FileDetailView::nextItem( const KFileItem *fileItem ) const
+{
+ if ( fileItem ) {
+ FileDetailViewItem *item = viewItem( fileItem );
+ if ( item && item->itemBelow() )
+ return ((FileDetailViewItem*) item->itemBelow())->fileInfo();
+ else
+ return 0L;
+ }
+ else
+ return firstFileItem();
+}
+
+KFileItem * FileDetailView::prevItem( const KFileItem *fileItem ) const
+{
+ if ( fileItem ) {
+ FileDetailViewItem *item = viewItem( fileItem );
+ if ( item && item->itemAbove() )
+ return ((FileDetailViewItem*) item->itemAbove())->fileInfo();
+ else
+ return 0L;
+ }
+ else
+ return firstFileItem();
+}
+
+void FileDetailView::keyPressEvent( QKeyEvent *e )
+{
+ KListView::keyPressEvent( e );
+
+ if ( e->key() == Key_Return || e->key() == Key_Enter ) {
+ if ( e->state() & ControlButton )
+ e->ignore();
+ else
+ e->accept();
+ }
+}
+
+//
+// mimetype determination on demand
+//
+void FileDetailView::mimeTypeDeterminationFinished()
+{
+ // anything to do?
+}
+
+void FileDetailView::determineIcon( FileDetailViewItem *item )
+{
+ (void) item->fileInfo()->determineMimeType();
+ updateView( item->fileInfo() );
+}
+
+void FileDetailView::listingCompleted()
+{
+ mResolver->start();
+}
+
+void FileDetailView::startDrag()
+{
+ /**
+ * The item drawer for DragPixmapGenerator
+ */
+ struct ItemDrawer : public DragPixmapItemDrawer<KFileItem*> {
+ ItemDrawer(const QFontMetrics& fontMetrics)
+ : mFontMetrics(fontMetrics) {}
+
+ QSize itemSize(KFileItem* fileItem) {
+ if (!fileItem) return QSize();
+ QString name = fileItem->name();
+ int width = QMIN(mGenerator->maxWidth(), mFontMetrics.width(name));
+ int height = mFontMetrics.height();
+ return QSize(width, height);
+ }
+
+ void drawItem(QPainter* painter, int left, int top, KFileItem* fileItem) {
+ QString name = fileItem->name();
+ painter->save();
+ KWordWrap::drawFadeoutText(painter,
+ left, top + mFontMetrics.ascent(),
+ mGenerator->maxWidth(), name);
+ painter->restore();
+ }
+
+ QFontMetrics mFontMetrics;
+ };
+ ItemDrawer drawer(fontMetrics());
+
+
+ KURL::List urls;
+ KFileItemListIterator it(*KFileView::selectedItems());
+
+ DragPixmapGenerator<KFileItem*> generator;
+ generator.setItemDrawer(&drawer);
+
+ for ( ; it.current(); ++it ) {
+ urls.append(it.current()->url());
+ generator.addItem(it.current());
+ }
+
+ if (urls.isEmpty()) {
+ kdWarning() << "No item to drag\n";
+ return;
+ }
+
+ QDragObject* drag=new KURLDrag(urls, this, 0);
+ QPixmap dragPixmap = generator.generate();
+
+ drag->setPixmap( dragPixmap, QPoint(-generator.DRAG_OFFSET, -generator.DRAG_OFFSET));
+ drag->dragCopy();
+}
+
+
+void FileDetailView::setShownFileItem(KFileItem* fileItem)
+{
+ if( fileItem == mShownFileItem ) return;
+ FileDetailViewItem* oldShownItem=viewItem(mShownFileItem);
+ FileDetailViewItem* newShownItem=viewItem(fileItem);
+
+ FileViewBase::setShownFileItem(fileItem);
+ if (oldShownItem) oldShownItem->repaint();
+ if (newShownItem) newShownItem->repaint();
+}
+
+
+//----------------------------------------------------------------------
+//
+// Drop support
+//
+//----------------------------------------------------------------------
+bool FileDetailView::acceptDrag(QDropEvent* event) const {
+ return KURLDrag::canDecode(event);
+}
+
+void FileDetailView::contentsDropEvent(QDropEvent *event) {
+ KFileItem* fileItem=0L;
+ QListViewItem *item=itemAt(contentsToViewport(event->pos() ) );
+
+ if (item) {
+ fileItem=static_cast<FileDetailViewItem*>(item)->fileInfo();
+ }
+ emit dropped(event,fileItem);
+}
+
+} // namespace