[Digikam-devel] extragear/graphics/digikam

Marcel Wiesweg marcel.wiesweg at gmx.de
Tue Feb 13 21:00:19 GMT 2007


SVN commit 633338 by mwiesweg:

Adding tags to many images - if writing to file metadata is disabled - is now 10-20x faster

Three optimizations (thanks to callgrind):
- in MetadataHub::write(QString), if no file write will be needed,
  do not create a DMetadata object (requires disk access -> slow)
- do not update AlbumIconView on every call to slotImageAttributesChanged
- use begin and commitTransaction around loops where many tags are added.
  Here, the biggest speed gain comes from the fact that not after every assigned
  tag the database file is touched, and the AlbumManager KDirWatch triggers a rescan

CCMAIL: digikam-devel at kde.org


 M  +17 -7     digikam/albumiconview.cpp  
 M  +51 -0     digikam/metadatahub.cpp  
 M  +1 -0      digikam/metadatahub.h  
 M  +2 -0      digikam/tagfilterview.cpp  
 M  +2 -0      digikam/tagfolderview.cpp  
 M  +4 -0      libs/imageproperties/imagedescedittab.cpp  
 M  +2 -0      libs/imageproperties/talbumlistview.cpp  


--- trunk/extragear/graphics/digikam/digikam/albumiconview.cpp #633337:633338
@@ -1320,6 +1320,8 @@
 {
     float cnt = list.count();
     int i = 0;
+
+    AlbumManager::instance()->albumDB()->beginTransaction();
     for (QPtrList<ImageInfo>::const_iterator it = list.begin(); it != list.end(); ++it)
     {
         MetadataHub hub;
@@ -1340,6 +1342,7 @@
             kapp->processEvents();
         }
     }
+    AlbumManager::instance()->albumDB()->commitTransaction();
 
     if (d->currentAlbum && d->currentAlbum->type() == Album::TAG)
     {
@@ -1886,6 +1889,7 @@
     float cnt = (float)countSelected();
     rating    = QMIN(5, QMAX(0, rating));
 
+    AlbumManager::instance()->albumDB()->beginTransaction();
     for (IconItem *it = firstItem() ; it ; it = it->nextItem())
     {
         if (it->isSelected())
@@ -1903,6 +1907,7 @@
             kapp->processEvents();
         }
     }
+    AlbumManager::instance()->albumDB()->commitTransaction();
 
     emit signalProgressBarMode(StatusProgressBar::TextMode, QString::null);
     updateContents();
@@ -1944,18 +1949,23 @@
         job->showErrorDialog(this);
 }
 
-void AlbumIconView::slotImageAttributesChanged(Q_LLONG /*imageId*/)
+void AlbumIconView::slotImageAttributesChanged(Q_LLONG imageId)
 {
-    // we might check if the item with imageId is currently visible,
-    // but I think it is ok to simply repaint in any case.
-    // We also do not need to check whether the change originates
-    // from our own actions above, the additional update should be killed by Qt.
-    updateContents();
+    AlbumIconItem *firstItem = static_cast<AlbumIconItem *>(findFirstVisibleItem());
+    AlbumIconItem *lastItem = static_cast<AlbumIconItem *>(findLastVisibleItem());
+    for (AlbumIconItem *item = firstItem; item && item != lastItem;
+         item = static_cast<AlbumIconItem *>(item->nextItem()))
+    {
+        if (item->imageInfo()->id() == imageId)
+        {
+            updateContents();
+            return;
+        }
+    }
 }
 
 void AlbumIconView::slotAlbumImagesChanged(int /*albumId*/)
 {
-    // Same considerations as above
     updateContents();
 }
 
