Re: Speeding up annotation
Robert Krawitz <rlk-FrUbXkNCsVf2fBVCVOL8/[email protected]> Sat, 11 Jan 2020 23:24:58 -0500 (EST)
| Newsgroups | gmane.comp.kde.kimdaba |
|---|---|
| Message-ID | <20200112042458.5AB1A4249B2@localhost> |
Here are the two patches for annotation dialog: - patch-annotation-selection.patch improves the selection regeneration. - patch-annotation-2.patch improves the recomputation of the options, by improving the computation of the selected/unselected sets, and by only applying changes rather than reapplying everything. Combined, it goes from taking a few minutes to apply a change to 30,000 images to taking a second or so. -- Robert Krawitz <rlk-FrUbXkNCsVf2fBVCVOL8/[email protected]> *** MIT Engineers A Proud Tradition http://mitathletics.com *** Member of the League for Programming Freedom -- http://ProgFree.org Project lead for Gutenprint -- http://gimp-print.sourceforge.net "Linux doesn't dictate how I work, I dictate how Linux works." --Eric Crampton _______________________________________________ KPhotoAlbum mailing list [email protected] https://mail.kdab.com/mailman/listinfo/kphotoalbum
patch-annotation-2.patch
(application/octet-stream, 6.5 KB)
diff --git a/AnnotationDialog/Dialog.cpp b/AnnotationDialog/Dialog.cpp
index a3030df7..1c958588 100644
--- a/AnnotationDialog/Dialog.cpp
+++ b/AnnotationDialog/Dialog.cpp
@@ -1043,6 +1043,17 @@ void AnnotationDialog::Dialog::closeDialog()
QDialog::reject();
}
+StringSet AnnotationDialog::Dialog::changedOptions(ListSelect *ls)
+{
+ StringSet on, partialOn, off, changes;
+ std::tie(on, partialOn, off) = selectionForMultiSelect(ls, m_origList);
+ changes += (ls->itemsOn() - on);
+ changes += (on - ls->itemsOn());
+ changes += (ls->itemsOff() - off);
+ changes += (off - ls->itemsOff());
+ return changes;
+}
+
bool AnnotationDialog::Dialog::hasChanges()
{
bool changed = false;
@@ -1057,14 +1068,9 @@ bool AnnotationDialog::Dialog::hasChanges()
else if (m_setup == InputMultiImageConfigMode) {
changed |= (!m_startDate->date().isNull());
changed |= (!m_endDate->date().isNull());
-
Q_FOREACH (ListSelect *ls, m_optionList) {
- StringSet on, partialOn;
- std::tie(on, partialOn) = selectionForMultiSelect(ls, m_origList);
- changed |= (on != ls->itemsOn());
- changed |= (partialOn != ls->itemsUnchanged());
+ changed |= !(changedOptions(ls).isEmpty());
}
-
changed |= (!m_imageLabel->text().isEmpty());
changed |= (m_description->toPlainText() != m_firstDescription);
changed |= m_ratingChanged;
@@ -1323,28 +1329,41 @@ KActionCollection *AnnotationDialog::Dialog::actions()
void AnnotationDialog::Dialog::setUpCategoryListBoxForMultiImageSelection(ListSelect *listSel, const DB::ImageInfoList &images)
{
- StringSet on, partialOn;
- std::tie(on, partialOn) = selectionForMultiSelect(listSel, images);
+ StringSet on, partialOn, off;
+ std::tie(on, partialOn, off) = selectionForMultiSelect(listSel, images);
listSel->setSelection(on, partialOn);
}
-std::tuple<StringSet, StringSet> AnnotationDialog::Dialog::selectionForMultiSelect(ListSelect *listSel, const DB::ImageInfoList &images)
+std::tuple<StringSet, StringSet, StringSet> AnnotationDialog::Dialog::selectionForMultiSelect(ListSelect *listSel, const DB::ImageInfoList &images)
{
const QString category = listSel->category();
const StringSet allItems = DB::ImageDB::instance()->categoryCollection()->categoryForName(category)->itemsInclCategories().toSet();
- StringSet itemsNotSelectedOnAllImages;
StringSet itemsOnSomeImages;
+ StringSet itemsOnAllImages;
+ bool firstImage = true;
for (DB::ImageInfoList::ConstIterator imageIt = images.begin(); imageIt != images.end(); ++imageIt) {
const StringSet itemsOnThisImage = (*imageIt)->itemsOfCategory(category);
- itemsNotSelectedOnAllImages += (allItems - itemsOnThisImage);
- itemsOnSomeImages += itemsOnThisImage;
+ if (firstImage) {
+ itemsOnAllImages = itemsOnThisImage;
+ firstImage = false;
+ } else {
+ foreach (const QString &item, itemsOnThisImage) {
+ if (! itemsOnAllImages.contains(item) &&
+ ! itemsOnSomeImages.contains(item)) {
+ itemsOnSomeImages += item;
+ }
+ }
+ foreach (const QString &item, itemsOnAllImages) {
+ if (! itemsOnThisImage.contains(item)) {
+ itemsOnAllImages -= item;
+ }
+ }
+ }
}
+ const StringSet itemsOnNoImages = allItems - itemsOnSomeImages - itemsOnAllImages;
- const StringSet itemsOnAllImages = allItems - itemsNotSelectedOnAllImages;
- const StringSet itemsPartiallyOn = itemsOnSomeImages - itemsOnAllImages;
-
- return std::make_tuple(itemsOnAllImages, itemsPartiallyOn);
+ return std::make_tuple(itemsOnAllImages, itemsOnSomeImages, itemsOnNoImages);
}
void AnnotationDialog::Dialog::slotRatingChanged(unsigned int)
@@ -1383,16 +1402,23 @@ void AnnotationDialog::Dialog::saveAndClose()
ls->slotReturn();
}
+ Q_FOREACH(ListSelect *ls, m_optionList) {
+ StringSet changes = changedOptions(ls);
+ if (!(changes.isEmpty())) {
+ StringSet newItemsOn = ls->itemsOn() & changes;
+ StringSet newItemsOff = ls->itemsOff() & changes;
+ for (DB::ImageInfoListConstIterator it = m_origList.constBegin(); it != m_origList.constEnd(); ++it) {
+ DB::ImageInfoPtr info = *it;
+ info->addCategoryInfo(ls->category(), newItemsOn);
+ info->removeCategoryInfo(ls->category(), newItemsOff);
+ }
+ }
+ }
for (DB::ImageInfoListConstIterator it = m_origList.constBegin(); it != m_origList.constEnd(); ++it) {
DB::ImageInfoPtr info = *it;
if (!m_startDate->date().isNull())
info->setDate(DB::ImageDate(m_startDate->date(), m_endDate->date(), m_time->time()));
- Q_FOREACH (ListSelect *ls, m_optionList) {
- info->addCategoryInfo(ls->category(), ls->itemsOn());
- info->removeCategoryInfo(ls->category(), ls->itemsOff());
- }
-
if (!m_imageLabel->text().isEmpty()) {
info->setLabel(m_imageLabel->text());
}
@@ -1406,13 +1432,13 @@ void AnnotationDialog::Dialog::saveAndClose()
}
}
m_ratingChanged = false;
+
}
m_accept = QDialog::Accepted;
if (anyChanges) {
MainWindow::DirtyIndicator::markDirty();
}
-
QDialog::accept();
}
diff --git a/AnnotationDialog/Dialog.h b/AnnotationDialog/Dialog.h
index a40ebac9..6b6c5c40 100644
--- a/AnnotationDialog/Dialog.h
+++ b/AnnotationDialog/Dialog.h
@@ -155,6 +155,7 @@ protected:
void showTornOfWindows();
void hideTornOfWindows();
bool hasChanges();
+ StringSet changedOptions(ListSelect *);
void showHelpDialog(UsageMode);
void resizeEvent(QResizeEvent *) override;
void moveEvent(QMoveEvent *) override;
@@ -163,7 +164,7 @@ protected:
void loadWindowLayout();
void setupActions();
void setUpCategoryListBoxForMultiImageSelection(ListSelect *, const DB::ImageInfoList &images);
- std::tuple<Utilities::StringSet, Utilities::StringSet> selectionForMultiSelect(ListSelect *, const DB::ImageInfoList &images);
+ std::tuple<Utilities::StringSet, Utilities::StringSet, Utilities::StringSet> selectionForMultiSelect(ListSelect *, const DB::ImageInfoList &images);
void saveAndClose();
void ShowHideSearch(bool show);
patch-annotation-selection.patch
(application/octet-stream, 1.5 KB)
diff --git a/ThumbnailView/ThumbnailWidget.cpp b/ThumbnailView/ThumbnailWidget.cpp
index 470d4da8..6ad0a696 100644
--- a/ThumbnailView/ThumbnailWidget.cpp
+++ b/ThumbnailView/ThumbnailWidget.cpp
@@ -34,6 +34,8 @@
#include <KLocalizedString>
#include <QScrollBar>
#include <QTimer>
+#include <QItemSelection>
+#include <QItemSelectionRange>
#include <math.h>
#include <qcursor.h>
#include <qfontmetrics.h>
@@ -410,8 +412,28 @@ void ThumbnailView::ThumbnailWidget::changeSingleSelection(const DB::FileName &f
void ThumbnailView::ThumbnailWidget::select(const DB::FileNameList &items)
{
- Q_FOREACH (const DB::FileName &fileName, items)
- selectionModel()->select(model()->fileNameToIndex(fileName), QItemSelectionModel::Select);
+ QItemSelection selection;
+ QModelIndex start;
+ QModelIndex end;
+ int count = 0;
+ Q_FOREACH (const DB::FileName &fileName, items) {
+ QModelIndex index = model()->fileNameToIndex(fileName);
+ if (count == 0) {
+ start = index;
+ end = index;
+ } else if (index.row() == end.row() + 1) {
+ end = index;
+ } else {
+ selection.merge(QItemSelection(start, end), QItemSelectionModel::Select);
+ start = index;
+ end = index;
+ }
+ count++;
+ }
+ if (count > 0) {
+ selection.merge(QItemSelection(start, end), QItemSelectionModel::Select);
+ }
+ selectionModel()->select(selection, QItemSelectionModel::Select);
}
bool ThumbnailView::ThumbnailWidget::isItemUnderCursorSelected() const