[Digikam-devel] [Bug 134013] Tag menu extremly slow

Marcel Wiesweg marcel.wiesweg at gmx.de
Sat Sep 16 21:15:20 BST 2006


------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.
         
http://bugs.kde.org/show_bug.cgi?id=134013         
marcel.wiesweg gmx de changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|                            |FIXED



------- Additional Comments From marcel.wiesweg gmx de  2006-09-16 22:15 -------
SVN commit 585276 by mwiesweg:

Cache tag thumbnails
- add a cache (actually it is a QMap) to AlbumThumbnailLoader
- add a method to SyncJob to load icon for a TAlbum, using the AlbumThumbnailLoader
- use this in TagPopupMenu

BUG: 134013


 M  +59 -0     digikam/albumthumbnailloader.cpp  
 M  +7 -0      digikam/albumthumbnailloader.h  
 M  +61 -1     digikam/syncjob.cpp  
 M  +8 -0      digikam/syncjob.h  
 M  +3 -3      digikam/tagspopupmenu.cpp  
 M  +1 -1      libs/imageproperties/imagedescedittab.cpp  


--- trunk/extragear/graphics/digikam/digikam/albumthumbnailloader.cpp #585275:585276
 @ -43,6 +43,7  @
 {
 
 typedef QMap<KURL, QValueList<int> > UrlAlbumMap;
+typedef QMap<int, QPixmap> TagThumbnailMap;
 
 class AlbumThumbnailLoaderPrivate
 {
 @ -63,9 +64,23  @
 
     UrlAlbumMap             urlAlbumMap;
 
+    TagThumbnailMap         tagThumbnailMap;
+
     //QCache<QPixmap>        *m_cache;
 };
 
+class AlbumThumbnailLoaderEvent : public QCustomEvent
+{
+public:
+    AlbumThumbnailLoaderEvent(int albumID, const QPixmap &thumbnail)
+        : QCustomEvent(QEvent::User),
+          albumID(albumID), thumbnail(thumbnail)
+        {};
+
+    int albumID;
+    QPixmap thumbnail;
+};
+
 AlbumThumbnailLoader *AlbumThumbnailLoader::m_instance = 0;
 
 AlbumThumbnailLoader *AlbumThumbnailLoader::instance()
 @ -83,6 +98,12  @
 AlbumThumbnailLoader::AlbumThumbnailLoader()
 {
     d = new AlbumThumbnailLoaderPrivate;
+
+    connect(AlbumManager::instance(), SIGNAL(signalAlbumIconChanged(Album*)),
+            this, SLOT(slotIconChanged(Album*)));
+
+    connect(AlbumManager::instance(), SIGNAL(signalAlbumDeleted(Album*)),
+            this, SLOT(slotIconChanged(Album*)));
 }
 
 AlbumThumbnailLoader::~AlbumThumbnailLoader()
 @ -190,6 +211,19  @
     return pix;
     */
 
+    // First check cached thumbnails.
+    // At startup, this is not relevant, as the views will add their requests in a row.
+    // This is to speed up context menu and IE imagedescedit
+    TagThumbnailMap::iterator ttit = d->tagThumbnailMap.find(album->globalID());
+    if (ttit != d->tagThumbnailMap.end())
+    {
+        // It is not necessary to return cached icon asynchronously - they could be
+        // returned by getTagThumbnail already - but this would make the API
+        // less elegant, it feels much better this way.
+        QApplication::postEvent(this, new AlbumThumbnailLoaderEvent(album->globalID(), *ttit));
+        return;
+    }
+
     // Check if the URL has already been added (ThumbnailJob will _not_ check this)
     UrlAlbumMap::iterator it = d->urlAlbumMap.find(url);
 
 @ -291,6 +325,7  @
                     if (tagThumbnail.isNull())
                     {
                         tagThumbnail = createTagThumbnail(thumbnail);
+                        d->tagThumbnailMap.insert(album->globalID(), tagThumbnail);
                     }
 
                     emit signalThumbnail(album, tagThumbnail);
 @ -307,6 +342,30  @
 
 }
 
