[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kfm-devel
Subject:    Re: [PATH] Improve icons layout
From:       Benoit Walter <b.walter () free ! fr>
Date:       2004-01-20 19:45:29
Message-ID: 200401202045.29731.b.walter () free ! fr
[Download RAW message or body]

Thanks for the comment, updated patch removes the added members in KFileIVI. 
The previewIconSize function is fast enough, so it shouldn't have any effect 
on performance. I also removed m_canPreview which was actually not needed.


On Tuesday 20 January 2004 19:57, David Faure wrote:
> I can't really comment on the rest of the patch, but the above seems to eat
> quite some memory unnecessarily. This is for each item - and in some
> directories there can be many many items, so better not enlarge KFileIVI if
> not needed.
>
> m_iconView is already stored in QIconViewItem, just cast iconView()
> to a KonqIconViewWidget * like we already do in kfileivi.cc
>
> m_canPreview is ok (it fits with the other bool, no size increase)
>
> m_thumbSize can apparently be removed and always recalculated on the fly
> as iconview->previewIconSize( size ), unless that's too slow.
>
> Thanks for taking into account the memory consumption issue.

["libkonq2.diff" (text/x-diff)]

Index: kfileivi.cc
===================================================================
RCS file: /home/kde/kdebase/libkonq/kfileivi.cc,v
retrieving revision 1.80
diff -u -3 -p -r1.80 kfileivi.cc
--- kfileivi.cc	30 Aug 2003 16:40:14 -0000	1.80
+++ kfileivi.cc	20 Jan 2004 19:42:02 -0000
@@ -47,13 +47,17 @@ struct KFileIVI::Private
 };
 
 KFileIVI::KFileIVI( KonqIconViewWidget *iconview, KFileItem* fileitem, int size )
-    : KIconViewItem( iconview, fileitem->text(),
-		     fileitem->pixmap( size, KIcon::DefaultState ) ),
-    m_size( size ), m_state( KIcon::DefaultState ),
-    m_bDisabled( false ), m_bThumbnail( false ), m_fileitem( fileitem )
+ : KIconViewItem( iconview, fileitem->text() ), m_size( size ),
+   m_state( KIcon::DefaultState ), m_bDisabled( false ),
+   m_bThumbnail( false ), m_fileitem( fileitem )
 {
-    setDropEnabled( S_ISDIR( m_fileitem->mode() ) );
     d = new KFileIVI::Private;
+    if ( needEnlarge() )
+        QIconViewItem::setPixmap( enlargedFileItemPixmap() );
+    else
+        QIconViewItem::setPixmap( m_fileitem->pixmap( m_size, m_state ) );
+    
+    setDropEnabled( S_ISDIR( m_fileitem->mode() ) );
 
     // Cache entry for the icon effects
     d->icons.reset( *pixmap(), QIconSet::Large );
@@ -100,13 +104,14 @@ void KFileIVI::invalidateThumb( int stat
     m_state = state;
 
     QIconViewItem::setPixmap( d->icons.pixmap( QIconSet::Large, mode ),
-			      false, redraw );
+                 false, redraw );
 }
 
 void KFileIVI::setIcon( int size, int state, bool recalc, bool redraw )
 {
     m_size = size;
     m_bThumbnail = false;
+    
     if ( m_bDisabled )
       m_state = KIcon::DisabledState;
     else
@@ -124,7 +129,10 @@ void KFileIVI::setIcon( int size, int st
         d->m_overlay = DesktopIcon(d->m_overlayName, halfSize);
     }
 
-    setPixmapDirect(m_fileitem->pixmap( m_size, m_state ) , recalc, redraw );
+    if ( needEnlarge() )
+        setPixmapDirect( enlargedFileItemPixmap(), recalc, redraw );
+    else
+        setPixmapDirect( m_fileitem->pixmap( m_size, m_state ), recalc, redraw );
 }
 
 void KFileIVI::setOverlay( const QString& iconName )