--- trunk/extragear/graphics/digikam/digikam/metadatahub.cpp #633337:633338
@@ -556,6 +556,11 @@
 
 bool MetadataHub::write(const QString &filePath, WriteMode writeMode, const MetadataWriteSettings &settings)
 {
+    // if no DMetadata object is needed at all, don't construct one -
+    // important optimization if writing to file is turned off in setup!
+    if (!needWriteMetadata(writeMode, settings))
+        return false;
+
     DMetadata metadata(filePath);
     if (write(metadata, writeMode, settings))
     {
@@ -566,6 +571,52 @@
     return false;
 }
 
+bool MetadataHub::needWriteMetadata(WriteMode writeMode, const MetadataWriteSettings &settings) const
+{
+    // This is the same logic as in write(DMetadata) but without actually writing.
+    // Adapt if the method above changes
+
+    bool saveComment  = (settings.saveComments && d->commentStatus == MetadataAvailable);
+    bool saveDateTime = (settings.saveDateTime && d->dateTimeStatus == MetadataAvailable);
+    bool saveRating   = (settings.saveIptcRating && d->ratingStatus == MetadataAvailable);
+    bool saveTags     = false;
+    if (settings.saveIptcTags)
+    {
+        saveTags = false;
+        // find at least one tag to write
+        for (QMap<TAlbum *, TagStatus>::iterator it = d->tags.begin(); it != d->tags.end(); ++it)
+        {
+            if (it.data() == MetadataAvailable)
+            {
+                saveTags = true;
+                break;
+            }
+        }
+    }
+
+    bool writeAllFields;
+    if (writeMode == FullWrite)
+        writeAllFields = true;
+    else if (writeMode == FullWriteIfChanged)
+        writeAllFields = (
+                           (saveComment  && d->commentChanged)  ||
+                           (saveDateTime && d->dateTimeChanged) ||
+                           (saveRating   && d->ratingChanged)   ||
+                           (saveTags     && d->tagsChanged)
+                         );
+    else // PartialWrite
+        writeAllFields = false;
+
+    return (
+            (saveComment && (writeAllFields || d->commentChanged))   ||
+            (saveDateTime && (writeAllFields || d->dateTimeChanged)) ||
+            (saveRating && (writeAllFields || d->ratingChanged))     ||
+            (saveTags && (writeAllFields || d->tagsChanged))         ||
+            (settings.saveIptcPhotographerId && writeAllFields)      ||
+            (settings.saveIptcCredits && writeAllFields)
+           );
+}
+
 MetadataWriteSettings MetadataHub::defaultWriteSettings()
 {
     if (AlbumSettings::instance())
--- trunk/extragear/graphics/digikam/digikam/metadatahub.h #633337:633338
@@ -330,6 +330,7 @@
     void load(const QDateTime &dateTime, const QString &comment, int rating);
     void loadTags(const QValueList<TAlbum *> &loadedTags);
     void loadTags(const QStringList &loadedTagPaths);
+    bool needWriteMetadata(WriteMode writeMode, const MetadataWriteSettings &settings) const;
 
 private:
 
--- trunk/extragear/graphics/digikam/digikam/tagfilterview.cpp #633337:633338
@@ -524,6 +524,7 @@
             emit signalProgressBarMode(StatusProgressBar::ProgressBarMode, 
                                        i18n("Assign tag to pictures. Please wait..."));
 
+            AlbumManager::instance()->albumDB()->beginTransaction();
             int i=0;
             for (QValueList<int>::const_iterator it = imageIDs.begin();
                  it != imageIDs.end(); ++it)
@@ -540,6 +541,7 @@
                 emit signalProgressValue((int)((i++/(float)imageIDs.count())*100.0));
                 kapp->processEvents();
             }
+            AlbumManager::instance()->albumDB()->commitTransaction();
 
             ImageAttributesWatch::instance()->imagesChanged(destAlbum->id());
 
--- trunk/extragear/graphics/digikam/digikam/tagfolderview.cpp #633337:633338
@@ -808,6 +808,7 @@
             emit signalProgressBarMode(StatusProgressBar::ProgressBarMode, 
                                        i18n("Assign tag to pictures. Please wait..."));
 
+            AlbumManager::instance()->albumDB()->beginTransaction();
             int i=0;
             for (QValueList<int>::const_iterator it = imageIDs.begin();
                  it != imageIDs.end(); ++it)
@@ -824,6 +825,7 @@
                 emit signalProgressValue((int)((i++/(float)imageIDs.count())*100.0));
                 kapp->processEvents();
             }
+            AlbumManager::instance()->albumDB()->commitTransaction();
 
             ImageAttributesWatch::instance()->imagesChanged(destAlbum->id());
 
--- trunk/extragear/graphics/digikam/libs/imageproperties/imagedescedittab.cpp #633337:633338
@@ -454,6 +454,7 @@
 
     // we are now changing attributes ourselves
     d->ignoreImageAttributesWatch = true;
+    AlbumManager::instance()->albumDB()->beginTransaction();
     int i=0;
     for (ImageInfo *info = d->currInfos.first(); info; info = d->currInfos.next())
     {
@@ -465,6 +466,7 @@
         emit signalProgressValue((int)((i++/(float)d->currInfos.count())*100.0));
         kapp->processEvents();
     }
+    AlbumManager::instance()->albumDB()->commitTransaction();
     d->ignoreImageAttributesWatch = false;
 
     emit signalProgressBarMode(StatusProgressBar::TextMode, QString::null);
@@ -537,6 +539,7 @@
                                i18n("Reading metadata from files. Please wait..."));
 
     d->ignoreImageAttributesWatch = true;
+    AlbumManager::instance()->albumDB()->beginTransaction();
     int i=0;
     for (ImageInfo *info = d->currInfos.first(); info; info = d->currInfos.next())
     {
@@ -550,6 +553,7 @@
         emit signalProgressValue((int)((i++/(float)d->currInfos.count())*100.0));
         kapp->processEvents();
     }
+    AlbumManager::instance()->albumDB()->commitTransaction();
     d->ignoreImageAttributesWatch = false;
 
     emit signalProgressBarMode(StatusProgressBar::TextMode, QString::null);
--- trunk/extragear/graphics/digikam/libs/imageproperties/talbumlistview.cpp #633337:633338
@@ -419,6 +419,7 @@
             emit signalProgressBarMode(StatusProgressBar::ProgressBarMode, 
                                        i18n("Assign tag to pictures. Please wait..."));
 
+            AlbumManager::instance()->albumDB()->beginTransaction();
             int i=0;
             for (QValueList<int>::const_iterator it = imageIDs.begin();
                  it != imageIDs.end(); ++it)
@@ -435,6 +436,7 @@
                 emit signalProgressValue((int)((i++/(float)imageIDs.count())*100.0));
                 kapp->processEvents();
             }
+            AlbumManager::instance()->albumDB()->commitTransaction();
 
             ImageAttributesWatch::instance()->imagesChanged(destAlbum->id());
 



More information about the Digikam-devel mailing list