+void AlbumThumbnailLoader::customEvent(QCustomEvent *e)
+{
+    // for cached thumbnails
+
+    AlbumThumbnailLoaderEvent *atle = (AlbumThumbnailLoaderEvent *)e;
+    AlbumManager *manager = AlbumManager::instance();
+    Album *album = manager->findAlbum(atle->albumID);
+    if (album)
+    {
+        if (atle->thumbnail.isNull())
+            emit signalFailed(album);
+        else
+            emit signalThumbnail(album, atle->thumbnail);
+    }
+}
+
+void AlbumThumbnailLoader::slotIconChanged(Album* album)
+{
+    if(!album || album->type() != Album::TAG)
+        return;
+
+    d->tagThumbnailMap.remove(album->globalID());
+}
+
 QPixmap AlbumThumbnailLoader::createTagThumbnail(const QPixmap &albumThumbnail)
 {
     // tag thumbnails are cropped
--- trunk/extragear/graphics/digikam/digikam/albumthumbnailloader.h #585275:585276
 @ -30,6 +30,8  @
 
 #include <kurl.h>
 
+class QCustomEvent;
+
 namespace Digikam
 {
 
 @ -110,7 +112,12  @
 
     void slotGotThumbnailFromIcon(const KURL&, const QPixmap&);
     void slotThumbnailLost(const KURL&);
+    void slotIconChanged(Album* album);
 
+protected:
+
+    void customEvent(QCustomEvent *e);
+
 private:
 
     AlbumThumbnailLoader();
--- trunk/extragear/graphics/digikam/digikam/syncjob.cpp #585275:585276
 @ -44,6 +44,8  @
 #include "syncjob.h"
 #include "thumbnailjob.h"
 #include "thumbnailsize.h"
+#include "albumthumbnailloader.h"
+#include "album.h"
 
 void qt_enter_modal( QWidget *widget );
 void qt_leave_modal( QWidget *widget );
 @ -70,6 +72,12  @
     return sj.fileMovePriv(src, dest);
 }
 
+QPixmap SyncJob::getTagThumbnail(TAlbum *album)
+{
+    SyncJob sj;
+    return sj.getTagThumbnailPriv(album);
+}
+
 QPixmap SyncJob::getTagThumbnail(const QString &name, int size)
 {
     SyncJob sj;
 @ -79,6 +87,7  @
 SyncJob::SyncJob()
 {
     thumbnail_ = 0;
+    album_ = 0;
 }
 
 SyncJob::~SyncJob()
 @ -152,6 +161,57  @
     qApp->exit_loop();
 }
 
+QPixmap SyncJob::getTagThumbnailPriv(TAlbum *album)
+{
+    if (thumbnail_)
+        delete thumbnail_;
+    thumbnail_ = new QPixmap;
+
+    AlbumThumbnailLoader *loader = AlbumThumbnailLoader::instance();
+
+    if (!loader->getTagThumbnail(album, *thumbnail_))
+    {
+        if (thumbnail_->isNull())
+        {
+            return loader->getStandardTagIcon(album);
+        }
+        else
+        {
+            return loader->blendIcons(loader->getStandardTagIcon(), *thumbnail_);
+        }
+    }
+    else
+    {
+        connect(loader, SIGNAL(signalThumbnail(Album *, const QPixmap&)),
+                this, SLOT(slotGotThumbnailFromIcon(Album *, const QPixmap&)));
+
+        connect(loader, SIGNAL(signalFailed(Album *)),
+                this, SLOT(slotLoadThumbnailFailed(Album *)));
+
+        album_ = album;
+        enter_loop();
+    }
+    return *thumbnail_;
+}
+
+void SyncJob::slotLoadThumbnailFailed(Album *album)
+{
+    // TODO: setting _lastError*
+    if (album == album_)
+    {
+        qApp->exit_loop();
+    }
+}
+
+void SyncJob::slotGotThumbnailFromIcon(Album *album, const QPixmap& pix)
+{
+    if (album == album_)
+    {
+        *thumbnail_ = pix;
+        qApp->exit_loop();
+    }
+}
+
 QPixmap SyncJob::getTagThumbnailPriv(const QString &name, int size)
 {
     thumbnailSize_ = size;
 @ -181,7 +241,7  @
     {
         KIconLoader *iconLoader = KApplication::kApplication()->iconLoader();
         *thumbnail_ = iconLoader->loadIcon(name, KIcon::NoGroup, thumbnailSize_,
-                                          KIcon::DefaultState, 0, true);
+                                           KIcon::DefaultState, 0, true);
     }
     return *thumbnail_;
 }