@@ -179,7 +187,7 @@ void KFileIVI::setPixmapDirect( const QP
     d->icons = QIconSet();
     d->icons.setPixmap( pixmap, QIconSet::Large, mode );
     QIconViewItem::setPixmap( d->icons.pixmap( QIconSet::Large, mode ),
-			      recalc, redraw );
+                 recalc, redraw );
 }
 
 void KFileIVI::setDisabled( bool disabled )
@@ -189,7 +197,12 @@ void KFileIVI::setDisabled( bool disable
         m_bDisabled = disabled;
         bool active = ( m_state == KIcon::ActiveState );
         m_state = m_bDisabled ? KIcon::DisabledState : ( active ? KIcon::ActiveState \
                : KIcon::DefaultState );
-        QIconViewItem::setPixmap( m_fileitem->pixmap( m_size, m_state ), false, true \
); +        
+        if ( needEnlarge() )
+            QIconViewItem::setPixmap( enlargedFileItemPixmap(), false, true );
+        else
+            QIconViewItem::setPixmap( m_fileitem->pixmap( m_size, m_state ),
+                                      false, true );
     }
 }
 
@@ -208,7 +221,7 @@ void KFileIVI::setThumbnailPixmap( const
 
     // Recalc when setting this pixmap!
     QIconViewItem::setPixmap( d->icons.pixmap( QIconSet::Large,
-			      QIconSet::Normal ), true );
+                 QIconSet::Normal ), true );
 }
 
 void KFileIVI::setActive( bool active )
@@ -240,7 +253,9 @@ void KFileIVI::setEffect( int state )
     KIconEffect *effect = KGlobal::iconLoader()->iconEffect();
 
     bool haveEffect = effect->hasEffect( KIcon::Desktop, m_state ) !=
-                      effect->hasEffect( KIcon::Desktop, state );
+                      effect->hasEffect( KIcon::Desktop, state ) &&
+                      effect->fingerprint( KIcon::Desktop, m_state ) !=
+	                  effect->fingerprint( KIcon::Desktop, state );
 
                 //kdDebug(1203) << "desktop;defaultstate=" <<
                 //      effect->fingerprint(KIcon::Desktop, KIcon::DefaultState) <<
@@ -249,27 +264,31 @@ void KFileIVI::setEffect( int state )
                 //      effect->fingerprint(KIcon::Desktop, KIcon::ActiveState) <<
                 //      endl;
 
-    if( haveEffect &&
-        effect->fingerprint( KIcon::Desktop, m_state ) !=
-	effect->fingerprint( KIcon::Desktop, state ) )
+    m_state = state;
+    
+    if( haveEffect )
     {
-	// 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( QIconSet::Large, mode ) )
-		d->icons.setPixmap( effect->apply( d->thumb, KIcon::Desktop, state ),
-				    QIconSet::Large, mode );
-	}
-	else
-	{
-	    if( d->icons.isGenerated( QIconSet::Large, mode ) )
-		d->icons.setPixmap( m_fileitem->pixmap( m_size, state ),
-				    QIconSet::Large, mode );
-	}
-	QIconViewItem::setPixmap( d->icons.pixmap( QIconSet::Large, mode ) );
+        // 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( QIconSet::Large, mode ) )
+            d->icons.setPixmap( effect->apply( d->thumb, KIcon::Desktop, m_state ),
+                        QIconSet::Large, mode );
+        }
+        else
+        {
+            if( d->icons.isGenerated( QIconSet::Large, mode ) ) {
+                if ( needEnlarge() )
+                    d->icons.setPixmap( enlargedFileItemPixmap(),
+                                        QIconSet::Large, mode );
+                else
+                    d->icons.setPixmap( m_fileitem->pixmap( m_size, m_state ),
+                                        QIconSet::Large, mode );
+            }
+        }
+        QIconViewItem::setPixmap( d->icons.pixmap( QIconSet::Large, mode ) );
     }
