kfileiconview.cpp

00001 // -*- c++ -*-
00002 /* This file is part of the KDE libraries
00003    Copyright (C) 1997 Stephan Kulow <coolo@kde.org>
00004                  2000,2001,2002 Carsten Pfeiffer <pfeiffer@kde.org>
00005 
00006    This library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public
00008    License as published by the Free Software Foundation; either
00009    version 2 of the License, or (at your option) any later version.
00010 
00011    This library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public License
00017    along with this library; see the file COPYING.LIB.   If not, write to
00018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019    Boston, MA 02110-1301, USA.
00020 */
00021 
00022 #include <qfontmetrics.h>
00023 #include <qkeycode.h>
00024 #include <qlabel.h>
00025 #include <qpainter.h>
00026 #include <qpixmap.h>
00027 #include <qregexp.h>
00028 #include <qtimer.h>
00029 #include <qtooltip.h>
00030 
00031 #include <kaction.h>
00032 #include <kapplication.h>
00033 #include <klocale.h>
00034 #include <kfileitem.h>
00035 #include <kiconeffect.h>
00036 #include <kglobalsettings.h>
00037 #include <kdesktopfile.h>
00038 #include <kurldrag.h>
00039 #include <kio/previewjob.h>
00040 
00041 #include "kfileiconview.h"
00042 #include "config-kfile.h"
00043 
00044 #define DEFAULT_PREVIEW_SIZE 60
00045 #define DEFAULT_SHOW_PREVIEWS false
00046 #define DEFAULT_VIEW_MODE "SmallColumns"
00047 
00048 KFileIconViewItem::~KFileIconViewItem()
00049 {
00050     fileInfo()->removeExtraData( iconView() );
00051 }
00052 
00053 class KFileIconView::KFileIconViewPrivate
00054 {
00055 public:
00056     KFileIconViewPrivate( KFileIconView *parent ) {
00057         previewIconSize = 60;
00058         job = 0;
00059         dropItem = 0;
00060 
00061         noArrangement = false;
00062     ignoreMaximumSize = false;
00063     smallColumns = new KRadioAction( i18n("Small Icons"), 0, parent,
00064                      SLOT( slotSmallColumns() ),
00065                      parent->actionCollection(),
00066                      "small columns" );
00067 
00068     largeRows = new KRadioAction( i18n("Large Icons"), 0, parent,
00069                       SLOT( slotLargeRows() ),
00070                       parent->actionCollection(),
00071                       "large rows" );
00072 
00073     smallColumns->setExclusiveGroup(QString::fromLatin1("IconView mode"));
00074     largeRows->setExclusiveGroup(QString::fromLatin1("IconView mode"));
00075 
00076         previews = new KToggleAction( i18n("Thumbnail Previews"), 0,
00077                                       parent->actionCollection(),
00078                                       "show previews" );
00079         zoomIn = KStdAction::zoomIn( parent, SLOT( zoomIn() ),
00080                                      parent->actionCollection(), "zoomIn" );
00081         zoomOut = KStdAction::zoomOut( parent, SLOT( zoomOut() ),
00082                                      parent->actionCollection(), "zoomOut" );
00083 
00084         previews->setGroup("previews");
00085         zoomIn->setGroup("previews");
00086         zoomOut->setGroup("previews");
00087 
00088         connect( previews, SIGNAL( toggled( bool )),
00089                  parent, SLOT( slotPreviewsToggled( bool )));
00090 
00091         connect( &previewTimer, SIGNAL( timeout() ),
00092                  parent, SLOT( showPreviews() ));
00093         connect( &autoOpenTimer, SIGNAL( timeout() ),
00094                  parent, SLOT( slotAutoOpen() ));
00095     }
00096 
00097     ~KFileIconViewPrivate() {
00098         if ( job )
00099             job->kill();
00100     }
00101 
00102     KRadioAction *smallColumns, *largeRows;
00103     KAction *zoomIn, *zoomOut;
00104     KToggleAction *previews;
00105     KIO::PreviewJob *job;
00106     KFileIconViewItem *dropItem;
00107     QTimer previewTimer;
00108     QTimer autoOpenTimer;
00109     QStringList previewMimeTypes;
00110     int previewIconSize;
00111     bool noArrangement :1;
00112     bool ignoreMaximumSize :1;
00113 };
00114 
00115 KFileIconView::KFileIconView(QWidget *parent, const char *name)
00116     : KIconView(parent, name), KFileView()
00117 {
00118     d = new KFileIconViewPrivate( this );
00119 
00120     setViewName( i18n("Icon View") );
00121 
00122     toolTip = 0;
00123     setResizeMode( Adjust );
00124     setMaxItemWidth( 300 );
00125     setWordWrapIconText( false );
00126     setArrangement( TopToBottom );
00127     setAutoArrange( true );
00128     setItemsMovable( false );
00129     setMode( KIconView::Select );
00130     KIconView::setSorting( true );
00131     // as long as QIconView only shows tooltips when the cursor is over the
00132     // icon (and not the text), we have to create our own tooltips
00133     setShowToolTips( false );
00134     slotSmallColumns();
00135     d->smallColumns->setChecked( true );
00136 
00137     connect( this, SIGNAL( returnPressed(QIconViewItem *) ),
00138          SLOT( slotActivate( QIconViewItem *) ) );
00139 
00140     // we want single click _and_ double click (as convenience)
00141     connect( this, SIGNAL( clicked(QIconViewItem *, const QPoint&) ),
00142          SLOT( selected( QIconViewItem *) ) );
00143     connect( this, SIGNAL( doubleClicked(QIconViewItem *, const QPoint&) ),
00144          SLOT( slotActivate( QIconViewItem *) ) );
00145 
00146     connect( this, SIGNAL( onItem( QIconViewItem * ) ),
00147          SLOT( showToolTip( QIconViewItem * ) ) );
00148     connect( this, SIGNAL( onViewport() ),
00149          SLOT( removeToolTip() ) );
00150     connect( this, SIGNAL( contextMenuRequested(QIconViewItem*,const QPoint&)),
00151          SLOT( slotActivateMenu( QIconViewItem*, const QPoint& ) ) );
00152 
00153     KFile::SelectionMode sm = KFileView::selectionMode();
00154     switch ( sm ) {
00155     case KFile::Multi:
00156     QIconView::setSelectionMode( QIconView::Multi );
00157     break;
00158     case KFile::Extended:
00159     QIconView::setSelectionMode( QIconView::Extended );
00160     break;
00161     case KFile::NoSelection:
00162     QIconView::setSelectionMode( QIconView::NoSelection );
00163     break;
00164     default: // fall through
00165     case KFile::Single:
00166     QIconView::setSelectionMode( QIconView::Single );
00167     break;
00168     }
00169 
00170     if ( sm == KFile::Multi || sm == KFile::Extended )
00171     connect( this, SIGNAL( selectionChanged() ),
00172          SLOT( slotSelectionChanged() ));
00173     else
00174     connect( this, SIGNAL( selectionChanged( QIconViewItem * )),
00175          SLOT( highlighted( QIconViewItem * )));
00176 
00177     viewport()->installEventFilter( this );
00178 
00179     // for mimetype resolving
00180     m_resolver = new KMimeTypeResolver<KFileIconViewItem,KFileIconView>(this);
00181 }
00182 
00183 KFileIconView::~KFileIconView()
00184 {
00185     delete m_resolver;
00186     removeToolTip();
00187     delete d;
00188 }
00189 
00190 void KFileIconView::readConfig( KConfig *kc, const QString& group )
00191 {
00192     QString gr = group.isEmpty() ? QString("KFileIconView") : group;
00193     KConfigGroupSaver cs( kc, gr );
00194     QString small = QString::fromLatin1("SmallColumns");
00195     d->previewIconSize = kc->readNumEntry( "Preview Size", DEFAULT_PREVIEW_SIZE );
00196     d->previews->setChecked( kc->readBoolEntry( "ShowPreviews", DEFAULT_SHOW_PREVIEWS ) );
00197 
00198     if ( kc->readEntry("ViewMode", DEFAULT_VIEW_MODE ) == small ) {
00199     d->smallColumns->setChecked( true );
00200     slotSmallColumns();
00201     }
00202     else {
00203     d->largeRows->setChecked( true );
00204     slotLargeRows();
00205     }
00206 
00207     if ( d->previews->isChecked() )
00208         showPreviews();
00209 }
00210 
00211 void KFileIconView::writeConfig( KConfig *kc, const QString& group )
00212 {
00213     QString gr = group.isEmpty() ? QString("KFileIconView") : group;
00214     KConfigGroupSaver cs( kc, gr );
00215 
00216     QString viewMode =  d->smallColumns->isChecked() ?
00217         QString::fromLatin1("SmallColumns") :
00218         QString::fromLatin1("LargeRows");
00219     if(!kc->hasDefault( "ViewMode" ) && viewMode == DEFAULT_VIEW_MODE )
00220         kc->revertToDefault( "ViewMode" );
00221     else
00222         kc->writeEntry( "ViewMode", viewMode );
00223 
00224     int previewsIconSize = d->previewIconSize;
00225     if(!kc->hasDefault( "Preview Size" ) && previewsIconSize == DEFAULT_PREVIEW_SIZE )
00226         kc->revertToDefault( "Preview Size" );
00227     else
00228         kc->writeEntry( "Preview Size", previewsIconSize );
00229 
00230     bool showPreviews = d->previews->isChecked();
00231     if(!kc->hasDefault( "ShowPreviews" ) && showPreviews == DEFAULT_SHOW_PREVIEWS )
00232         kc->revertToDefault( "ShowPreviews" );
00233     else
00234         kc->writeEntry( "ShowPreviews", showPreviews );
00235 }
00236 
00237 void KFileIconView::removeToolTip()
00238 {
00239     delete toolTip;
00240     toolTip = 0;
00241 }
00242 
00243 void KFileIconView::showToolTip( QIconViewItem *item )
00244 {
00245     delete toolTip;
00246     toolTip = 0;
00247 
00248     if ( !item )
00249     return;
00250 
00251     int w = maxItemWidth() - ( itemTextPos() == QIconView::Bottom ? 0 :
00252                    item->pixmapRect().width() ) - 4;
00253     if ( fontMetrics().width( item->text() ) >= w ) {
00254     toolTip = new QLabel( QString::fromLatin1(" %1 ").arg(item->text()), 0,
00255                   "myToolTip",
00256                   WStyle_StaysOnTop | WStyle_Customize | WStyle_NoBorder | WStyle_Tool | WX11BypassWM );
00257     toolTip->setFrameStyle( QFrame::Plain | QFrame::Box );
00258     toolTip->setLineWidth( 1 );
00259     toolTip->setAlignment( AlignLeft | AlignTop );
00260     toolTip->move( QCursor::pos() + QPoint( 14, 14 ) );
00261     toolTip->adjustSize();
00262     QRect screen = QApplication::desktop()->screenGeometry(
00263             QApplication::desktop()->screenNumber(QCursor::pos()));
00264     if (toolTip->x()+toolTip->width() > screen.right()) {
00265         toolTip->move(toolTip->x()+screen.right()-toolTip->x()-toolTip->width(), toolTip->y());
00266     }
00267     if (toolTip->y()+toolTip->height() > screen.bottom()) {
00268         toolTip->move(toolTip->x(), screen.bottom()-toolTip->y()-toolTip->height()+toolTip->y());
00269     }
00270     toolTip->setFont( QToolTip::font() );
00271     toolTip->setPalette( QToolTip::palette(), true );
00272     toolTip->show();
00273     }
00274 }
00275 
00276 void KFileIconView::slotActivateMenu( QIconViewItem* item, const QPoint& pos )
00277 {
00278     if ( !item ) {
00279     sig->activateMenu( 0, pos );
00280     return;
00281     }
00282 
00283     KFileIconViewItem *i = (KFileIconViewItem*) item;
00284     sig->activateMenu( i->fileInfo(), pos );
00285 }
00286 
00287 void KFileIconView::hideEvent( QHideEvent *e )
00288 {
00289     removeToolTip();
00290     KIconView::hideEvent( e );
00291 }
00292 
00293 void KFileIconView::keyPressEvent( QKeyEvent *e )
00294 {
00295     KIconView::keyPressEvent( e );
00296 
00297     // ignore Ctrl-Return so that the dialog can catch it.
00298     if ( (e->state() & ControlButton) &&
00299          (e->key() == Key_Return || e->key() == Key_Enter) )
00300         e->ignore();
00301 }
00302 
00303 void KFileIconView::setSelected( const KFileItem *info, bool enable )
00304 {
00305     KFileIconViewItem *item = viewItem( info );
00306     if ( item )
00307         KIconView::setSelected( item, enable, true );
00308 }
00309 
00310 void KFileIconView::selectAll()
00311 {
00312     if (KFileView::selectionMode() == KFile::NoSelection ||
00313         KFileView::selectionMode() == KFile::Single)
00314     return;
00315 
00316     KIconView::selectAll( true );
00317 }
00318 
00319 void KFileIconView::clearSelection()
00320 {
00321     KIconView::clearSelection();
00322 }
00323 
00324 void KFileIconView::invertSelection()
00325 {
00326     KIconView::invertSelection();
00327 }
00328 
00329 void KFileIconView::clearView()
00330 {
00331     m_resolver->m_lstPendingMimeIconItems.clear();
00332 
00333     KIconView::clear();
00334     stopPreview();
00335 }
00336 
00337 void KFileIconView::insertItem( KFileItem *i )
00338 {
00339     if ( i->mimetype() == "application/x-desktop" )
00340     {
00341         KDesktopFile df( i->url().path(), true );
00342         if ( df.readType() == "Link" )
00343         {
00344            i->setName( df.readName() );
00345         }
00346     }
00347     KFileView::insertItem( i );
00348 
00349     QIconView* qview = static_cast<QIconView*>( this );
00350     // Since creating and initializing an item leads to a repaint,
00351     // we disable updates on the IconView for a while.
00352     qview->setUpdatesEnabled( false );
00353     KFileIconViewItem *item = new KFileIconViewItem( qview, i );
00354     
00355     initItem( item, i, true );
00356     qview->setUpdatesEnabled( true );
00357 
00358     if ( !i->isMimeTypeKnown() )
00359         m_resolver->m_lstPendingMimeIconItems.append( item );
00360 
00361     i->setExtraData( this, item );
00362 }
00363 
00364 void KFileIconView::slotActivate( QIconViewItem *item )
00365 {
00366     if ( !item )
00367         return;
00368 
00369     const KFileItem *fi = ( (KFileIconViewItem*)item )->fileInfo();
00370     
00371     if ( fi->mimetype() == "application/x-desktop" )
00372     {
00373         KDesktopFile df( fi->url().path(), true );
00374         if ( df.readType() == "Link"  )
00375         {
00376             KURL lu( df.readURL() );
00377             if ( lu.isLocalFile() )
00378             {
00379                 fi = new KFileItem( KURL( df.readURL() ), "inode/directory", S_IFDIR );
00380             }
00381         }
00382     }
00383     if ( fi )
00384         sig->activate( fi );
00385 }
00386 
00387 void KFileIconView::selected( QIconViewItem *item )
00388 {
00389     if ( !item || (KApplication::keyboardMouseState() & (ShiftButton | ControlButton)) != 0 )
00390         return;
00391     
00392     const KFileItem *fi = ( (KFileIconViewItem*)item )->fileInfo();
00393     if ( fi->mimetype() == "application/x-desktop" )
00394     {
00395         KDesktopFile df( fi->url().path(), true );
00396         if ( df.readType() == "Link" )
00397         {
00398             KURL lu( df.readURL() );
00399             if ( lu.isLocalFile() )
00400             {
00401                 fi = new KFileItem( KURL( df.readURL() ), "inode/directory", S_IFDIR );
00402             }
00403         }
00404     }
00405     
00406     if ( KGlobalSettings::singleClick() ) 
00407     {
00408         if ( fi && (fi->isDir() || !onlyDoubleClickSelectsFiles()) )
00409             sig->activate( fi );
00410     }
00411 }
00412 
00413 void KFileIconView::setCurrentItem( const KFileItem *item )
00414 {
00415     KFileIconViewItem *it = viewItem( item );
00416     if ( it )
00417         KIconView::setCurrentItem( it );
00418 }
00419 
00420 KFileItem * KFileIconView::currentFileItem() const
00421 {
00422     KFileIconViewItem *current = static_cast<KFileIconViewItem*>( currentItem() );
00423     if ( current )
00424         return current->fileInfo();
00425 
00426     return 0L;
00427 }
00428 
00429 void KFileIconView::highlighted( QIconViewItem *item )
00430 {
00431     if ( !item )
00432     return;
00433     const KFileItem *fi = ( (KFileIconViewItem*)item )->fileInfo();
00434     if ( fi )
00435     sig->highlightFile( fi );
00436 }
00437 
00438 void KFileIconView::setSelectionMode( KFile::SelectionMode sm )
00439 {
00440     disconnect( SIGNAL( selectionChanged() ), this );
00441     disconnect( SIGNAL( selectionChanged( QIconViewItem * )), this );
00442 
00443     KFileView::setSelectionMode( sm );
00444     switch ( KFileView::selectionMode() ) {
00445     case KFile::Multi:
00446     QIconView::setSelectionMode( QIconView::Multi );
00447     break;
00448     case KFile::Extended:
00449     QIconView::setSelectionMode( QIconView::Extended );
00450     break;
00451     case KFile::NoSelection:
00452     QIconView::setSelectionMode( QIconView::NoSelection );
00453     break;
00454     default: // fall through
00455     case KFile::Single:
00456     QIconView::setSelectionMode( QIconView::Single );
00457     break;
00458     }
00459 
00460     if ( sm == KFile::Multi || sm == KFile::Extended )
00461     connect( this, SIGNAL( selectionChanged() ),
00462          SLOT( slotSelectionChanged() ));
00463     else
00464     connect( this, SIGNAL( selectionChanged( QIconViewItem * )),
00465          SLOT( highlighted( QIconViewItem * )));
00466 }
00467 
00468 bool KFileIconView::isSelected( const KFileItem *i ) const
00469 {
00470     KFileIconViewItem *item = viewItem( i );
00471     return (item && item->isSelected());
00472 }
00473 
00474 void KFileIconView::updateView( bool b )
00475 {
00476     if ( !b )
00477         return; // eh?
00478 
00479     KFileIconViewItem *item = static_cast<KFileIconViewItem*>(QIconView::firstItem());
00480     if ( item ) {
00481         do {
00482             if ( d->previews->isChecked() ) {
00483                 if ( canPreview( item->fileInfo() ) )
00484                     item->setPixmapSize( QSize( d->previewIconSize, d->previewIconSize ) );
00485             }
00486             else {
00487                 // unset pixmap size (used for previews)
00488                 if ( !item->pixmapSize().isNull() )
00489                     item->setPixmapSize( QSize( 0, 0 ) );
00490             }
00491             // recalculate item parameters but avoid an in-place repaint
00492             item->setPixmap( (item->fileInfo())->pixmap( myIconSize ), true, false );
00493             item = static_cast<KFileIconViewItem *>(item->nextItem());
00494         } while ( item != 0L );
00495     }
00496 }
00497 
00498 void KFileIconView::updateView( const KFileItem *i )
00499 {
00500     KFileIconViewItem *item = viewItem( i );
00501     if ( item )
00502         initItem( item, i, true );
00503 }
00504 
00505 void KFileIconView::removeItem( const KFileItem *i )
00506 {
00507     if ( !i )
00508     return;
00509 
00510     if ( d->job )
00511         d->job->removeItem( i );
00512 
00513     KFileIconViewItem *item = viewItem( i );
00514     m_resolver->m_lstPendingMimeIconItems.remove( item );
00515     delete item;
00516 
00517     KFileView::removeItem( i );
00518 }
00519 
00520 void KFileIconView::setIconSize( int size )
00521 {
00522     myIconSize = size;
00523     updateIcons();
00524 }
00525 
00526 void KFileIconView::setPreviewSize( int size )
00527 {
00528     if ( size < 30 )
00529         size = 30; // minimum
00530 
00531     d->previewIconSize = size;
00532     if ( d->previews->isChecked() )
00533         showPreviews();
00534 }
00535 
00536 void KFileIconView::setIgnoreMaximumSize(bool ignoreSize)
00537 {
00538     d->ignoreMaximumSize = ignoreSize;
00539 }
00540 
00541 void KFileIconView::updateIcons()
00542 {
00543     updateView( true );
00544     arrangeItemsInGrid();
00545 }
00546 
00547 void KFileIconView::ensureItemVisible( const KFileItem *i )
00548 {
00549     KFileIconViewItem *item = viewItem( i );
00550     if ( item )
00551     KIconView::ensureItemVisible( item );
00552 }
00553 
00554 void KFileIconView::slotSelectionChanged()
00555 {
00556     sig->highlightFile( 0L );
00557 }
00558 
00559 void KFileIconView::slotSmallColumns()
00560 {
00561     // setItemTextPos(), setArrangement(), setWordWrapIconText() and
00562     // setIconSize() all call arrangeItemsInGrid() :( Prevent this.
00563     d->noArrangement = true; // stop arrangeItemsInGrid()!
00564 
00565     // Make sure to uncheck previews if selected
00566     if ( d->previews->isChecked() )
00567     {
00568         stopPreview();
00569         d->previews->setChecked( false );
00570     }
00571     setGridX( -1 );
00572     setMaxItemWidth( 300 );
00573     setItemTextPos( Right );
00574     setArrangement( TopToBottom );
00575     setWordWrapIconText( false );
00576     setSpacing( 0 );
00577 
00578     d->noArrangement = false; // now we can arrange
00579     setIconSize( KIcon::SizeSmall );
00580 }
00581 
00582 void KFileIconView::slotLargeRows()
00583 {
00584     // setItemTextPos(), setArrangement(), setWordWrapIconText() and
00585     // setIconSize() all call arrangeItemsInGrid() :( Prevent this.
00586     d->noArrangement = true; // stop arrangeItemsInGrid()!
00587 
00588     setGridX( KGlobal::iconLoader()->currentSize( KIcon::Desktop ) + 50 );
00589     setItemTextPos( Bottom );
00590     setArrangement( LeftToRight );
00591     setWordWrapIconText( true );
00592     setSpacing( 5 ); // default in QIconView
00593 
00594     d->noArrangement = false; // now we can arrange
00595     setIconSize( KIcon::SizeMedium );
00596 }
00597 
00598 void KFileIconView::stopPreview()
00599 {
00600     if ( d->job ) {
00601         d->job->kill();
00602         d->job = 0L;
00603     }
00604 }
00605 
00606 void KFileIconView::slotPreviewsToggled( bool on )
00607 {
00608     if ( on )
00609         showPreviews();
00610     else {
00611         stopPreview();
00612         slotLargeRows();
00613     }
00614 }
00615 
00616 void KFileIconView::showPreviews()
00617 {
00618     if ( d->previewMimeTypes.isEmpty() )
00619         d->previewMimeTypes = KIO::PreviewJob::supportedMimeTypes();
00620 
00621     stopPreview();
00622     d->previews->setChecked( true );
00623 
00624     if ( !d->largeRows->isChecked() ) {
00625         d->largeRows->setChecked( true );
00626         slotLargeRows(); // also sets the icon size and updates the grid
00627     }
00628     else {
00629         updateIcons();
00630     }
00631 
00632     d->job = KIO::filePreview(*items(), d->previewIconSize,d->previewIconSize);
00633     d->job->setIgnoreMaximumSize(d->ignoreMaximumSize);
00634 
00635     connect( d->job, SIGNAL( result( KIO::Job * )),
00636              this, SLOT( slotPreviewResult( KIO::Job * )));
00637     connect( d->job, SIGNAL( gotPreview( const KFileItem*, const QPixmap& )),
00638              SLOT( gotPreview( const KFileItem*, const QPixmap& ) ));
00639 //     connect( d->job, SIGNAL( failed( const KFileItem* )),
00640 //              this, SLOT( slotFailed( const KFileItem* ) ));
00641 }
00642 
00643 void KFileIconView::slotPreviewResult( KIO::Job *job )
00644 {
00645     if ( job == d->job )
00646         d->job = 0L;
00647 }
00648 
00649 void KFileIconView::gotPreview( const KFileItem *item, const QPixmap& pix )
00650 {
00651     KFileIconViewItem *it = viewItem( item );
00652     if ( it )
00653         if( item->overlays() & KIcon::HiddenOverlay )
00654         {
00655             QPixmap p( pix );
00656 
00657             KIconEffect::semiTransparent( p );
00658             it->setPixmap( p );
00659         }
00660         else
00661             it->setPixmap( pix );
00662 }
00663 
00664 bool KFileIconView::canPreview( const KFileItem *item ) const
00665 {
00666     QStringList::Iterator it = d->previewMimeTypes.begin();
00667     QRegExp r;
00668     r.setWildcard( true );
00669 
00670     for ( ; it != d->previewMimeTypes.end(); ++it ) {
00671         QString type = *it;
00672         // the "mimetype" can be "image/*"
00673         if ( type.at( type.length() - 1 ) == '*' ) {
00674             r.setPattern( type );
00675             if ( r.search( item->mimetype() ) != -1 )
00676                 return true;
00677         }
00678         else
00679             if ( item->mimetype() == type )
00680                 return true;
00681     }
00682 
00683     return false;
00684 }
00685 
00686 KFileItem * KFileIconView::firstFileItem() const
00687 {
00688     KFileIconViewItem *item = static_cast<KFileIconViewItem*>( firstItem() );
00689     if ( item )
00690         return item->fileInfo();
00691     return 0L;
00692 }
00693 
00694 KFileItem * KFileIconView::nextItem( const KFileItem *fileItem ) const
00695 {
00696     if ( fileItem ) {
00697         KFileIconViewItem *item = viewItem( fileItem );
00698         if ( item && item->nextItem() )
00699             return ((KFileIconViewItem*) item->nextItem())->fileInfo();
00700     }
00701     return 0L;
00702 }
00703 
00704 KFileItem * KFileIconView::prevItem( const KFileItem *fileItem ) const
00705 {
00706     if ( fileItem ) {
00707         KFileIconViewItem *item = viewItem( fileItem );
00708         if ( item && item->prevItem() )
00709             return ((KFileIconViewItem*) item->prevItem())->fileInfo();
00710     }
00711     return 0L;
00712 }
00713 
00714 void KFileIconView::setSorting( QDir::SortSpec spec )
00715 {
00716     KFileView::setSorting( spec );
00717     KFileItemListIterator it( *items() );
00718 
00719     KFileItem *item;
00720 
00721     if ( spec & QDir::Time ) {
00722         for ( ; (item = it.current()); ++it )
00723             // warning, time_t is often signed -> cast it
00724             viewItem(item)->setKey( sortingKey( (unsigned long)item->time( KIO::UDS_MODIFICATION_TIME ), item->isDir(), spec ));
00725     }
00726 
00727     else if ( spec & QDir::Size ) {
00728         for ( ; (item = it.current()); ++it )
00729             viewItem(item)->setKey( sortingKey( item->size(), item->isDir(),
00730                                                 spec ));
00731     }
00732     else { // Name or Unsorted
00733         for ( ; (item = it.current()); ++it )
00734             viewItem(item)->setKey( sortingKey( item->text(), item->isDir(),
00735                                                 spec ));
00736     }
00737 
00738     KIconView::setSorting( true, !isReversed() );
00739     sort( !isReversed() );
00740 }
00741 
00742 //
00743 // mimetype determination on demand
00744 //
00745 void KFileIconView::mimeTypeDeterminationFinished()
00746 {
00747     // anything to do?
00748 }
00749 
00750 void KFileIconView::determineIcon( KFileIconViewItem *item )
00751 {
00752     (void) item->fileInfo()->determineMimeType();
00753     updateView( item->fileInfo() );
00754 }
00755 
00756 void KFileIconView::listingCompleted()
00757 {
00758     arrangeItemsInGrid();
00759 
00760     // QIconView doesn't set the current item automatically, so we have to do
00761     // that. We don't want to emit selectionChanged() tho.
00762     if ( !currentItem() ) {
00763         bool block = signalsBlocked();
00764         blockSignals( true );
00765         QIconViewItem *item = viewItem( firstFileItem() );
00766         KIconView::setCurrentItem( item );
00767         KIconView::setSelected( item, false );
00768         blockSignals( block );
00769     }
00770 
00771     m_resolver->start( d->previews->isChecked() ? 0 : 10 );
00772 }
00773 
00774 // need to remove our tooltip, eventually
00775 bool KFileIconView::eventFilter( QObject *o, QEvent *e )
00776 {
00777     if ( o == viewport() || o == this ) {
00778         int type = e->type();
00779         if ( type == QEvent::Leave ||
00780              type == QEvent::FocusOut )
00781             removeToolTip();
00782     }
00783 
00784     return KIconView::eventFilter( o, e );
00785 }
00786 
00788 
00789 // ### workaround for Qt3 Bug
00790 void KFileIconView::showEvent( QShowEvent *e )
00791 {
00792     KIconView::showEvent( e );
00793 }
00794 
00795 
00796 void KFileIconView::initItem( KFileIconViewItem *item, const KFileItem *i,
00797                               bool updateTextAndPixmap )
00798 {
00799     if ( d->previews->isChecked() && canPreview( i ) )
00800         item->setPixmapSize( QSize( d->previewIconSize, d->previewIconSize ) );
00801 
00802     if ( updateTextAndPixmap )
00803     {
00804         // this causes a repaint of the item, which we want to avoid during
00805         // directory listing, when all items are created. We want to paint all
00806         // items at once, not every single item in that case.
00807         item->setText( i->text() , false, false );
00808         item->setPixmap( i->pixmap( myIconSize ) );
00809     }
00810 
00811     // see also setSorting()
00812     QDir::SortSpec spec = KFileView::sorting();
00813 
00814     if ( spec & QDir::Time )
00815         // warning, time_t is often signed -> cast it
00816         item->setKey( sortingKey( (unsigned long) i->time( KIO::UDS_MODIFICATION_TIME ),
00817                                   i->isDir(), spec ));
00818     else if ( spec & QDir::Size )
00819         item->setKey( sortingKey( i->size(), i->isDir(), spec ));
00820 
00821     else // Name or Unsorted
00822         item->setKey( sortingKey( i->text(), i->isDir(), spec ));
00823 
00824     //qDebug("** key for: %s: %s", i->text().latin1(), item->key().latin1());
00825 
00826     if ( d->previews->isChecked() )
00827         d->previewTimer.start( 10, true );
00828 }
00829 
00830 void KFileIconView::arrangeItemsInGrid( bool update )
00831 {
00832     if ( d->noArrangement )
00833         return;
00834 
00835     KIconView::arrangeItemsInGrid( update );
00836 }
00837 
00838 void KFileIconView::zoomIn()
00839 {
00840     setPreviewSize( d->previewIconSize + 30 );
00841 }
00842 
00843 void KFileIconView::zoomOut()
00844 {
00845     setPreviewSize( d->previewIconSize - 30 );
00846 }
00847 
00848 QDragObject *KFileIconView::dragObject()
00849 {
00850     // create a list of the URL:s that we want to drag
00851     KURL::List urls;
00852     KFileItemListIterator it( * KFileView::selectedItems() );
00853     for ( ; it.current(); ++it ){
00854         urls.append( (*it)->url() );
00855     }
00856     QPixmap pixmap;
00857     if( urls.count() > 1 )
00858         pixmap = DesktopIcon( "kmultiple", iconSize() );
00859     if( pixmap.isNull() )
00860         pixmap = currentFileItem()->pixmap( iconSize() );
00861 
00862     QPoint hotspot;
00863     hotspot.setX( pixmap.width() / 2 );
00864     hotspot.setY( pixmap.height() / 2 );
00865     QDragObject* myDragObject = new KURLDrag( urls, widget() );
00866     myDragObject->setPixmap( pixmap, hotspot );
00867     return myDragObject;
00868 }
00869 
00870 void KFileIconView::slotAutoOpen()
00871 {
00872     d->autoOpenTimer.stop();
00873     if( !d->dropItem )
00874         return;
00875 
00876     KFileItem *fileItem = d->dropItem->fileInfo();
00877     if (!fileItem)
00878         return;
00879 
00880     if( fileItem->isFile() )
00881         return;
00882 
00883     if ( fileItem->isDir() || fileItem->isLink())
00884         sig->activate( fileItem );
00885 }
00886 
00887 bool KFileIconView::acceptDrag(QDropEvent* e) const
00888 {
00889    return KURLDrag::canDecode( e ) &&
00890        (e->source()!=const_cast<KFileIconView*>(this)) &&
00891        ( e->action() == QDropEvent::Copy
00892       || e->action() == QDropEvent::Move
00893       || e->action() == QDropEvent::Link );
00894 }
00895 
00896 void KFileIconView::contentsDragEnterEvent( QDragEnterEvent *e )
00897 {
00898     if ( ! acceptDrag( e ) ) { // can we decode this ?
00899         e->ignore();            // No
00900         return;
00901     }
00902     e->acceptAction();     // Yes
00903 
00904     if ((dropOptions() & AutoOpenDirs) == 0)
00905        return;
00906 
00907     KFileIconViewItem *item = dynamic_cast<KFileIconViewItem*>(findItem( contentsToViewport( e->pos() ) ));
00908     if ( item ) {  // are we over an item ?
00909        d->dropItem = item;
00910        d->autoOpenTimer.start( autoOpenDelay() ); // restart timer
00911     }
00912     else
00913     {
00914        d->dropItem = 0;
00915        d->autoOpenTimer.stop();
00916     }
00917 }
00918 
00919 void KFileIconView::contentsDragMoveEvent( QDragMoveEvent *e )
00920 {
00921     if ( ! acceptDrag( e ) ) { // can we decode this ?
00922         e->ignore();            // No
00923         return;
00924     }
00925     e->acceptAction();     // Yes
00926 
00927     if ((dropOptions() & AutoOpenDirs) == 0)
00928        return;
00929 
00930     KFileIconViewItem *item = dynamic_cast<KFileIconViewItem*>(findItem( contentsToViewport( e->pos() ) ));
00931     if ( item ) {  // are we over an item ?
00932        if (d->dropItem != item)
00933        {
00934            d->dropItem = item;
00935            d->autoOpenTimer.start( autoOpenDelay() ); // restart timer
00936        }
00937     }
00938     else
00939     {
00940        d->dropItem = 0;
00941        d->autoOpenTimer.stop();
00942     }
00943 }
00944 
00945 void KFileIconView::contentsDragLeaveEvent( QDragLeaveEvent * )
00946 {
00947     d->dropItem = 0;
00948     d->autoOpenTimer.stop();
00949 }
00950 
00951 void KFileIconView::contentsDropEvent( QDropEvent *e )
00952 {
00953     d->dropItem = 0;
00954     d->autoOpenTimer.stop();
00955 
00956     if ( ! acceptDrag( e ) ) { // can we decode this ?
00957         e->ignore();            // No
00958         return;
00959     }
00960     e->acceptAction();     // Yes
00961 
00962     KFileIconViewItem *item = dynamic_cast<KFileIconViewItem*>(findItem( contentsToViewport( e->pos() ) ));
00963     KFileItem * fileItem = 0;
00964     if (item)
00965         fileItem = item->fileInfo();
00966 
00967     emit dropped(e, fileItem);
00968 
00969     KURL::List urls;
00970     if (KURLDrag::decode( e, urls ) && !urls.isEmpty())
00971     {
00972         emit dropped(e, urls, fileItem ? fileItem->url() : KURL());
00973         sig->dropURLs(fileItem, e, urls);
00974     }
00975 }
00976 
00977 void KFileIconView::virtual_hook( int id, void* data )
00978 { KIconView::virtual_hook( id, data );
00979   KFileView::virtual_hook( id, data ); }
00980 
00981 #include "kfileiconview.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys