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