-    m_state = state;
 }
 
 void KFileIVI::refreshIcon( bool redraw )
@@ -423,4 +442,46 @@ void KFileIVI::setAnimated( bool a )
     d->m_animated = a;
 }
 
-/* vim: set noet sw=4 ts=8 softtabstop=4: */
+QPixmap KFileIVI::enlargedFileItemPixmap() const
+{
+    // Enlarge the icon for items that can be previewed to match
+    // the size of a thumbnail
+    int size = m_size ? m_size :
+        KGlobal::iconLoader()->currentSize( KIcon::Desktop );
+    
+    QPixmap pix( m_fileitem->pixmap( size, m_state ) );
+    int w, h, dx, dy;
+    int thumbSize =
+        static_cast<KonqIconViewWidget*>(iconView())->previewIconSize( size );
+    
+    // Text under Icons
+    if ( static_cast<KonqIconViewWidget*>
+         (iconView())->itemTextPos() == QIconView::Bottom ) {
+        w = h = thumbSize;
+        dx = ( w - size ) / 2;
+        dy = h - size;
+    }
+    // Text alongside Icons
+    else {
+        w = size;
+        h = thumbSize;
+        dx = 0;
+        dy = ( h - size ) / 2;
+    }
+    
+    // Copy the file item pixmap into a larger, transparent pixmap
+    QPixmap p( w, h );
+    QBitmap mask( w, h );
+    mask.fill( color0 );
+    bitBlt( &mask, dx, dy, pix.mask() );
+    bitBlt( &p, dx, dy, &pix );
+    p.setMask( mask );
+    return p;
+}
+
+bool KFileIVI::needEnlarge() const
+{
+    KonqIconViewWidget* view = static_cast<KonqIconViewWidget*>(iconView());
+    return ( view->previewIconSize( m_size ) != m_size &&
+             view->canPreview( item() ) );
+}
Index: kfileivi.h
===================================================================
RCS file: /home/kde/kdebase/libkonq/kfileivi.h,v
retrieving revision 1.48
diff -u -3 -p -r1.48 kfileivi.h
--- kfileivi.h	2 Jul 2003 13:13:43 -0000	1.48
+++ kfileivi.h	20 Jan 2004 19:42:03 -0000
@@ -216,6 +216,10 @@ private:
     virtual void setPixmap ( const QPixmap & icon ) { KIconViewItem::setPixmap( icon \
                ); }
     virtual void setPixmap ( const QPixmap & icon, bool recalc, bool redraw = TRUE )
         { KIconViewItem::setPixmap( icon, recalc, redraw ); }
+
+    bool KFileIVI::needEnlarge() const;
+    QPixmap enlargedFileItemPixmap() const;
+
     int m_size, m_state;
     bool m_bDisabled;
     bool m_bThumbnail;
Index: konq_iconviewwidget.cc
===================================================================
RCS file: /home/kde/kdebase/libkonq/konq_iconviewwidget.cc,v
retrieving revision 1.269
diff -u -3 -p -r1.269 konq_iconviewwidget.cc
--- konq_iconviewwidget.cc	9 Jan 2004 17:55:59 -0000	1.269
+++ konq_iconviewwidget.cc	20 Jan 2004 19:42:20 -0000
@@ -45,6 +45,7 @@
 #include <kurldrag.h>
 #include <kstandarddirs.h>
 #include <kprotocolinfo.h>
+#include <ktrader.h>
 
 #include <assert.h>
 #include <unistd.h>
@@ -344,6 +345,10 @@ struct KonqIconViewWidgetPrivate
         m_movieBlocked = 0;
         pFileTip = 0;
         pActivateDoubleClick = 0L;
