diff options
Diffstat (limited to 'libkonq/tdefileivi.cpp')
-rw-r--r-- | libkonq/tdefileivi.cpp | 621 |
1 files changed, 621 insertions, 0 deletions
diff --git a/libkonq/tdefileivi.cpp b/libkonq/tdefileivi.cpp new file mode 100644 index 000000000..ad2d743a1 --- /dev/null +++ b/libkonq/tdefileivi.cpp @@ -0,0 +1,621 @@ +/* This file is part of the KDE project + Copyright (C) 1999, 2000, 2001, 2002 David Faure <faure@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "tdefileivi.h" +#include "kivdirectoryoverlay.h" +#include "kivfreespaceoverlay.h" +#include "konq_iconviewwidget.h" +#include "konq_operations.h" +#include "konq_settings.h" + +#include <tqpainter.h> + +#include <kurldrag.h> +#include <kiconeffect.h> +#include <tdefileitem.h> +#include <kdebug.h> +#include <krun.h> +#include <kservice.h> +#include <kmimetype.h> // for KDEDesktopMimeType +#include <kstandarddirs.h> + +#undef Bool + +/** + * Private data for KFileIVI + */ +struct KFileIVI::Private +{ + TQIconSet icons; // Icon states (cached to prevent re-applying icon effects + // every time) + TQPixmap thumb; // Raw unprocessed thumbnail + TQString m_animatedIcon; // Name of animation + bool m_animated; // Animation currently running ? + KIVDirectoryOverlay* m_directoryOverlay; + KIVFreeSpaceOverlay* m_freeSpaceOverlay; + TQPixmap m_overlay; + TQString m_overlayName; + int m_progress; +}; + +KFileIVI::KFileIVI( KonqIconViewWidget *iconview, KFileItem* fileitem, int size ) + : TDEIconViewItem( iconview, fileitem->text() ), + m_size( size ), m_state( TDEIcon::DefaultState ), + m_bDisabled( false ), m_bThumbnail( false ), m_fileitem( fileitem ) +{ + d = new KFileIVI::Private; + + updatePixmapSize(); + setPixmap( m_fileitem->pixmap( m_size, m_state ) ); + setDropEnabled( S_ISDIR( m_fileitem->mode() ) ); + + // Cache entry for the icon effects + d->icons.reset( *pixmap(), TQIconSet::Large ); + d->m_animated = false; + + // iconName() requires the mimetype to be known + if ( fileitem->isMimeTypeKnown() ) + { + TQString icon = fileitem->iconName(); + if ( !icon.isEmpty() ) + setMouseOverAnimation( icon ); + else + setMouseOverAnimation( "unknown" ); + } + d->m_progress = -1; + d->m_directoryOverlay = 0; + d->m_freeSpaceOverlay = 0; +} + +KFileIVI::~KFileIVI() +{ + delete d->m_directoryOverlay; + delete d->m_freeSpaceOverlay; + delete d; +} + +void KFileIVI::invalidateThumb( int state, bool redraw ) +{ + TQIconSet::Mode mode; + switch( state ) + { + case TDEIcon::DisabledState: + mode = TQIconSet::Disabled; + break; + case TDEIcon::ActiveState: + mode = TQIconSet::Active; + break; + case TDEIcon::DefaultState: + default: + mode = TQIconSet::Normal; + break; + } + d->icons = TQIconSet(); + d->icons.setPixmap( TDEGlobal::iconLoader()->iconEffect()-> + apply( d->thumb, TDEIcon::Desktop, state ), + TQIconSet::Large, mode ); + m_state = state; + + TQIconViewItem::setPixmap( d->icons.pixmap( TQIconSet::Large, mode ), + false, redraw ); +} + +void KFileIVI::setIcon( int size, int state, bool recalc, bool redraw ) +{ + m_size = size; + m_bThumbnail = false; + if ( m_bDisabled ) + m_state = TDEIcon::DisabledState; + else + m_state = state; + + if ( d->m_overlayName.isNull() ) + d->m_overlay = TQPixmap(); + else { + int halfSize; + if (m_size == 0) { + halfSize = IconSize(TDEIcon::Desktop) / 2; + } else { + halfSize = m_size / 2; + } + d->m_overlay = DesktopIcon(d->m_overlayName, halfSize); + } + + setPixmapDirect(m_fileitem->pixmap( m_size, m_state ) , recalc, redraw ); +} + +void KFileIVI::setOverlay( const TQString& iconName ) +{ + d->m_overlayName = iconName; + + refreshIcon(true); +} + +void KFileIVI::setOverlayProgressBar( const int progress ) +{ + d->m_progress = progress; + + refreshIcon(true); +} + +KIVDirectoryOverlay* KFileIVI::setShowDirectoryOverlay( bool show ) +{ + if ( !m_fileitem->isDir() || m_fileitem->iconName() != "folder" ) + return 0; + + if (show) { + if (!d->m_directoryOverlay) + d->m_directoryOverlay = new KIVDirectoryOverlay(this); + return d->m_directoryOverlay; + } else { + delete d->m_directoryOverlay; + d->m_directoryOverlay = 0; + setOverlay(TQString()); + return 0; + } +} + +bool KFileIVI::showDirectoryOverlay( ) +{ + return (bool)d->m_directoryOverlay; +} + +KIVFreeSpaceOverlay* KFileIVI::setShowFreeSpaceOverlay( bool show ) +{ + if ( !m_fileitem->mimetype().startsWith("media/") ) { + return 0; + } + + if (show) { + if (!d->m_freeSpaceOverlay) + d->m_freeSpaceOverlay = new KIVFreeSpaceOverlay(this); + return d->m_freeSpaceOverlay; + } else { + delete d->m_freeSpaceOverlay; + d->m_freeSpaceOverlay = 0; + setOverlayProgressBar(-1); + return 0; + } +} + +bool KFileIVI::showFreeSpaceOverlay( ) +{ + return (bool)d->m_freeSpaceOverlay; +} + +void KFileIVI::setPixmapDirect( const TQPixmap& pixmap, bool recalc, bool redraw ) +{ + TQIconSet::Mode mode; + switch( m_state ) + { + case TDEIcon::DisabledState: + mode = TQIconSet::Disabled; + break; + case TDEIcon::ActiveState: + mode = TQIconSet::Active; + break; + case TDEIcon::DefaultState: + default: + mode = TQIconSet::Normal; + break; + } + + // We cannot just reset() the iconset here, because setIcon can be + // called with any state and not just normal state. So we just + // create a dummy empty iconset as base object. + d->icons = TQIconSet(); + d->icons.setPixmap( pixmap, TQIconSet::Large, mode ); + + updatePixmapSize(); + TQIconViewItem::setPixmap( d->icons.pixmap( TQIconSet::Large, mode ), + recalc, redraw ); +} + +void KFileIVI::setDisabled( bool disabled ) +{ + if ( m_bDisabled != disabled ) + { + m_bDisabled = disabled; + bool active = ( m_state == TDEIcon::ActiveState ); + setEffect( m_bDisabled ? TDEIcon::DisabledState : + ( active ? TDEIcon::ActiveState : TDEIcon::DefaultState ) ); + } +} + +void KFileIVI::setThumbnailPixmap( const TQPixmap & pixmap ) +{ + m_bThumbnail = true; + d->thumb = pixmap; + // TQIconSet::reset() doesn't seem to clear the other generated pixmaps, + // so we just create a blank TQIconSet here + d->icons = TQIconSet(); + d->icons.setPixmap( TDEGlobal::iconLoader()->iconEffect()-> + apply( pixmap, TDEIcon::Desktop, TDEIcon::DefaultState ), + TQIconSet::Large, TQIconSet::Normal ); + + m_state = TDEIcon::DefaultState; + + // Recalc when setting this pixmap! + updatePixmapSize(); + TQIconViewItem::setPixmap( d->icons.pixmap( TQIconSet::Large, + TQIconSet::Normal ), true ); +} + +void KFileIVI::setActive( bool active ) +{ + if ( active ) + setEffect( TDEIcon::ActiveState ); + else + setEffect( m_bDisabled ? TDEIcon::DisabledState : TDEIcon::DefaultState ); +} + +void KFileIVI::setEffect( int state ) +{ + TQIconSet::Mode mode; + switch( state ) + { + case TDEIcon::DisabledState: + mode = TQIconSet::Disabled; + break; + case TDEIcon::ActiveState: + mode = TQIconSet::Active; + break; + case TDEIcon::DefaultState: + default: + mode = TQIconSet::Normal; + break; + } + // Do not update if the fingerprint is identical (prevents flicker)! + + TDEIconEffect *effect = TDEGlobal::iconLoader()->iconEffect(); + + bool haveEffect = effect->hasEffect( TDEIcon::Desktop, m_state ) != + effect->hasEffect( TDEIcon::Desktop, state ); + + //kdDebug(1203) << "desktop;defaultstate=" << + // effect->fingerprint(TDEIcon::Desktop, TDEIcon::DefaultState) << + // endl; + //kdDebug(1203) << "desktop;activestate=" << + // effect->fingerprint(TDEIcon::Desktop, TDEIcon::ActiveState) << + // endl; + + if( haveEffect && + effect->fingerprint( TDEIcon::Desktop, m_state ) != + effect->fingerprint( TDEIcon::Desktop, state ) ) + { + // Effects on are not applied until they are first accessed to + // save memory. Do this now when needed + if( m_bThumbnail ) + { + if( d->icons.isGenerated( TQIconSet::Large, mode ) ) + d->icons.setPixmap( effect->apply( d->thumb, TDEIcon::Desktop, state ), + TQIconSet::Large, mode ); + } + else + { + if( d->icons.isGenerated( TQIconSet::Large, mode ) ) + d->icons.setPixmap( m_fileitem->pixmap( m_size, state ), + TQIconSet::Large, mode ); + } + TQIconViewItem::setPixmap( d->icons.pixmap( TQIconSet::Large, mode ) ); + } + m_state = state; +} + +void KFileIVI::refreshIcon( bool redraw ) +{ + if (!isThumbnail()) { + setIcon( m_size, m_state, true, redraw ); + } +} + +void KFileIVI::invalidateThumbnail() +{ + d->thumb = TQPixmap(); +} + +bool KFileIVI::isThumbnailInvalid() const +{ + return d->thumb.isNull(); +} + +bool KFileIVI::acceptDrop( const TQMimeSource *mime ) const +{ + if ( mime->provides( "text/uri-list" ) ) // We're dragging URLs + { + if ( m_fileitem->acceptsDrops() ) // Directory, executables, ... + return true; + + // Use cache + KURL::List uris = ( static_cast<KonqIconViewWidget*>(iconView()) )->dragURLs(); + + // Check if we want to drop something on itself + // (Nothing will happen, but it's a convenient way to move icons) + KURL::List::Iterator it = uris.begin(); + for ( ; it != uris.end() ; it++ ) + { + if ( m_fileitem->url().equals( *it, true /*ignore trailing slashes*/ ) ) + return true; + } + } + return TQIconViewItem::acceptDrop( mime ); +} + +void KFileIVI::setKey( const TQString &key ) +{ + TQString theKey = key; + + TQVariant sortDirProp = iconView()->property( "sortDirectoriesFirst" ); + + bool isdir = ( S_ISDIR( m_fileitem->mode() ) && ( !sortDirProp.isValid() || ( sortDirProp.type() == TQVariant::Bool && sortDirProp.toBool() ) ) ); + + // The order is: .dir (0), dir (1), .file (2), file (3) + int sortChar = isdir ? 1 : 3; + if ( m_fileitem->text()[0] == '.' ) + --sortChar; + + if ( !iconView()->sortDirection() ) // reverse sorting + sortChar = 3 - sortChar; + + theKey.prepend( TQChar( sortChar + '0' ) ); + + TQIconViewItem::setKey( theKey ); +} + +void KFileIVI::dropped( TQDropEvent *e, const TQValueList<TQIconDragItem> & ) +{ + KonqOperations::doDrop( item(), item()->url(), e, iconView() ); +} + +void KFileIVI::returnPressed() +{ + if ( static_cast<KonqIconViewWidget*>(iconView())->isDesktop() ) { + KURL url = m_fileitem->url(); + if (url.protocol() == "media") { + TQString mimetype = m_fileitem->mimetype(); + TQString lockingAction = TQString::null; + if (mimetype.contains("encrypted_locked")) { + lockingAction = "konqueror/servicemenus/media_unlock.desktop"; + } + else if (mimetype.contains("encrypted_unlocked")) { + lockingAction = "konqueror/servicemenus/media_lock.desktop"; + } + if (!lockingAction.isEmpty()) { + TQString lockingService = TDEGlobal::dirs()->findResource("data", lockingAction); + if (!lockingService.isEmpty()) { + TQValueList<KDEDesktopMimeType::Service> serviceList = KDEDesktopMimeType::userDefinedServices(lockingService, m_fileitem->isLocalFile()); + if (serviceList.count() == 1) { + KURL::List m_lstURLs; + m_lstURLs.append(m_fileitem->url()); + KDEDesktopMimeType::executeService(m_lstURLs, serviceList[0]); + } + } + } + else { + (void) new KRun( url, m_fileitem->mode(), m_fileitem->isLocalFile() ); + } + } + else { + // When clicking on a link to e.g. $HOME from the desktop, we want to open $HOME + // Symlink resolution must only happen on the desktop though (#63014) + if ( m_fileitem->isLink() && url.isLocalFile() ) { + url = KURL( url, m_fileitem->linkDest() ); + } + + (void) new KRun( url, m_fileitem->mode(), m_fileitem->isLocalFile() ); + } + } + else { + m_fileitem->run(); + } +} + + +void KFileIVI::paintItem( TQPainter *p, const TQColorGroup &c ) +{ + TQColorGroup cg = updateColors(c); + paintFontUpdate( p ); + + //*** TEMPORARY CODE - MUST BE MADE CONFIGURABLE FIRST - Martijn + // SET UNDERLINE ON HOVER ONLY + /*if ( ( ( KonqIconViewWidget* ) iconView() )->m_pActiveItem == this ) + { + TQFont f( p->font() ); + f.setUnderline( TRUE ); + p->setFont( f ); + }*/ + + TDEIconViewItem::paintItem( p, cg ); + paintOverlay(p); + paintOverlayProgressBar(p); + +} + +void KFileIVI::paintOverlay( TQPainter *p ) const +{ + if ( !d->m_overlay.isNull() ) { + TQRect rect = pixmapRect(true); + p->drawPixmap(x() + rect.x() , y() + pixmapRect().height() - d->m_overlay.height(), d->m_overlay); + } +} + +void KFileIVI::paintOverlayProgressBar( TQPainter *p ) const +{ + if (d->m_progress != -1) { +// // Pie chart +// TQRect rect = pixmapRect(true); +// rect.setX(x() + rect.x()); +// rect.setY(y() + rect.y() + ((pixmapRect().height()*3)/4)); +// rect.setWidth(pixmapRect().width()/4); +// rect.setHeight(pixmapRect().height()/4); +// +// p->save(); +// +// p->setPen(TQPen::NoPen); +// p->setBrush(TQt::red); +// p->drawEllipse(rect); +// p->setBrush(TQt::green); +// p->drawPie(rect, 1440, (((100-d->m_progress)*5760)/100)); + +// // Horizontal progress bar +// TQRect rect = pixmapRect(true); +// int verticalOffset = 0; +// int usedBarWidth = ((d->m_progress*pixmapRect().width())/100); +// int endPosition = x() + rect.x() + usedBarWidth; +// +// p->save(); +// +// p->setPen(TQPen::NoPen); +// p->setBrush(TQt::red); +// p->drawRect(TQRect(x() + rect.x(), y() + rect.y() + (pixmapRect().height() - verticalOffset), usedBarWidth, 1)); +// p->setBrush(TQt::green); +// p->drawRect(TQRect(endPosition, y() + rect.y() + (pixmapRect().height() - verticalOffset), pixmapRect().width() - usedBarWidth, 1)); + + // Vertical progress bar + TQRect rect = pixmapRect(true); + int horizontalOffset = 0; + int usedBarHeight = (((100-d->m_progress)*pixmapRect().height())/100); + int endPosition = y() + rect.y() + usedBarHeight; + + p->save(); + + p->setPen(TQPen::NoPen); + p->setBrush(TQt::green); + p->drawRect(TQRect(x() + rect.x() + (pixmapRect().width() - horizontalOffset), y() + rect.y(), 1, usedBarHeight)); + p->setBrush(TQt::red); + p->drawRect(TQRect(x() + rect.x() + (pixmapRect().width() - horizontalOffset), endPosition, 1, pixmapRect().height() - usedBarHeight)); + + p->restore(); + } +} + +void KFileIVI::paintFontUpdate( TQPainter *p ) const +{ + if ( m_fileitem->isLink() ) + { + TQFont f( p->font() ); + f.setItalic( TRUE ); + p->setFont( f ); + } +} + +TQColorGroup KFileIVI::updateColors( const TQColorGroup &c ) const +{ + TQColorGroup cg( c ); + cg.setColor( TQColorGroup::Text, static_cast<KonqIconViewWidget*>(iconView())->itemColor() ); + return cg; +} + +bool KFileIVI::move( int x, int y ) +{ + if ( static_cast<KonqIconViewWidget*>(iconView())->isDesktop() ) { + if ( x < 5 ) + x = 5; + if ( x > iconView()->viewport()->width() - ( width() + 5 ) ) + x = iconView()->viewport()->width() - ( width() + 5 ); + if ( y < 5 ) + y = 5; + if ( y > iconView()->viewport()->height() - ( height() + 5 ) ) + y = iconView()->viewport()->height() - ( height() + 5 ); + } + return TQIconViewItem::move( x, y ); +} + +bool KFileIVI::hasAnimation() const +{ + return !d->m_animatedIcon.isEmpty() && !m_bThumbnail; +} + +void KFileIVI::setMouseOverAnimation( const TQString& movieFileName ) +{ + if ( !movieFileName.isEmpty() ) + { + //kdDebug(1203) << "TDEIconViewItem::setMouseOverAnimation " << movieFileName << endl; + d->m_animatedIcon = movieFileName; + } +} + +TQString KFileIVI::mouseOverAnimation() const +{ + return d->m_animatedIcon; +} + +bool KFileIVI::isAnimated() const +{ + return d->m_animated; +} + +void KFileIVI::setAnimated( bool a ) +{ + d->m_animated = a; +} + +int KFileIVI::compare( TQIconViewItem *i ) const +{ + KonqIconViewWidget* view = static_cast<KonqIconViewWidget*>(iconView()); + if ( view->caseInsensitiveSort() ) + return key().localeAwareCompare( i->key() ); + else + return view->m_pSettings->caseSensitiveCompare( key(), i->key() ); +} + +void KFileIVI::updatePixmapSize() +{ + int size = m_size ? m_size : + TDEGlobal::iconLoader()->currentSize( TDEIcon::Desktop ); + + KonqIconViewWidget* view = static_cast<KonqIconViewWidget*>( iconView() ); + + bool mimeDetermined = false; + if ( m_fileitem->isMimeTypeKnown() ) { + mimeDetermined = true; + } + + if (mimeDetermined) { + bool changed = false; + if ( view && view->canPreview( item() ) ) { + int previewSize = view->previewIconSize( size ); + if (previewSize != size) { + setPixmapSize( TQSize( previewSize, previewSize ) ); + changed = true; + } + } + else { + TQSize pixSize = TQSize( size, size ); + if ( pixSize != pixmapSize() ) { + setPixmapSize( pixSize ); + changed = true; + } + } + if (changed) { + view->adjustItems(); + } + } + else { + TQSize pixSize = TQSize( size, size ); + if ( pixSize != pixmapSize() ) { + setPixmapSize( pixSize ); + } + } +} + +void KFileIVI::mimeTypeAndIconDetermined() +{ + updatePixmapSize(); +} |