tdefileivi.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 "tdefileivi.h" 00021 #include "kivdirectoryoverlay.h" 00022 #include "kivfreespaceoverlay.h" 00023 #include "konq_iconviewwidget.h" 00024 #include "konq_operations.h" 00025 #include "konq_settings.h" 00026 00027 #include <tqpainter.h> 00028 00029 #include <kurldrag.h> 00030 #include <kiconeffect.h> 00031 #include <tdefileitem.h> 00032 #include <kdebug.h> 00033 #include <krun.h> 00034 #include <kservice.h> 00035 00036 #undef Bool 00037 00041 struct KFileIVI::Private 00042 { 00043 TQIconSet icons; // Icon states (cached to prevent re-applying icon effects 00044 // every time) 00045 TQPixmap thumb; // Raw unprocessed thumbnail 00046 TQString m_animatedIcon; // Name of animation 00047 bool m_animated; // Animation currently running ? 00048 KIVDirectoryOverlay* m_directoryOverlay; 00049 KIVFreeSpaceOverlay* m_freeSpaceOverlay; 00050 TQPixmap m_overlay; 00051 TQString m_overlayName; 00052 int m_progress; 00053 }; 00054 00055 KFileIVI::KFileIVI( KonqIconViewWidget *iconview, KFileItem* fileitem, int size ) 00056 : TDEIconViewItem( iconview, fileitem->text() ), 00057 m_size( size ), m_state( TDEIcon::DefaultState ), 00058 m_bDisabled( false ), m_bThumbnail( false ), m_fileitem( fileitem ) 00059 { 00060 d = new KFileIVI::Private; 00061 00062 updatePixmapSize(); 00063 setPixmap( m_fileitem->pixmap( m_size, m_state ) ); 00064 setDropEnabled( S_ISDIR( m_fileitem->mode() ) ); 00065 00066 // Cache entry for the icon effects 00067 d->icons.reset( *pixmap(), TQIconSet::Large ); 00068 d->m_animated = false; 00069 00070 // iconName() requires the mimetype to be known 00071 if ( fileitem->isMimeTypeKnown() ) 00072 { 00073 TQString icon = fileitem->iconName(); 00074 if ( !icon.isEmpty() ) 00075 setMouseOverAnimation( icon ); 00076 else 00077 setMouseOverAnimation( "unknown" ); 00078 } 00079 d->m_progress = -1; 00080 d->m_directoryOverlay = 0; 00081 d->m_freeSpaceOverlay = 0; 00082 } 00083 00084 KFileIVI::~KFileIVI() 00085 { 00086 delete d->m_directoryOverlay; 00087 delete d->m_freeSpaceOverlay; 00088 delete d; 00089 } 00090 00091 void KFileIVI::invalidateThumb( int state, bool redraw ) 00092 { 00093 TQIconSet::Mode mode; 00094 switch( state ) 00095 { 00096 case TDEIcon::DisabledState: 00097 mode = TQIconSet::Disabled; 00098 break; 00099 case TDEIcon::ActiveState: 00100 mode = TQIconSet::Active; 00101 break; 00102 case TDEIcon::DefaultState: 00103 default: 00104 mode = TQIconSet::Normal; 00105 break; 00106 } 00107 d->icons = TQIconSet(); 00108 d->icons.setPixmap( TDEGlobal::iconLoader()->iconEffect()-> 00109 apply( d->thumb, TDEIcon::Desktop, state ), 00110 TQIconSet::Large, mode ); 00111 m_state = state; 00112 00113 TQIconViewItem::setPixmap( d->icons.pixmap( TQIconSet::Large, mode ), 00114 false, redraw ); 00115 } 00116 00117 void KFileIVI::setIcon( int size, int state, bool recalc, bool redraw ) 00118 { 00119 m_size = size; 00120 m_bThumbnail = false; 00121 if ( m_bDisabled ) 00122 m_state = TDEIcon::DisabledState; 00123 else 00124 m_state = state; 00125 00126 if ( d->m_overlayName.isNull() ) 00127 d->m_overlay = TQPixmap(); 00128 else { 00129 int halfSize; 00130 if (m_size == 0) { 00131 halfSize = IconSize(TDEIcon::Desktop) / 2; 00132 } else { 00133 halfSize = m_size / 2; 00134 } 00135 d->m_overlay = DesktopIcon(d->m_overlayName, halfSize); 00136 } 00137 00138 setPixmapDirect(m_fileitem->pixmap( m_size, m_state ) , recalc, redraw ); 00139 } 00140 00141 void KFileIVI::setOverlay( const TQString& iconName ) 00142 { 00143 d->m_overlayName = iconName; 00144 00145 refreshIcon(true); 00146 } 00147 00148 void KFileIVI::setOverlayProgressBar( const int progress ) 00149 { 00150 d->m_progress = progress; 00151 00152 refreshIcon(true); 00153 } 00154 00155 KIVDirectoryOverlay* KFileIVI::setShowDirectoryOverlay( bool show ) 00156 { 00157 if ( !m_fileitem->isDir() || m_fileitem->iconName() != "folder" ) 00158 return 0; 00159 00160 if (show) { 00161 if (!d->m_directoryOverlay) 00162 d->m_directoryOverlay = new KIVDirectoryOverlay(this); 00163 return d->m_directoryOverlay; 00164 } else { 00165 delete d->m_directoryOverlay; 00166 d->m_directoryOverlay = 0; 00167 setOverlay(TQString()); 00168 return 0; 00169 } 00170 } 00171 00172 bool KFileIVI::showDirectoryOverlay( ) 00173 { 00174 return (bool)d->m_directoryOverlay; 00175 } 00176 00177 KIVFreeSpaceOverlay* KFileIVI::setShowFreeSpaceOverlay( bool show ) 00178 { 00179 if ( !m_fileitem->mimetype().startsWith("media/") ) { 00180 return 0; 00181 } 00182 00183 if (show) { 00184 if (!d->m_freeSpaceOverlay) 00185 d->m_freeSpaceOverlay = new KIVFreeSpaceOverlay(this); 00186 return d->m_freeSpaceOverlay; 00187 } else { 00188 delete d->m_freeSpaceOverlay; 00189 d->m_freeSpaceOverlay = 0; 00190 setOverlayProgressBar(-1); 00191 return 0; 00192 } 00193 } 00194 00195 bool KFileIVI::showFreeSpaceOverlay( ) 00196 { 00197 return (bool)d->m_freeSpaceOverlay; 00198 } 00199 00200 void KFileIVI::setPixmapDirect( const TQPixmap& pixmap, bool recalc, bool redraw ) 00201 { 00202 TQIconSet::Mode mode; 00203 switch( m_state ) 00204 { 00205 case TDEIcon::DisabledState: 00206 mode = TQIconSet::Disabled; 00207 break; 00208 case TDEIcon::ActiveState: 00209 mode = TQIconSet::Active; 00210 break; 00211 case TDEIcon::DefaultState: 00212 default: 00213 mode = TQIconSet::Normal; 00214 break; 00215 } 00216 00217 // We cannot just reset() the iconset here, because setIcon can be 00218 // called with any state and not just normal state. So we just 00219 // create a dummy empty iconset as base object. 00220 d->icons = TQIconSet(); 00221 d->icons.setPixmap( pixmap, TQIconSet::Large, mode ); 00222 00223 updatePixmapSize(); 00224 TQIconViewItem::setPixmap( d->icons.pixmap( TQIconSet::Large, mode ), 00225 recalc, redraw ); 00226 } 00227 00228 void KFileIVI::setDisabled( bool disabled ) 00229 { 00230 if ( m_bDisabled != disabled ) 00231 { 00232 m_bDisabled = disabled; 00233 bool active = ( m_state == TDEIcon::ActiveState ); 00234 setEffect( m_bDisabled ? TDEIcon::DisabledState : 00235 ( active ? TDEIcon::ActiveState : TDEIcon::DefaultState ) ); 00236 } 00237 } 00238 00239 void KFileIVI::setThumbnailPixmap( const TQPixmap & pixmap ) 00240 { 00241 m_bThumbnail = true; 00242 d->thumb = pixmap; 00243 // TQIconSet::reset() doesn't seem to clear the other generated pixmaps, 00244 // so we just create a blank TQIconSet here 00245 d->icons = TQIconSet(); 00246 d->icons.setPixmap( TDEGlobal::iconLoader()->iconEffect()-> 00247 apply( pixmap, TDEIcon::Desktop, TDEIcon::DefaultState ), 00248 TQIconSet::Large, TQIconSet::Normal ); 00249 00250 m_state = TDEIcon::DefaultState; 00251 00252 // Recalc when setting this pixmap! 00253 updatePixmapSize(); 00254 TQIconViewItem::setPixmap( d->icons.pixmap( TQIconSet::Large, 00255 TQIconSet::Normal ), true ); 00256 } 00257 00258 void KFileIVI::setActive( bool active ) 00259 { 00260 if ( active ) 00261 setEffect( TDEIcon::ActiveState ); 00262 else 00263 setEffect( m_bDisabled ? TDEIcon::DisabledState : TDEIcon::DefaultState ); 00264 } 00265 00266 void KFileIVI::setEffect( int state ) 00267 { 00268 TQIconSet::Mode mode; 00269 switch( state ) 00270 { 00271 case TDEIcon::DisabledState: 00272 mode = TQIconSet::Disabled; 00273 break; 00274 case TDEIcon::ActiveState: 00275 mode = TQIconSet::Active; 00276 break; 00277 case TDEIcon::DefaultState: 00278 default: 00279 mode = TQIconSet::Normal; 00280 break; 00281 } 00282 // Do not update if the fingerprint is identical (prevents flicker)! 00283 00284 TDEIconEffect *effect = TDEGlobal::iconLoader()->iconEffect(); 00285 00286 bool haveEffect = effect->hasEffect( TDEIcon::Desktop, m_state ) != 00287 effect->hasEffect( TDEIcon::Desktop, state ); 00288 00289 //kdDebug(1203) << "desktop;defaultstate=" << 00290 // effect->fingerprint(TDEIcon::Desktop, TDEIcon::DefaultState) << 00291 // endl; 00292 //kdDebug(1203) << "desktop;activestate=" << 00293 // effect->fingerprint(TDEIcon::Desktop, TDEIcon::ActiveState) << 00294 // endl; 00295 00296 if( haveEffect && 00297 effect->fingerprint( TDEIcon::Desktop, m_state ) != 00298 effect->fingerprint( TDEIcon::Desktop, state ) ) 00299 { 00300 // Effects on are not applied until they are first accessed to 00301 // save memory. Do this now when needed 00302 if( m_bThumbnail ) 00303 { 00304 if( d->icons.isGenerated( TQIconSet::Large, mode ) ) 00305 d->icons.setPixmap( effect->apply( d->thumb, TDEIcon::Desktop, state ), 00306 TQIconSet::Large, mode ); 00307 } 00308 else 00309 { 00310 if( d->icons.isGenerated( TQIconSet::Large, mode ) ) 00311 d->icons.setPixmap( m_fileitem->pixmap( m_size, state ), 00312 TQIconSet::Large, mode ); 00313 } 00314 TQIconViewItem::setPixmap( d->icons.pixmap( TQIconSet::Large, mode ) ); 00315 } 00316 m_state = state; 00317 } 00318 00319 void KFileIVI::refreshIcon( bool redraw ) 00320 { 00321 if (!isThumbnail()) { 00322 setIcon( m_size, m_state, true, redraw ); 00323 } 00324 } 00325 00326 void KFileIVI::invalidateThumbnail() 00327 { 00328 d->thumb = TQPixmap(); 00329 } 00330 00331 bool KFileIVI::isThumbnailInvalid() const 00332 { 00333 return d->thumb.isNull(); 00334 } 00335 00336 bool KFileIVI::acceptDrop( const TQMimeSource *mime ) const 00337 { 00338 if ( mime->provides( "text/uri-list" ) ) // We're dragging URLs 00339 { 00340 if ( m_fileitem->acceptsDrops() ) // Directory, executables, ... 00341 return true; 00342 00343 // Use cache 00344 KURL::List uris = ( static_cast<KonqIconViewWidget*>(iconView()) )->dragURLs(); 00345 00346 // Check if we want to drop something on itself 00347 // (Nothing will happen, but it's a convenient way to move icons) 00348 KURL::List::Iterator it = uris.begin(); 00349 for ( ; it != uris.end() ; it++ ) 00350 { 00351 if ( m_fileitem->url().equals( *it, true /*ignore trailing slashes*/ ) ) 00352 return true; 00353 } 00354 } 00355 return TQIconViewItem::acceptDrop( mime ); 00356 } 00357 00358 void KFileIVI::setKey( const TQString &key ) 00359 { 00360 TQString theKey = key; 00361 00362 TQVariant sortDirProp = iconView()->property( "sortDirectoriesFirst" ); 00363 00364 bool isdir = ( S_ISDIR( m_fileitem->mode() ) && ( !sortDirProp.isValid() || ( sortDirProp.type() == TQVariant::Bool && sortDirProp.toBool() ) ) ); 00365 00366 // The order is: .dir (0), dir (1), .file (2), file (3) 00367 int sortChar = isdir ? 1 : 3; 00368 if ( m_fileitem->text()[0] == '.' ) 00369 --sortChar; 00370 00371 if ( !iconView()->sortDirection() ) // reverse sorting 00372 sortChar = 3 - sortChar; 00373 00374 theKey.prepend( TQChar( sortChar + '0' ) ); 00375 00376 TQIconViewItem::setKey( theKey ); 00377 } 00378 00379 void KFileIVI::dropped( TQDropEvent *e, const TQValueList<TQIconDragItem> & ) 00380 { 00381 KonqOperations::doDrop( item(), item()->url(), e, iconView() ); 00382 } 00383 00384 void KFileIVI::returnPressed() 00385 { 00386 if ( static_cast<KonqIconViewWidget*>(iconView())->isDesktop() ) { 00387 KURL url = m_fileitem->url(); 00388 if (url.protocol() == "media") { 00389 // The user reasonably expects to be placed within the media:/ tree 00390 // when opening a media device from the desktop 00391 KService::Ptr service = KService::serviceByDesktopName("konqueror"); 00392 if (service) { 00393 // HACK 00394 // There doesn't seem to be a way to prevent KRun from resolving the URL to its 00395 // local path, so simpy launch Konqueror with the correct arguments instead... 00396 KRun::runCommand("konqueror " + url.url(), "konqueror", service->icon()); 00397 } 00398 else { 00399 (void) new KRun( url, m_fileitem->mode(), m_fileitem->isLocalFile() ); 00400 } 00401 } 00402 else { 00403 // When clicking on a link to e.g. $HOME from the desktop, we want to open $HOME 00404 // Symlink resolution must only happen on the desktop though (#63014) 00405 if ( m_fileitem->isLink() && url.isLocalFile() ) { 00406 url = KURL( url, m_fileitem->linkDest() ); 00407 } 00408 00409 (void) new KRun( url, m_fileitem->mode(), m_fileitem->isLocalFile() ); 00410 } 00411 } 00412 else { 00413 m_fileitem->run(); 00414 } 00415 } 00416 00417 00418 void KFileIVI::paintItem( TQPainter *p, const TQColorGroup &c ) 00419 { 00420 TQColorGroup cg = updateColors(c); 00421 paintFontUpdate( p ); 00422 00423 //*** TEMPORARY CODE - MUST BE MADE CONFIGURABLE FIRST - Martijn 00424 // SET UNDERLINE ON HOVER ONLY 00425 /*if ( ( ( KonqIconViewWidget* ) iconView() )->m_pActiveItem == this ) 00426 { 00427 TQFont f( p->font() ); 00428 f.setUnderline( TRUE ); 00429 p->setFont( f ); 00430 }*/ 00431 00432 TDEIconViewItem::paintItem( p, cg ); 00433 paintOverlay(p); 00434 paintOverlayProgressBar(p); 00435 00436 } 00437 00438 void KFileIVI::paintOverlay( TQPainter *p ) const 00439 { 00440 if ( !d->m_overlay.isNull() ) { 00441 TQRect rect = pixmapRect(true); 00442 p->drawPixmap(x() + rect.x() , y() + pixmapRect().height() - d->m_overlay.height(), d->m_overlay); 00443 } 00444 } 00445 00446 void KFileIVI::paintOverlayProgressBar( TQPainter *p ) const 00447 { 00448 if (d->m_progress != -1) { 00449 // // Pie chart 00450 // TQRect rect = pixmapRect(true); 00451 // rect.setX(x() + rect.x()); 00452 // rect.setY(y() + rect.y() + ((pixmapRect().height()*3)/4)); 00453 // rect.setWidth(pixmapRect().width()/4); 00454 // rect.setHeight(pixmapRect().height()/4); 00455 // 00456 // p->save(); 00457 // 00458 // p->setPen(TQPen::NoPen); 00459 // p->setBrush(TQt::red); 00460 // p->drawEllipse(rect); 00461 // p->setBrush(TQt::green); 00462 // p->drawPie(rect, 1440, (((100-d->m_progress)*5760)/100)); 00463 00464 // // Horizontal progress bar 00465 // TQRect rect = pixmapRect(true); 00466 // int verticalOffset = 0; 00467 // int usedBarWidth = ((d->m_progress*pixmapRect().width())/100); 00468 // int endPosition = x() + rect.x() + usedBarWidth; 00469 // 00470 // p->save(); 00471 // 00472 // p->setPen(TQPen::NoPen); 00473 // p->setBrush(TQt::red); 00474 // p->drawRect(TQRect(x() + rect.x(), y() + rect.y() + (pixmapRect().height() - verticalOffset), usedBarWidth, 1)); 00475 // p->setBrush(TQt::green); 00476 // p->drawRect(TQRect(endPosition, y() + rect.y() + (pixmapRect().height() - verticalOffset), pixmapRect().width() - usedBarWidth, 1)); 00477 00478 // Vertical progress bar 00479 TQRect rect = pixmapRect(true); 00480 int horizontalOffset = 0; 00481 int usedBarHeight = (((100-d->m_progress)*pixmapRect().height())/100); 00482 int endPosition = y() + rect.y() + usedBarHeight; 00483 00484 p->save(); 00485 00486 p->setPen(TQPen::NoPen); 00487 p->setBrush(TQt::green); 00488 p->drawRect(TQRect(x() + rect.x() + (pixmapRect().width() - horizontalOffset), y() + rect.y(), 1, usedBarHeight)); 00489 p->setBrush(TQt::red); 00490 p->drawRect(TQRect(x() + rect.x() + (pixmapRect().width() - horizontalOffset), endPosition, 1, pixmapRect().height() - usedBarHeight)); 00491 00492 p->restore(); 00493 } 00494 } 00495 00496 void KFileIVI::paintFontUpdate( TQPainter *p ) const 00497 { 00498 if ( m_fileitem->isLink() ) 00499 { 00500 TQFont f( p->font() ); 00501 f.setItalic( TRUE ); 00502 p->setFont( f ); 00503 } 00504 } 00505 00506 TQColorGroup KFileIVI::updateColors( const TQColorGroup &c ) const 00507 { 00508 TQColorGroup cg( c ); 00509 cg.setColor( TQColorGroup::Text, static_cast<KonqIconViewWidget*>(iconView())->itemColor() ); 00510 return cg; 00511 } 00512 00513 bool KFileIVI::move( int x, int y ) 00514 { 00515 if ( static_cast<KonqIconViewWidget*>(iconView())->isDesktop() ) { 00516 if ( x < 5 ) 00517 x = 5; 00518 if ( x > iconView()->viewport()->width() - ( width() + 5 ) ) 00519 x = iconView()->viewport()->width() - ( width() + 5 ); 00520 if ( y < 5 ) 00521 y = 5; 00522 if ( y > iconView()->viewport()->height() - ( height() + 5 ) ) 00523 y = iconView()->viewport()->height() - ( height() + 5 ); 00524 } 00525 return TQIconViewItem::move( x, y ); 00526 } 00527 00528 bool KFileIVI::hasAnimation() const 00529 { 00530 return !d->m_animatedIcon.isEmpty() && !m_bThumbnail; 00531 } 00532 00533 void KFileIVI::setMouseOverAnimation( const TQString& movieFileName ) 00534 { 00535 if ( !movieFileName.isEmpty() ) 00536 { 00537 //kdDebug(1203) << "TDEIconViewItem::setMouseOverAnimation " << movieFileName << endl; 00538 d->m_animatedIcon = movieFileName; 00539 } 00540 } 00541 00542 TQString KFileIVI::mouseOverAnimation() const 00543 { 00544 return d->m_animatedIcon; 00545 } 00546 00547 bool KFileIVI::isAnimated() const 00548 { 00549 return d->m_animated; 00550 } 00551 00552 void KFileIVI::setAnimated( bool a ) 00553 { 00554 d->m_animated = a; 00555 } 00556 00557 int KFileIVI::compare( TQIconViewItem *i ) const 00558 { 00559 KonqIconViewWidget* view = static_cast<KonqIconViewWidget*>(iconView()); 00560 if ( view->caseInsensitiveSort() ) 00561 return key().localeAwareCompare( i->key() ); 00562 else 00563 return view->m_pSettings->caseSensitiveCompare( key(), i->key() ); 00564 } 00565 00566 void KFileIVI::updatePixmapSize() 00567 { 00568 int size = m_size ? m_size : 00569 TDEGlobal::iconLoader()->currentSize( TDEIcon::Desktop ); 00570 00571 KonqIconViewWidget* view = static_cast<KonqIconViewWidget*>( iconView() ); 00572 00573 bool mimeDetermined = false; 00574 if ( m_fileitem->isMimeTypeKnown() ) { 00575 mimeDetermined = true; 00576 } 00577 00578 if (mimeDetermined) { 00579 bool changed = false; 00580 if ( view && view->canPreview( item() ) ) { 00581 int previewSize = view->previewIconSize( size ); 00582 if (previewSize != size) { 00583 setPixmapSize( TQSize( previewSize, previewSize ) ); 00584 changed = true; 00585 } 00586 } 00587 else { 00588 TQSize pixSize = TQSize( size, size ); 00589 if ( pixSize != pixmapSize() ) { 00590 setPixmapSize( pixSize ); 00591 changed = true; 00592 } 00593 } 00594 if (changed) { 00595 view->adjustItems(); 00596 } 00597 } 00598 else { 00599 TQSize pixSize = TQSize( size, size ); 00600 if ( pixSize != pixmapSize() ) { 00601 setPixmapSize( pixSize ); 00602 } 00603 } 00604 } 00605 00606 void KFileIVI::mimeTypeAndIconDetermined() 00607 { 00608 updatePixmapSize(); 00609 } 00610 00611 /* vim: set noet sw=4 ts=8 softtabstop=4: */
Trinity API Reference