+        pPreviewMimeTypes = 0L;
+       
+        KConfigGroup group( KGlobal::config(), "PreviewSettings" );
+        bBoostPreview = group.readBoolEntry("BoostSize", false);
     }
     ~KonqIconViewWidgetPrivate() {
         delete pSoundPlayer;
@@ -351,6 +356,7 @@ struct KonqIconViewWidgetPrivate
         delete m_movie;
         delete pFileTip;
         delete pActivateDoubleClick;
+        delete pPreviewMimeTypes;
         //delete pPreviewJob; done by stopImagePreview
     }
     KFileIVI *pActiveItem;
@@ -363,8 +369,6 @@ struct KonqIconViewWidgetPrivate
     bool bAllowSetWallpaper;
     int gridXspacing;
 
-    QTimer* rearrangeIconsTimer;
-
     // Animated icons support
     bool doAnimations;
     QMovie* m_movie;
@@ -374,6 +378,8 @@ struct KonqIconViewWidgetPrivate
     KIO::PreviewJob *pPreviewJob;
     KFileTip* pFileTip;
     QStringList previewSettings;
+    QStringList* pPreviewMimeTypes;
+    bool bBoostPreview;
     bool renameItem;
     bool firstClick;
     bool releaseMouseEvent;
@@ -389,7 +395,6 @@ KonqIconViewWidget::KonqIconViewWidget( 
       m_bSetGridX( !kdesktop ) /* No line breaking on the desktop */
 {
     d = new KonqIconViewWidgetPrivate;
-    d->rearrangeIconsTimer = new QTimer( this );
     connect( this, SIGNAL( dropped( QDropEvent *, const QValueList<QIconDragItem> & \
                ) ),
              this, SLOT( slotDropped( QDropEvent*, const QValueList<QIconDragItem> & \
) ) );  
@@ -402,8 +407,6 @@ KonqIconViewWidget::KonqIconViewWidget( 
     connect( this, SIGNAL(onViewport()), SLOT(slotOnViewport()) );
     connect( this, SIGNAL(itemRenamed(QIconViewItem *, const QString &)), \
SLOT(slotItemRenamed(QIconViewItem *, const QString &)) );  
-    connect( d->rearrangeIconsTimer, SIGNAL( timeout() ), SLOT( slotRearrangeIcons() \
                ) );
-
     // hardcoded settings
     setSelectionMode( QIconView::Extended );
     setItemTextPos( QIconView::Bottom );
@@ -686,21 +689,58 @@ void KonqIconViewWidget::slotPreview(con
         KFileIVI* current = static_cast<KFileIVI *>(it);
         if (current->item() == item)
         {
-            bool needsUpdate = ( !current->pixmap() || current->pixmap()->width() < \
                pix.width() || current->pixmap()->height() < pix.height() );
-            if(item->overlays() & KIcon::HiddenOverlay)
-            {
-                QPixmap p(pix);
-
-                KIconEffect::semiTransparent(p);
-                current->setThumbnailPixmap(p);
-            } else {
-                current->setThumbnailPixmap(pix);
+            if ( !d->bBoostPreview ) {
+                if (item->overlays() & KIcon::HiddenOverlay) {
+                    QPixmap p(pix);
+                    KIconEffect::semiTransparent(p);
+                    current->setThumbnailPixmap(p);
+                }
+                else
+                    current->setThumbnailPixmap(pix);
+                break;
+            }
+            
+            // Create a pixmap as large as the current icon and copy the
+            // thumbnail pixmap
+            int w, h, dx, dy;
+            
+            // Text under Icons
+            if ( itemTextPos() == QIconView::Bottom ) {
+                QSize s = current->pixmap()->size();
+                w = s.width();
+                h = s.height();
+                dx = ( w - pix.width() ) / 2;
+                dy = h - pix.height();
+            }
+            
+            // Text alongside Icons
+            else {
+                w = pix.width();
+                h = current->pixmap()->height();
+                dx = 0;
+                dy = ( h - pix.height() ) / 2;
             }
-            if ( needsUpdate
-                    && autoArrange()
-                    && !d->rearrangeIconsTimer->isActive() ) {
-                d->rearrangeIconsTimer->start( 500, true );
+            
+            QPixmap p( w, h );
+            QBitmap mask( w, h );
+            mask.fill( color0 );
+            QBitmap* imask;
+            if ( pix.mask() )
+                imask = new QBitmap( *( pix.mask() ) );
+            else {
+                imask = new QBitmap( pix.size() );
+                imask->fill( color1 );
             }
+            bitBlt( &mask, dx, dy, imask );
+            bitBlt( &p, dx, dy, &pix );
+            p.setMask( mask );
+            delete imask;
+            
+            if(item->overlays() & KIcon::HiddenOverlay)
+                KIconEffect::semiTransparent(p);
+            
+            current->setThumbnailPixmap( p );
+            break;
         }
     }
 }
@@ -708,10 +748,6 @@ void KonqIconViewWidget::slotPreview(con
 void KonqIconViewWidget::slotPreviewResult()
 {
     d->pPreviewJob = 0;
-    if ( d->rearrangeIconsTimer->isActive() ) {
-        d->rearrangeIconsTimer->stop();
-        slotRearrangeIcons();
-    }
     emit imagePreviewFinished();
 }
 
@@ -900,11 +936,16 @@ void KonqIconViewWidget::setIcons( int s
         {
             ivi->setIcon( size, ivi->state(), true, false );
         }
-        else
+        else {
             ivi->invalidateThumb( ivi->state(), false );
+            if ( sizeChanged )
+                ivi->setIcon( size, ivi->state(), true, false );
+        }
     }
 
-    if ( autoArrange() && (oldGridX != gridX() || !stopImagePreviewFor.isEmpty()) )
+    if ( autoArrange() &&
+         ( oldGridX != gridX() || !stopImagePreviewFor.isEmpty() ||
+           d->bBoostPreview ) )
         arrangeItemsInGrid( true ); // take new grid into account and repaint
     else
         viewport()->update(); //Repaint later..
@@ -939,6 +980,10 @@ void KonqIconViewWidget::setItemTextPos(
     }
 
     KIconView::setItemTextPos( pos );
+
+    // Update the icons if preview size is boosted
+    if ( d->bBoostPreview )
+        setIcons( m_size );
 }
 
 void KonqIconViewWidget::calculateGridX()
@@ -957,6 +1002,7 @@ int KonqIconViewWidget::gridXValue() con
 
 void KonqIconViewWidget::refreshMimeTypes()
 {
+    updatePreviewMimeTypes();
     for ( QIconViewItem *it = firstItem(); it; it = it->nextItem() )
         (static_cast<KFileIVI *>( it ))->item()->refreshMimeType();
     setIcons( m_size );
@@ -1018,19 +1064,11 @@ void KonqIconViewWidget::startImagePrevi
     int size;
 
     KConfigGroup group( KGlobal::config(), "PreviewSettings" );
-    if ( group.readBoolEntry("BoostSize", false) ) {
-        if (iconSize < 28)
-            size = 48;
-        else if (iconSize < 40)
-            size = 64;
-        else if (iconSize < 60)
-            size = 96;
-        else
-            size = 128;
-    } else {
-        size = iconSize;
+    d->bBoostPreview = group.readBoolEntry("BoostSize", false);
+    size = previewIconSize( iconSize );
+
+    if ( !d->bBoostPreview )
         iconSize /= 2;
-    }
 
     d->pPreviewJob = KIO::filePreview( items, size, size, iconSize,
         m_pSettings->textPreviewIconTransparency(), true /* scale */,
@@ -1081,13 +1119,6 @@ void KonqIconViewWidget::slotAboutToCrea
    // Do nothing :-)
 }
 
-void KonqIconViewWidget::slotRearrangeIcons()
-{
-    // We cannot actually call arrangeItemsInGrid directly as a slot because it has \
                a default parameter.
-  arrangeItemsInGrid();
-}
-
-
 void KonqIconViewWidget::drawBackground( QPainter *p, const QRect &r )
 {
     drawBackground(p, r, r.topLeft());
@@ -1969,6 +2000,53 @@ void KonqIconViewWidget::lineupIcons()
     return;
 }
 
+bool KonqIconViewWidget::canPreview( KFileItem* item )
+{
+    if ( d->pPreviewMimeTypes == 0L )
+        updatePreviewMimeTypes();
+    
+    return mimeTypeMatch( item->mimetype(), *( d->pPreviewMimeTypes ) );
+}
+
+void KonqIconViewWidget::updatePreviewMimeTypes()
+{
+    if ( d->pPreviewMimeTypes == 0L )
+        d->pPreviewMimeTypes = new QStringList;
+    else
+        d->pPreviewMimeTypes->clear();
+    
+    // Load the list of plugins to determine which mimetypes are supported
+    KTrader::OfferList plugins = KTrader::self()->query("ThumbCreator");
+    KTrader::OfferList::ConstIterator it;
+    
+    for ( it = plugins.begin(); it != plugins.end(); ++it ) {
+        if ( d->previewSettings.contains((*it)->desktopEntryName()) ) {
+            QStringList mimeTypes = (*it)->property("MimeTypes").toStringList();
+            for (QStringList::ConstIterator mt = mimeTypes.begin(); mt != \
mimeTypes.end(); ++mt) +                d->pPreviewMimeTypes->append(*mt);
+        }
+    }
+}
+
+int KonqIconViewWidget::previewIconSize( int size ) const
+{
+    int iconSize = size ? size : KGlobal::iconLoader()->currentSize( KIcon::Desktop \
); +    int previewIconSize;
+    
+    if (!d->bBoostPreview)
+        previewIconSize = iconSize;
+    else if (iconSize < 28)
+        previewIconSize = 48;
+    else if (iconSize < 40)
+        previewIconSize = 64;
+    else if (iconSize < 60)
+        previewIconSize = 96;
+    else
+        previewIconSize = 128;
+    
+    return previewIconSize;
+}
+
 void KonqIconViewWidget::visualActivate(QIconViewItem * item)
 {
     // Rect of the QIconViewItem.
@@ -1995,6 +2073,11 @@ void KonqIconViewWidget::backgroundPixma
 void KonqIconViewWidget::setPreviewSettings( const QStringList& settings )
 {
     d->previewSettings = settings;
+    updatePreviewMimeTypes();
+    
+    // Update the icons if preview size is boosted
+    if ( d->bBoostPreview )
+        setIcons( m_size );
 }
 
 const QStringList& KonqIconViewWidget::previewSettings()
Index: konq_iconviewwidget.h
===================================================================
RCS file: /home/kde/kdebase/libkonq/konq_iconviewwidget.h,v
retrieving revision 1.103
diff -u -3 -p -r1.103 konq_iconviewwidget.h
--- konq_iconviewwidget.h	12 Dec 2003 00:03:58 -0000	1.103
+++ konq_iconviewwidget.h	20 Jan 2004 19:42:21 -0000
@@ -257,9 +257,6 @@ protected slots:
     void slotAboutToCreate(const QPoint &pos, const QValueList<KIO::CopyInfo> \
&files);  void doubleClickTimeout();
 
-private slots:
-    void slotRearrangeIcons();
-
 protected:
     virtual QDragObject *dragObject();
     KonqIconDrag *konqDragObject( QWidget * dragSource = 0L );
@@ -282,8 +279,13 @@ protected:
     virtual void wheelEvent( QWheelEvent* );
     void readAnimatedIconsConfig();
     void mousePressChangeValue();
+    
+    bool canPreview( KFileItem* item );
+    int previewIconSize( int size ) const;
 
 private:
+    void updatePreviewMimeTypes();
+    
     KURL m_url;
     const KFileItem * m_rootItem;
 



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic