/* This file is based on tdefiledetailview.cpp v1.43 from the KDE libs. Original copyright follows. */ /* This file is part of the KDE libraries Copyright (C) 1997 Stephan Kulow 2000, 2001 Carsten Pfeiffer 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // TQt #include #include #include #include #include #include // KDE #include #include #include #include #include #include #include #include // Local #include "archive.h" #include "dragpixmapgenerator.h" #include "filedetailviewitem.h" #include "filedetailview.moc" #include "timeutils.h" namespace Gwenview { static TQPixmap createShownItemPixmap(int size, const TQColor& color) { TQPixmap pix(size, size); pix.fill(TQt::red); TQPainter painter(&pix); int margin = 2; TQPointArray pa(3); int arrowSize = size/2 - margin; int center = size/2 - 1; pa[0] = TQPoint((size - arrowSize) / 2, center - arrowSize); pa[1] = TQPoint((size + arrowSize) / 2, center); pa[2] = TQPoint(pa[0].x(), center + arrowSize); painter.setBrush(color); painter.setPen(color); painter.drawPolygon(pa); painter.end(); pix.setMask(pix.createHeuristicMask()); return pix; } FileDetailView::FileDetailView(TQWidget *parent, const char *name) : TDEListView(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(), TQT_SIGNAL( sectionClicked(int)), TQT_SLOT(slotSortingChanged(int) )); connect( this, TQT_SIGNAL( returnPressed(TQListViewItem *) ), TQT_SLOT( slotActivate( TQListViewItem *) ) ); connect( this, TQT_SIGNAL( clicked(TQListViewItem *, const TQPoint&, int)), TQT_SLOT( selected( TQListViewItem *) ) ); connect( this, TQT_SIGNAL( doubleClicked(TQListViewItem *, const TQPoint&, int)), TQT_SLOT( slotActivate( TQListViewItem *) ) ); connect( this, TQT_SIGNAL(contextMenuRequested( TQListViewItem *, const TQPoint &, int )), this, TQT_SLOT( slotActivateMenu( TQListViewItem *, const TQPoint& ))); TQListView::setSelectionMode( TQListView::Extended ); connect( this, TQT_SIGNAL( selectionChanged() ), TQT_SLOT( slotSelectionChanged() )); // FileViewStack need to be aware of sort changes, to update the sort menu connect( sig, TQT_SIGNAL(sortingChanged(TQDir::SortSpec)), this, TQT_SIGNAL(sortingChanged(TQDir::SortSpec)) ); setSorting( sorting() ); mResolver = new KMimeTypeResolver( this ); setDragEnabled(true); setAcceptDrops(true); setDropVisualizer(false); setDropHighlighter(false); int size = IconSize(TDEIcon::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) TDEListView::setSelected(item, enable); } void FileDetailView::setCurrentItem( const KFileItem *item ) { if (!item) return; FileDetailViewItem *listItem = viewItem(item); if (listItem) TDEListView::setCurrentItem(listItem); } KFileItem * FileDetailView::currentFileItem() const { FileDetailViewItem *current = static_cast( currentItem() ); if ( current ) return current->fileInfo(); return 0L; } void FileDetailView::clearSelection() { TDEListView::clearSelection(); } void FileDetailView::selectAll() { TDEListView::selectAll( true ); } void FileDetailView::invertSelection() { TDEListView::invertSelection(); } void FileDetailView::slotActivateMenu (TQListViewItem *item,const TQPoint& 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; TDEListView::clear(); } void FileDetailView::insertItem( KFileItem *i ) { KFileView::insertItem( i ); FileDetailViewItem *item = new FileDetailViewItem( (TQListView*) this, i ); setSortingKey( item, i ); i->setExtraData( this, item ); if ( !i->isMimeTypeKnown() ) mResolver->m_lstPendingMimeIconItems.append( item ); } void FileDetailView::slotActivate( TQListViewItem *item ) { if ( !item ) return; const KFileItem *fi = ( (FileDetailViewItem*)item )->fileInfo(); if ( fi ) sig->activate( fi ); } void FileDetailView::selected( TQListViewItem *item ) { if ( !item ) return; if ( TDEGlobalSettings::singleClick() ) { const KFileItem *fi = ( (FileDetailViewItem*)item )->fileInfo(); if ( fi && (fi->isDir() || !onlyDoubleClickSelectsFiles()) ) sig->activate( fi ); } } void FileDetailView::highlighted( TQListViewItem *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; TQListViewItemIterator it( (TQListView*)this ); for ( ; it.current(); ++it ) { FileDetailViewItem *item=static_cast(it.current()); item->setPixmap( 0, item->fileInfo()->pixmap(TDEIcon::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) { TQDir::SortSpec spec = KFileView::sorting(); bool isDirOrArchive=item->isDir() || Archive::fileItemIsArchive(item); TQString key; if ( spec & TQDir::Time ) { time_t time = TimeUtils::getTime(item); key=sortingKey(time, isDirOrArchive, spec); } else if ( spec & TQDir::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 ) { TQDir::SortSpec sort = sorting(); int sortSpec = -1; bool reversed = col == mSortingCol && (sort & TQDir::Reversed) == 0; mSortingCol = col; switch( col ) { case COL_NAME: sortSpec = (sort & ~TQDir::SortByMask | TQDir::Name); break; case COL_SIZE: sortSpec = (sort & ~TQDir::SortByMask | TQDir::Size); break; case COL_DATE: sortSpec = (sort & ~TQDir::SortByMask | TQDir::Time); break; // the following columns have no equivalent in TQDir, so we set it // to TQDir::Unsorted and remember the column (mSortingCol) case COL_OWNER: case COL_GROUP: case COL_PERM: // grmbl, TQDir::Unsorted == SortByMask. sortSpec = (sort & ~TQDir::SortByMask);// | TQDir::Unsorted; break; default: break; } if ( reversed ) sortSpec |= TQDir::Reversed; else sortSpec &= ~TQDir::Reversed; if ( sort & TQDir::IgnoreCase ) sortSpec |= TQDir::IgnoreCase; else sortSpec &= ~TQDir::IgnoreCase; KFileView::setSorting( static_cast( sortSpec ) ); KFileItem *item; KFileItemListIterator it( *items() ); for ( ; (item = it.current() ); ++it ) { FileDetailViewItem* thumbItem=viewItem( item ); if (thumbItem) setSortingKey(thumbItem,item); } TDEListView::setSorting( mSortingCol, !reversed ); TDEListView::sort(); if (!mBlockSortingSignal) sig->changeSorting( static_cast( sortSpec ) ); } void FileDetailView::setSorting( TQDir::SortSpec spec ) { int col = 0; if ( spec & TQDir::Time ) col = COL_DATE; else if ( spec & TQDir::Size ) col = COL_SIZE; else if ( spec & TQDir::Unsorted ) col = mSortingCol; else col = COL_NAME; // inversed, because slotSortingChanged will reverse it if ( spec & TQDir::Reversed ) spec = (TQDir::SortSpec) (spec & ~TQDir::Reversed); else spec = (TQDir::SortSpec) (spec | TQDir::Reversed); mSortingCol = col; KFileView::setSorting( (TQDir::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 ) TDEListView::ensureItemVisible( item ); } // we're in multiselection mode void FileDetailView::slotSelectionChanged() { sig->highlightFile( 0L ); } KFileItem * FileDetailView::firstFileItem() const { FileDetailViewItem *item = static_cast( 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( TQKeyEvent *e ) { TDEListView::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 { ItemDrawer(const TQFontMetrics& fontMetrics) : mFontMetrics(fontMetrics) {} TQSize itemSize(KFileItem* fileItem) { if (!fileItem) return TQSize(); TQString name = fileItem->name(); int width = TQMIN(mGenerator->maxWidth(), mFontMetrics.width(name)); int height = mFontMetrics.height(); return TQSize(width, height); } void drawItem(TQPainter* painter, int left, int top, KFileItem* fileItem) { TQString name = fileItem->name(); painter->save(); KWordWrap::drawFadeoutText(painter, left, top + mFontMetrics.ascent(), mGenerator->maxWidth(), name); painter->restore(); } TQFontMetrics mFontMetrics; }; ItemDrawer drawer(fontMetrics()); KURL::List urls; KFileItemListIterator it(*KFileView::selectedItems()); DragPixmapGenerator 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; } TQDragObject* drag=new KURLDrag(urls, this, 0); TQPixmap dragPixmap = generator.generate(); drag->setPixmap( dragPixmap, TQPoint(-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(TQDropEvent* event) const { return KURLDrag::canDecode(event); } void FileDetailView::contentsDropEvent(TQDropEvent *event) { KFileItem* fileItem=0L; TQListViewItem *item=itemAt(contentsToViewport(event->pos() ) ); if (item) { fileItem=static_cast(item)->fileInfo(); } emit dropped(event,fileItem); } } // namespace