kfileivi.cc
00001 /* This file is part of the KDE project 00002 Copyright (C) 1999, 2000, 2001, 2002 David Faure <faure@kde.org> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License as published by the Free Software Foundation; either 00007 version 2 of the License, or (at your option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to 00016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00017 Boston, MA 02110-1301, USA. 00018 */ 00019 00020 #include "kfileivi.h" 00021 #include "kivdirectoryoverlay.h" 00022 #include "konq_iconviewwidget.h" 00023 #include "konq_operations.h" 00024 #include "konq_settings.h" 00025 00026 #include <tqpainter.h> 00027 00028 #include <kurldrag.h> 00029 #include <kiconeffect.h> 00030 #include <kfileitem.h> 00031 #include <kdebug.h> 00032 #include <krun.h> 00033 00034 #undef Bool 00035 00039 struct KFileIVI::Private 00040 { 00041 TQIconSet icons; // Icon states (cached to prevent re-applying icon effects 00042 // every time) 00043 TQPixmap thumb; // Raw unprocessed thumbnail 00044 TQString m_animatedIcon; // Name of animation 00045 bool m_animated; // Animation currently running ? 00046 KIVDirectoryOverlay* m_directoryOverlay; 00047 TQPixmap m_overlay; 00048 TQString m_overlayName; 00049 }; 00050 00051 KFileIVI::KFileIVI( KonqIconViewWidget *iconview, KFileItem* fileitem, int size ) 00052 : KIconViewItem( iconview, fileitem->text() ), 00053 m_size( size ), m_state( KIcon::DefaultState ), 00054 m_bDisabled( false ), m_bThumbnail( false ), m_fileitem( fileitem ) 00055 { 00056 d = new KFileIVI::Private; 00057 00058 updatePixmapSize(); 00059 setPixmap( m_fileitem->pixmap( m_size, m_state ) ); 00060 setDropEnabled( S_ISDIR( m_fileitem->mode() ) ); 00061 00062 // Cache entry for the icon effects 00063 d->icons.reset( *pixmap(), TQIconSet::Large ); 00064 d->m_animated = false; 00065 00066 // iconName() requires the mimetype to be known 00067 if ( fileitem->isMimeTypeKnown() ) 00068 { 00069 TQString icon = fileitem->iconName(); 00070 if ( !icon.isEmpty() ) 00071 setMouseOverAnimation( icon ); 00072 else 00073 setMouseOverAnimation( "unknown" ); 00074 } 00075 d->m_directoryOverlay = 0; 00076 } 00077 00078 KFileIVI::~KFileIVI() 00079 { 00080 delete d->m_directoryOverlay; 00081 delete d; 00082 } 00083 00084 void KFileIVI::invalidateThumb( int state, bool redraw ) 00085 { 00086 TQIconSet::Mode mode; 00087 switch( state ) 00088 { 00089 case KIcon::DisabledState: 00090 mode = TQIconSet::Disabled; 00091 break; 00092 case KIcon::ActiveState: 00093 mode = TQIconSet::Active; 00094 break; 00095 case KIcon::DefaultState: 00096 default: 00097 mode = TQIconSet::Normal; 00098 break; 00099 } 00100 d->icons = TQIconSet(); 00101 d->icons.setPixmap( KGlobal::iconLoader()->iconEffect()-> 00102 apply( d->thumb, KIcon::Desktop, state ), 00103 TQIconSet::Large, mode ); 00104 m_state = state; 00105 00106 TQIconViewItem::setPixmap( d->icons.pixmap( TQIconSet::Large, mode ), 00107 false, redraw ); 00108 } 00109 00110 void KFileIVI::setIcon( int size, int state, bool recalc, bool redraw ) 00111 { 00112 m_size = size; 00113 m_bThumbnail = false; 00114 if ( m_bDisabled ) 00115 m_state = KIcon::DisabledState; 00116 else 00117 m_state = state; 00118 00119 if ( d->m_overlayName.isNull() ) 00120 d->m_overlay = TQPixmap(); 00121 else { 00122 int halfSize; 00123 if (m_size == 0) { 00124 halfSize = IconSize(KIcon::Desktop) / 2; 00125 } else { 00126 halfSize = m_size / 2; 00127 } 00128 d->m_overlay = DesktopIcon(d->m_overlayName, halfSize); 00129 } 00130 00131 setPixmapDirect(m_fileitem->pixmap( m_size, m_state ) , recalc, redraw ); 00132 } 00133 00134 void KFileIVI::setOverlay( const TQString& iconName ) 00135 { 00136 d->m_overlayName = iconName; 00137 00138 refreshIcon(true); 00139 } 00140 00141 KIVDirectoryOverlay* KFileIVI::setShowDirectoryOverlay( bool show ) 00142 { 00143 if ( !m_fileitem->isDir() || m_fileitem->iconName() != "folder" ) 00144 return 0; 00145 00146 if (show) { 00147 if (!d->m_directoryOverlay) 00148 d->m_directoryOverlay = new KIVDirectoryOverlay(this); 00149 return d->m_directoryOverlay; 00150 } else { 00151 delete d->m_directoryOverlay; 00152 d->m_directoryOverlay = 0; 00153 setOverlay(TQString()); 00154 return 0; 00155 } 00156 } 00157 00158 bool KFileIVI::showDirectoryOverlay( ) 00159 { 00160 return (bool)d->m_directoryOverlay; 00161 } 00162 00163 void KFileIVI::setPixmapDirect( const TQPixmap& pixmap, bool recalc, bool redraw ) 00164 { 00165 TQIconSet::Mode mode; 00166 switch( m_state ) 00167 { 00168 case KIcon::DisabledState: 00169 mode = TQIconSet::Disabled; 00170 break; 00171 case KIcon::ActiveState: 00172 mode = TQIconSet::Active; 00173 break; 00174 case KIcon::DefaultState: 00175 default: 00176 mode = TQIconSet::Normal; 00177 break; 00178 } 00179 00180 // We cannot just reset() the iconset here, because setIcon can be 00181 // called with any state and not just normal state. So we just 00182 // create a dummy empty iconset as base object. 00183 d->icons = TQIconSet(); 00184 d->icons.setPixmap( pixmap, TQIconSet::Large, mode ); 00185 00186 updatePixmapSize(); 00187 TQIconViewItem::setPixmap( d->icons.pixmap( TQIconSet::Large, mode ), 00188 recalc, redraw ); 00189 } 00190 00191 void KFileIVI::setDisabled( bool disabled ) 00192 { 00193 if ( m_bDisabled != disabled ) 00194 { 00195 m_bDisabled = disabled; 00196 bool active = ( m_state == KIcon::ActiveState ); 00197 setEffect( m_bDisabled ? KIcon::DisabledState : 00198 ( active ? KIcon::ActiveState : KIcon::DefaultState ) ); 00199 } 00200 } 00201 00202 void KFileIVI::setThumbnailPixmap( const TQPixmap & pixmap ) 00203 { 00204 m_bThumbnail = true; 00205 d->thumb = pixmap; 00206 // TQIconSet::reset() doesn't seem to clear the other generated pixmaps, 00207 // so we just create a blank TQIconSet here 00208 d->icons = TQIconSet(); 00209 d->icons.setPixmap( KGlobal::iconLoader()->iconEffect()-> 00210 apply( pixmap, KIcon::Desktop, KIcon::DefaultState ), 00211 TQIconSet::Large, TQIconSet::Normal ); 00212 00213 m_state = KIcon::DefaultState; 00214 00215 // Recalc when setting this pixmap! 00216 updatePixmapSize(); 00217 TQIconViewItem::setPixmap( d->icons.pixmap( TQIconSet::Large, 00218 TQIconSet::Normal ), true ); 00219 } 00220 00221 void KFileIVI::setActive( bool active ) 00222 { 00223 if ( active ) 00224 setEffect( KIcon::ActiveState ); 00225 else 00226 setEffect( m_bDisabled ? KIcon::DisabledState : KIcon::DefaultState ); 00227 } 00228 00229 void KFileIVI::setEffect( int state ) 00230 { 00231 TQIconSet::Mode mode; 00232 switch( state ) 00233 { 00234 case KIcon::DisabledState: 00235 mode = TQIconSet::Disabled; 00236 break; 00237 case KIcon::ActiveState: 00238 mode = TQIconSet::Active; 00239 break; 00240 case KIcon::DefaultState: 00241 default: 00242 mode = TQIconSet::Normal; 00243 break; 00244 } 00245 // Do not update if the fingerprint is identical (prevents flicker)! 00246 00247 KIconEffect *effect = KGlobal::iconLoader()->iconEffect(); 00248 00249 bool haveEffect = effect->hasEffect( KIcon::Desktop, m_state ) != 00250 effect->hasEffect( KIcon::Desktop, state ); 00251 00252 //kdDebug(1203) << "desktop;defaultstate=" << 00253 // effect->fingerprint(KIcon::Desktop, KIcon::DefaultState) << 00254 // endl; 00255 //kdDebug(1203) << "desktop;activestate=" << 00256 // effect->fingerprint(KIcon::Desktop, KIcon::ActiveState) << 00257 // endl; 00258 00259 if( haveEffect && 00260 effect->fingerprint( KIcon::Desktop, m_state ) != 00261 effect->fingerprint( KIcon::Desktop, state ) ) 00262 { 00263 // Effects on are not applied until they are first accessed to 00264 // save memory. Do this now when needed 00265 if( m_bThumbnail ) 00266 { 00267 if( d->icons.isGenerated( TQIconSet::Large, mode ) ) 00268 d->icons.setPixmap( effect->apply( d->thumb, KIcon::Desktop, state ), 00269 TQIconSet::Large, mode ); 00270 } 00271 else 00272 { 00273 if( d->icons.isGenerated( TQIconSet::Large, mode ) ) 00274 d->icons.setPixmap( m_fileitem->pixmap( m_size, state ), 00275 TQIconSet::Large, mode ); 00276 } 00277 TQIconViewItem::setPixmap( d->icons.pixmap( TQIconSet::Large, mode ) ); 00278 } 00279 m_state = state; 00280 } 00281 00282 void KFileIVI::refreshIcon( bool redraw ) 00283 { 00284 if (!isThumbnail()) 00285 setIcon( m_size, m_state, true, redraw ); 00286 } 00287 00288 void KFileIVI::invalidateThumbnail() 00289 { 00290 d->thumb = TQPixmap(); 00291 } 00292 00293 bool KFileIVI::isThumbnailInvalid() const 00294 { 00295 return d->thumb.isNull(); 00296 } 00297 00298 bool KFileIVI::acceptDrop( const TQMimeSource *mime ) const 00299 { 00300 if ( mime->provides( "text/uri-list" ) ) // We're dragging URLs 00301 { 00302 if ( m_fileitem->acceptsDrops() ) // Directory, executables, ... 00303 return true; 00304 00305 // Use cache 00306 KURL::List uris = ( static_cast<KonqIconViewWidget*>(iconView()) )->dragURLs(); 00307 00308 // Check if we want to drop something on itself 00309 // (Nothing will happen, but it's a convenient way to move icons) 00310 KURL::List::Iterator it = uris.begin(); 00311 for ( ; it != uris.end() ; it++ ) 00312 { 00313 if ( m_fileitem->url().equals( *it, true /*ignore trailing slashes*/ ) ) 00314 return true; 00315 } 00316 } 00317 return TQIconViewItem::acceptDrop( mime ); 00318 } 00319 00320 void KFileIVI::setKey( const TQString &key ) 00321 { 00322 TQString theKey = key; 00323 00324 TQVariant sortDirProp = iconView()->property( "sortDirectoriesFirst" ); 00325 00326 bool isdir = ( S_ISDIR( m_fileitem->mode() ) && ( !sortDirProp.isValid() || ( sortDirProp.type() == TQVariant::Bool && sortDirProp.toBool() ) ) ); 00327 00328 // The order is: .dir (0), dir (1), .file (2), file (3) 00329 int sortChar = isdir ? 1 : 3; 00330 if ( m_fileitem->text()[0] == '.' ) 00331 --sortChar; 00332 00333 if ( !iconView()->sortDirection() ) // reverse sorting 00334 sortChar = 3 - sortChar; 00335 00336 theKey.prepend( TQChar( sortChar + '0' ) ); 00337 00338 TQIconViewItem::setKey( theKey ); 00339 } 00340 00341 void KFileIVI::dropped( TQDropEvent *e, const TQValueList<TQIconDragItem> & ) 00342 { 00343 KonqOperations::doDrop( item(), item()->url(), e, iconView() ); 00344 } 00345 00346 void KFileIVI::returnPressed() 00347 { 00348 if ( static_cast<KonqIconViewWidget*>(iconView())->isDesktop() ) { 00349 KURL url = m_fileitem->url(); 00350 // When clicking on a link to e.g. $HOME from the desktop, we want to open $HOME 00351 // Symlink resolution must only happen on the desktop though (#63014) 00352 if ( m_fileitem->isLink() && url.isLocalFile() ) 00353 url = KURL( url, m_fileitem->linkDest() ); 00354 00355 (void) new KRun( url, m_fileitem->mode(), m_fileitem->isLocalFile() ); 00356 } else { 00357 m_fileitem->run(); 00358 } 00359 } 00360 00361 00362 void KFileIVI::paintItem( TQPainter *p, const TQColorGroup &c ) 00363 { 00364 TQColorGroup cg = updateColors(c); 00365 paintFontUpdate( p ); 00366 00367 //*** TEMPORARY CODE - MUST BE MADE CONFIGURABLE FIRST - Martijn 00368 // SET UNDERLINE ON HOVER ONLY 00369 /*if ( ( ( KonqIconViewWidget* ) iconView() )->m_pActiveItem == this ) 00370 { 00371 TQFont f( p->font() ); 00372 f.setUnderline( TRUE ); 00373 p->setFont( f ); 00374 }*/ 00375 00376 KIconViewItem::paintItem( p, cg ); 00377 paintOverlay(p); 00378 00379 } 00380 00381 void KFileIVI::paintOverlay( TQPainter *p ) const 00382 { 00383 if ( !d->m_overlay.isNull() ) { 00384 TQRect rect = pixmapRect(true); 00385 p->drawPixmap(x() + rect.x() , y() + pixmapRect().height() - d->m_overlay.height(), d->m_overlay); 00386 } 00387 } 00388 00389 void KFileIVI::paintFontUpdate( TQPainter *p ) const 00390 { 00391 if ( m_fileitem->isLink() ) 00392 { 00393 TQFont f( p->font() ); 00394 f.setItalic( TRUE ); 00395 p->setFont( f ); 00396 } 00397 } 00398 00399 TQColorGroup KFileIVI::updateColors( const TQColorGroup &c ) const 00400 { 00401 TQColorGroup cg( c ); 00402 cg.setColor( TQColorGroup::Text, static_cast<KonqIconViewWidget*>(iconView())->itemColor() ); 00403 return cg; 00404 } 00405 00406 bool KFileIVI::move( int x, int y ) 00407 { 00408 if ( static_cast<KonqIconViewWidget*>(iconView())->isDesktop() ) { 00409 if ( x < 5 ) 00410 x = 5; 00411 if ( x > iconView()->viewport()->width() - ( width() + 5 ) ) 00412 x = iconView()->viewport()->width() - ( width() + 5 ); 00413 if ( y < 5 ) 00414 y = 5; 00415 if ( y > iconView()->viewport()->height() - ( height() + 5 ) ) 00416 y = iconView()->viewport()->height() - ( height() + 5 ); 00417 } 00418 return TQIconViewItem::move( x, y ); 00419 } 00420 00421 bool KFileIVI::hasAnimation() const 00422 { 00423 return !d->m_animatedIcon.isEmpty() && !m_bThumbnail; 00424 } 00425 00426 void KFileIVI::setMouseOverAnimation( const TQString& movieFileName ) 00427 { 00428 if ( !movieFileName.isEmpty() ) 00429 { 00430 //kdDebug(1203) << "KIconViewItem::setMouseOverAnimation " << movieFileName << endl; 00431 d->m_animatedIcon = movieFileName; 00432 } 00433 } 00434 00435 TQString KFileIVI::mouseOverAnimation() const 00436 { 00437 return d->m_animatedIcon; 00438 } 00439 00440 bool KFileIVI::isAnimated() const 00441 { 00442 return d->m_animated; 00443 } 00444 00445 void KFileIVI::setAnimated( bool a ) 00446 { 00447 d->m_animated = a; 00448 } 00449 00450 int KFileIVI::compare( TQIconViewItem *i ) const 00451 { 00452 KonqIconViewWidget* view = static_cast<KonqIconViewWidget*>(iconView()); 00453 if ( view->caseInsensitiveSort() ) 00454 return key().localeAwareCompare( i->key() ); 00455 else 00456 return view->m_pSettings->caseSensitiveCompare( key(), i->key() ); 00457 } 00458 00459 void KFileIVI::updatePixmapSize() 00460 { 00461 int size = m_size ? m_size : 00462 KGlobal::iconLoader()->currentSize( KIcon::Desktop ); 00463 00464 KonqIconViewWidget* view = static_cast<KonqIconViewWidget*>( iconView() ); 00465 00466 if ( view && view->canPreview( item() ) ) { 00467 int previewSize = view->previewIconSize( size ); 00468 setPixmapSize( TQSize( previewSize, previewSize ) ); 00469 } 00470 else { 00471 TQSize pixSize = TQSize( size, size ); 00472 if ( pixSize != pixmapSize() ) 00473 setPixmapSize( pixSize ); 00474 } 00475 } 00476 00477 /* vim: set noet sw=4 ts=8 softtabstop=4: */