--- trunk/extragear/graphics/digikam/digikam/syncjob.h #585275:585276
 @ -46,6 +46,9  @
 namespace Digikam
 {
 
+class Album;
+class TAlbum;
+
 class SyncJob : public QObject
 {
     Q_OBJECT
 @ -59,6 +62,7  @
     static bool file_move(const KURL &src, const KURL &dest);
 
     /* Load the image or icon for the tag thumbnail */    
+    static QPixmap getTagThumbnail(TAlbum *album);
     static QPixmap getTagThumbnail(const QString &name, int size);
 
     static QString lastErrorMsg();
 @ -74,6 +78,7  @
 
     bool fileMovePriv(const KURL &src, const KURL &dest);
     
+    QPixmap getTagThumbnailPriv(TAlbum *album);
     QPixmap getTagThumbnailPriv(const QString &name, int size);
 
     void enter_loop();
 @ -83,11 +88,14  @
     bool            success_;
     
     QPixmap         *thumbnail_;
+    Album           *album_;
     int             thumbnailSize_;
 
 private slots:
 
     void slotResult( KIO::Job * job );
+    void slotGotThumbnailFromIcon(Album *album, const QPixmap& pix);
+    void slotLoadThumbnailFailed(Album *album);
     void slotGotThumbnailFromIcon(const KURL& url, const QPixmap& pix);
     void slotLoadThumbnailFailed();
 };
--- trunk/extragear/graphics/digikam/digikam/tagspopupmenu.cpp #585275:585276
 @ -155,7 +155,7  @
                           ADDTAGID + album->id());
         popup->insertSeparator();
                 
-        QPixmap pix = SyncJob::getTagThumbnail(album->icon(), KIcon::SizeSmall);
+        QPixmap pix = SyncJob::getTagThumbnail(album);
         if ((m_mode == ASSIGN) && (m_assignedTags.contains(album->id())))
         {
             popup->insertItem(new TagsPopupCheckedMenuItem(popup, album->title(), pix),
 @ -175,7 +175,7  @
     {
         if (!album->isRoot())
         {
-            QPixmap pix = SyncJob::getTagThumbnail(album->icon(), KIcon::SizeSmall);
+            QPixmap pix = SyncJob::getTagThumbnail(album);
             popup->insertItem(pix, album->title(), m_addToID + album->id());
             popup->insertSeparator();
         }
 @ -280,7 +280,7  @
                 continue;
         }
         
-        QPixmap pix = SyncJob::getTagThumbnail(((TAlbum*)a)->icon(), KIcon::SizeSmall);
+        QPixmap pix = SyncJob::getTagThumbnail((TAlbum*)a);
         if (a->firstChild())
         {
             menu->insertItem(pix, a->title(), buildSubMenu(a->id()));
--- trunk/extragear/graphics/digikam/libs/imageproperties/imagedescedittab.cpp #585275:585276
 @ -915,7 +915,7  @
             TAlbum* album = albumMan->findTAlbum(*it);
             if (album)
             {
-                QPixmap pix = SyncJob::getTagThumbnail(album->icon(), KIcon::SizeSmall);
+                QPixmap pix = SyncJob::getTagThumbnail(album);
                 QString text = album->title() + " (" + ((TAlbum*)album->parent())->prettyURL() + ")";
                 menu->insertItem(pix, text, album->id());
             }



More information about the Digikam-devel mailing list