diff options
author | 2020-07-30 19:45:19 +0200 | |
---|---|---|
committer | 2020-07-30 19:45:19 +0200 | |
commit | 52b1f1cb9f8d4e1fb1fcbde59930a105a819b0b4 (patch) | |
tree | 22f1205f0276563548f2864997c82a8af7307fcd /kde/patch | |
parent | 42f29689f597520389829b6d22c56ee21ace7657 (diff) | |
download | ktown-52b1f1cb9f8d4e1fb1fcbde59930a105a819b0b4.tar.gz ktown-52b1f1cb9f8d4e1fb1fcbde59930a105a819b0b4.tar.xz |
Cleanup unused KDE patches
Thanks to Patrick Volkerding for the effort.
Diffstat (limited to 'kde/patch')
179 files changed, 1 insertions, 23375 deletions
diff --git a/kde/patch/akonadi.patch b/kde/patch/akonadi.patch deleted file mode 100644 index ddab2a8..0000000 --- a/kde/patch/akonadi.patch +++ /dev/null @@ -1,12 +0,0 @@ -# Remove hardcoded absolute path to stdlib header. -# This is Windows-centric and breaks on any linux GCC upgrade. -# Thanks to Gentoo where I found the following two patches at -# https://packages.gentoo.org/packages/kde-apps/akonadi -# No longer needed since 17.04.0. -#cat $CWD/patch/akonadi/akonadi_revert-abs-path.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } -#cat $CWD/patch/akonadi/akonadi_rename-header.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - -# Temporary fix for non-working Akonadi in combination with mariadb 10.2.8 -# (actually this is a bug in qtsql, not in akonadi or mariadb): -#cat $CWD/patch/akonadi/akonadi_mariadb_qtsql.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - diff --git a/kde/patch/akonadi/akonadi_mariadb_qtsql.patch b/kde/patch/akonadi/akonadi_mariadb_qtsql.patch deleted file mode 100644 index 7ec6d7c..0000000 --- a/kde/patch/akonadi/akonadi_mariadb_qtsql.patch +++ /dev/null @@ -1,91 +0,0 @@ -Patch taken from https://cgit.kde.org/akonadi.git/patch/?id=b145f47f000978b9d39edc1882849ec7f6b3ef79 - -Upstream bug reports: -https://bugs.kde.org/show_bug.cgi?id=383991 -https://bugreports.qt.io/browse/QTBUG-63108 - -From b145f47f000978b9d39edc1882849ec7f6b3ef79 Mon Sep 17 00:00:00 2001 -From: Heinz Wiesinger <pprkut@liwjatan.at> -Date: Sun, 17 Sep 2017 10:56:44 +0200 -Subject: Only remove init connections to the database on server shutdown. - -Summary: -With MariaDB 10.2 libmysqlclient was replaced with libmariadb that -changed how establishing database connections behaves. The MySQL -QSQL driver calls mysql_server_end() on QSqlDatabase::removeDatabase() -if the overall connection count dropped to 0 (which it does when -the init connection is removed). -A future QSqlDatabase:addDatabase() would call mysql_server_init() -again, but this no longer works with libmariadb as that one only -allows calling mysql_server_init() once. Future calls are simply -ignored. - -In order to prevent this from happening we have to keep the -init connection open until the server shuts down, so the connection -count only drops to 0 at shutdown and mysql_server_end() isn't -called before. - -This is a workaround for QTBUG-63108 - -CCBUG: 383991 - -Reviewers: dvratil, mlaurent - -Reviewed By: dvratil - -Subscribers: #kde_pim - -Tags: #kde_pim - -Differential Revision: https://phabricator.kde.org/D7858 ---- - src/server/akonadi.cpp | 3 ++- - src/server/storage/dbconfigmysql.cpp | 4 +++- - 2 files changed, 5 insertions(+), 2 deletions(-) - -diff --git a/src/server/akonadi.cpp b/src/server/akonadi.cpp -index 4364e63..bcb7e88 100644 ---- a/src/server/akonadi.cpp -+++ b/src/server/akonadi.cpp -@@ -423,13 +423,14 @@ bool AkonadiServer::createDatabase() - success = false; - } - } -- QSqlDatabase::removeDatabase(initCon); - return success; - } - - void AkonadiServer::stopDatabaseProcess() - { - if (!DbConfig::configuredDatabase()->useInternalServer()) { -+ // closing initConnection this late to work around QTBUG-63108 -+ QSqlDatabase::removeDatabase(QStringLiteral("initConnection")); - return; - } - -diff --git a/src/server/storage/dbconfigmysql.cpp b/src/server/storage/dbconfigmysql.cpp -index 2bd231d..d565706 100644 ---- a/src/server/storage/dbconfigmysql.cpp -+++ b/src/server/storage/dbconfigmysql.cpp -@@ -492,7 +492,6 @@ bool DbConfigMysql::startInternalServer() - } - } - -- QSqlDatabase::removeDatabase(initCon); - return success; - } - -@@ -520,6 +519,9 @@ void DbConfigMysql::stopInternalServer() - return; - } - -+ // closing initConnection this late to work around QTBUG-63108 -+ QSqlDatabase::removeDatabase(QStringLiteral("initConnection")); -+ - disconnect(mDatabaseProcess, static_cast<void(QProcess::*)(int,QProcess::ExitStatus)>(&QProcess::finished), - this, &DbConfigMysql::processFinished); - --- -cgit v0.11.2 - - diff --git a/kde/patch/akonadi/akonadi_rename-header.patch b/kde/patch/akonadi/akonadi_rename-header.patch deleted file mode 100644 index 73347f0..0000000 --- a/kde/patch/akonadi/akonadi_rename-header.patch +++ /dev/null @@ -1,77 +0,0 @@ -commit 248671e8200ff0883877b6d0e56700ef99ff3b51 -Author: Andreas Sturmlechner <andreas.sturmlechner@gmail.com> -Date: Sat Jan 7 14:38:17 2017 +0100 - - Rename exception.h to exceptionbase.h - - REVIEW: 129788 - -diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt -index 6ac851e..fa996b9 100644 ---- a/src/core/CMakeLists.txt -+++ b/src/core/CMakeLists.txt -@@ -95,7 +95,7 @@ ecm_generate_headers(AkonadiCore_base_HEADERS - EntityDeletedAttribute - EntityDisplayAttribute - EntityHiddenAttribute -- Exception -+ ExceptionBase - GidExtractorInterface - IndexPolicyAttribute - Item -diff --git a/src/core/exception.cpp b/src/core/exception.cpp -index f229c1a..14f7330 100644 ---- a/src/core/exception.cpp -+++ b/src/core/exception.cpp -@@ -17,7 +17,7 @@ - 02110-1301, USA. - */ - --#include "exception.h" -+#include "exceptionbase.h" - - #include <QString> - -diff --git a/src/core/exception.h b/src/core/exceptionbase.h -similarity index 100% -rename from src/core/exception.h -rename to src/core/exceptionbase.h -diff --git a/src/core/item.h b/src/core/item.h -index de71cad..5ec62c8 100644 ---- a/src/core/item.h -+++ b/src/core/item.h -@@ -23,7 +23,7 @@ - - #include "akonadicore_export.h" - #include "attribute.h" --#include "exception.h" -+#include "exceptionbase.h" - #include "tag.h" - #include "collection.h" - #include "relation.h" -diff --git a/src/core/itempayloadinternals_p.h b/src/core/itempayloadinternals_p.h -index 0a4de3c..1626f10 100644 ---- a/src/core/itempayloadinternals_p.h -+++ b/src/core/itempayloadinternals_p.h -@@ -32,7 +32,7 @@ - - #include <boost/shared_ptr.hpp> - --#include "exception.h" -+#include "exceptionbase.h" - - //@cond PRIVATE Doxygen 1.7.1 hangs processing this file. so skip it. - //for more info, see https://bugzilla.gnome.org/show_bug.cgi?id=531637 -diff --git a/src/core/protocolhelper.cpp b/src/core/protocolhelper.cpp -index f740e9d..c218f0c 100644 ---- a/src/core/protocolhelper.cpp -+++ b/src/core/protocolhelper.cpp -@@ -23,7 +23,7 @@ - #include "collectionstatistics.h" - #include "item_p.h" - #include "collection_p.h" --#include "exception.h" -+#include "exceptionbase.h" - #include "itemserializer_p.h" - #include "itemserializerplugin.h" - #include "servermanager.h" diff --git a/kde/patch/akonadi/akonadi_revert-abs-path.patch b/kde/patch/akonadi/akonadi_revert-abs-path.patch deleted file mode 100644 index 3b48253..0000000 --- a/kde/patch/akonadi/akonadi_revert-abs-path.patch +++ /dev/null @@ -1,70 +0,0 @@ -commit d98e29a07f4acc3bf01f06f25b3eef5522397e2e -Author: Andreas Sturmlechner <andreas.sturmlechner@gmail.com> -Date: Thu Jan 5 22:41:02 2017 +0100 - - Revert "Workaround an include loop on case-insensitive systems" - - Do not hardcode absolute patchs to GCC headers. - - This reverts commit 59b9d6b79425c9ec1e5df059a2593580048c4adf. - - REVIEW: 129788 - -diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt -index 72589cd..6ac851e 100644 ---- a/src/core/CMakeLists.txt -+++ b/src/core/CMakeLists.txt -@@ -257,21 +257,6 @@ ecm_generate_headers(AkonadiCore_jobs_HEADERS - RELATIVE jobs - ) - --# This is a workaround for conflict between our "Exception" fancy header and --# C++ stdlib's "exception" header which occurs in case-insensitive systems. --# For that reason we generate std_exception.h file, which contains an absolute --# path to the stdlib's exception header file, which resolves the ambiguity --# when including <exception> from within Akonadi. --include(FindStdlibInclude) --findStdlibInclude("exception" std_exception_file) --if (NOT "${std_exception_file}" STREQUAL "") -- configure_file(${CMAKE_CURRENT_SOURCE_DIR}/std_exception.h.in -- ${CMAKE_CURRENT_BINARY_DIR}/std_exception.h -- ) --else() -- message(FATAL_ERROR "stdlib <exception> include absolute path not found") --endif() -- - set(akonadicore_dbus_xml ${Akonadi_SOURCE_DIR}/src/interfaces/org.freedesktop.Akonadi.NotificationManager.xml) - qt5_add_dbus_interface(akonadicore_dbus_SRCS ${akonadicore_dbus_xml} notificationmanagerinterface) - -@@ -338,7 +323,6 @@ install(TARGETS - - install(FILES - ${CMAKE_CURRENT_BINARY_DIR}/akonadicore_export.h -- ${CMAKE_CURRENT_BINARY_DIR}/std_exception.h - ${AkonadiCore_base_HEADERS} - ${AkonadiCore_models_HEADERS} - ${AkonadiCore_jobs_HEADERS} -diff --git a/src/core/exception.h b/src/core/exception.h -index d07ca71..2a376df 100644 ---- a/src/core/exception.h -+++ b/src/core/exception.h -@@ -20,16 +20,11 @@ - #ifndef AKONADI_EXCEPTION_H - #define AKONADI_EXCEPTION_H - --// The std_exception.h file is generated at build-time and #includes C++ stdlib --// header "exception" by aboslute path. This is to workaround an include loop on --// case-insensitive systems, where #include <exception> includes our "Exception" --// fancy header instead of stdlib's exception, causing an endless loop of --// includes between "Exception" and "exception.h". --#include "std_exception.h" -- - #include "akonadicore_export.h" -+#include <QObject> -+#include <QByteArray> -+#include <exception> - --class QByteArray; - class QString; - - namespace Akonadi diff --git a/kde/patch/akonadi4.patch b/kde/patch/akonadi4.patch index 388c3ea..8ff0118 100644 --- a/kde/patch/akonadi4.patch +++ b/kde/patch/akonadi4.patch @@ -1,4 +1,3 @@ # Backport a patch from git master since there will not be another # official akonadi release after the current 1.13: cat $CWD/patch/akonadi4/akonadi_dont-leak-old-external-payload-files.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - diff --git a/kde/patch/amarok.patch b/kde/patch/amarok.patch index 9fc3963..7ede8ad 100644 --- a/kde/patch/amarok.patch +++ b/kde/patch/amarok.patch @@ -1,4 +1,3 @@ # Fix a crash in KDE 4.11: # See also https://bugs.kde.org/show_bug.cgi?id=320855 cat $CWD/patch/amarok/amarok_kdebug_320855.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - diff --git a/kde/patch/ark/ark_kdebug357057.patch b/kde/patch/ark/ark_kdebug357057.patch deleted file mode 100644 index 76c0bab..0000000 --- a/kde/patch/ark/ark_kdebug357057.patch +++ /dev/null @@ -1,37 +0,0 @@ -From: Elvis Angelaccio <elvis.angelaccio@kdemail.net> -Date: Wed, 23 Dec 2015 16:19:29 +0000 -Subject: Fallback to read-only mode if there are no read-write executables -X-Git-Url: http://quickgit.kde.org/?p=ark.git&a=commitdiff&h=087e5aab49c60ac5930742fe892fa930048e2f43 ---- -Fallback to read-only mode if there are no read-write executables - -Commit 2d000a0 introduced executables check when loading a plugin. However the -current behavior is too restrictive: if one wants only to open a rar or a -zip archive, there is no need to require also the rar or zip program to be -installed. Plus, some distributions (e.g. Archlinux) ship only unrar in their -official repositories. - -With this commit, Ark is able to understand that e.g. unrar is installed but -rar is not. In this case, Ark can and should fallback to read-only mode, -to disable the Add/Delete actions in the toolbar. - -BUG: 357057 -FIXED-IN: 15.12.1 - -CC: rthomsen6@gmail.com ---- - - ---- a/kerfuffle/archive_kerfuffle.cpp -+++ b/kerfuffle/archive_kerfuffle.cpp -@@ -173,6 +173,9 @@ - - if (iface->findExecutables(!isReadOnly)) { - return new Archive(iface, isReadOnly, parent); -+ } else if (!isReadOnly && iface->findExecutables(false)) { -+ qCWarning(ARK) << "Failed to find read-write executables: falling back to read-only mode for read-write plugin" << pluginName; -+ return new Archive(iface, true, parent); - } else { - qCWarning(ARK) << "Failed to find needed executables for plugin" << pluginName; - } - diff --git a/kde/patch/baloo5/baloo-4.96.0_kaboutdata.diff b/kde/patch/baloo5/baloo-4.96.0_kaboutdata.diff deleted file mode 100644 index 36ec0d1..0000000 --- a/kde/patch/baloo5/baloo-4.96.0_kaboutdata.diff +++ /dev/null @@ -1,69 +0,0 @@ -From: Andreas Hartmetz <ahartmetz@gmail.com> -Date: Wed, 14 May 2014 02:36:57 +0000 -Subject: Adapt to changes in KAboutData. -X-Git-Url: http://quickgit.kde.org/?p=baloo.git&a=commitdiff&h=46e3ea7828c8066e75bec87ba0a19d5ef3bd700a ---- -Adapt to changes in KAboutData. ---- - - ---- a/src/file/kcm/kcm.cpp -+++ b/src/file/kcm/kcm.cpp -@@ -58,8 +58,8 @@ - : KCModule(parent, args) - { - KAboutData* about = new KAboutData( -- "kcm_baloofile", "kcm_baloofile", i18n("Configure Desktop Search"), -- "0.1", QString(), KAboutData::License_GPL, -+ "kcm_baloofile", i18n("Configure Desktop Search"), -+ "0.1", QString(), KAboutLicense::GPL, - i18n("Copyright 2007-2010 Sebastian Trüg")); - about->addAuthor(i18n("Sebastian Trüg"), QString(), "trueg@kde.org"); - about->addAuthor(i18n("Vishesh Handa"), QString(), "vhanda@kde.org"); - ---- a/src/file/main.cpp -+++ b/src/file/main.cpp -@@ -44,9 +44,9 @@ - lowerSchedulingPriority(); - lowerPriority(); - -- KAboutData aboutData("baloo_file", "baloo_file", i18n("Baloo File"), "0.1", -+ KAboutData aboutData("baloo_file", i18n("Baloo File"), "0.1", - i18n("An application to handle file metadata"), -- KAboutData::License_LGPL_V2); -+ KAboutLicense::LGPL_V2); - aboutData.addAuthor(i18n("Vishesh Handa"), i18n("Maintainer"), "me@vhanda.in", "http://vhanda.in"); - - KAboutData::setApplicationData(aboutData); - ---- a/src/tools/baloosearch/main.cpp -+++ b/src/tools/baloosearch/main.cpp -@@ -55,11 +55,10 @@ - int main(int argc, char* argv[]) - { - KAboutData aboutData("baloosearch", -- "baloosearch", - i18n("Baloo Search"), - "0.1", - i18n("Baloo Search - A debugging tool"), -- KAboutData::License_GPL, -+ KAboutLicense::GPL, - i18n("(c) 2013, Vishesh Handa")); - aboutData.addAuthor(i18n("Vishesh Handa"), i18n("Maintainer"), "me@vhanda.in"); - - ---- a/src/tools/balooshow/main.cpp -+++ b/src/tools/balooshow/main.cpp -@@ -46,11 +46,10 @@ - int main(int argc, char* argv[]) - { - KAboutData aboutData("balooshow", -- "balooshow", - i18n("Baloo Show"), - "0.1", - i18n("The Baloo data Viewer - A debugging tool"), -- KAboutData::License_GPL, -+ KAboutLicense::GPL, - i18n("(c) 2012, Vishesh Handa")); - aboutData.addAuthor(i18n("Vishesh Handa"), i18n("Maintainer"), "me@vhanda.in"); - diff --git a/kde/patch/calligra.patch b/kde/patch/calligra.patch deleted file mode 100644 index a0a45af..0000000 --- a/kde/patch/calligra.patch +++ /dev/null @@ -1,15 +0,0 @@ -# Fix build against Qt 5.11: -#cat $CWD/patch/calligra/calligra3_qt511.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - -# Fix build against Qt 5.13: -#cat $CWD/patch/calligra/calligra3_qt513.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - -# Fix build against poppler 0.71: -#cat $CWD/patch/calligra/calligra3_poppler-0.71.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - -# Fix build against poppler 0.72: -#cat $CWD/patch/calligra/calligra3_poppler-0.72.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - -# Fix build against poppler 0.73: -#cat $CWD/patch/calligra/calligra3_poppler-0.73.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - diff --git a/kde/patch/calligra/calligra3_poppler-0.71.patch b/kde/patch/calligra/calligra3_poppler-0.71.patch deleted file mode 100644 index 65284a3..0000000 --- a/kde/patch/calligra/calligra3_poppler-0.71.patch +++ /dev/null @@ -1,131 +0,0 @@ -diff --git a/filters/karbon/pdf/PdfImport.cpp b/filters/karbon/pdf/PdfImport.cpp -index 48b08dfa32d..e910dae0756 100644 ---- a/filters/karbon/pdf/PdfImport.cpp -+++ b/filters/karbon/pdf/PdfImport.cpp -@@ -88,9 +88,9 @@ KoFilter::ConversionStatus PdfImport::convert(const QByteArray& from, const QByt - SvgOutputDev * dev = new SvgOutputDev(m_chain->outputFile()); - if (dev->isOk()) { - int rotate = 0; -- GBool useMediaBox = gTrue; -- GBool crop = gFalse; -- GBool printing = gFalse; -+ bool useMediaBox = true; -+ bool crop = false; -+ bool printing = false; - pdfDoc->displayPages(dev, firstPage, lastPage, hDPI, vDPI, rotate, useMediaBox, crop, printing); - dev->dumpContent(); - } -diff --git a/filters/karbon/pdf/SvgOutputDev.cpp b/filters/karbon/pdf/SvgOutputDev.cpp -index 5692824bc45..43205170991 100644 ---- a/filters/karbon/pdf/SvgOutputDev.cpp -+++ b/filters/karbon/pdf/SvgOutputDev.cpp -@@ -39,7 +39,7 @@ class SvgOutputDev::Private - { - public: - Private(const QString &fname) -- : svgFile(fname), defs(0), body(0), state(gTrue) -+ : svgFile(fname), defs(0), body(0), state(true) - , brush(Qt::SolidPattern) {} - - ~Private() { -@@ -52,7 +52,7 @@ public: - QString defsData; - QTextStream * defs; - QTextStream * body; -- GBool state; -+ bool state; - QSizeF pageSize; - QPen pen; - QBrush brush; -@@ -62,7 +62,7 @@ SvgOutputDev::SvgOutputDev(const QString &fileName) - : d(new Private(fileName)) - { - if (! d->svgFile.open(QIODevice::WriteOnly)) { -- d->state = gFalse; -+ d->state = false; - return; - } - -@@ -75,24 +75,24 @@ SvgOutputDev::~SvgOutputDev() - delete d; - } - --GBool SvgOutputDev::isOk() -+bool SvgOutputDev::isOk() - { - return d->state; - } - --GBool SvgOutputDev::upsideDown() -+bool SvgOutputDev::upsideDown() - { -- return gTrue; -+ return true; - } - --GBool SvgOutputDev::useDrawChar() -+bool SvgOutputDev::useDrawChar() - { -- return gFalse; -+ return false; - } - --GBool SvgOutputDev::interpretType3Chars() -+bool SvgOutputDev::interpretType3Chars() - { -- return gFalse; -+ return false; - } - - void SvgOutputDev::startPage(int pageNum, GfxState *state, XRef */*xref*/) -@@ -480,7 +480,7 @@ void SvgOutputDev::drawString(GfxState * state, GooString * s) - - void SvgOutputDev::drawImage(GfxState *state, Object */*ref*/, Stream *str, - int width, int height, GfxImageColorMap *colorMap, -- int *maskColors, GBool /*inlineImg*/) -+ int *maskColors, bool /*inlineImg*/) - { - ImageStream * imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), colorMap->getBits()); - imgStr->reset(); -@@ -549,7 +549,7 @@ void SvgOutputDev::drawImage(GfxState *state, Object */*ref*/, Stream *str, - - void SvgOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, - int width, int height, GfxImageColorMap *colorMap, -- GBool /*interpolate*/, int *maskColors, GBool inlineImg) -+ bool /*interpolate*/, int *maskColors, bool inlineImg) - { - drawImage(state, ref, str, width, height, colorMap, maskColors, inlineImg); - } -diff --git a/filters/karbon/pdf/SvgOutputDev.h b/filters/karbon/pdf/SvgOutputDev.h -index 2a4490848bf..cdb1d4e43b1 100644 ---- a/filters/karbon/pdf/SvgOutputDev.h -+++ b/filters/karbon/pdf/SvgOutputDev.h -@@ -44,11 +44,11 @@ public: - explicit SvgOutputDev(const QString &fileName); - virtual ~SvgOutputDev(); - -- GBool isOk(); -+ bool isOk(); - -- virtual GBool upsideDown(); -- virtual GBool useDrawChar(); -- virtual GBool interpretType3Chars(); -+ virtual bool upsideDown(); -+ virtual bool useDrawChar(); -+ virtual bool interpretType3Chars(); - virtual void startPage(int pageNum, GfxState *state, XRef *xref); - virtual void endPage(); - -@@ -63,10 +63,10 @@ public: - // images - virtual void drawImage(GfxState *state, Object *ref, Stream *str, - int width, int height, GfxImageColorMap *colorMap, -- int *maskColors, GBool inlineImg); -+ int *maskColors, bool inlineImg); - virtual void drawImage(GfxState *state, Object *ref, Stream *str, - int width, int height, GfxImageColorMap *colorMap, -- GBool interpolate, int *maskColors, GBool inlineImg); -+ bool interpolate, int *maskColors, bool inlineImg); - - // styles - virtual void updateAll(GfxState *state); diff --git a/kde/patch/calligra/calligra3_poppler-0.72.patch b/kde/patch/calligra/calligra3_poppler-0.72.patch deleted file mode 100644 index 2cab98f..0000000 --- a/kde/patch/calligra/calligra3_poppler-0.72.patch +++ /dev/null @@ -1,29 +0,0 @@ -diff --git a/filters/karbon/pdf/SvgOutputDev.cpp b/filters/karbon/pdf/SvgOutputDev.cpp -index 80f01a5f76f..ea69228dbc1 100644 ---- a/filters/karbon/pdf/SvgOutputDev.cpp -+++ b/filters/karbon/pdf/SvgOutputDev.cpp -@@ -407,7 +407,7 @@ void SvgOutputDev::drawString(GfxState * state, const GooString * s) - - QString str; - -- const char * p = s->getCString(); -+ const char * p = s->c_str(); - int len = s->getLength(); - CharCode code; - Unicode *u = nullptr; -@@ -459,11 +459,11 @@ void SvgOutputDev::drawString(GfxState * state, const GooString * s) - *d->body << " y=\"" << y << "px\""; - - if (font && font->getFamily()) { -- *d->body << " font-family=\"" << QString::fromLatin1(font->getFamily()->getCString()) << "\""; -- //debugPdf << "font family:" << QString::fromLatin1( font->getFamily()->getCString() ); -+ *d->body << " font-family=\"" << QString::fromLatin1(font->getFamily()->c_str()) << "\""; -+ //debugPdf << "font family:" << QString::fromLatin1( font->getFamily()->c_str() ); - } else if (font && font->getName()) { -- *d->body << " font-family=\"" << QString::fromLatin1(font->getName()->getCString()) << "\""; -- //debugPdf << "font name:" << QString::fromLatin1( font->getName()->getCString() ); -+ *d->body << " font-family=\"" << QString::fromLatin1(font->getName()->c_str()) << "\""; -+ //debugPdf << "font name:" << QString::fromLatin1( font->getName()->c_str() ); - } - *d->body << " font-size=\"" << qMax(state->getFontSize(), state->getTransformedFontSize()) << "px\""; - diff --git a/kde/patch/calligra/calligra3_poppler-0.73.patch b/kde/patch/calligra/calligra3_poppler-0.73.patch deleted file mode 100644 index 86738de..0000000 --- a/kde/patch/calligra/calligra3_poppler-0.73.patch +++ /dev/null @@ -1,32 +0,0 @@ -From a1ddd91e6c354e8f0dda40f8a522053c3fa19c39 Mon Sep 17 00:00:00 2001 -From: Albert Astals Cid <aacid@kde.org> -Date: Tue, 15 Jan 2019 22:24:08 +0100 -Subject: [PATCH] Guchar -> unsigned char - -It was just a typdef and it's now gone ---- - filters/karbon/pdf/SvgOutputDev.cpp | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/filters/karbon/pdf/SvgOutputDev.cpp b/filters/karbon/pdf/SvgOutputDev.cpp -index 80f01a5f76f..1a5aa30bc40 100644 ---- a/filters/karbon/pdf/SvgOutputDev.cpp -+++ b/filters/karbon/pdf/SvgOutputDev.cpp -@@ -496,7 +496,7 @@ void SvgOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, - if (maskColors) { - for (int y = 0; y < height; y++) { - dest = (unsigned int *)(buffer + y * 4 * width); -- Guchar * pix = imgStr->getLine(); -+ unsigned char * pix = imgStr->getLine(); - colorMap->getRGBLine(pix, dest, width); - - for (int x = 0; x < width; x++) { -@@ -515,7 +515,7 @@ void SvgOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, - } else { - for (int y = 0; y < height; y++) { - dest = (unsigned int *)(buffer + y * 4 * width); -- Guchar * pix = imgStr->getLine(); -+ unsigned char * pix = imgStr->getLine(); - colorMap->getRGBLine(pix, dest, width); - } - diff --git a/kde/patch/calligra/calligra3_qt511.patch b/kde/patch/calligra/calligra3_qt511.patch deleted file mode 100644 index 0ddf0f2..0000000 --- a/kde/patch/calligra/calligra3_qt511.patch +++ /dev/null @@ -1,135 +0,0 @@ -From ee83e0f2c251072e47a2799619cdc79efe67e651 Mon Sep 17 00:00:00 2001 -From: David Faure <faure@kde.org> -Date: Tue, 3 Apr 2018 00:31:19 +0200 -Subject: Fix compilation with Qt 5.11 (missing include) - ---- - stage/part/KPrPresentationTool.cpp | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/stage/part/KPrPresentationTool.cpp b/stage/part/KPrPresentationTool.cpp -index ae743da..3007f91 100644 ---- a/stage/part/KPrPresentationTool.cpp -+++ b/stage/part/KPrPresentationTool.cpp -@@ -32,6 +32,7 @@ - #include <QDesktopServices> - #include <QUrl> - #include <QDBusConnection> -+#include <QFrame> - - #include <KoShape.h> - #include <KoShapeManager.h> ---- -From a7ebecb9fbee2190e649c44ed53f1299013baa30 Mon Sep 17 00:00:00 2001 -From: Andreas Sturmlechner <andreas.sturmlechner@gmail.com> -Date: Sun, 18 Mar 2018 11:56:57 +0100 -Subject: Fix build with Qt 5.11 (missing headers) - -Reviewers: #calligra:_3.0, anthonyfieroni, danders - -Reviewed By: #calligra:_3.0, anthonyfieroni, danders - -Subscribers: anthonyfieroni, danders - -Tags: #calligra:_3.0 - -Differential Revision: https://phabricator.kde.org/D11454 ---- - libs/widgets/KoCsvImportDialog.cpp | 1 + - libs/widgets/KoPageLayoutWidget.cpp | 2 ++ - plugins/chartshape/dialogs/TableEditorDialog.cpp | 1 + - plugins/formulashape/FormulaToolWidget.cpp | 1 + - sheets/dialogs/LayoutDialog.cpp | 1 + - words/part/dialogs/KWAnchoringProperties.cpp | 1 + - words/part/dialogs/KWRunAroundProperties.cpp | 2 ++ - 15 files changed, 18 insertions(+), 1 deletion(-) - -diff --git a/libs/widgets/KoCsvImportDialog.cpp b/libs/widgets/KoCsvImportDialog.cpp -index 0ffdcf6..cdca006 100644 ---- a/libs/widgets/KoCsvImportDialog.cpp -+++ b/libs/widgets/KoCsvImportDialog.cpp -@@ -21,6 +21,7 @@ - #include "KoCsvImportDialog.h" - - // Qt -+#include <QButtonGroup> - #include <QTextCodec> - #include <QTextStream> - -diff --git a/libs/widgets/KoPageLayoutWidget.cpp b/libs/widgets/KoPageLayoutWidget.cpp -index f91555c..a3816f9 100644 ---- a/libs/widgets/KoPageLayoutWidget.cpp -+++ b/libs/widgets/KoPageLayoutWidget.cpp -@@ -23,6 +23,8 @@ - - #include <KoUnit.h> - -+#include <QButtonGroup> -+ - class Q_DECL_HIDDEN KoPageLayoutWidget::Private - { - public: -diff --git a/plugins/chartshape/dialogs/TableEditorDialog.cpp b/plugins/chartshape/dialogs/TableEditorDialog.cpp -index c0d5136..d2a772e 100644 ---- a/plugins/chartshape/dialogs/TableEditorDialog.cpp -+++ b/plugins/chartshape/dialogs/TableEditorDialog.cpp -@@ -24,6 +24,7 @@ - - // Qt - #include <QAbstractItemModel> -+#include <QAction> - - // Calligra - #include <KoIcon.h> -diff --git a/plugins/formulashape/FormulaToolWidget.cpp b/plugins/formulashape/FormulaToolWidget.cpp -index ed10919..8f52177 100644 ---- a/plugins/formulashape/FormulaToolWidget.cpp -+++ b/plugins/formulashape/FormulaToolWidget.cpp -@@ -30,6 +30,7 @@ - #include <QWidgetAction> - #include <QTableWidget> - #include <QAction> -+#include <QHeaderView> - #include <QMenu> - - FormulaToolWidget::FormulaToolWidget( KoFormulaTool* tool, QWidget* parent ) -diff --git a/sheets/dialogs/LayoutDialog.cpp b/sheets/dialogs/LayoutDialog.cpp -index a0a9832..7d7db53 100644 ---- a/sheets/dialogs/LayoutDialog.cpp -+++ b/sheets/dialogs/LayoutDialog.cpp -@@ -36,6 +36,7 @@ - #include <math.h> - - #include <QIntValidator> -+#include <QButtonGroup> - #include <QCheckBox> - #include <QFrame> - #include <QLabel> -diff --git a/words/part/dialogs/KWAnchoringProperties.cpp b/words/part/dialogs/KWAnchoringProperties.cpp -index d64208c..bfddb3a 100644 ---- a/words/part/dialogs/KWAnchoringProperties.cpp -+++ b/words/part/dialogs/KWAnchoringProperties.cpp -@@ -35,6 +35,7 @@ - - #include <kundo2command.h> - -+#include <QButtonGroup> - #include <QComboBox> - - const int KWAnchoringProperties::vertRels[4][20] = { -diff --git a/words/part/dialogs/KWRunAroundProperties.cpp b/words/part/dialogs/KWRunAroundProperties.cpp -index e38599a..7e8b2d5 100644 ---- a/words/part/dialogs/KWRunAroundProperties.cpp -+++ b/words/part/dialogs/KWRunAroundProperties.cpp -@@ -28,6 +28,8 @@ - - #include <kundo2command.h> - -+#include <QButtonGroup> -+ - KWRunAroundProperties::KWRunAroundProperties(FrameConfigSharedState *state) - : m_state(state) - { --- -cgit v0.11.2 - diff --git a/kde/patch/calligra/calligra3_qt513.patch b/kde/patch/calligra/calligra3_qt513.patch deleted file mode 100644 index 987b353..0000000 --- a/kde/patch/calligra/calligra3_qt513.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0c5430697bdcf41a45046107b28014e40c49a11a Mon Sep 17 00:00:00 2001 -From: David Faure <faure@kde.org> -Date: Tue, 23 Jul 2019 13:02:34 +0200 -Subject: [PATCH] Fix compilation with Qt 5.13 (missing include) - ---- - sheets/plugins/calendar/CalendarToolWidget.cpp | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/sheets/plugins/calendar/CalendarToolWidget.cpp b/sheets/plugins/calendar/CalendarToolWidget.cpp -index b10b23022a2..0c5eeb68cf3 100644 ---- a/sheets/plugins/calendar/CalendarToolWidget.cpp -+++ b/sheets/plugins/calendar/CalendarToolWidget.cpp -@@ -30,6 +30,7 @@ - #include <kdatepicker.h> - - #include <QPushButton> -+#include <QDate> - - namespace Calligra - { - diff --git a/kde/patch/calligraplan/calligraplan.kcalcore.1.patch b/kde/patch/calligraplan/calligraplan.kcalcore.1.patch deleted file mode 100644 index dcbe903..0000000 --- a/kde/patch/calligraplan/calligraplan.kcalcore.1.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 3a01affd66f8dfdcc124e23595217f3ae5a09723 Mon Sep 17 00:00:00 2001 -From: Dag Andersen <danders@get2net.dk> -Date: Thu, 20 Jun 2019 10:52:00 +0200 -Subject: ICal: Adapt to api changes in KCalCore - ---- - CMakeLists.txt | 37 +++++++++++----------- - src/CMakeLists.txt | 4 +++ - .../filters/icalendar/export/icalendarexport.cpp | 5 +++ - 3 files changed, 27 insertions(+), 19 deletions(-) - -diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt -index 0dabbaf..49fa642 100644 ---- a/src/CMakeLists.txt -+++ b/src/CMakeLists.txt -@@ -75,6 +75,10 @@ if ("${KF5CalendarCore_VERSION}" VERSION_GREATER 5.6.40) - set(HAVE_QDATETIME_KCALCORE TRUE) - endif() - -+if ("${KF5CalendarCore_VERSION}" VERSION_GREATER 5.11.42) -+ set(KCALCORE_HAVE_NO_PERSION_PTR TRUE) -+endif() -+ - if (PLANCHARTDEBUG) - add_definitions(-DPLAN_CHART_DEBUG) - endif () -diff --git a/src/plugins/filters/icalendar/export/icalendarexport.cpp b/src/plugins/filters/icalendar/export/icalendarexport.cpp -index cd75598..ce29bfe 100644 ---- a/src/plugins/filters/icalendar/export/icalendarexport.cpp -+++ b/src/plugins/filters/icalendar/export/icalendarexport.cpp -@@ -141,8 +141,13 @@ void ICalendarExport::createTodos(KCalCore::Calendar::Ptr cal, const Node *node, - todo->setOrganizer(node->projectNode()->leader()); - } - if ( node->type() != Node::Type_Project && ! node->leader().isEmpty()) { -+#if KCALCORE_HAVE_NO_PERSION_PTR -+ KCalCore::Person p = KCalCore::Person::fromFullName(node->leader()); -+ KCalCore::Attendee::Ptr a(new KCalCore::Attendee(p.name(), p.email())); -+#else - KCalCore::Person::Ptr p = KCalCore::Person::fromFullName(node->leader()); - KCalCore::Attendee::Ptr a(new KCalCore::Attendee(p->name(), p->email())); -+#endif - a->setRole(KCalCore::Attendee::NonParticipant); - todo->addAttendee(a); - } --- -cgit v1.1 - diff --git a/kde/patch/calligraplan/calligraplan.kcalcore.2.patch b/kde/patch/calligraplan/calligraplan.kcalcore.2.patch deleted file mode 100644 index 5c118e1..0000000 --- a/kde/patch/calligraplan/calligraplan.kcalcore.2.patch +++ /dev/null @@ -1,85 +0,0 @@ -From a9eaf1c98ed408fd6e8897fa9e2f99ed17db1ebc Mon Sep 17 00:00:00 2001 -From: David Faure <faure@kde.org> -Date: Tue, 23 Jul 2019 12:26:17 +0200 -Subject: Port to KCalCore API changes - -The code is in #if 0, but I tested compilation of this in the calligra -stable branch: -https://commits.kde.org/calligra/2d484fda1b31a72659088a4bfce5c3708e923cb0 - -So you can use KCalCore again if you want :-) -It's turning into a KF5 framework so the API will be stable from now on. - -CCMAIL: danders@get2net.dk ---- - .../filters/icalendar/export/icalendarexport.cpp | 20 +++++++++++++++++--- - 1 file changed, 17 insertions(+), 3 deletions(-) - -diff --git a/src/plugins/filters/icalendar/export/icalendarexport.cpp b/src/plugins/filters/icalendar/export/icalendarexport.cpp -index b21320f..828b641 100644 ---- a/src/plugins/filters/icalendar/export/icalendarexport.cpp -+++ b/src/plugins/filters/icalendar/export/icalendarexport.cpp -@@ -35,6 +35,7 @@ - #include <kcalcore/attachment.h> - #include <kcalcore/icalformat.h> - #include <kcalcore/memorycalendar.h> -+#include <kcalcore_version.h> - - #include <QTextCodec> - #include <QByteArray> -@@ -355,14 +356,15 @@ void ICalendarExport::createTodos(KCalCore::Calendar::Ptr cal, const Node *node, - todo->setOrganizer(node->projectNode()->leader()); - } - if ( node->type() != Node::Type_Project && ! node->leader().isEmpty()) { --#if KCALCORE_HAVE_NO_PERSION_PTR -+#if KCALCORE_VERSION >= QT_VERSION_CHECK(5, 11, 80) - KCalCore::Person p = KCalCore::Person::fromFullName(node->leader()); -- KCalCore::Attendee::Ptr a(new KCalCore::Attendee(p.name(), p.email())); -+ KCalCore::Attendee a(p.name(), p.email()); -+ a.setRole(KCalCore::Attendee::NonParticipant); - #else - KCalCore::Person::Ptr p = KCalCore::Person::fromFullName(node->leader()); - KCalCore::Attendee::Ptr a(new KCalCore::Attendee(p->name(), p->email())); --#endif - a->setRole(KCalCore::Attendee::NonParticipant); -+#endif - todo->addAttendee(a); - } - DateTime st = node->startTime(id); -@@ -381,13 +383,21 @@ void ICalendarExport::createTodos(KCalCore::Calendar::Ptr cal, const Node *node, - const QList<Resource*> lst = task->requestedResources(); - foreach(const Resource *r, lst) { - if (r->type() == Resource::Type_Work) { -+#if KCALCORE_VERSION >= QT_VERSION_CHECK(5, 11, 80) -+ todo->addAttendee(KCalCore::Attendee(r->name(), r->email())); -+#else - todo->addAttendee(KCalCore::Attendee::Ptr(new KCalCore::Attendee(r->name(), r->email()))); -+#endif - } - } - } else { - foreach(const Resource *r, s->resources()) { - if (r->type() == Resource::Type_Work) { -+#if KCALCORE_VERSION >= QT_VERSION_CHECK(5, 11, 80) -+ todo->addAttendee(KCalCore::Attendee(r->name(), r->email())); -+#else - todo->addAttendee(KCalCore::Attendee::Ptr(new KCalCore::Attendee(r->name(), r->email()))); -+#endif - } - } - -@@ -398,7 +408,11 @@ void ICalendarExport::createTodos(KCalCore::Calendar::Ptr cal, const Node *node, - todo->setPercentComplete(task->completion().percentFinished()); - } - foreach(const Document *doc, node->documents().documents()) { -+#if KCALCORE_VERSION >= QT_VERSION_CHECK(5, 11, 80) -+ todo->addAttachment(KCalCore::Attachment(doc->url().url())); -+#else - todo->addAttachment(KCalCore::Attachment::Ptr(new KCalCore::Attachment(doc->url().url()))); -+#endif - } - if (! parent.isNull()) { - todo->setRelatedTo(parent->uid(), KCalCore::Incidence::RelTypeParent); --- -cgit v1.1 - diff --git a/kde/patch/calligraplan/calligraplan.kcalendarcore.patch b/kde/patch/calligraplan/calligraplan.kcalendarcore.patch deleted file mode 100644 index 42aa135..0000000 --- a/kde/patch/calligraplan/calligraplan.kcalendarcore.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 2f5505cf03ff865349d06e1d5c39007c52e7cd10 Mon Sep 17 00:00:00 2001 -From: Andreas Sturmlechner <asturm@gentoo.org> -Date: Fri, 16 Aug 2019 15:49:09 +0200 -Subject: [PATCH] Fix headers after kcalcore->kcalendercore rename happened - ---- - .../filters/icalendar/export/icalendarexport.cpp | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/src/plugins/filters/icalendar/export/icalendarexport.cpp b/src/plugins/filters/icalendar/export/icalendarexport.cpp -index bb6b097d..729d6e50 100644 ---- a/src/plugins/filters/icalendar/export/icalendarexport.cpp -+++ b/src/plugins/filters/icalendar/export/icalendarexport.cpp -@@ -31,11 +31,11 @@ - #include <kptdocuments.h> - #include "kptdebug.h" - --#include <kcalcore/attendee.h> --#include <kcalcore/attachment.h> --#include <kcalcore/icalformat.h> --#include <kcalcore/memorycalendar.h> --#include <kcalcore_version.h> -+#include <kcalendarcore/attendee.h> -+#include <kcalendarcore/attachment.h> -+#include <kcalendarcore/icalformat.h> -+#include <kcalendarcore/memorycalendar.h> -+#include <kcalcore_version.h> - - #include <QTextCodec> - #include <QByteArray> --- -2.22.1 - - diff --git a/kde/patch/calligraplan/calligraplan.missingheader.patch b/kde/patch/calligraplan/calligraplan.missingheader.patch deleted file mode 100644 index b5941c5..0000000 --- a/kde/patch/calligraplan/calligraplan.missingheader.patch +++ /dev/null @@ -1,25 +0,0 @@ -From fe36bf6f0dc1f0c1e927850dd78093cfe3b7aae2 Mon Sep 17 00:00:00 2001 -From: Albert Astals Cid <aacid@kde.org> -Date: Sun, 28 Jul 2019 00:07:33 +0200 -Subject: Fix compile on CI - -src/workpackage/view.h:148:31: error: field m_scheduleActions has incomplete type QMap<QAction*, KPlato::Schedule*> ---- - src/workpackage/view.h | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/workpackage/view.h b/src/workpackage/view.h -index 6cae32b..cd2fc4e 100644 ---- a/src/workpackage/view.h -+++ b/src/workpackage/view.h -@@ -24,6 +24,7 @@ - - #include <KoView.h> - -+#include <QMap> - #include <QStackedWidget> - - class QPrinter; --- -cgit v1.1 - diff --git a/kde/patch/calligraplan/calligraplan.qt-511.patch b/kde/patch/calligraplan/calligraplan.qt-511.patch deleted file mode 100644 index c0776fa..0000000 --- a/kde/patch/calligraplan/calligraplan.qt-511.patch +++ /dev/null @@ -1,125 +0,0 @@ -From f53805bdc108b608e40f217e6a78e7e4df4284f2 Mon Sep 17 00:00:00 2001 -From: Andreas Sturmlechner <andreas.sturmlechner@gmail.com> -Date: Sun, 18 Mar 2018 11:56:57 +0100 -Subject: [PATCH] Fix build with Qt 5.11 (missing headers) - -Reviewers: #calligra:_3.0 - -Tags: #calligra:_3.0 - -Differential Revision: https://phabricator.kde.org/D11454 ---- - plan/src/kptview.h | 1 + - plan/src/kptviewlist.cpp | 1 + - plan/src/libs/ui/kptaccountseditor.cpp | 1 + - plan/src/libs/ui/kptdocumentspanel.h | 1 + - plan/src/libs/ui/kptitemviewsettup.cpp | 2 +- - plan/src/libs/ui/kpttaskeditor.cpp | 1 + - plan/src/libs/ui/reportsgenerator/ReportsGeneratorView.cpp | 1 + - plan/src/libs/widgets/KoPageLayoutWidget.cpp | 2 ++ - 15 files changed, 18 insertions(+), 1 deletion(-) - -diff --git a/plan/src/kptview.h b/plan/src/kptview.h -index 44d11935e71..a98e55342db 100644 ---- a/plan/src/kptview.h -+++ b/plan/src/kptview.h -@@ -28,6 +28,7 @@ - #include "kptcontext.h" - #include "kptviewbase.h" - -+#include <QActionGroup> - #include <QDockWidget> - #include <QMap> - -diff --git a/plan/src/kptviewlist.cpp b/plan/src/kptviewlist.cpp -index f34e702e055..0e6db7b2ffe 100644 ---- a/plan/src/kptviewlist.cpp -+++ b/plan/src/kptviewlist.cpp -@@ -25,6 +25,7 @@ - #include <QStyle> - #include <QBrush> - #include <QContextMenuEvent> -+#include <QHeaderView> - #include <QMenu> - - #include <kmessagebox.h> -diff --git a/plan/src/libs/ui/kptaccountseditor.cpp b/plan/src/libs/ui/kptaccountseditor.cpp -index 7991fafd779..54e3a87c94f 100644 ---- a/plan/src/libs/ui/kptaccountseditor.cpp -+++ b/plan/src/libs/ui/kptaccountseditor.cpp -@@ -40,6 +40,7 @@ - #include <QContextMenuEvent> - #include <QMenu> - #include <QAction> -+#include <QHeaderView> - - #include <KLocalizedString> - #include <kactioncollection.h> -diff --git a/plan/src/libs/ui/kptdocumentspanel.h b/plan/src/libs/ui/kptdocumentspanel.h -index 00ea3af80b2..491cb1ebb86 100644 ---- a/plan/src/libs/ui/kptdocumentspanel.h -+++ b/plan/src/libs/ui/kptdocumentspanel.h -@@ -26,6 +26,7 @@ - - #include "kptdocuments.h" - -+#include <QModelIndexList> - #include <QWidget> - #include <kundo2qstack.h> - -diff --git a/plan/src/libs/ui/kptitemviewsettup.cpp b/plan/src/libs/ui/kptitemviewsettup.cpp -index d1c3b1fc157..7c97a070b9a 100644 ---- a/plan/src/libs/ui/kptitemviewsettup.cpp -+++ b/plan/src/libs/ui/kptitemviewsettup.cpp -@@ -25,9 +25,9 @@ - - #include "KoPageLayoutWidget.h" - -+#include <QHeaderView> - #include <QPushButton> - -- - namespace KPlato - { - -diff --git a/plan/src/libs/ui/kpttaskeditor.cpp b/plan/src/libs/ui/kpttaskeditor.cpp -index 21546118d33..91db5acbb18 100644 ---- a/plan/src/libs/ui/kpttaskeditor.cpp -+++ b/plan/src/libs/ui/kpttaskeditor.cpp -@@ -45,6 +45,7 @@ - #include <QVBoxLayout> - #include <QDragMoveEvent> - #include <QAction> -+#include <QHeaderView> - #include <QMenu> - - #include <kactionmenu.h> -diff --git a/plan/src/libs/ui/reportsgenerator/ReportsGeneratorView.cpp b/plan/src/libs/ui/reportsgenerator/ReportsGeneratorView.cpp -index 344ebc2b599..9146f06ab8c 100644 ---- a/plan/src/libs/ui/reportsgenerator/ReportsGeneratorView.cpp -+++ b/plan/src/libs/ui/reportsgenerator/ReportsGeneratorView.cpp -@@ -31,6 +31,7 @@ - #include <KFile> - - #include <QAction> -+#include <QHeaderView> - #include <QTreeView> - #include <QStandardItemModel> - #include <QModelIndex> -diff --git a/plan/src/libs/widgets/KoPageLayoutWidget.cpp b/plan/src/libs/widgets/KoPageLayoutWidget.cpp -index c9e17b748a9..b67e9848807 100644 ---- a/plan/src/libs/widgets/KoPageLayoutWidget.cpp -+++ b/plan/src/libs/widgets/KoPageLayoutWidget.cpp -@@ -23,6 +23,8 @@ - - #include <KoUnit.h> - -+#include <QButtonGroup> -+ - class Q_DECL_HIDDEN KoPageLayoutWidget::Private - { - public: --- -2.16.2 - - diff --git a/kde/patch/cantor.patch b/kde/patch/cantor.patch deleted file mode 100644 index 54f2b47..0000000 --- a/kde/patch/cantor.patch +++ /dev/null @@ -1,4 +0,0 @@ -# Fix build against KF 5.31.0 (repaired in 16.12.3): -#cat $CWD/patch/cantor/cantor_python.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } -#cat $CWD/patch/cantor/cantor_julia.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - diff --git a/kde/patch/cantor/cantor_julia.patch b/kde/patch/cantor/cantor_julia.patch deleted file mode 100644 index 5c381ca..0000000 --- a/kde/patch/cantor/cantor_julia.patch +++ /dev/null @@ -1,193 +0,0 @@ -Patch taken from: -https://gitweb.gentoo.org/repo/gentoo.git/plain/kde-apps/cantor/files/cantor-16.12.2-julia-kf-5.31.patch - -From 45322d9f58f50df3d4d5755d4199e579f6fd8646 Mon Sep 17 00:00:00 2001 -From: Andreas Sturmlechner <andreas.sturmlechner@gmail.com> -Date: Sat, 11 Feb 2017 22:46:35 +0100 -Subject: [PATCH] [julia] Fix build with -fno-operator-names - -REVIEW: 129942 ---- - src/backends/julia/juliaexpression.cpp | 6 +++--- - src/backends/julia/juliaextensions.cpp | 4 ++-- - src/backends/julia/juliahighlighter.cpp | 4 ++-- - src/backends/julia/juliakeywords.cpp | 10 +++++----- - src/backends/julia/juliaserver/juliaserver.cpp | 4 ++-- - src/backends/julia/juliaserver/main.cpp | 4 ++-- - src/backends/julia/juliasession.cpp | 4 ++-- - 7 files changed, 18 insertions(+), 18 deletions(-) - -diff --git a/src/backends/julia/juliaexpression.cpp b/src/backends/julia/juliaexpression.cpp -index 27cdd85..618200d 100644 ---- a/src/backends/julia/juliaexpression.cpp -+++ b/src/backends/julia/juliaexpression.cpp -@@ -40,7 +40,7 @@ void JuliaExpression::evaluate() - - // Plots integration - m_plot_filename.clear(); -- if (juliaSession->integratePlots() and checkPlotShowingCommands()) { -+ if (juliaSession->integratePlots() && checkPlotShowingCommands()) { - // Simply add plot saving command to the end of execution - QStringList inlinePlotFormats; - inlinePlotFormats << QLatin1String("svg"); -@@ -73,8 +73,8 @@ void JuliaExpression::finalize() - setResult(new Cantor::TextResult(juliaSession->getOutput())); - setStatus(Cantor::Expression::Error); - } else { -- if (not m_plot_filename.isEmpty() -- and QFileInfo(m_plot_filename).exists()) { -+ if (!m_plot_filename.isEmpty() -+ && QFileInfo(m_plot_filename).exists()) { - // If we have plot in result, show it - setResult( - new Cantor::ImageResult(QUrl::fromLocalFile(m_plot_filename))); -diff --git a/src/backends/julia/juliaextensions.cpp b/src/backends/julia/juliaextensions.cpp -index 4585c6f..ad5e3a9 100644 ---- a/src/backends/julia/juliaextensions.cpp -+++ b/src/backends/julia/juliaextensions.cpp -@@ -138,7 +138,7 @@ QString JuliaPlotExtension::plotFunction2d( - { - auto new_left = left; - auto new_right = right; -- if (new_left.isEmpty() and new_right.isEmpty()) { -+ if (new_left.isEmpty() && new_right.isEmpty()) { - new_left = QLatin1String("-1"); - new_right = QLatin1String("1"); - } else if (new_left.isEmpty()) { -@@ -165,7 +165,7 @@ QString JuliaPlotExtension::plotFunction3d( - { - - auto update_interval = [](Interval &interval) { -- if (interval.first.isEmpty() and interval.second.isEmpty()) { -+ if (interval.first.isEmpty() && interval.second.isEmpty()) { - interval.first = QLatin1String("-1"); - interval.second = QLatin1String("1"); - } else if (interval.first.isEmpty()) { -diff --git a/src/backends/julia/juliahighlighter.cpp b/src/backends/julia/juliahighlighter.cpp -index 4795361..f7d3622 100644 ---- a/src/backends/julia/juliahighlighter.cpp -+++ b/src/backends/julia/juliahighlighter.cpp -@@ -98,7 +98,7 @@ void JuliaHighlighter::highlightBlock(const QString &text) - while (pos < text.length()) { - // Trying to close current environments - bool triggered = false; -- for (int i = 0; i < flags.size() and not triggered; i++) { -+ for (int i = 0; i < flags.size() && !triggered; i++) { - int flag = flags[i]; - QRegExp ®exp = regexps_ends[i]; - QTextCharFormat &format = formats[i]; -@@ -144,7 +144,7 @@ void JuliaHighlighter::highlightBlock(const QString &text) - singleLineCommentStart.indexIn(text, pos); - - if (singleLineCommentStartPos != -1 -- and singleLineCommentStartPos < minPos) { -+ && singleLineCommentStartPos < minPos) { - // single line comment starts earlier - setFormat(pos, text.length() - pos, commentFormat()); - break; -diff --git a/src/backends/julia/juliakeywords.cpp b/src/backends/julia/juliakeywords.cpp -index f0a5846..8a0efec 100644 ---- a/src/backends/julia/juliakeywords.cpp -+++ b/src/backends/julia/juliakeywords.cpp -@@ -62,11 +62,11 @@ void JuliaKeywords::loadFromFile() - const QStringRef name = xml.name(); - - if (name == QLatin1String("keywords") -- or name == QLatin1String("variables") -- or name == QLatin1String("plot_showing_commands")) { -+ || name == QLatin1String("variables") -+ || name == QLatin1String("plot_showing_commands")) { - while (xml.readNextStartElement()) { - Q_ASSERT( -- xml.isStartElement() and xml.name() == QLatin1String("word") -+ xml.isStartElement() && xml.name() == QLatin1String("word") - ); - - const QString text = xml.readElementText(); -@@ -91,7 +91,7 @@ void JuliaKeywords::loadFromFile() - - void JuliaKeywords::addVariable(const QString &variable) - { -- if (not m_variables.contains(variable)) { -+ if (!m_variables.contains(variable)) { - m_variables << variable; - } - } -@@ -104,7 +104,7 @@ void JuliaKeywords::clearVariables() - - void JuliaKeywords::addFunction(const QString &function) - { -- if (not m_functions.contains(function)) { -+ if (!m_functions.contains(function)) { - m_functions << function; - } - } -diff --git a/src/backends/julia/juliaserver/juliaserver.cpp b/src/backends/julia/juliaserver/juliaserver.cpp -index c9beb4c..91585cf 100644 ---- a/src/backends/julia/juliaserver/juliaserver.cpp -+++ b/src/backends/julia/juliaserver/juliaserver.cpp -@@ -47,7 +47,7 @@ void JuliaServer::runJuliaCommand(const QString &command) - { - // Redirect stdout, stderr to temprorary files - QTemporaryFile output, error; -- if (not output.open() or not error.open()) { -+ if (!output.open() || !error.open()) { - qFatal("Unable to create temprorary files for stdout/stderr"); - return; - } -@@ -90,7 +90,7 @@ void JuliaServer::runJuliaCommand(const QString &command) - bool is_nothing = jl_unbox_bool( - static_cast<jl_value_t *>(jl_call2(equality, nothing, val)) - ); -- if (not is_nothing) { -+ if (!is_nothing) { - jl_static_show(JL_STDOUT, val); - } - m_was_exception = false; -diff --git a/src/backends/julia/juliaserver/main.cpp b/src/backends/julia/juliaserver/main.cpp -index ad7e4d9..11687ec 100644 ---- a/src/backends/julia/juliaserver/main.cpp -+++ b/src/backends/julia/juliaserver/main.cpp -@@ -30,7 +30,7 @@ int main(int argc, char *argv[]) - { - QCoreApplication app(argc, argv); - -- if (not QDBusConnection::sessionBus().isConnected()) { -+ if (!QDBusConnection::sessionBus().isConnected()) { - qWarning() << "Can't connect to the D-Bus session bus.\n" - "To start it, run: eval `dbus-launch --auto-syntax`"; - return 1; -@@ -39,7 +39,7 @@ int main(int argc, char *argv[]) - const QString &serviceName = - QString::fromLatin1("org.kde.Cantor.Julia-%1").arg(app.applicationPid()); - -- if (not QDBusConnection::sessionBus().registerService(serviceName)) { -+ if (!QDBusConnection::sessionBus().registerService(serviceName)) { - qWarning() << QDBusConnection::sessionBus().lastError().message(); - return 2; - } -diff --git a/src/backends/julia/juliasession.cpp b/src/backends/julia/juliasession.cpp -index 425e6cb..9183e11 100644 ---- a/src/backends/julia/juliasession.cpp -+++ b/src/backends/julia/juliasession.cpp -@@ -86,7 +86,7 @@ void JuliaSession::login() - QDBusConnection::sessionBus() - ); - -- if (not m_interface->isValid()) { -+ if (!m_interface->isValid()) { - qWarning() << QDBusConnection::sessionBus().lastError().message(); - return; - } -@@ -213,7 +213,7 @@ bool JuliaSession::getWasException() - { - const QDBusReply<bool> &reply = - m_interface->call(QLatin1String("getWasException")); -- return reply.isValid() and reply.value(); -+ return reply.isValid() && reply.value(); - } - - void JuliaSession::listVariables() --- -2.10.2 - diff --git a/kde/patch/cantor/cantor_python.patch b/kde/patch/cantor/cantor_python.patch deleted file mode 100644 index aa2b398..0000000 --- a/kde/patch/cantor/cantor_python.patch +++ /dev/null @@ -1,31 +0,0 @@ -Patch taken from: -https://gitweb.gentoo.org/repo/gentoo.git/plain/kde-apps/cantor/files/cantor-16.12.2-python-kf-5.31.patch - -commit 4b8ef6bed62daced90c7826985650c2a813d2996 -Author: Jonathan Riddell <jr@jriddell.org> -Date: Wed Feb 8 14:56:48 2017 +0000 - - remove modern C++ use to fix compile with current KDE policy - -diff --git a/src/backends/python/pythonhighlighter.cpp b/src/backends/python/pythonhighlighter.cpp -index 4064524..87b10dd 100644 ---- a/src/backends/python/pythonhighlighter.cpp -+++ b/src/backends/python/pythonhighlighter.cpp -@@ -87,7 +87,7 @@ void PythonHighlighter::highlightBlock(const QString &text) - while (pos < text.length()) { - // Trying to close current environments - bool triggered = false; -- for (int i = 0; i < flags.size() and not triggered; i++) { -+ for (int i = 0; i < flags.size() && !triggered; i++) { - int flag = flags[i]; - QRegExp ®exp = regexps[i]; - QTextCharFormat &format = formats[i]; -@@ -126,7 +126,7 @@ void PythonHighlighter::highlightBlock(const QString &text) - singleLineCommentStart.indexIn(text, pos); - - if (singleLineCommentStartPos != -1 -- and singleLineCommentStartPos < minPos) { -+ && singleLineCommentStartPos < minPos) { - setFormat(pos, text.length() - pos, commentFormat()); - break; - } else if (minRegexp) { diff --git a/kde/patch/digikam.patch b/kde/patch/digikam.patch deleted file mode 100644 index 8f50ec2..0000000 --- a/kde/patch/digikam.patch +++ /dev/null @@ -1,12 +0,0 @@ -# Fix compilation with clang. -# Fixed in digikam 5.5.0. -#cat $CWD/patch/digikam/digikam_clang_fix.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - -# Fix linking issue, backport from git master: -#cd core -# cat $CWD/patch/digikam/digikam_databasemodel.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } -#cd - - -# Fix crashes with imagemagick 7 (fixed post digikam 6.4.0): -cat $CWD/patch/digikam/digikam_imagemagick7.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - diff --git a/kde/patch/digikam/digikam_clang_fix.patch b/kde/patch/digikam/digikam_clang_fix.patch deleted file mode 100644 index a4d77b0..0000000 --- a/kde/patch/digikam/digikam_clang_fix.patch +++ /dev/null @@ -1,38 +0,0 @@ -Taken from: -http://pkgs.fedoraproject.org/cgit/rpms/digikam.git/ -And added and extra '/core/' path componenent. - -From 86cd0d1d89c8b4d13f06dc8a353bdd99f13c4758 Mon Sep 17 00:00:00 2001 -From: Gilles Caulier <caulier.gilles@gmail.com> -Date: Wed, 18 Jan 2017 10:13:20 +0100 -Subject: [PATCH 2/2] Fix compilation with clang - ---- - libs/dmetadata/metaengine_p.cpp | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/core/libs/dmetadata/metaengine_p.cpp b/core/libs/dmetadata/metaengine_p.cpp -index 2c83b58..2b44e06 100644 ---- a/core/libs/dmetadata/metaengine_p.cpp -+++ b/core/libs/dmetadata/metaengine_p.cpp -@@ -49,7 +49,7 @@ extern "C" - #include "digikam_debug.h" - - // Pragma directives to reduce warnings from Exiv2. --#if not defined(__APPLE__) && defined(__GNUC__) -+#if !defined(__APPLE__) && defined(__GNUC__) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" - #endif -@@ -723,7 +723,7 @@ void MetaEngine::Private::loadSidecarData(Exiv2::Image::AutoPtr xmpsidecar) - } // namespace Digikam - - // Restore warnings --#if not defined(__APPLE__) && defined(__GNUC__) -+#if !defined(__APPLE__) && defined(__GNUC__) - #pragma GCC diagnostic pop - #endif - --- -2.9.3 - diff --git a/kde/patch/digikam/digikam_databasemodel.patch b/kde/patch/digikam/digikam_databasemodel.patch deleted file mode 100644 index 8b2fff7..0000000 --- a/kde/patch/digikam/digikam_databasemodel.patch +++ /dev/null @@ -1,13337 +0,0 @@ -From 7e00441c257e7e9e5dc5ab983fc06046fb72b0c5 Mon Sep 17 00:00:00 2001 -From: Gilles Caulier <caulier.gilles@gmail.com> -Date: Sat, 22 Jul 2017 15:46:08 +0200 -Subject: fix broken linking stage under MacOS with macports. move database - models into libdigikamdatabase. Let's others model in place to be included - into libdigikamcore - ---- - libs/database/CMakeLists.txt | 16 +- - libs/database/models/imagefiltermodel.cpp | 1116 ++++++++++++++++++ - libs/database/models/imagefiltermodel.h | 299 +++++ - libs/database/models/imagefiltermodelpriv.cpp | 258 ++++ - libs/database/models/imagefiltermodelpriv.h | 159 +++ - libs/database/models/imagefiltermodelthreads.cpp | 40 + - libs/database/models/imagefiltermodelthreads.h | 100 ++ - libs/database/models/imagefiltersettings.cpp | 952 +++++++++++++++ - libs/database/models/imagefiltersettings.h | 349 ++++++ - libs/database/models/imagelistmodel.cpp | 70 ++ - libs/database/models/imagelistmodel.h | 63 + - libs/database/models/imagemodel.cpp | 1368 ++++++++++++++++++++++ - libs/database/models/imagemodel.h | 364 ++++++ - libs/database/models/imagesortsettings.cpp | 400 +++++++ - libs/database/models/imagesortsettings.h | 225 ++++ - libs/database/models/imagethumbnailmodel.cpp | 323 +++++ - libs/database/models/imagethumbnailmodel.h | 140 +++ - libs/database/models/imageversionsmodel.cpp | 183 +++ - libs/database/models/imageversionsmodel.h | 75 ++ - libs/models/CMakeLists.txt | 15 +- - libs/models/imagefiltermodel.cpp | 1116 ------------------ - libs/models/imagefiltermodel.h | 299 ----- - libs/models/imagefiltermodelpriv.cpp | 258 ---- - libs/models/imagefiltermodelpriv.h | 159 --- - libs/models/imagefiltermodelthreads.cpp | 40 - - libs/models/imagefiltermodelthreads.h | 100 -- - libs/models/imagefiltersettings.cpp | 952 --------------- - libs/models/imagefiltersettings.h | 349 ------ - libs/models/imagelistmodel.cpp | 70 -- - libs/models/imagelistmodel.h | 63 - - libs/models/imagemodel.cpp | 1368 ---------------------- - libs/models/imagemodel.h | 364 ------ - libs/models/imagesortsettings.cpp | 400 ------- - libs/models/imagesortsettings.h | 225 ---- - libs/models/imagethumbnailmodel.cpp | 323 ----- - libs/models/imagethumbnailmodel.h | 140 --- - libs/models/imageversionsmodel.cpp | 183 --- - libs/models/imageversionsmodel.h | 75 -- - 38 files changed, 6499 insertions(+), 6500 deletions(-) - create mode 100644 libs/database/models/imagefiltermodel.cpp - create mode 100644 libs/database/models/imagefiltermodel.h - create mode 100644 libs/database/models/imagefiltermodelpriv.cpp - create mode 100644 libs/database/models/imagefiltermodelpriv.h - create mode 100644 libs/database/models/imagefiltermodelthreads.cpp - create mode 100644 libs/database/models/imagefiltermodelthreads.h - create mode 100644 libs/database/models/imagefiltersettings.cpp - create mode 100644 libs/database/models/imagefiltersettings.h - create mode 100644 libs/database/models/imagelistmodel.cpp - create mode 100644 libs/database/models/imagelistmodel.h - create mode 100644 libs/database/models/imagemodel.cpp - create mode 100644 libs/database/models/imagemodel.h - create mode 100644 libs/database/models/imagesortsettings.cpp - create mode 100644 libs/database/models/imagesortsettings.h - create mode 100644 libs/database/models/imagethumbnailmodel.cpp - create mode 100644 libs/database/models/imagethumbnailmodel.h - create mode 100644 libs/database/models/imageversionsmodel.cpp - create mode 100644 libs/database/models/imageversionsmodel.h - delete mode 100644 libs/models/imagefiltermodel.cpp - delete mode 100644 libs/models/imagefiltermodel.h - delete mode 100644 libs/models/imagefiltermodelpriv.cpp - delete mode 100644 libs/models/imagefiltermodelpriv.h - delete mode 100644 libs/models/imagefiltermodelthreads.cpp - delete mode 100644 libs/models/imagefiltermodelthreads.h - delete mode 100644 libs/models/imagefiltersettings.cpp - delete mode 100644 libs/models/imagefiltersettings.h - delete mode 100644 libs/models/imagelistmodel.cpp - delete mode 100644 libs/models/imagelistmodel.h - delete mode 100644 libs/models/imagemodel.cpp - delete mode 100644 libs/models/imagemodel.h - delete mode 100644 libs/models/imagesortsettings.cpp - delete mode 100644 libs/models/imagesortsettings.h - delete mode 100644 libs/models/imagethumbnailmodel.cpp - delete mode 100644 libs/models/imagethumbnailmodel.h - delete mode 100644 libs/models/imageversionsmodel.cpp - delete mode 100644 libs/models/imageversionsmodel.h - -diff --git a/libs/database/CMakeLists.txt b/libs/database/CMakeLists.txt -index 7d05536..a431a36 100644 ---- a/libs/database/CMakeLists.txt -+++ b/libs/database/CMakeLists.txt -@@ -13,6 +13,18 @@ endif (POLICY CMP0063) - # Boost uses operator names (and, not, ...) - string(REPLACE "-fno-operator-names" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - -+set(libdatabasemodels_SRCS -+ models/imagemodel.cpp -+ models/imagefiltermodel.cpp -+ models/imagefiltermodelpriv.cpp -+ models/imagefiltermodelthreads.cpp -+ models/imagefiltersettings.cpp -+ models/imagelistmodel.cpp -+ models/imagesortsettings.cpp -+ models/imagethumbnailmodel.cpp -+ models/imageversionsmodel.cpp -+) -+ - set(libdatabasecore_SRCS - server/databaseserverstarter.cpp - server/databaseservererror.cpp -@@ -152,10 +164,10 @@ if(ENABLE_DBUS) - include_directories($<TARGET_PROPERTY:Qt5::DBus,INTERFACE_INCLUDE_DIRECTORIES>) - endif() - --add_library(digikamdatabase_src OBJECT ${digikamdatabase_LIB_SRCS}) -+add_library(digikamdatabase_src OBJECT ${digikamdatabase_LIB_SRCS} ${libdatabasemodels_SRCS}) - add_library(digikamdatabasemain_src OBJECT ${libdatabaseutils_SRCS} ${libimgqsort_SRCS}) - add_library(digikamdatabasecore_src OBJECT ${libdatabasecore_SRCS}) --add_library(digikamdatabase SHARED $<TARGET_OBJECTS:digikamdatabase_src> $<TARGET_OBJECTS:digikamdatabasemodels_src>) -+add_library(digikamdatabase $<TARGET_OBJECTS:digikamdatabase_src>) - - generate_export_header(digikamdatabase - BASE_NAME digikam_database -diff --git a/libs/database/models/imagefiltermodel.cpp b/libs/database/models/imagefiltermodel.cpp -new file mode 100644 -index 0000000..3d57e05 ---- /dev/null -+++ b/libs/database/models/imagefiltermodel.cpp -@@ -0,0 +1,1116 @@ -+/* ============================================================ -+ * -+ * This file is a part of digiKam project -+ * http://www.digikam.org -+ * -+ * Date : 2009-03-05 -+ * Description : Qt item model for database entries -+ * -+ * Copyright (C) 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -+ * Copyright (C) 2011-2017 by Gilles Caulier <caulier dot gilles at gmail dot com> -+ * Copyright (C) 2010 by Andi Clemens <andi dot clemens at gmail dot com> -+ * Copyright (C) 2011 by Michael G. Hansen <mike at mghansen dot de> -+ * Copyright (C) 2014 by Mohamed Anwer <m dot anwer at gmx dot com> -+ * -+ * This program is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU General -+ * Public License as published by the Free Software Foundation; -+ * either version 2, or (at your option) -+ * any later version. -+ * -+ * This program 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 General Public License for more details. -+ * -+ * ============================================================ */ -+ -+#include "imagefiltermodel.h" -+#include "imagefiltermodelpriv.h" -+#include "imagefiltermodelthreads.h" -+ -+// Local includes -+ -+#include "digikam_debug.h" -+#include "coredbaccess.h" -+#include "coredbchangesets.h" -+#include "coredbwatch.h" -+#include "imageinfolist.h" -+#include "imagemodel.h" -+ -+namespace Digikam -+{ -+ -+ImageSortFilterModel::ImageSortFilterModel(QObject* parent) -+ : DCategorizedSortFilterProxyModel(parent), m_chainedModel(0) -+{ -+} -+ -+void ImageSortFilterModel::setSourceImageModel(ImageModel* source) -+{ -+ if (m_chainedModel) -+ { -+ m_chainedModel->setSourceImageModel(source); -+ } -+ else -+ { -+ setDirectSourceImageModel(source); -+ } -+} -+ -+void ImageSortFilterModel::setSourceFilterModel(ImageSortFilterModel* source) -+{ -+ if (source) -+ { -+ ImageModel* const model = sourceImageModel(); -+ -+ if (model) -+ { -+ source->setSourceImageModel(model); -+ } -+ } -+ -+ m_chainedModel = source; -+ setSourceModel(source); -+} -+ -+void ImageSortFilterModel::setDirectSourceImageModel(ImageModel* model) -+{ -+ setSourceModel(model); -+} -+ -+void ImageSortFilterModel::setSourceModel(QAbstractItemModel* model) -+{ -+ // made it protected, only setSourceImageModel is public -+ DCategorizedSortFilterProxyModel::setSourceModel(model); -+} -+ -+ImageModel* ImageSortFilterModel::sourceImageModel() const -+{ -+ if (m_chainedModel) -+ { -+ return m_chainedModel->sourceImageModel(); -+ } -+ -+ return static_cast<ImageModel*>(sourceModel()); -+} -+ -+ImageSortFilterModel* ImageSortFilterModel::sourceFilterModel() const -+{ -+ return m_chainedModel; -+} -+ -+ImageFilterModel* ImageSortFilterModel::imageFilterModel() const -+{ -+ // reimplemented in ImageFilterModel -+ if (m_chainedModel) -+ { -+ return m_chainedModel->imageFilterModel(); -+ } -+ -+ return 0; -+} -+ -+QModelIndex ImageSortFilterModel::mapToSourceImageModel(const QModelIndex& index) const -+{ -+ if (m_chainedModel) -+ { -+ return m_chainedModel->mapToSourceImageModel(mapToSource(index)); -+ } -+ -+ return mapToSource(index); -+} -+ -+QModelIndex ImageSortFilterModel::mapFromSourceImageModel(const QModelIndex& albummodel_index) const -+{ -+ if (m_chainedModel) -+ { -+ return mapFromSource(m_chainedModel->mapFromSourceImageModel(albummodel_index)); -+ } -+ -+ return mapFromSource(albummodel_index); -+} -+ -+ -+QModelIndex ImageSortFilterModel::mapFromDirectSourceToSourceImageModel(const QModelIndex& sourceModel_index) const -+{ -+ if (m_chainedModel) -+ { -+ return m_chainedModel->mapToSourceImageModel(sourceModel_index); -+ } -+ return sourceModel_index; -+} -+ -+// -------------- Convenience mappers ------------------------------------------------------------------- -+ -+QList<QModelIndex> ImageSortFilterModel::mapListToSource(const QList<QModelIndex>& indexes) const -+{ -+ QList<QModelIndex> sourceIndexes; -+ foreach(const QModelIndex& index, indexes) -+ { -+ sourceIndexes << mapToSourceImageModel(index); -+ } -+ return sourceIndexes; -+} -+ -+QList<QModelIndex> ImageSortFilterModel::mapListFromSource(const QList<QModelIndex>& sourceIndexes) const -+{ -+ QList<QModelIndex> indexes; -+ foreach(const QModelIndex& index, sourceIndexes) -+ { -+ indexes << mapFromSourceImageModel(index); -+ } -+ return indexes; -+} -+ -+ImageInfo ImageSortFilterModel::imageInfo(const QModelIndex& index) const -+{ -+ return sourceImageModel()->imageInfo(mapToSourceImageModel(index)); -+} -+ -+qlonglong ImageSortFilterModel::imageId(const QModelIndex& index) const -+{ -+ return sourceImageModel()->imageId(mapToSourceImageModel(index)); -+} -+ -+QList<ImageInfo> ImageSortFilterModel::imageInfos(const QList<QModelIndex>& indexes) const -+{ -+ QList<ImageInfo> infos; -+ ImageModel* const model = sourceImageModel(); -+ -+ foreach(const QModelIndex& index, indexes) -+ { -+ infos << model->imageInfo(mapToSourceImageModel(index)); -+ } -+ -+ return infos; -+} -+ -+QList<qlonglong> ImageSortFilterModel::imageIds(const QList<QModelIndex>& indexes) const -+{ -+ QList<qlonglong> ids; -+ ImageModel* const model = sourceImageModel(); -+ -+ foreach(const QModelIndex& index, indexes) -+ { -+ ids << model->imageId(mapToSourceImageModel(index)); -+ } -+ -+ return ids; -+} -+ -+QModelIndex ImageSortFilterModel::indexForPath(const QString& filePath) const -+{ -+ return mapFromSourceImageModel(sourceImageModel()->indexForPath(filePath)); -+} -+ -+QModelIndex ImageSortFilterModel::indexForImageInfo(const ImageInfo& info) const -+{ -+ return mapFromSourceImageModel(sourceImageModel()->indexForImageInfo(info)); -+} -+ -+QModelIndex ImageSortFilterModel::indexForImageId(qlonglong id) const -+{ -+ return mapFromSourceImageModel(sourceImageModel()->indexForImageId(id)); -+} -+ -+QList<ImageInfo> ImageSortFilterModel::imageInfosSorted() const -+{ -+ QList<ImageInfo> infos; -+ const int size = rowCount(); -+ ImageModel* const model = sourceImageModel(); -+ -+ for (int i=0; i<size; ++i) -+ { -+ infos << model->imageInfo(mapToSourceImageModel(index(i, 0))); -+ } -+ -+ return infos; -+} -+ -+// -------------------------------------------------------------------------------------------- -+ -+ImageFilterModel::ImageFilterModel(QObject* parent) -+ : ImageSortFilterModel(parent), -+ d_ptr(new ImageFilterModelPrivate) -+{ -+ d_ptr->init(this); -+} -+ -+ImageFilterModel::ImageFilterModel(ImageFilterModelPrivate& dd, QObject* parent) -+ : ImageSortFilterModel(parent), -+ d_ptr(&dd) -+{ -+ d_ptr->init(this); -+} -+ -+ImageFilterModel::~ImageFilterModel() -+{ -+ Q_D(ImageFilterModel); -+ delete d; -+} -+ -+void ImageFilterModel::setDirectSourceImageModel(ImageModel* sourceModel) -+{ -+ Q_D(ImageFilterModel); -+ -+ if (d->imageModel) -+ { -+ d->imageModel->unsetPreprocessor(d); -+ disconnect(d->imageModel, SIGNAL(modelReset()), -+ this, SLOT(slotModelReset())); -+ slotModelReset(); -+ } -+ -+ d->imageModel = sourceModel; -+ -+ if (d->imageModel) -+ { -+ d->imageModel->setPreprocessor(d); -+ -+ connect(d->imageModel, SIGNAL(preprocess(QList<ImageInfo>,QList<QVariant>)), -+ d, SLOT(preprocessInfos(QList<ImageInfo>,QList<QVariant>))); -+ -+ connect(d->imageModel, SIGNAL(processAdded(QList<ImageInfo>,QList<QVariant>)), -+ d, SLOT(processAddedInfos(QList<ImageInfo>,QList<QVariant>))); -+ -+ connect(d, SIGNAL(reAddImageInfos(QList<ImageInfo>,QList<QVariant>)), -+ d->imageModel, SLOT(reAddImageInfos(QList<ImageInfo>,QList<QVariant>))); -+ -+ connect(d, SIGNAL(reAddingFinished()), -+ d->imageModel, SLOT(reAddingFinished())); -+ -+ connect(d->imageModel, SIGNAL(modelReset()), -+ this, SLOT(slotModelReset())); -+ -+ connect(d->imageModel, SIGNAL(imageChange(ImageChangeset,QItemSelection)), -+ this, SLOT(slotImageChange(ImageChangeset))); -+ -+ connect(d->imageModel, SIGNAL(imageTagChange(ImageTagChangeset,QItemSelection)), -+ this, SLOT(slotImageTagChange(ImageTagChangeset))); -+ } -+ -+ setSourceModel(d->imageModel); -+} -+ -+QVariant ImageFilterModel::data(const QModelIndex& index, int role) const -+{ -+ Q_D(const ImageFilterModel); -+ -+ if (!index.isValid()) -+ { -+ return QVariant(); -+ } -+ -+ switch (role) -+ { -+ // Attention: This breaks should there ever be another filter model between this and the ImageModel -+ -+ case DCategorizedSortFilterProxyModel::CategoryDisplayRole: -+ return categoryIdentifier(d->imageModel->imageInfoRef(mapToSource(index))); -+ case CategorizationModeRole: -+ return d->sorter.categorizationMode; -+ case SortOrderRole: -+ return d->sorter.sortRole; -+ //case CategoryCountRole: -+ // return categoryCount(d->imageModel->imageInfoRef(mapToSource(index))); -+ case CategoryAlbumIdRole: -+ return d->imageModel->imageInfoRef(mapToSource(index)).albumId(); -+ case CategoryFormatRole: -+ return d->imageModel->imageInfoRef(mapToSource(index)).format(); -+ case GroupIsOpenRole: -+ return d->groupFilter.isAllOpen() || -+ d->groupFilter.isOpen(d->imageModel->imageInfoRef(mapToSource(index)).id()); -+ case ImageFilterModelPointerRole: -+ return QVariant::fromValue(const_cast<ImageFilterModel*>(this)); -+ } -+ -+ return DCategorizedSortFilterProxyModel::data(index, role); -+} -+ -+ImageFilterModel* ImageFilterModel::imageFilterModel() const -+{ -+ return const_cast<ImageFilterModel*>(this); -+} -+ -+DatabaseFields::Set ImageFilterModel::suggestedWatchFlags() const -+{ -+ DatabaseFields::Set watchFlags; -+ watchFlags |= DatabaseFields::Name | DatabaseFields::FileSize | DatabaseFields::ModificationDate; -+ watchFlags |= DatabaseFields::Rating | DatabaseFields::CreationDate | DatabaseFields::Orientation | -+ DatabaseFields::Width | DatabaseFields::Height; -+ watchFlags |= DatabaseFields::Comment; -+ watchFlags |= DatabaseFields::ImageRelations; -+ return watchFlags; -+} -+ -+// -------------- Filter settings -------------- -+ -+void ImageFilterModel::setDayFilter(const QList<QDateTime>& days) -+{ -+ Q_D(ImageFilterModel); -+ d->filter.setDayFilter(days); -+ setImageFilterSettings(d->filter); -+} -+ -+void ImageFilterModel::setTagFilter(const QList<int>& includedTags, const QList<int>& excludedTags, -+ ImageFilterSettings::MatchingCondition matchingCond, -+ bool showUnTagged, const QList<int>& clTagIds, const QList<int>& plTagIds) -+{ -+ Q_D(ImageFilterModel); -+ d->filter.setTagFilter(includedTags, excludedTags, matchingCond, showUnTagged, clTagIds, plTagIds); -+ setImageFilterSettings(d->filter); -+} -+ -+void ImageFilterModel::setRatingFilter(int rating, ImageFilterSettings::RatingCondition ratingCond, bool isUnratedExcluded) -+{ -+ Q_D(ImageFilterModel); -+ d->filter.setRatingFilter(rating, ratingCond, isUnratedExcluded); -+ setImageFilterSettings(d->filter); -+} -+ -+void ImageFilterModel::setUrlWhitelist(const QList<QUrl> urlList, const QString& id) -+{ -+ Q_D(ImageFilterModel); -+ d->filter.setUrlWhitelist(urlList, id); -+ setImageFilterSettings(d->filter); -+} -+ -+void ImageFilterModel::setIdWhitelist(const QList<qlonglong>& idList, const QString& id) -+{ -+ Q_D(ImageFilterModel); -+ d->filter.setIdWhitelist(idList, id); -+ setImageFilterSettings(d->filter); -+} -+ -+void ImageFilterModel::setMimeTypeFilter(int mimeTypeFilter) -+{ -+ Q_D(ImageFilterModel); -+ d->filter.setMimeTypeFilter(mimeTypeFilter); -+ setImageFilterSettings(d->filter); -+} -+ -+void ImageFilterModel::setGeolocationFilter(const ImageFilterSettings::GeolocationCondition& condition) -+{ -+ Q_D(ImageFilterModel); -+ d->filter.setGeolocationFilter(condition); -+ setImageFilterSettings(d->filter); -+} -+ -+void ImageFilterModel::setTextFilter(const SearchTextFilterSettings& settings) -+{ -+ Q_D(ImageFilterModel); -+ d->filter.setTextFilter(settings); -+ setImageFilterSettings(d->filter); -+} -+ -+void ImageFilterModel::setImageFilterSettings(const ImageFilterSettings& settings) -+{ -+ Q_D(ImageFilterModel); -+ -+ { -+ QMutexLocker lock(&d->mutex); -+ d->version++; -+ d->filter = settings; -+ d->filterCopy = settings; -+ d->versionFilterCopy = d->versionFilter; -+ d->groupFilterCopy = d->groupFilter; -+ -+ d->needPrepareComments = settings.isFilteringByText(); -+ d->needPrepareTags = settings.isFilteringByTags(); -+ d->needPrepareGroups = true; -+ d->needPrepare = d->needPrepareComments || d->needPrepareTags || d->needPrepareGroups; -+ -+ d->hasOneMatch = false; -+ d->hasOneMatchForText = false; -+ } -+ -+ d->filterResults.clear(); -+ -+ //d->categoryCountHashInt.clear(); -+ //d->categoryCountHashString.clear(); -+ if (d->imageModel) -+ { -+ d->infosToProcess(d->imageModel->imageInfos()); -+ } -+ -+ emit filterSettingsChanged(settings); -+} -+ -+void ImageFilterModel::setVersionManagerSettings(const VersionManagerSettings& settings) -+{ -+ Q_D(ImageFilterModel); -+ d->versionFilter.setVersionManagerSettings(settings); -+ setVersionImageFilterSettings(d->versionFilter); -+} -+ -+void ImageFilterModel::setExceptionList(const QList<qlonglong>& idList, const QString& id) -+{ -+ Q_D(ImageFilterModel); -+ d->versionFilter.setExceptionList(idList, id); -+ setVersionImageFilterSettings(d->versionFilter); -+} -+ -+void ImageFilterModel::setVersionImageFilterSettings(const VersionImageFilterSettings& settings) -+{ -+ Q_D(ImageFilterModel); -+ d->versionFilter = settings; -+ slotUpdateFilter(); -+} -+ -+bool ImageFilterModel::isGroupOpen(qlonglong group) const -+{ -+ Q_D(const ImageFilterModel); -+ return d->groupFilter.isOpen(group); -+} -+ -+bool ImageFilterModel::isAllGroupsOpen() const -+{ -+ Q_D(const ImageFilterModel); -+ return d->groupFilter.isAllOpen(); -+} -+ -+void ImageFilterModel::setGroupOpen(qlonglong group, bool open) -+{ -+ Q_D(ImageFilterModel); -+ d->groupFilter.setOpen(group, open); -+ setGroupImageFilterSettings(d->groupFilter); -+} -+ -+void ImageFilterModel::toggleGroupOpen(qlonglong group) -+{ -+ setGroupOpen(group, !isGroupOpen(group)); -+} -+ -+void ImageFilterModel::setAllGroupsOpen(bool open) -+{ -+ Q_D(ImageFilterModel); -+ d->groupFilter.setAllOpen(open); -+ setGroupImageFilterSettings(d->groupFilter); -+} -+ -+void ImageFilterModel::setGroupImageFilterSettings(const GroupImageFilterSettings& settings) -+{ -+ Q_D(ImageFilterModel); -+ d->groupFilter = settings; -+ slotUpdateFilter(); -+} -+ -+void ImageFilterModel::slotUpdateFilter() -+{ -+ Q_D(ImageFilterModel); -+ setImageFilterSettings(d->filter); -+} -+ -+ImageFilterSettings ImageFilterModel::imageFilterSettings() const -+{ -+ Q_D(const ImageFilterModel); -+ return d->filter; -+} -+ -+ImageSortSettings ImageFilterModel::imageSortSettings() const -+{ -+ Q_D(const ImageFilterModel); -+ return d->sorter; -+} -+ -+VersionImageFilterSettings ImageFilterModel::versionImageFilterSettings() const -+{ -+ Q_D(const ImageFilterModel); -+ return d->versionFilter; -+} -+ -+GroupImageFilterSettings ImageFilterModel::groupImageFilterSettings() const -+{ -+ Q_D(const ImageFilterModel); -+ return d->groupFilter; -+} -+ -+void ImageFilterModel::slotModelReset() -+{ -+ Q_D(ImageFilterModel); -+ { -+ QMutexLocker lock(&d->mutex); -+ // discard all packages on the way that are marked as send out for re-add -+ d->lastDiscardVersion = d->version; -+ d->sentOutForReAdd = 0; -+ // discard all packages on the way -+ d->version++; -+ d->sentOut = 0; -+ -+ d->hasOneMatch = false; -+ d->hasOneMatchForText = false; -+ } -+ d->filterResults.clear(); -+} -+ -+bool ImageFilterModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const -+{ -+ Q_D(const ImageFilterModel); -+ -+ if (source_parent.isValid()) -+ { -+ return false; -+ } -+ -+ qlonglong id = d->imageModel->imageId(source_row); -+ QHash<qlonglong, bool>::const_iterator it = d->filterResults.constFind(id); -+ -+ if (it != d->filterResults.constEnd()) -+ { -+ return it.value(); -+ } -+ -+ // usually done in thread and cache, unless source model changed -+ ImageInfo info = d->imageModel->imageInfo(source_row); -+ bool match = d->filter.matches(info); -+ match = match ? d->versionFilter.matches(info) : false; -+ -+ return match ? d->groupFilter.matches(info) : false; -+} -+ -+void ImageFilterModel::setSendImageInfoSignals(bool sendSignals) -+{ -+ if (sendSignals) -+ { -+ connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), -+ this, SLOT(slotRowsInserted(QModelIndex,int,int))); -+ -+ connect(this, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), -+ this, SLOT(slotRowsAboutToBeRemoved(QModelIndex,int,int))); -+ } -+ else -+ { -+ disconnect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), -+ this, SLOT(slotRowsInserted(QModelIndex,int,int))); -+ -+ disconnect(this, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), -+ this, SLOT(slotRowsAboutToBeRemoved(QModelIndex,int,int))); -+ } -+} -+ -+void ImageFilterModel::slotRowsInserted(const QModelIndex& /*parent*/, int start, int end) -+{ -+ QList<ImageInfo> infos; -+ -+ for (int i=start; i<=end; ++i) -+ { -+ infos << imageInfo(index(i, 0)); -+ } -+ -+ emit imageInfosAdded(infos); -+} -+ -+void ImageFilterModel::slotRowsAboutToBeRemoved(const QModelIndex& /*parent*/, int start, int end) -+{ -+ QList<ImageInfo> infos; -+ -+ for (int i=start; i<=end; ++i) -+ { -+ infos << imageInfo(index(i, 0)); -+ } -+ -+ emit imageInfosAboutToBeRemoved(infos); -+} -+ -+// -------------- Threaded preparation & filtering -------------- -+ -+void ImageFilterModel::addPrepareHook(ImageFilterModelPrepareHook* hook) -+{ -+ Q_D(ImageFilterModel); -+ QMutexLocker lock(&d->mutex); -+ d->prepareHooks << hook; -+} -+ -+void ImageFilterModel::removePrepareHook(ImageFilterModelPrepareHook* hook) -+{ -+ Q_D(ImageFilterModel); -+ QMutexLocker lock(&d->mutex); -+ d->prepareHooks.removeAll(hook); -+} -+ -+void ImageFilterModelPreparer::process(ImageFilterModelTodoPackage package) -+{ -+ if (!checkVersion(package)) -+ { -+ emit discarded(package); -+ return; -+ } -+ -+ // get thread-local copy -+ bool needPrepareTags, needPrepareComments, needPrepareGroups; -+ QList<ImageFilterModelPrepareHook*> prepareHooks; -+ { -+ QMutexLocker lock(&d->mutex); -+ needPrepareTags = d->needPrepareTags; -+ needPrepareComments = d->needPrepareComments; -+ needPrepareGroups = d->needPrepareGroups; -+ prepareHooks = d->prepareHooks; -+ } -+ -+ //TODO: Make efficient!! -+ if (needPrepareComments) -+ { -+ foreach(const ImageInfo& info, package.infos) -+ { -+ info.comment(); -+ } -+ } -+ -+ if (!checkVersion(package)) -+ { -+ emit discarded(package); -+ return; -+ } -+ -+ // The downside of QVector: At some point, we may need a QList for an API. -+ // Nonetheless, QList and ImageInfo is fast. We could as well -+ // reimplement ImageInfoList to ImageInfoVector (internally with templates?) -+ ImageInfoList infoList; -+ -+ if (needPrepareTags || needPrepareGroups) -+ { -+ infoList = package.infos.toList(); -+ } -+ -+ if (needPrepareTags) -+ { -+ infoList.loadTagIds(); -+ } -+ -+ if (needPrepareGroups) -+ { -+ infoList.loadGroupImageIds(); -+ } -+ -+ foreach(ImageFilterModelPrepareHook* hook, prepareHooks) -+ { -+ hook->prepare(package.infos); -+ } -+ -+ emit processed(package); -+} -+ -+void ImageFilterModelFilterer::process(ImageFilterModelTodoPackage package) -+{ -+ if (!checkVersion(package)) -+ { -+ emit discarded(package); -+ return; -+ } -+ -+ // get thread-local copy -+ ImageFilterSettings localFilter; -+ VersionImageFilterSettings localVersionFilter; -+ GroupImageFilterSettings localGroupFilter; -+ bool hasOneMatch; -+ bool hasOneMatchForText; -+ { -+ QMutexLocker lock(&d->mutex); -+ localFilter = d->filterCopy; -+ localVersionFilter = d->versionFilterCopy; -+ localGroupFilter = d->groupFilterCopy; -+ hasOneMatch = d->hasOneMatch; -+ hasOneMatchForText = d->hasOneMatchForText; -+ } -+ -+ // Actual filtering. The variants to spare checking hasOneMatch over and over again. -+ if (hasOneMatch && hasOneMatchForText) -+ { -+ foreach(const ImageInfo& info, package.infos) -+ { -+ package.filterResults[info.id()] = localFilter.matches(info) && -+ localVersionFilter.matches(info) && -+ localGroupFilter.matches(info); -+ } -+ } -+ else if (hasOneMatch) -+ { -+ bool matchForText; -+ -+ foreach(const ImageInfo& info, package.infos) -+ { -+ package.filterResults[info.id()] = localFilter.matches(info, &matchForText) && -+ localVersionFilter.matches(info) && -+ localGroupFilter.matches(info); -+ -+ if (matchForText) -+ { -+ hasOneMatchForText = true; -+ } -+ } -+ } -+ else -+ { -+ bool result, matchForText; -+ -+ foreach(const ImageInfo& info, package.infos) -+ { -+ result = localFilter.matches(info, &matchForText) && -+ localVersionFilter.matches(info) && -+ localGroupFilter.matches(info); -+ package.filterResults[info.id()] = result; -+ -+ if (result) -+ { -+ hasOneMatch = true; -+ } -+ -+ if (matchForText) -+ { -+ hasOneMatchForText = true; -+ } -+ } -+ } -+ -+ if (checkVersion(package)) -+ { -+ QMutexLocker lock(&d->mutex); -+ d->hasOneMatch = hasOneMatch; -+ d->hasOneMatchForText = hasOneMatchForText; -+ } -+ -+ emit processed(package); -+} -+ -+// -------------- Sorting and Categorization ------------------------------------------------------- -+ -+void ImageFilterModel::setImageSortSettings(const ImageSortSettings& sorter) -+{ -+ Q_D(ImageFilterModel); -+ d->sorter = sorter; -+ setCategorizedModel(d->sorter.categorizationMode != ImageSortSettings::NoCategories); -+ invalidate(); -+} -+ -+void ImageFilterModel::setCategorizationMode(ImageSortSettings::CategorizationMode mode) -+{ -+ Q_D(ImageFilterModel); -+ d->sorter.setCategorizationMode(mode); -+ setImageSortSettings(d->sorter); -+} -+ -+void ImageFilterModel::setCategorizationSortOrder(ImageSortSettings::SortOrder order) -+{ -+ Q_D(ImageFilterModel); -+ d->sorter.setCategorizationSortOrder(order); -+ setImageSortSettings(d->sorter); -+} -+ -+void ImageFilterModel::setSortRole(ImageSortSettings::SortRole role) -+{ -+ Q_D(ImageFilterModel); -+ d->sorter.setSortRole(role); -+ setImageSortSettings(d->sorter); -+} -+ -+void ImageFilterModel::setSortOrder(ImageSortSettings::SortOrder order) -+{ -+ Q_D(ImageFilterModel); -+ d->sorter.setSortOrder(order); -+ setImageSortSettings(d->sorter); -+} -+ -+void ImageFilterModel::setStringTypeNatural(bool natural) -+{ -+ Q_D(ImageFilterModel); -+ d->sorter.setStringTypeNatural(natural); -+ setImageSortSettings(d->sorter); -+} -+ -+int ImageFilterModel::compareCategories(const QModelIndex& left, const QModelIndex& right) const -+{ -+ // source indexes -+ Q_D(const ImageFilterModel); -+ -+ if (!d->sorter.isCategorized()) -+ { -+ return 0; -+ } -+ -+ if (!left.isValid() || !right.isValid()) -+ { -+ return -1; -+ } -+ -+ const ImageInfo& leftInfo = d->imageModel->imageInfoRef(left); -+ const ImageInfo& rightInfo = d->imageModel->imageInfoRef(right); -+ -+ // Check grouping -+ qlonglong leftGroupImageId = leftInfo.groupImageId(); -+ qlonglong rightGroupImageId = rightInfo.groupImageId(); -+ -+ return compareInfosCategories(leftGroupImageId == -1 ? leftInfo : ImageInfo(leftGroupImageId), -+ rightGroupImageId == -1 ? rightInfo : ImageInfo(rightGroupImageId)); -+} -+ -+bool ImageFilterModel::subSortLessThan(const QModelIndex& left, const QModelIndex& right) const -+{ -+ // source indexes -+ Q_D(const ImageFilterModel); -+ -+ if (!left.isValid() || !right.isValid()) -+ { -+ return true; -+ } -+ -+ if (left == right) -+ { -+ return false; -+ } -+ -+ const ImageInfo& leftInfo = d->imageModel->imageInfoRef(left); -+ const ImageInfo& rightInfo = d->imageModel->imageInfoRef(right); -+ -+ if (leftInfo == rightInfo) -+ { -+ return d->sorter.lessThan(left.data(ImageModel::ExtraDataRole), right.data(ImageModel::ExtraDataRole)); -+ } -+ -+ // Check grouping -+ qlonglong leftGroupImageId = leftInfo.groupImageId(); -+ qlonglong rightGroupImageId = rightInfo.groupImageId(); -+ -+ // Either no grouping (-1), or same group image, or same image -+ if (leftGroupImageId == rightGroupImageId) -+ { -+ return infosLessThan(leftInfo, rightInfo); -+ } -+ -+ // We have grouping to handle -+ -+ // Is one grouped on the other? Sort behind leader. -+ if (leftGroupImageId == rightInfo.id()) -+ { -+ return false; -+ } -+ if (rightGroupImageId == leftInfo.id()) -+ { -+ return true; -+ } -+ -+ // Use the group leader for sorting -+ return infosLessThan(leftGroupImageId == -1 ? leftInfo : ImageInfo(leftGroupImageId), -+ rightGroupImageId == -1 ? rightInfo : ImageInfo(rightGroupImageId)); -+} -+ -+int ImageFilterModel::compareInfosCategories(const ImageInfo& left, const ImageInfo& right) const -+{ -+ // Note: reimplemented in ImageAlbumFilterModel -+ Q_D(const ImageFilterModel); -+ return d->sorter.compareCategories(left, right); -+} -+ -+// Feel free to optimize. QString::number is 3x slower. -+static inline QString fastNumberToString(int id) -+{ -+ const int size = sizeof(int) * 2; -+ char c[size+1]; -+ c[size] = '\0'; -+ char* p = c; -+ int number = id; -+ -+ for (int i=0; i<size; ++i) -+ { -+ *p = 'a' + (number & 0xF); -+ number >>= 4; -+ ++p; -+ } -+ -+ return QString::fromLatin1(c); -+} -+ -+QString ImageFilterModel::categoryIdentifier(const ImageInfo& i) const -+{ -+ Q_D(const ImageFilterModel); -+ -+ if (!d->sorter.isCategorized()) -+ { -+ return QString(); -+ } -+ -+ qlonglong groupedImageId = i.groupImageId(); -+ ImageInfo info = groupedImageId == -1 ? i : ImageInfo(groupedImageId); -+ -+ switch (d->sorter.categorizationMode) -+ { -+ case ImageSortSettings::NoCategories: -+ return QString(); -+ case ImageSortSettings::OneCategory: -+ return QString(); -+ case ImageSortSettings::CategoryByAlbum: -+ return fastNumberToString(info.albumId()); -+ case ImageSortSettings::CategoryByFormat: -+ return info.format(); -+ default: -+ return QString(); -+ } -+} -+ -+bool ImageFilterModel::infosLessThan(const ImageInfo& left, const ImageInfo& right) const -+{ -+ Q_D(const ImageFilterModel); -+ return d->sorter.lessThan(left, right); -+} -+ -+// -------------- Watching changes ----------------------------------------------------------------- -+ -+void ImageFilterModel::slotImageTagChange(const ImageTagChangeset& changeset) -+{ -+ Q_D(ImageFilterModel); -+ -+ if (!d->imageModel || d->imageModel->isEmpty()) -+ { -+ return; -+ } -+ -+ // already scheduled to re-filter? -+ if (d->updateFilterTimer->isActive()) -+ { -+ return; -+ } -+ -+ // do we filter at all? -+ if (!d->versionFilter.isFilteringByTags() && -+ !d->filter.isFilteringByTags() && -+ !d->filter.isFilteringByText()) -+ { -+ return; -+ } -+ -+ // is one of our images affected? -+ foreach(const qlonglong& id, changeset.ids()) -+ { -+ // if one matching image id is found, trigger a refresh -+ if (d->imageModel->hasImage(id)) -+ { -+ d->updateFilterTimer->start(); -+ return; -+ } -+ } -+} -+ -+void ImageFilterModel::slotImageChange(const ImageChangeset& changeset) -+{ -+ Q_D(ImageFilterModel); -+ -+ if (!d->imageModel || d->imageModel->isEmpty()) -+ { -+ return; -+ } -+ -+ // already scheduled to re-filter? -+ if (d->updateFilterTimer->isActive()) -+ { -+ return; -+ } -+ -+ // is one of the values affected that we filter or sort by? -+ DatabaseFields::Set set = changeset.changes(); -+ bool sortAffected = (set & d->sorter.watchFlags()); -+ bool filterAffected = (set & d->filter.watchFlags()) || (set & d->groupFilter.watchFlags()); -+ -+ if (!sortAffected && !filterAffected) -+ { -+ return; -+ } -+ -+ // is one of our images affected? -+ bool imageAffected = false; -+ -+ foreach(const qlonglong& id, changeset.ids()) -+ { -+ // if one matching image id is found, trigger a refresh -+ if (d->imageModel->hasImage(id)) -+ { -+ imageAffected = true; -+ break; -+ } -+ } -+ -+ if (!imageAffected) -+ { -+ return; -+ } -+ -+ if (filterAffected) -+ { -+ d->updateFilterTimer->start(); -+ } -+ else -+ { -+ invalidate(); // just resort, reuse filter results -+ } -+} -+ -+// ------------------------------------------------------------------------------------------------------- -+ -+NoDuplicatesImageFilterModel::NoDuplicatesImageFilterModel(QObject* parent) -+ : ImageSortFilterModel(parent) -+{ -+} -+ -+bool NoDuplicatesImageFilterModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const -+{ -+ QModelIndex index = sourceModel()->index(source_row, 0, source_parent); -+ -+ if (index.data(ImageModel::ExtraDataDuplicateCount).toInt() <= 1) -+ { -+ return true; -+ } -+ -+ QModelIndex previousIndex = sourceModel()->index(source_row - 1, 0, source_parent); -+ -+ if (!previousIndex.isValid()) -+ { -+ return true; -+ } -+ -+ if (sourceImageModel()->imageId(mapFromDirectSourceToSourceImageModel(index)) == sourceImageModel()->imageId(mapFromDirectSourceToSourceImageModel(previousIndex))) -+ { -+ return false; -+ } -+ return true; -+} -+ -+/* -+void NoDuplicatesImageFilterModel::setSourceModel(QAbstractItemModel* model) -+{ -+ if (sourceModel()) -+ { -+ } -+ -+ ImageSortFilterModel::setSourceModel(model); -+ -+ if (sourceModel()) -+ { -+ connect(sourceModel(), SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), -+ this, SLOT(slotRowsAboutToBeRemoved(QModelIndex,int,int))); -+ } -+} -+ -+void NoDuplicatesImageFilterModel::slotRowsAboutToBeRemoved(const QModelIndex& parent, int begin, int end) -+{ -+ bool needInvalidate = false; -+ -+ for (int i = begin; i<=end; ++i) -+ { -+ QModelIndex index = sourceModel()->index(i, 0, parent); -+ -+ // filtered out by us? -+ if (!mapFromSource(index).isValid()) -+ { -+ continue; -+ } -+ -+ QModelIndex sourceIndex = mapFromDirectSourceToSourceImageModel(index); -+ qlonglong id = sourceImageModel()->imageId(sourceIndex); -+ -+ if (sourceImageModel()->numberOfIndexesForImageId(id) > 1) -+ { -+ needInvalidate = true; -+ } -+ } -+}*/ -+ -+} // namespace Digikam -diff --git a/libs/database/models/imagefiltermodel.h b/libs/database/models/imagefiltermodel.h -new file mode 100644 -index 0000000..d131b3e ---- /dev/null -+++ b/libs/database/models/imagefiltermodel.h -@@ -0,0 +1,299 @@ -+/* ============================================================ -+ * -+ * This file is a part of digiKam project -+ * http://www.digikam.org -+ * -+ * Date : 2009-03-05 -+ * Description : Qt item model for database entries -+ * -+ * Copyright (C) 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -+ * Copyright (C) 2011 by Gilles Caulier <caulier dot gilles at gmail dot com> -+ * Copyright (C) 2010 by Andi Clemens <andi dot clemens at gmail dot com> -+ * Copyright (C) 2011 by Michael G. Hansen <mike at mghansen dot de> -+ * Copyright (C) 2014 by Mohamed Anwer <m dot anwer at gmx dot com> -+ * -+ * This program is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU General -+ * Public License as published by the Free Software Foundation; -+ * either version 2, or (at your option) -+ * any later version. -+ * -+ * This program 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 General Public License for more details. -+ * -+ * ============================================================ */ -+ -+#ifndef IMAGEFILTERMODEL_H -+#define IMAGEFILTERMODEL_H -+ -+// Local includes -+ -+#include "dcategorizedsortfilterproxymodel.h" -+#include "textfilter.h" -+#include "imagefiltersettings.h" -+#include "imagemodel.h" -+#include "imagesortsettings.h" -+#include "digikam_export.h" -+ -+namespace Digikam -+{ -+ -+class ImageChangeset; -+class ImageFilterModel; -+class ImageTagChangeset; -+ -+class DIGIKAM_DATABASE_EXPORT ImageFilterModelPrepareHook -+{ -+public: -+ -+ virtual ~ImageFilterModelPrepareHook() {}; -+ virtual void prepare(const QVector<ImageInfo>& infos) = 0; -+}; -+ -+// ----------------------------------------------------------------------------------------------- -+ -+class DIGIKAM_DATABASE_EXPORT ImageSortFilterModel : public DCategorizedSortFilterProxyModel -+{ -+ Q_OBJECT -+ -+public: -+ -+ explicit ImageSortFilterModel(QObject* parent = 0); -+ -+ void setSourceImageModel(ImageModel* model); -+ ImageModel* sourceImageModel() const; -+ -+ void setSourceFilterModel(ImageSortFilterModel* model); -+ ImageSortFilterModel* sourceFilterModel() const; -+ -+ QModelIndex mapToSourceImageModel(const QModelIndex& index) const; -+ QModelIndex mapFromSourceImageModel(const QModelIndex& imagemodel_index) const; -+ QModelIndex mapFromDirectSourceToSourceImageModel(const QModelIndex& sourceModel_index) const; -+ -+ /// Convenience methods mapped to ImageModel. -+ /// Mentioned indexes returned come from the source image model. -+ QList<QModelIndex> mapListToSource(const QList<QModelIndex>& indexes) const; -+ QList<QModelIndex> mapListFromSource(const QList<QModelIndex>& sourceIndexes) const; -+ -+ ImageInfo imageInfo(const QModelIndex& index) const; -+ qlonglong imageId(const QModelIndex& index) const; -+ QList<ImageInfo> imageInfos(const QList<QModelIndex>& indexes) const; -+ QList<qlonglong> imageIds(const QList<QModelIndex>& indexes) const; -+ -+ QModelIndex indexForPath(const QString& filePath) const; -+ QModelIndex indexForImageInfo(const ImageInfo& info) const; -+ QModelIndex indexForImageId(qlonglong id) const; -+ -+ /** Returns a list of all image infos, sorted according to this model. -+ * If you do not need a sorted list, use ImageModel's imageInfos() method. -+ */ -+ QList<ImageInfo> imageInfosSorted() const; -+ -+ /// Returns this, any chained ImageFilterModel, or 0. -+ virtual ImageFilterModel* imageFilterModel() const; -+ -+protected: -+ -+ /// Reimplement if needed. Called only when model shall be set as (direct) sourceModel. -+ virtual void setDirectSourceImageModel(ImageModel* model); -+ -+ // made protected -+ virtual void setSourceModel(QAbstractItemModel* model); -+ -+protected: -+ -+ ImageSortFilterModel* m_chainedModel; -+}; -+ -+// ----------------------------------------------------------------------------------------------- -+ -+class DIGIKAM_DATABASE_EXPORT ImageFilterModel : public ImageSortFilterModel -+{ -+ Q_OBJECT -+ -+public: -+ -+ enum ImageFilterModelRoles -+ { -+ /// Returns the current categorization mode -+ CategorizationModeRole = ImageModel::FilterModelRoles + 1, -+ /// Returns the current sort order -+ SortOrderRole = ImageModel::FilterModelRoles + 2, -+ // / Returns the number of items in the index' category -+ //CategoryCountRole = ImageModel::FilterModelRoles + 3, -+ /// Returns the id of the PAlbum of the index which is used for category -+ CategoryAlbumIdRole = ImageModel::FilterModelRoles + 3, -+ /// Returns the format of the index which is used for category -+ CategoryFormatRole = ImageModel::FilterModelRoles + 4, -+ /// Returns true if the given image is a group leader, and the group is opened -+ GroupIsOpenRole = ImageModel::FilterModelRoles + 5, -+ ImageFilterModelPointerRole = ImageModel::FilterModelRoles + 50 -+ }; -+ -+public: -+ -+ explicit ImageFilterModel(QObject* parent = 0); -+ ~ImageFilterModel(); -+ -+ /** Add a hook to get added images for preparation tasks before they are added in the model */ -+ void addPrepareHook(ImageFilterModelPrepareHook* hook); -+ void removePrepareHook(ImageFilterModelPrepareHook* hook); -+ -+ /** Returns a set of DatabaseFields suggested to set as watch flags on the source ImageModel. -+ * The contained flags will be those that this model can sort or filter by. */ -+ DatabaseFields::Set suggestedWatchFlags() const; -+ -+ ImageFilterSettings imageFilterSettings() const; -+ VersionImageFilterSettings versionImageFilterSettings() const; -+ GroupImageFilterSettings groupImageFilterSettings() const; -+ ImageSortSettings imageSortSettings() const; -+ -+ // group is identified by the id of its group leader -+ bool isGroupOpen(qlonglong group) const; -+ bool isAllGroupsOpen() const; -+ -+ /// Enables sending imageInfosAdded and imageInfosAboutToBeRemoved -+ void setSendImageInfoSignals(bool sendSignals); -+ -+ virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; -+ virtual ImageFilterModel* imageFilterModel() const; -+ -+public Q_SLOTS: -+ -+ /** Changes the current version image filter settings and refilters. */ -+ void setVersionImageFilterSettings(const VersionImageFilterSettings& settings); -+ -+ /** Changes the current version image filter settings and refilters. */ -+ void setGroupImageFilterSettings(const GroupImageFilterSettings& settings); -+ -+ /** Adjust the current ImageFilterSettings. -+ * Equivalent to retrieving the current filter settings, adjusting the parameter -+ * and calling setImageFilterSettings. -+ * Provided for convenience. -+ * It is encouraged to use setImageFilterSettings if you change more than one -+ * parameter at a time. -+ */ -+ void setDayFilter(const QList<QDateTime>& days); -+ void setTagFilter(const QList<int>& includedTags, const QList<int>& excludedTags, -+ ImageFilterSettings::MatchingCondition matchingCond, bool showUnTagged, -+ const QList<int>& clTagIds, const QList<int>& plTagIds); -+ void setRatingFilter(int rating, ImageFilterSettings::RatingCondition ratingCond, bool isUnratedExcluded); -+ void setMimeTypeFilter(int mimeTypeFilter); -+ void setGeolocationFilter(const ImageFilterSettings::GeolocationCondition& condition); -+ void setTextFilter(const SearchTextFilterSettings& settings); -+ -+ void setCategorizationMode(ImageSortSettings::CategorizationMode mode); -+ void setCategorizationSortOrder(ImageSortSettings::SortOrder order); -+ void setSortRole(ImageSortSettings::SortRole role); -+ void setSortOrder(ImageSortSettings::SortOrder order); -+ void setStringTypeNatural(bool natural); -+ void setUrlWhitelist(const QList<QUrl> urlList, const QString& id); -+ void setIdWhitelist(const QList<qlonglong>& idList, const QString& id); -+ -+ void setVersionManagerSettings(const VersionManagerSettings& settings); -+ void setExceptionList(const QList<qlonglong>& idlist, const QString& id); -+ -+ void setGroupOpen(qlonglong group, bool open); -+ void toggleGroupOpen(qlonglong group); -+ void setAllGroupsOpen(bool open); -+ -+ /** Changes the current image filter settings and refilters. */ -+ virtual void setImageFilterSettings(const ImageFilterSettings& settings); -+ -+ /** Changes the current image sort settings and resorts. */ -+ virtual void setImageSortSettings(const ImageSortSettings& settings); -+ -+Q_SIGNALS: -+ -+ /// Signals that the set filter matches at least one index -+ void filterMatches(bool matches); -+ -+ /** Signals that the set text filter matches at least one entry. -+ If no text filter is set, this signal is emitted -+ with 'false' when filterMatches() is emitted. -+ */ -+ void filterMatchesForText(bool matchesByText); -+ -+ /** Emitted when the filter settings have been changed -+ (the model may not yet have been updated) -+ */ -+ void filterSettingsChanged(const ImageFilterSettings& settings); -+ -+ /** These signals need to be explicitly enabled with setSendImageInfoSignals() -+ */ -+ void imageInfosAdded(const QList<ImageInfo>& infos); -+ void imageInfosAboutToBeRemoved(const QList<ImageInfo>& infos); -+ -+public: -+ -+ // Declared as public because of use in sub-classes. -+ class ImageFilterModelPrivate; -+ -+protected: -+ -+ ImageFilterModelPrivate* const d_ptr; -+ -+protected: -+ -+ ImageFilterModel(ImageFilterModelPrivate& dd, QObject* parent); -+ -+ virtual void setDirectSourceImageModel(ImageModel* model); -+ -+ virtual bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const; -+ -+ virtual int compareCategories(const QModelIndex& left, const QModelIndex& right) const; -+ virtual bool subSortLessThan(const QModelIndex& left, const QModelIndex& right) const; -+ //virtual int categoryCount(const ImageInfo& info) const; -+ -+ /** Reimplement to customize category sorting, -+ * Return negative if category of left < category right, -+ * Return 0 if left and right are in the same category, else return positive. -+ */ -+ virtual int compareInfosCategories(const ImageInfo& left, const ImageInfo& right) const; -+ -+ /** Reimplement to customize sorting. Do not take categories into account here. -+ */ -+ virtual bool infosLessThan(const ImageInfo& left, const ImageInfo& right) const; -+ -+ /** Returns a unique identifier for the category if info. The string need not be for user display. -+ */ -+ virtual QString categoryIdentifier(const ImageInfo& info) const; -+ -+protected Q_SLOTS: -+ -+ void slotModelReset(); -+ void slotUpdateFilter(); -+ -+ void slotImageTagChange(const ImageTagChangeset& changeset); -+ void slotImageChange(const ImageChangeset& changeset); -+ -+ void slotRowsInserted(const QModelIndex& parent, int start, int end); -+ void slotRowsAboutToBeRemoved(const QModelIndex& parent, int start, int end); -+ -+private: -+ -+ Q_DECLARE_PRIVATE(ImageFilterModel) -+}; -+ -+// ----------------------------------------------------------------------------------------------------- -+ -+class DIGIKAM_DATABASE_EXPORT NoDuplicatesImageFilterModel : public ImageSortFilterModel -+{ -+ Q_OBJECT -+ -+public: -+ -+ explicit NoDuplicatesImageFilterModel(QObject* parent = 0); -+ -+protected: -+ -+ virtual bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const; -+}; -+ -+} // namespace Digikam -+ -+Q_DECLARE_METATYPE(Digikam::ImageFilterModel*) -+ -+#endif // IMAGEMODEL_H -diff --git a/libs/database/models/imagefiltermodelpriv.cpp b/libs/database/models/imagefiltermodelpriv.cpp -new file mode 100644 -index 0000000..07d9e79 ---- /dev/null -+++ b/libs/database/models/imagefiltermodelpriv.cpp -@@ -0,0 +1,258 @@ -+/* ============================================================ -+ * -+ * This file is a part of digiKam project -+ * http://www.digikam.org -+ * -+ * Date : 2009-03-05 -+ * Description : Qt item model for database entries -+ * -+ * Copyright (C) 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -+ * Copyright (C) 2011-2017 by Gilles Caulier <caulier dot gilles at gmail dot com> -+ * Copyright (C) 2010 by Andi Clemens <andi dot clemens at gmail dot com> -+ * Copyright (C) 2011 by Michael G. Hansen <mike at mghansen dot de> -+ * Copyright (C) 2014 by Mohamed Anwer <m dot anwer at gmx dot com> -+ * -+ * This program is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU General -+ * Public License as published by the Free Software Foundation; -+ * either version 2, or (at your option) -+ * any later version. -+ * -+ * This program 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 General Public License for more details. -+ * -+ * ============================================================ */ -+ -+#include "imagefiltermodelpriv.h" -+ -+// Local includes -+ -+#include "digikam_debug.h" -+#include "imagefiltermodelthreads.h" -+ -+namespace Digikam -+{ -+ -+ImageFilterModel::ImageFilterModelPrivate::ImageFilterModelPrivate() -+{ -+ imageModel = 0; -+ version = 0; -+ lastDiscardVersion = 0; -+ sentOut = 0; -+ sentOutForReAdd = 0; -+ updateFilterTimer = 0; -+ needPrepare = false; -+ needPrepareComments = false; -+ needPrepareTags = false; -+ needPrepareGroups = false; -+ preparer = 0; -+ filterer = 0; -+ hasOneMatch = false; -+ hasOneMatchForText = false; -+ -+ setupWorkers(); -+} -+ -+ImageFilterModel::ImageFilterModelPrivate::~ImageFilterModelPrivate() -+{ -+ // facilitate thread stopping -+ ++version; -+ preparer->deactivate(); -+ filterer->deactivate(); -+ delete preparer; -+ delete filterer; -+} -+ -+void ImageFilterModel::ImageFilterModelPrivate::init(ImageFilterModel* _q) -+{ -+ q = _q; -+ -+ updateFilterTimer = new QTimer(this); -+ updateFilterTimer->setSingleShot(true); -+ updateFilterTimer->setInterval(250); -+ -+ connect(updateFilterTimer, SIGNAL(timeout()), -+ q, SLOT(slotUpdateFilter())); -+ -+ // inter-thread redirection -+ qRegisterMetaType<ImageFilterModelTodoPackage>("ImageFilterModelTodoPackage"); -+} -+ -+void ImageFilterModel::ImageFilterModelPrivate::preprocessInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues) -+{ -+ infosToProcess(infos, extraValues, true); -+} -+ -+void ImageFilterModel::ImageFilterModelPrivate::processAddedInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues) -+{ -+ // These have already been added, we just process them afterwards -+ infosToProcess(infos, extraValues, false); -+} -+ -+void ImageFilterModel::ImageFilterModelPrivate::setupWorkers() -+{ -+ preparer = new ImageFilterModelPreparer(this); -+ filterer = new ImageFilterModelFilterer(this); -+ -+ // A package in constructed in infosToProcess. -+ // Normal flow is infosToProcess -> preparer::process -> filterer::process -> packageFinished. -+ // If no preparation is needed, the first step is skipped. -+ // If filter version changes, both will discard old package and send them to packageDiscarded. -+ -+ connect(this, SIGNAL(packageToPrepare(ImageFilterModelTodoPackage)), -+ preparer, SLOT(process(ImageFilterModelTodoPackage))); -+ -+ connect(this, SIGNAL(packageToFilter(ImageFilterModelTodoPackage)), -+ filterer, SLOT(process(ImageFilterModelTodoPackage))); -+ -+ connect(preparer, SIGNAL(processed(ImageFilterModelTodoPackage)), -+ filterer, SLOT(process(ImageFilterModelTodoPackage))); -+ -+ connect(filterer, SIGNAL(processed(ImageFilterModelTodoPackage)), -+ this, SLOT(packageFinished(ImageFilterModelTodoPackage))); -+ -+ connect(preparer, SIGNAL(discarded(ImageFilterModelTodoPackage)), -+ this, SLOT(packageDiscarded(ImageFilterModelTodoPackage))); -+ -+ connect(filterer, SIGNAL(discarded(ImageFilterModelTodoPackage)), -+ this, SLOT(packageDiscarded(ImageFilterModelTodoPackage))); -+} -+ -+void ImageFilterModel::ImageFilterModelPrivate::infosToProcess(const QList<ImageInfo>& infos) -+{ -+ infosToProcess(infos, QList<QVariant>(), false); -+} -+ -+void ImageFilterModel::ImageFilterModelPrivate::infosToProcess(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues, bool forReAdd) -+{ -+ if (infos.isEmpty()) -+ { -+ return; -+ } -+ -+ filterer->schedule(); -+ -+ if (needPrepare) -+ { -+ preparer->schedule(); -+ } -+ -+ Q_ASSERT(extraValues.isEmpty() || infos.size() == extraValues.size()); -+ -+ // prepare and filter in chunks -+ const int size = infos.size(); -+ const int maxChunkSize = needPrepare ? PrepareChunkSize : FilterChunkSize; -+ const bool hasExtraValues = !extraValues.isEmpty(); -+ QList<ImageInfo>::const_iterator it = infos.constBegin(), end; -+ QList<QVariant>::const_iterator xit = extraValues.constBegin(), xend; -+ int index = 0; -+ QVector<ImageInfo> infoVector; -+ QVector<QVariant> extraValueVector; -+ -+ while (it != infos.constEnd()) -+ { -+ const int chunkSize = qMin(maxChunkSize, size - index); -+ infoVector.resize(chunkSize); -+ end = it + chunkSize; -+ qCopy(it, end, infoVector.begin()); -+ -+ if (hasExtraValues) -+ { -+ extraValueVector.resize(chunkSize); -+ xend = xit + chunkSize; -+ qCopy(xit, xend, extraValueVector.begin()); -+ xit = xend; -+ } -+ -+ it = end; -+ index += chunkSize; -+ -+ ++sentOut; -+ -+ if (forReAdd) -+ { -+ ++sentOutForReAdd; -+ } -+ -+ if (needPrepare) -+ { -+ emit packageToPrepare(ImageFilterModelTodoPackage(infoVector, extraValueVector, version, forReAdd)); -+ } -+ else -+ { -+ emit packageToFilter(ImageFilterModelTodoPackage(infoVector, extraValueVector, version, forReAdd)); -+ } -+ } -+} -+ -+void ImageFilterModel::ImageFilterModelPrivate::packageFinished(const ImageFilterModelTodoPackage& package) -+{ -+ // check if it got discarded on the journey -+ if (package.version != version) -+ { -+ packageDiscarded(package); -+ return; -+ } -+ -+ // incorporate result -+ QHash<qlonglong, bool>::const_iterator it = package.filterResults.constBegin(); -+ -+ for (; it != package.filterResults.constEnd(); ++it) -+ { -+ filterResults.insert(it.key(), it.value()); -+ } -+ -+ // re-add if necessary -+ if (package.isForReAdd) -+ { -+ emit reAddImageInfos(package.infos.toList(), package.extraValues.toList()); -+ -+ if (sentOutForReAdd == 1) // last package -+ { -+ emit reAddingFinished(); -+ } -+ } -+ -+ // decrement counters -+ --sentOut; -+ -+ if (package.isForReAdd) -+ { -+ --sentOutForReAdd; -+ } -+ -+ // If all packages have returned, filtered and readded, and no more are expected, -+ // and there is need to tell the filter result to the view, do that -+ if (sentOut == 0 && sentOutForReAdd == 0 && !imageModel->isRefreshing()) -+ { -+ q->invalidate(); // use invalidate, not invalidateFilter only. Sorting may have changed as well. -+ emit (q->filterMatches(hasOneMatch)); -+ emit (q->filterMatchesForText(hasOneMatchForText)); -+ filterer->deactivate(); -+ preparer->deactivate(); -+ } -+} -+ -+void ImageFilterModel::ImageFilterModelPrivate::packageDiscarded(const ImageFilterModelTodoPackage& package) -+{ -+ // Either, the model was reset, or the filter changed -+ // In the former case throw all away, in the latter case, recycle -+ if (package.version > lastDiscardVersion) -+ { -+ // Recycle packages: Send again with current version -+ // Do not increment sentOut or sentOutForReAdd here: it was not decremented! -+ -+ if (needPrepare) -+ { -+ emit packageToPrepare(ImageFilterModelTodoPackage(package.infos, package.extraValues, version, package.isForReAdd)); -+ } -+ else -+ { -+ emit packageToFilter(ImageFilterModelTodoPackage(package.infos, package.extraValues, version, package.isForReAdd)); -+ } -+ } -+} -+ -+} // namespace Digikam -diff --git a/libs/database/models/imagefiltermodelpriv.h b/libs/database/models/imagefiltermodelpriv.h -new file mode 100644 -index 0000000..a9e3f22 ---- /dev/null -+++ b/libs/database/models/imagefiltermodelpriv.h -@@ -0,0 +1,159 @@ -+/* ============================================================ -+ * -+ * This file is a part of digiKam project -+ * http://www.digikam.org -+ * -+ * Date : 2009-03-11 -+ * Description : Qt item model for database entries - private shared header -+ * -+ * Copyright (C) 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -+ * -+ * This program is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU General -+ * Public License as published by the Free Software Foundation; -+ * either version 2, or (at your option) -+ * any later version. -+ * -+ * This program 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 General Public License for more details. -+ * -+ * ============================================================ */ -+ -+#ifndef IMAGEFILTERMODELPRIV_H -+#define IMAGEFILTERMODELPRIV_H -+ -+// Qt includes -+ -+#include <QHash> -+#include <QMutex> -+#include <QMutexLocker> -+#include <QSet> -+#include <QThread> -+#include <QTimer> -+#include <QWaitCondition> -+ -+// Local includes -+ -+#include "imageinfo.h" -+#include "imagefiltermodel.h" -+ -+#include "digikam_export.h" -+// Yes, we need the EXPORT macro in a private header because -+// this private header is shared across binary objects. -+// This does NOT make this classes here any more public! -+ -+namespace Digikam -+{ -+ -+const int PrepareChunkSize = 101; -+const int FilterChunkSize = 2001; -+ -+class ImageFilterModelTodoPackage -+{ -+public: -+ -+ ImageFilterModelTodoPackage() -+ : version(0), isForReAdd(false) -+ { -+ } -+ -+ ImageFilterModelTodoPackage(const QVector<ImageInfo>& infos, const QVector<QVariant>& extraValues, int version, bool isForReAdd) -+ : infos(infos), extraValues(extraValues), version(version), isForReAdd(isForReAdd) -+ { -+ } -+ -+ QVector<ImageInfo> infos; -+ QVector<QVariant> extraValues; -+ unsigned int version; -+ bool isForReAdd; -+ QHash<qlonglong, bool> filterResults; -+}; -+ -+// ------------------------------------------------------------------------------------------------ -+ -+class ImageFilterModelPreparer; -+class ImageFilterModelFilterer; -+ -+class DIGIKAM_DATABASE_EXPORT ImageFilterModel::ImageFilterModelPrivate : public QObject -+{ -+ Q_OBJECT -+ -+public: -+ -+ ImageFilterModelPrivate(); -+ ~ImageFilterModelPrivate(); -+ -+ void init(ImageFilterModel* q); -+ void setupWorkers(); -+ void infosToProcess(const QList<ImageInfo>& infos); -+ void infosToProcess(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues, bool forReAdd = true); -+ -+public: -+ -+ ImageFilterModel* q; -+ -+ ImageModel* imageModel; -+ -+ ImageFilterSettings filter; -+ ImageSortSettings sorter; -+ VersionImageFilterSettings versionFilter; -+ GroupImageFilterSettings groupFilter; -+ -+ volatile unsigned int version; -+ unsigned int lastDiscardVersion; -+ unsigned int lastFilteredVersion; -+ int sentOut; -+ int sentOutForReAdd; -+ -+ QTimer* updateFilterTimer; -+ -+ bool needPrepare; -+ bool needPrepareComments; -+ bool needPrepareTags; -+ bool needPrepareGroups; -+ -+ QMutex mutex; -+ ImageFilterSettings filterCopy; -+ VersionImageFilterSettings versionFilterCopy; -+ GroupImageFilterSettings groupFilterCopy; -+ ImageFilterModelPreparer* preparer; -+ ImageFilterModelFilterer* filterer; -+ -+ QHash<qlonglong, bool> filterResults; -+ bool hasOneMatch; -+ bool hasOneMatchForText; -+ -+ QList<ImageFilterModelPrepareHook*> prepareHooks; -+ -+/* -+ QHash<int, QSet<qlonglong> > categoryCountHashInt; -+ QHash<QString, QSet<qlonglong> > categoryCountHashString; -+ -+public: -+ -+ void cacheCategoryCount(int id, qlonglong imageid) const -+ { const_cast<ImageFilterModelPrivate*>(this)->categoryCountHashInt[id].insert(imageid); } -+ void cacheCategoryCount(const QString& id, qlonglong imageid) const -+ { const_cast<ImageFilterModelPrivate*>(this)->categoryCountHashString[id].insert(imageid); } -+*/ -+ -+public Q_SLOTS: -+ -+ void preprocessInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues); -+ void processAddedInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues); -+ void packageFinished(const ImageFilterModelTodoPackage& package); -+ void packageDiscarded(const ImageFilterModelTodoPackage& package); -+ -+Q_SIGNALS: -+ -+ void packageToPrepare(const ImageFilterModelTodoPackage& package); -+ void packageToFilter(const ImageFilterModelTodoPackage& package); -+ void reAddImageInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues); -+ void reAddingFinished(); -+}; -+ -+} // namespace Digikam -+ -+#endif // IMAGEFILTERMODELPRIV_H -diff --git a/libs/database/models/imagefiltermodelthreads.cpp b/libs/database/models/imagefiltermodelthreads.cpp -new file mode 100644 -index 0000000..aa5c462 ---- /dev/null -+++ b/libs/database/models/imagefiltermodelthreads.cpp -@@ -0,0 +1,40 @@ -+/* ============================================================ -+ * -+ * This file is a part of digiKam project -+ * http://www.digikam.org -+ * -+ * Date : 2009-03-05 -+ * Description : Qt item model for database entries -+ * -+ * Copyright (C) 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -+ * Copyright (C) 2011-2017 by Gilles Caulier <caulier dot gilles at gmail dot com> -+ * Copyright (C) 2010 by Andi Clemens <andi dot clemens at gmail dot com> -+ * Copyright (C) 2011 by Michael G. Hansen <mike at mghansen dot de> -+ * Copyright (C) 2014 by Mohamed Anwer <m dot anwer at gmx dot com> -+ * -+ * This program is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU General -+ * Public License as published by the Free Software Foundation; -+ * either version 2, or (at your option) -+ * any later version. -+ * -+ * This program 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 General Public License for more details. -+ * -+ * ============================================================ */ -+ -+#include "imagefiltermodel.h" -+#include "imagefiltermodelpriv.h" -+#include "imagefiltermodelthreads.h" -+ -+namespace Digikam -+{ -+ -+ImageFilterModelWorker::ImageFilterModelWorker(ImageFilterModel::ImageFilterModelPrivate* const d) -+ : d(d) -+{ -+} -+ -+} // namespace Digikam -diff --git a/libs/database/models/imagefiltermodelthreads.h b/libs/database/models/imagefiltermodelthreads.h -new file mode 100644 -index 0000000..83fa987 ---- /dev/null -+++ b/libs/database/models/imagefiltermodelthreads.h -@@ -0,0 +1,100 @@ -+/* ============================================================ -+ * -+ * This file is a part of digiKam project -+ * http://www.digikam.org -+ * -+ * Date : 2009-03-11 -+ * Description : Qt item model for database entries - private header -+ * -+ * Copyright (C) 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -+ * -+ * This program is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU General -+ * Public License as published by the Free Software Foundation; -+ * either version 2, or (at your option) -+ * any later version. -+ * -+ * This program 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 General Public License for more details. -+ * -+ * ============================================================ */ -+ -+#ifndef IMAGEFILTERMODELTHREADS_H -+#define IMAGEFILTERMODELTHREADS_H -+ -+// Qt includes -+ -+#include <QThread> -+ -+// Local includes -+ -+#include "digikam_export.h" -+#include "workerobject.h" -+ -+namespace Digikam -+{ -+ -+class DIGIKAM_DATABASE_EXPORT ImageFilterModelWorker : public WorkerObject -+{ -+ Q_OBJECT -+ -+public: -+ -+ explicit ImageFilterModelWorker(ImageFilterModel::ImageFilterModelPrivate* const d); -+ -+ bool checkVersion(const ImageFilterModelTodoPackage& package) -+ { -+ return d->version == package.version; -+ } -+ -+public Q_SLOTS: -+ -+ virtual void process(ImageFilterModelTodoPackage package) = 0; -+ -+Q_SIGNALS: -+ -+ void processed(const ImageFilterModelTodoPackage& package); -+ void discarded(const ImageFilterModelTodoPackage& package); -+ -+protected: -+ -+ ImageFilterModel::ImageFilterModelPrivate* d; -+}; -+ -+// ----------------------------------------------------------------------------------------- -+ -+class DIGIKAM_DATABASE_EXPORT ImageFilterModelPreparer : public ImageFilterModelWorker -+{ -+ Q_OBJECT -+ -+public: -+ -+ explicit ImageFilterModelPreparer(ImageFilterModel::ImageFilterModelPrivate* const d) -+ : ImageFilterModelWorker(d) -+ { -+ } -+ -+ void process(ImageFilterModelTodoPackage package); -+}; -+ -+// ---------------------------------------------------------------------------------------- -+ -+class DIGIKAM_DATABASE_EXPORT ImageFilterModelFilterer : public ImageFilterModelWorker -+{ -+ Q_OBJECT -+ -+public: -+ -+ explicit ImageFilterModelFilterer(ImageFilterModel::ImageFilterModelPrivate* const d) -+ : ImageFilterModelWorker(d) -+ { -+ } -+ -+ void process(ImageFilterModelTodoPackage package); -+}; -+ -+} // namespace Digikam -+ -+#endif // IMAGEFILTERMODELTHREADS_H -diff --git a/libs/database/models/imagefiltersettings.cpp b/libs/database/models/imagefiltersettings.cpp -new file mode 100644 -index 0000000..b61e7f9 ---- /dev/null -+++ b/libs/database/models/imagefiltersettings.cpp -@@ -0,0 +1,952 @@ -+/* ============================================================ -+ * -+ * This file is a part of digiKam project -+ * http://www.digikam.org -+ * -+ * Date : 2009-03-05 -+ * Description : Filter values for use with ImageFilterModel -+ * -+ * Copyright (C) 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -+ * Copyright (C) 2011-2017 by Gilles Caulier <caulier dot gilles at gmail dot com> -+ * Copyright (C) 2010 by Andi Clemens <andi dot clemens at gmail dot com> -+ * Copyright (C) 2011 by Michael G. Hansen <mike at mghansen dot de> -+ * Copyright (C) 2014 by Mohamed Anwer <m dot anwer at gmx dot com> -+ * -+ * This program is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU General -+ * Public License as published by the Free Software Foundation; -+ * either version 2, or (at your option) -+ * any later version. -+ * -+ * This program 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 General Public License for more details. -+ * -+ * ============================================================ */ -+ -+#include "imagefiltersettings.h" -+ -+// C++ includes -+ -+#include <cmath> -+ -+// Qt includes -+ -+#include <QDateTime> -+ -+// Local includes -+ -+#include "digikam_debug.h" -+#include "coredbfields.h" -+#include "digikam_globals.h" -+#include "imageinfo.h" -+#include "tagscache.h" -+#include "versionmanagersettings.h" -+ -+namespace Digikam -+{ -+ -+ImageFilterSettings::ImageFilterSettings() -+{ -+ m_untaggedFilter = false; -+ m_isUnratedExcluded = false; -+ m_ratingFilter = 0; -+ m_mimeTypeFilter = MimeFilter::AllFiles; -+ m_ratingCond = GreaterEqualCondition; -+ m_matchingCond = OrCondition; -+ m_geolocationCondition = GeolocationNoFilter; -+} -+ -+DatabaseFields::Set ImageFilterSettings::watchFlags() const -+{ -+ DatabaseFields::Set set; -+ -+ if (isFilteringByDay()) -+ { -+ set |= DatabaseFields::CreationDate; -+ } -+ -+ if (isFilteringByText()) -+ { -+ set |= DatabaseFields::Name; -+ set |= DatabaseFields::Comment; -+ } -+ -+ if (isFilteringByRating()) -+ { -+ set |= DatabaseFields::Rating; -+ } -+ -+ if (isFilteringByTypeMime()) -+ { -+ set |= DatabaseFields::Category; -+ set |= DatabaseFields::Format; -+ } -+ -+ if (isFilteringByGeolocation()) -+ { -+ set |= DatabaseFields::ImagePositionsAll; -+ } -+ -+ if (isFilteringByColorLabels()) -+ { -+ set |= DatabaseFields::ColorLabel; -+ } -+ -+ if (isFilteringByPickLabels()) -+ { -+ set |= DatabaseFields::PickLabel; -+ } -+ -+ return set; -+} -+ -+bool ImageFilterSettings::isFilteringByDay() const -+{ -+ if (!m_dayFilter.isEmpty()) -+ { -+ return true; -+ } -+ -+ return false; -+} -+ -+bool ImageFilterSettings::isFilteringByTags() const -+{ -+ if (!m_includeTagFilter.isEmpty() || !m_excludeTagFilter.isEmpty() || m_untaggedFilter) -+ { -+ return true; -+ } -+ -+ return false; -+} -+ -+bool ImageFilterSettings::isFilteringByColorLabels() const -+{ -+ if (!m_colorLabelTagFilter.isEmpty()) -+ { -+ return true; -+ } -+ -+ return false; -+} -+ -+bool ImageFilterSettings::isFilteringByPickLabels() const -+{ -+ if (!m_pickLabelTagFilter.isEmpty()) -+ { -+ return true; -+ } -+ -+ return false; -+} -+ -+bool ImageFilterSettings::isFilteringByText() const -+{ -+ if (!m_textFilterSettings.text.isEmpty()) -+ { -+ return true; -+ } -+ -+ return false; -+} -+ -+bool ImageFilterSettings::isFilteringByTypeMime() const -+{ -+ if (m_mimeTypeFilter != MimeFilter::AllFiles) -+ { -+ return true; -+ } -+ -+ return false; -+} -+ -+bool ImageFilterSettings::isFilteringByGeolocation() const -+{ -+ return (m_geolocationCondition != GeolocationNoFilter); -+} -+ -+bool ImageFilterSettings::isFilteringByRating() const -+{ -+ if (m_ratingFilter != 0 || m_ratingCond != GreaterEqualCondition || m_isUnratedExcluded) -+ { -+ return true; -+ } -+ -+ return false; -+} -+ -+bool ImageFilterSettings::isFilteringInternally() const -+{ -+ return (isFiltering() || !m_urlWhitelists.isEmpty() || !m_idWhitelists.isEmpty()); -+} -+ -+bool ImageFilterSettings::isFiltering() const -+{ -+ return isFilteringByDay() || -+ isFilteringByTags() || -+ isFilteringByText() || -+ isFilteringByRating() || -+ isFilteringByTypeMime() || -+ isFilteringByColorLabels() || -+ isFilteringByPickLabels() || -+ isFilteringByGeolocation(); -+} -+ -+void ImageFilterSettings::setDayFilter(const QList<QDateTime>& days) -+{ -+ m_dayFilter.clear(); -+ -+ for (QList<QDateTime>::const_iterator it = days.constBegin(); it != days.constEnd(); ++it) -+ { -+ m_dayFilter.insert(*it, true); -+ } -+} -+ -+void ImageFilterSettings::setTagFilter(const QList<int>& includedTags, -+ const QList<int>& excludedTags, -+ MatchingCondition matchingCondition, -+ bool showUnTagged, -+ const QList<int>& clTagIds, -+ const QList<int>& plTagIds) -+{ -+ m_includeTagFilter = includedTags; -+ m_excludeTagFilter = excludedTags; -+ m_matchingCond = matchingCondition; -+ m_untaggedFilter = showUnTagged; -+ m_colorLabelTagFilter = clTagIds; -+ m_pickLabelTagFilter = plTagIds; -+} -+ -+void ImageFilterSettings::setRatingFilter(int rating, RatingCondition ratingCondition, bool isUnratedExcluded) -+{ -+ m_ratingFilter = rating; -+ m_ratingCond = ratingCondition; -+ m_isUnratedExcluded = isUnratedExcluded; -+} -+ -+void ImageFilterSettings::setMimeTypeFilter(int mime) -+{ -+ m_mimeTypeFilter = (MimeFilter::TypeMimeFilter)mime; -+} -+ -+void ImageFilterSettings::setGeolocationFilter(const GeolocationCondition& condition) -+{ -+ m_geolocationCondition = condition; -+} -+ -+void ImageFilterSettings::setTextFilter(const SearchTextFilterSettings& settings) -+{ -+ m_textFilterSettings = settings; -+} -+ -+void ImageFilterSettings::setTagNames(const QHash<int, QString>& hash) -+{ -+ m_tagNameHash = hash; -+} -+ -+void ImageFilterSettings::setAlbumNames(const QHash<int, QString>& hash) -+{ -+ m_albumNameHash = hash; -+} -+ -+void ImageFilterSettings::setUrlWhitelist(const QList<QUrl>& urlList, const QString& id) -+{ -+ if (urlList.isEmpty()) -+ { -+ m_urlWhitelists.remove(id); -+ } -+ else -+ { -+ m_urlWhitelists.insert(id, urlList); -+ } -+} -+ -+void ImageFilterSettings::setIdWhitelist(const QList<qlonglong>& idList, const QString& id) -+{ -+ if (idList.isEmpty()) -+ { -+ m_idWhitelists.remove(id); -+ } -+ else -+ { -+ m_idWhitelists.insert(id, idList); -+ } -+} -+ -+template <class ContainerA, class ContainerB> -+bool containsAnyOf(const ContainerA& listA, const ContainerB& listB) -+{ -+ foreach (const typename ContainerA::value_type& a, listA) -+ { -+ if (listB.contains(a)) -+ { -+ return true; -+ } -+ } -+ return false; -+} -+ -+template <class ContainerA, typename Value, class ContainerB> -+bool containsNoneOfExcept(const ContainerA& list, const ContainerB& noneOfList, const Value& exception) -+{ -+ foreach (const typename ContainerB::value_type& n, noneOfList) -+ { -+ if (n != exception && list.contains(n)) -+ { -+ return false; -+ } -+ } -+ return true; -+} -+ -+bool ImageFilterSettings::matches(const ImageInfo& info, bool* const foundText) const -+{ -+ if (foundText) -+ { -+ *foundText = false; -+ } -+ -+ if (!isFilteringInternally()) -+ { -+ return true; -+ } -+ -+ bool match = false; -+ -+ if (!m_includeTagFilter.isEmpty() || !m_excludeTagFilter.isEmpty()) -+ { -+ QList<int> tagIds = info.tagIds(); -+ QList<int>::const_iterator it; -+ -+ match = m_includeTagFilter.isEmpty(); -+ -+ if (m_matchingCond == OrCondition) -+ { -+ for (it = m_includeTagFilter.begin(); it != m_includeTagFilter.end(); ++it) -+ { -+ if (tagIds.contains(*it)) -+ { -+ match = true; -+ break; -+ } -+ } -+ -+ match |= (m_untaggedFilter && tagIds.isEmpty()); -+ } -+ else // AND matching condition... -+ { -+ // m_untaggedFilter and non-empty tag filter, combined with AND, is logically no match -+ if (!m_untaggedFilter) -+ { -+ for (it = m_includeTagFilter.begin(); it != m_includeTagFilter.end(); ++it) -+ { -+ if (!tagIds.contains(*it)) -+ { -+ break; -+ } -+ } -+ -+ if (it == m_includeTagFilter.end()) -+ { -+ match = true; -+ } -+ } -+ } -+ -+ for (it = m_excludeTagFilter.begin(); it != m_excludeTagFilter.end(); ++it) -+ { -+ if (tagIds.contains(*it)) -+ { -+ match = false; -+ break; -+ } -+ } -+ } -+ else if (m_untaggedFilter) -+ { -+ match = !TagsCache::instance()->containsPublicTags(info.tagIds()); -+ } -+ else -+ { -+ match = true; -+ } -+ -+ //-- Filter by pick labels ------------------------------------------------ -+ -+ if (!m_pickLabelTagFilter.isEmpty()) -+ { -+ QList<int> tagIds = info.tagIds(); -+ bool matchPL = false; -+ -+ if (containsAnyOf(m_pickLabelTagFilter, tagIds)) -+ { -+ matchPL = true; -+ } -+ else if (!matchPL) -+ { -+ int noPickLabelTagId = TagsCache::instance()->tagForPickLabel(NoPickLabel); -+ -+ if (m_pickLabelTagFilter.contains(noPickLabelTagId)) -+ { -+ // Searching for "has no ColorLabel" requires special handling: -+ // Scan that the tag ids contains none of the ColorLabel tags, except maybe the NoColorLabel tag -+ matchPL = containsNoneOfExcept(tagIds, TagsCache::instance()->pickLabelTags(), noPickLabelTagId); -+ } -+ } -+ -+ match &= matchPL; -+ } -+ -+ //-- Filter by color labels ------------------------------------------------ -+ -+ if (!m_colorLabelTagFilter.isEmpty()) -+ { -+ QList<int> tagIds = info.tagIds(); -+ bool matchCL = false; -+ -+ if (containsAnyOf(m_colorLabelTagFilter, tagIds)) -+ { -+ matchCL = true; -+ } -+ else if (!matchCL) -+ { -+ int noColorLabelTagId = TagsCache::instance()->tagForColorLabel(NoColorLabel); -+ -+ if (m_colorLabelTagFilter.contains(noColorLabelTagId)) -+ { -+ // Searching for "has no ColorLabel" requires special handling: -+ // Scan that the tag ids contains none of the ColorLabel tags, except maybe the NoColorLabel tag -+ matchCL = containsNoneOfExcept(tagIds, TagsCache::instance()->colorLabelTags(), noColorLabelTagId); -+ } -+ } -+ -+ match &= matchCL; -+ } -+ -+ //-- Filter by date ----------------------------------------------------------- -+ -+ if (!m_dayFilter.isEmpty()) -+ { -+ match &= m_dayFilter.contains(QDateTime(info.dateTime().date(), QTime())); -+ } -+ -+ //-- Filter by rating --------------------------------------------------------- -+ -+ if (m_ratingFilter >= 0) -+ { -+ // for now we treat -1 (no rating) just like a rating of 0. -+ int rating = info.rating(); -+ -+ if (rating == -1) -+ { -+ rating = 0; -+ } -+ -+ if(m_isUnratedExcluded && rating == 0) -+ { -+ match = false; -+ } -+ else -+ { -+ if (m_ratingCond == GreaterEqualCondition) -+ { -+ // If the rating is not >=, i.e it is <, then it does not match. -+ if (rating < m_ratingFilter) -+ { -+ match = false; -+ } -+ } -+ else if (m_ratingCond == EqualCondition) -+ { -+ // If the rating is not =, i.e it is !=, then it does not match. -+ if (rating != m_ratingFilter) -+ { -+ match = false; -+ } -+ } -+ else -+ { -+ // If the rating is not <=, i.e it is >, then it does not match. -+ if (rating > m_ratingFilter) -+ { -+ match = false; -+ } -+ } -+ } -+ } -+ -+ // -- Filter by mime type ----------------------------------------------------- -+ -+ switch (m_mimeTypeFilter) -+ { -+ // info.format is a standardized string: Only one possibility per mime type -+ case MimeFilter::ImageFiles: -+ { -+ if (info.category() != DatabaseItem::Image) -+ { -+ match = false; -+ } -+ -+ break; -+ } -+ case MimeFilter::JPGFiles: -+ { -+ if (info.format() != QLatin1String("JPG")) -+ { -+ match = false; -+ } -+ -+ break; -+ } -+ case MimeFilter::PNGFiles: -+ { -+ if (info.format() != QLatin1String("PNG")) -+ { -+ match = false; -+ } -+ -+ break; -+ } -+ case MimeFilter::TIFFiles: -+ { -+ if (info.format() != QLatin1String("TIFF")) -+ { -+ match = false; -+ } -+ -+ break; -+ } -+ case MimeFilter::DNGFiles: -+ { -+ if (info.format() != QLatin1String("RAW-DNG")) -+ { -+ match = false; -+ } -+ -+ break; -+ } -+ case MimeFilter::NoRAWFiles: -+ { -+ if (info.format().startsWith(QLatin1String("RAW"))) -+ { -+ match = false; -+ } -+ -+ break; -+ } -+ case MimeFilter::RAWFiles: -+ { -+ if (!info.format().startsWith(QLatin1String("RAW"))) -+ { -+ match = false; -+ } -+ -+ break; -+ } -+ case MimeFilter::MoviesFiles: -+ { -+ if (info.category() != DatabaseItem::Video) -+ { -+ match = false; -+ } -+ -+ break; -+ } -+ case MimeFilter::AudioFiles: -+ { -+ if (info.category() != DatabaseItem::Audio) -+ { -+ match = false; -+ } -+ -+ break; -+ } -+ case MimeFilter::RasterFiles: -+ { -+ if (info.format() != QLatin1String("PSD") && // Adobe Photoshop Document -+ info.format() != QLatin1String("PSB") && // Adobe Photoshop Big -+ info.format() != QLatin1String("XCF") && // Gimp -+ info.format() != QLatin1String("KRA") && // Krita -+ info.format() != QLatin1String("ORA") // Open Raster -+ ) -+ { -+ match = false; -+ } -+ -+ break; -+ } -+ default: -+ { -+ // All Files: do nothing... -+ break; -+ } -+ } -+ -+ //-- Filter by geolocation ---------------------------------------------------- -+ -+ if (m_geolocationCondition!=GeolocationNoFilter) -+ { -+ if (m_geolocationCondition==GeolocationNoCoordinates) -+ { -+ if (info.hasCoordinates()) -+ { -+ match = false; -+ } -+ } -+ else if (m_geolocationCondition==GeolocationHasCoordinates) -+ { -+ if (!info.hasCoordinates()) -+ { -+ match = false; -+ } -+ } -+ } -+ -+ //-- Filter by text ----------------------------------------------------------- -+ -+ if (!m_textFilterSettings.text.isEmpty()) -+ { -+ bool textMatch = false; -+ -+ // Image name -+ if (m_textFilterSettings.textFields & SearchTextFilterSettings::ImageName && -+ info.name().contains(m_textFilterSettings.text, m_textFilterSettings.caseSensitive)) -+ { -+ textMatch = true; -+ } -+ -+ // Image title -+ if (m_textFilterSettings.textFields & SearchTextFilterSettings::ImageTitle && -+ info.title().contains(m_textFilterSettings.text, m_textFilterSettings.caseSensitive)) -+ { -+ textMatch = true; -+ } -+ -+ // Image comment -+ if (m_textFilterSettings.textFields & SearchTextFilterSettings::ImageComment && -+ info.comment().contains(m_textFilterSettings.text, m_textFilterSettings.caseSensitive)) -+ { -+ textMatch = true; -+ } -+ -+ // Tag names -+ foreach(int id, info.tagIds()) -+ { -+ if (m_textFilterSettings.textFields & SearchTextFilterSettings::TagName && -+ m_tagNameHash.value(id).contains(m_textFilterSettings.text, m_textFilterSettings.caseSensitive)) -+ { -+ textMatch = true; -+ } -+ } -+ -+ // Album names -+ if (m_textFilterSettings.textFields & SearchTextFilterSettings::AlbumName && -+ m_albumNameHash.value(info.albumId()).contains(m_textFilterSettings.text, m_textFilterSettings.caseSensitive)) -+ { -+ textMatch = true; -+ } -+ -+ // Image Aspect Ratio -+ if (m_textFilterSettings.textFields & SearchTextFilterSettings::ImageAspectRatio) -+ { -+ QRegExp expRatio (QLatin1String("^\\d+:\\d+$")); -+ QRegExp expFloat (QLatin1String("^\\d+(.\\d+)?$")); -+ -+ if (expRatio.indexIn(m_textFilterSettings.text) > -1 && m_textFilterSettings.text.contains(QRegExp(QLatin1String(":\\d+")))) -+ { -+ QString trimmedTextFilterSettingsText = m_textFilterSettings.text; -+ QStringList numberStringList = trimmedTextFilterSettingsText.split(QLatin1String(":"), QString::SkipEmptyParts); -+ -+ if (numberStringList.length() == 2) -+ { -+ QString numString = (QString)numberStringList.at(0), denomString = (QString)numberStringList.at(1); -+ bool canConverseNum = false; -+ bool canConverseDenom = false; -+ int num = numString.toInt(&canConverseNum, 10), denom = denomString.toInt(&canConverseDenom, 10); -+ -+ if (canConverseNum && canConverseDenom) -+ { -+ if (fabs(info.aspectRatio() - (double)num / denom) < 0.1) -+ textMatch = true; -+ } -+ } -+ } -+ else if (expFloat.indexIn(m_textFilterSettings.text) > -1) -+ { -+ QString trimmedTextFilterSettingsText = m_textFilterSettings.text; -+ bool canConverse = false; -+ double ratio = trimmedTextFilterSettingsText.toDouble(&canConverse); -+ -+ if (canConverse) -+ { -+ if (fabs(info.aspectRatio() - ratio) < 0.1) -+ textMatch = true; -+ } -+ } -+ } -+ -+ // Image Pixel Size -+ // See bug #341053 for details. -+ -+ if (m_textFilterSettings.textFields & SearchTextFilterSettings::ImagePixelSize) -+ { -+ QSize size = info.dimensions(); -+ int pixelSize = size.height()*size.width(); -+ QString text = m_textFilterSettings.text; -+ -+ if(text.contains(QRegExp(QLatin1String("^>\\d{1,15}$"))) && pixelSize > (text.remove(0,1)).toInt()) -+ { -+ textMatch = true; -+ } -+ else if(text.contains(QRegExp(QLatin1String("^<\\d{1,15}$"))) && pixelSize < (text.remove(0,1)).toInt()) -+ { -+ textMatch = true; -+ } -+ else if(text.contains(QRegExp(QLatin1String("^\\d+$"))) && pixelSize == text.toInt()) -+ { -+ textMatch = true; -+ } -+ } -+ -+ match &= textMatch; -+ -+ if (foundText) -+ { -+ *foundText = textMatch; -+ } -+ } -+ -+ // -- filter by URL-whitelists ------------------------------------------------ -+ // NOTE: whitelists are always AND for now. -+ -+ if (match) -+ { -+ const QUrl url = info.fileUrl(); -+ -+ for (QHash<QString, QList<QUrl>>::const_iterator it = m_urlWhitelists.constBegin(); -+ it!=m_urlWhitelists.constEnd(); ++it) -+ { -+ match = it->contains(url); -+ -+ if (!match) -+ { -+ break; -+ } -+ } -+ } -+ -+ if (match) -+ { -+ const qlonglong id = info.id(); -+ -+ for (QHash<QString, QList<qlonglong> >::const_iterator it = m_idWhitelists.constBegin(); -+ it!=m_idWhitelists.constEnd(); ++it) -+ { -+ match = it->contains(id); -+ -+ if (!match) -+ { -+ break; -+ } -+ } -+ } -+ -+ return match; -+} -+ -+// ------------------------------------------------------------------------------------------------- -+ -+VersionImageFilterSettings::VersionImageFilterSettings() -+{ -+ m_includeTagFilter = 0; -+ m_exceptionTagFilter = 0; -+} -+ -+VersionImageFilterSettings::VersionImageFilterSettings(const VersionManagerSettings& settings) -+{ -+ setVersionManagerSettings(settings); -+} -+ -+bool VersionImageFilterSettings::operator==(const VersionImageFilterSettings& other) const -+{ -+ return m_excludeTagFilter == other.m_excludeTagFilter && -+ m_exceptionLists == other.m_exceptionLists; -+} -+ -+bool VersionImageFilterSettings::matches(const ImageInfo& info) const -+{ -+ if (!isFiltering()) -+ { -+ return true; -+ } -+ -+ const qlonglong id = info.id(); -+ -+ for (QHash<QString, QList<qlonglong> >::const_iterator it = m_exceptionLists.constBegin(); -+ it != m_exceptionLists.constEnd(); ++it) -+ { -+ if (it->contains(id)) -+ { -+ return true; -+ } -+ } -+ -+ bool match = true; -+ QList<int> tagIds = info.tagIds(); -+ -+ if (!tagIds.contains(m_includeTagFilter)) -+ { -+ for (QList<int>::const_iterator it = m_excludeTagFilter.begin(); -+ it != m_excludeTagFilter.end(); ++it) -+ { -+ if (tagIds.contains(*it)) -+ { -+ match = false; -+ break; -+ } -+ } -+ } -+ -+ if (!match) -+ { -+ if (tagIds.contains(m_exceptionTagFilter)) -+ { -+ match = true; -+ } -+ } -+ -+ return match; -+} -+ -+bool VersionImageFilterSettings::isHiddenBySettings(const ImageInfo& info) const -+{ -+ QList<int> tagIds = info.tagIds(); -+ -+ foreach(int tagId, m_excludeTagFilter) -+ { -+ if (tagIds.contains(tagId)) -+ { -+ return true; -+ } -+ } -+ -+ return false; -+} -+ -+bool VersionImageFilterSettings::isExemptedBySettings(const ImageInfo& info) const -+{ -+ return info.tagIds().contains(m_exceptionTagFilter); -+} -+ -+void VersionImageFilterSettings::setVersionManagerSettings(const VersionManagerSettings& settings) -+{ -+ m_excludeTagFilter.clear(); -+ -+ if (!settings.enabled) -+ { -+ return; -+ } -+ -+ if (!(settings.showInViewFlags & VersionManagerSettings::ShowOriginal)) -+ { -+ m_excludeTagFilter << TagsCache::instance()->getOrCreateInternalTag(InternalTagName::originalVersion()); -+ } -+ -+ if (!(settings.showInViewFlags & VersionManagerSettings::ShowIntermediates)) -+ { -+ m_excludeTagFilter << TagsCache::instance()->getOrCreateInternalTag(InternalTagName::intermediateVersion()); -+ } -+ -+ m_includeTagFilter = TagsCache::instance()->getOrCreateInternalTag(InternalTagName::currentVersion()); -+ m_exceptionTagFilter = TagsCache::instance()->getOrCreateInternalTag(InternalTagName::versionAlwaysVisible()); -+} -+ -+void VersionImageFilterSettings::setExceptionList(const QList<qlonglong>& idList, const QString& id) -+{ -+ if (idList.isEmpty()) -+ { -+ m_exceptionLists.remove(id); -+ } -+ else -+ { -+ m_exceptionLists.insert(id, idList); -+ } -+} -+ -+bool VersionImageFilterSettings::isFiltering() const -+{ -+ return !m_excludeTagFilter.isEmpty(); -+} -+ -+bool VersionImageFilterSettings::isFilteringByTags() const -+{ -+ return isFiltering(); -+} -+ -+// ------------------------------------------------------------------------------------------------- -+ -+GroupImageFilterSettings::GroupImageFilterSettings() -+ : m_allOpen(false) -+{ -+} -+ -+bool GroupImageFilterSettings::operator==(const GroupImageFilterSettings& other) const -+{ -+ return (m_allOpen == other.m_allOpen && -+ m_openGroups == other.m_openGroups); -+} -+ -+bool GroupImageFilterSettings::matches(const ImageInfo& info) const -+{ -+ if (m_allOpen) -+ { -+ return true; -+ } -+ -+ if (info.isGrouped()) -+ { -+ return m_openGroups.contains(info.groupImage().id()); -+ } -+ return true; -+} -+ -+void GroupImageFilterSettings::setOpen(qlonglong group, bool open) -+{ -+ if (open) -+ { -+ m_openGroups << group; -+ } -+ else -+ { -+ m_openGroups.remove(group); -+ } -+} -+ -+bool GroupImageFilterSettings::isOpen(qlonglong group) const -+{ -+ return m_openGroups.contains(group); -+} -+ -+void GroupImageFilterSettings::setAllOpen(bool open) -+{ -+ m_allOpen = open; -+} -+ -+bool GroupImageFilterSettings::isAllOpen() const -+{ -+ return m_allOpen; -+} -+ -+bool GroupImageFilterSettings::isFiltering() const -+{ -+ return !m_allOpen; -+} -+ -+DatabaseFields::Set GroupImageFilterSettings::watchFlags() const -+{ -+ return DatabaseFields::ImageRelations; -+} -+ -+} // namespace Digikam -diff --git a/libs/database/models/imagefiltersettings.h b/libs/database/models/imagefiltersettings.h -new file mode 100644 -index 0000000..0e7beae ---- /dev/null -+++ b/libs/database/models/imagefiltersettings.h -@@ -0,0 +1,349 @@ -+/* ============================================================ -+ * -+ * This file is a part of digiKam project -+ * http://www.digikam.org -+ * -+ * Date : 2009-03-05 -+ * Description : Filter values for use with ImageFilterModel -+ * -+ * Copyright (C) 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -+ * Copyright (C) 2011-2017 by Gilles Caulier <caulier dot gilles at gmail dot com> -+ * Copyright (C) 2010 by Andi Clemens <andi dot clemens at gmail dot com> -+ * Copyright (C) 2011 by Michael G. Hansen <mike at mghansen dot de> -+ * Copyright (C) 2014 by Mohamed Anwer <m dot anwer at gmx dot com> -+ * -+ * This program is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU General -+ * Public License as published by the Free Software Foundation; -+ * either version 2, or (at your option) -+ * any later version. -+ * -+ * This program 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 General Public License for more details. -+ * -+ * ============================================================ */ -+ -+#ifndef IMAGEFILTERSETTINGS_H -+#define IMAGEFILTERSETTINGS_H -+ -+// Qt includes -+ -+#include <QHash> -+#include <QList> -+#include <QMap> -+#include <QString> -+#include <QSet> -+#include <QUrl> -+ -+// Local includes -+ -+#include "searchtextbar.h" -+#include "mimefilter.h" -+#include "digikam_export.h" -+ -+namespace Digikam -+{ -+ -+class ImageInfo; -+class VersionManagerSettings; -+ -+namespace DatabaseFields -+{ -+ class Set; -+} -+ -+// --------------------------------------------------------------------------------------- -+ -+class DIGIKAM_DATABASE_EXPORT SearchTextFilterSettings : public SearchTextSettings -+{ -+ -+public: -+ -+ enum TextFilterFields -+ { -+ None = 0x00, -+ ImageName = 0x01, -+ ImageTitle = 0x02, -+ ImageComment = 0x04, -+ TagName = 0x08, -+ AlbumName = 0x10, -+ ImageAspectRatio = 0x20, -+ ImagePixelSize = 0x40, -+ All = ImageName | ImageTitle | ImageComment | TagName | AlbumName | ImageAspectRatio | ImagePixelSize -+ }; -+ -+public: -+ -+ SearchTextFilterSettings() -+ { -+ textFields = None; -+ } -+ -+ explicit SearchTextFilterSettings(const SearchTextSettings& settings) -+ { -+ caseSensitive = settings.caseSensitive; -+ text = settings.text; -+ textFields = None; -+ } -+ -+ TextFilterFields textFields; -+}; -+ -+// --------------------------------------------------------------------------------------- -+ -+class DIGIKAM_DATABASE_EXPORT ImageFilterSettings -+{ -+public: -+ -+ ImageFilterSettings(); -+ -+ /** -+ * Returns true if the given ImageInfo matches the filter criteria. -+ * Optionally, foundText is set to true if it matched by text search. -+ */ -+ bool matches(const ImageInfo& info, bool* const foundText = 0) const; -+ -+public: -+ -+ /// --- Tags filter --- -+ -+ /// Possible logical matching condition used to sort tags id. -+ enum MatchingCondition -+ { -+ OrCondition, -+ AndCondition -+ }; -+ -+ void setTagFilter(const QList<int>& includedTags, -+ const QList<int>& excludedTags, -+ MatchingCondition matchingCond, -+ bool showUnTagged, -+ const QList<int>& clTagIds, -+ const QList<int>& plTagIds); -+ -+public: -+ -+ /// --- Rating filter --- -+ -+ /// Possible conditions used to filter rating: >=, =, <= -+ enum RatingCondition -+ { -+ GreaterEqualCondition, -+ EqualCondition, -+ LessEqualCondition -+ }; -+ -+ void setRatingFilter(int rating, RatingCondition ratingCond, bool isUnratedExcluded); -+ -+public: -+ -+ /// --- Date filter --- -+ void setDayFilter(const QList<QDateTime>& days); -+ -+public: -+ -+ /// --- Text filter --- -+ void setTextFilter(const SearchTextFilterSettings& settings); -+ void setTagNames(const QHash<int, QString>& tagNameHash); -+ void setAlbumNames(const QHash<int, QString>& albumNameHash); -+ -+public: -+ -+ /// --- Mime filter --- -+ void setMimeTypeFilter(int mimeTypeFilter); -+ -+public: -+ -+ /// --- Geolocation filter -+ enum GeolocationCondition -+ { -+ GeolocationNoFilter = 0, -+ GeolocationNoCoordinates = 1 << 1, -+ GeolocationHasCoordinates = 1 << 2 -+ }; -+ -+ void setGeolocationFilter(const GeolocationCondition& condition); -+ -+public: -+ -+ /// Returns if the day is a filter criteria -+ bool isFilteringByDay() const; -+ -+ /// Returns if the type mime is a filter criteria -+ bool isFilteringByTypeMime() const; -+ -+ /// Returns whether geolocation is a filter criteria -+ bool isFilteringByGeolocation() const; -+ -+ /// Returns if the rating is a filter criteria -+ bool isFilteringByRating() const; -+ -+ /// Returns if the pick labels is a filter criteria -+ bool isFilteringByPickLabels() const; -+ -+ /// Returns if the color labels is a filter criteria -+ bool isFilteringByColorLabels() const; -+ -+ /// Returns if the tag is a filter criteria -+ bool isFilteringByTags() const; -+ -+ /// Returns if the text (including comment) is a filter criteria -+ bool isFilteringByText() const; -+ -+ /// Returns if images will be filtered by these criteria at all -+ bool isFiltering() const; -+ -+public: -+ -+ /// --- URL whitelist filter -+ void setUrlWhitelist(const QList<QUrl>& urlList, const QString& id); -+ -+public: -+ -+ /// --- ID whitelist filter -+ void setIdWhitelist(const QList<qlonglong>& idList, const QString& id); -+ -+public: -+ -+ /// --- Change notification --- -+ -+ /** Returns database fields a change in which would affect the current filtering. -+ * To find out if an image tag change affects filtering, test isFilteringByTags(). -+ * The text filter will also be affected by changes in tags and album names. -+ */ -+ DatabaseFields::Set watchFlags() const; -+ -+private: -+ -+ /** -+ * @brief Returns whether some internal filtering (whitelist by id or URL) or normal filtering is going on -+ */ -+ bool isFilteringInternally() const; -+ -+private: -+ -+ /// --- Tags filter --- -+ bool m_untaggedFilter; -+ QList<int> m_includeTagFilter; -+ QList<int> m_excludeTagFilter; -+ MatchingCondition m_matchingCond; -+ QList<int> m_colorLabelTagFilter; -+ QList<int> m_pickLabelTagFilter; -+ -+ /// --- Rating filter --- -+ int m_ratingFilter; -+ RatingCondition m_ratingCond; -+ bool m_isUnratedExcluded; -+ -+ /// --- Date filter --- -+ QMap<QDateTime, bool> m_dayFilter; -+ -+ /// --- Text filter --- -+ SearchTextFilterSettings m_textFilterSettings; -+ -+ /// Helpers for text search: Set these if you want to search album or tag names with text search -+ QHash<int, QString> m_tagNameHash; -+ QHash<int, QString> m_albumNameHash; -+ -+ /// --- Mime filter --- -+ MimeFilter::TypeMimeFilter m_mimeTypeFilter; -+ -+ /// --- Geolocation filter -+ GeolocationCondition m_geolocationCondition; -+ -+ /// --- URL whitelist filter -+ QHash<QString,QList<QUrl>> m_urlWhitelists; -+ -+ /// --- ID whitelist filter -+ QHash<QString,QList<qlonglong> > m_idWhitelists; -+}; -+ -+// --------------------------------------------------------------------------------------- -+ -+class DIGIKAM_DATABASE_EXPORT VersionImageFilterSettings -+{ -+public: -+ -+ VersionImageFilterSettings(); -+ explicit VersionImageFilterSettings(const VersionManagerSettings& settings); -+ -+ bool operator==(const VersionImageFilterSettings& other) const; -+ -+ /** -+ * Returns true if the given ImageInfo matches the filter criteria. -+ */ -+ bool matches(const ImageInfo& info) const; -+ -+ bool isHiddenBySettings(const ImageInfo& info) const; -+ bool isExemptedBySettings(const ImageInfo& info) const; -+ -+ /// --- Tags filter --- -+ -+ void setVersionManagerSettings(const VersionManagerSettings& settings); -+ -+ /** -+ * Add list with exceptions: These images will be exempted from filtering by this filter -+ */ -+ void setExceptionList(const QList<qlonglong>& idlist, const QString& id); -+ -+ /// Returns if images will be filtered by these criteria at all -+ bool isFiltering() const; -+ -+ /// Returns if the tag is a filter criteria -+ bool isFilteringByTags() const; -+ -+ /// DatabaseFields::Set watchFlags() const: Would return 0 -+ -+protected: -+ -+ QList<int> m_excludeTagFilter; -+ int m_includeTagFilter; -+ int m_exceptionTagFilter; -+ QHash<QString,QList<qlonglong> > m_exceptionLists; -+}; -+ -+// --------------------------------------------------------------------------------------- -+ -+class DIGIKAM_DATABASE_EXPORT GroupImageFilterSettings -+{ -+public: -+ -+ GroupImageFilterSettings(); -+ -+ bool operator==(const GroupImageFilterSettings& other) const; -+ -+ /** -+ * Returns true if the given ImageInfo matches the filter criteria. -+ */ -+ bool matches(const ImageInfo& info) const; -+ -+ /** -+ * Open or close a group. -+ */ -+ void setOpen(qlonglong group, bool open); -+ bool isOpen(qlonglong group) const; -+ -+ /** -+ * Open all groups -+ */ -+ void setAllOpen(bool open); -+ bool isAllOpen() const; -+ -+ /// Returns if images will be filtered by these criteria at all -+ bool isFiltering() const; -+ -+ DatabaseFields::Set watchFlags() const; -+ -+protected: -+ -+ bool m_allOpen; -+ QSet<qlonglong> m_openGroups; -+}; -+ -+} // namespace Digikam -+ -+Q_DECLARE_METATYPE(Digikam::ImageFilterSettings::GeolocationCondition) -+ -+#endif // IMAGEFILTERSETTINGS_H -diff --git a/libs/database/models/imagelistmodel.cpp b/libs/database/models/imagelistmodel.cpp -new file mode 100644 -index 0000000..fafce34 ---- /dev/null -+++ b/libs/database/models/imagelistmodel.cpp -@@ -0,0 +1,70 @@ -+/* ============================================================ -+ * -+ * This file is a part of digiKam project -+ * http://www.digikam.org -+ * -+ * Date : 2010-12-06 -+ * Description : An image model based on a static list -+ * -+ * Copyright (C) 2010-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -+ * -+ * This program is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU General -+ * Public License as published by the Free Software Foundation; -+ * either version 2, or (at your option) -+ * any later version. -+ * -+ * This program 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 General Public License for more details. -+ * -+ * ============================================================ */ -+ -+#include "imagelistmodel.h" -+ -+// Local includes -+ -+#include "digikam_debug.h" -+#include "coredbaccess.h" -+#include "coredbchangesets.h" -+#include "coredbwatch.h" -+#include "imageinfo.h" -+#include "imageinfolist.h" -+ -+namespace Digikam -+{ -+ -+ImageListModel::ImageListModel(QObject* parent) -+ : ImageThumbnailModel(parent) -+{ -+ connect(CoreDbAccess::databaseWatch(), SIGNAL(collectionImageChange(CollectionImageChangeset)), -+ this, SLOT(slotCollectionImageChange(CollectionImageChangeset))); -+} -+ -+ImageListModel::~ImageListModel() -+{ -+} -+ -+void ImageListModel::slotCollectionImageChange(const CollectionImageChangeset& changeset) -+{ -+ if (isEmpty()) -+ { -+ return; -+ } -+ -+ switch (changeset.operation()) -+ { -+ case CollectionImageChangeset::Added: -+ break; -+ case CollectionImageChangeset::Removed: -+ case CollectionImageChangeset::RemovedAll: -+ removeImageInfos(ImageInfoList(changeset.ids())); -+ break; -+ -+ default: -+ break; -+ } -+} -+ -+} // namespace Digikam -diff --git a/libs/database/models/imagelistmodel.h b/libs/database/models/imagelistmodel.h -new file mode 100644 -index 0000000..a225b1b ---- /dev/null -+++ b/libs/database/models/imagelistmodel.h -@@ -0,0 +1,63 @@ -+/* ============================================================ -+ * -+ * This file is a part of digiKam project -+ * http://www.digikam.org -+ * -+ * Date : 2010-12-06 -+ * Description : An image model based on a static list -+ * -+ * Copyright (C) 2010-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -+ * -+ * This program is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU General -+ * Public License as published by the Free Software Foundation; -+ * either version 2, or (at your option) -+ * any later version. -+ * -+ * This program 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 General Public License for more details. -+ * -+ * ============================================================ */ -+ -+#ifndef IMAGELISTMODEL_H -+#define IMAGELISTMODEL_H -+ -+// Local includes -+ -+#include "imagethumbnailmodel.h" -+#include "digikam_export.h" -+ -+namespace Digikam -+{ -+ -+class ImageChangeset; -+class CollectionImageChangeset; -+ -+class DIGIKAM_DATABASE_EXPORT ImageListModel : public ImageThumbnailModel -+{ -+ Q_OBJECT -+ -+public: -+ -+ explicit ImageListModel(QObject* parent = 0); -+ ~ImageListModel(); -+ -+ // NOTE: necessary methods to add and remove ImageInfos to the model are inherited from ImageModel -+ -+Q_SIGNALS: -+ -+ /** -+ * Emitted when images are removed from the model because they are removed in the database -+ */ -+ void imageInfosRemoved(const QList<ImageInfo>& infos); -+ -+protected Q_SLOTS: -+ -+ void slotCollectionImageChange(const CollectionImageChangeset& changeset); -+}; -+ -+} // namespace Digikam -+ -+#endif // IMAGELISTMODEL_H -diff --git a/libs/database/models/imagemodel.cpp b/libs/database/models/imagemodel.cpp -new file mode 100644 -index 0000000..41b43cf ---- /dev/null -+++ b/libs/database/models/imagemodel.cpp -@@ -0,0 +1,1368 @@ -+/* ============================================================ -+ * -+ * This file is a part of digiKam project -+ * http://www.digikam.org -+ * -+ * Date : 2009-03-05 -+ * Description : Qt item model for database entries -+ * -+ * Copyright (C) 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -+ * -+ * This program is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU General -+ * Public License as published by the Free Software Foundation; -+ * either version 2, or (at your option) -+ * any later version. -+ * -+ * This program 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 General Public License for more details. -+ * -+ * ============================================================ */ -+ -+#include "imagemodel.h" -+ -+// Qt includes -+ -+#include <QHash> -+#include <QItemSelection> -+ -+// Local includes -+ -+#include "digikam_debug.h" -+#include "coredbchangesets.h" -+#include "coredbfields.h" -+#include "coredbwatch.h" -+#include "imageinfo.h" -+#include "imageinfolist.h" -+#include "abstractitemdragdrophandler.h" -+ -+namespace Digikam -+{ -+ -+class ImageModel::Private -+{ -+public: -+ -+ Private() -+ { -+ preprocessor = 0; -+ keepFilePathCache = false; -+ sendRemovalSignals = false; -+ incrementalUpdater = 0; -+ refreshing = false; -+ reAdding = false; -+ incrementalRefreshRequested = false; -+ } -+ -+ ImageInfoList infos; -+ QList<QVariant> extraValues; -+ QHash<qlonglong, int> idHash; -+ -+ bool keepFilePathCache; -+ QHash<QString, qlonglong> filePathHash; -+ -+ bool sendRemovalSignals; -+ -+ QObject* preprocessor; -+ bool refreshing; -+ bool reAdding; -+ bool incrementalRefreshRequested; -+ -+ DatabaseFields::Set watchFlags; -+ -+ class ImageModelIncrementalUpdater* incrementalUpdater; -+ -+ ImageInfoList pendingInfos; -+ QList<QVariant> pendingExtraValues; -+ -+ inline bool isValid(const QModelIndex& index) -+ { -+ if (!index.isValid()) -+ { -+ return false; -+ } -+ -+ if (index.row() < 0 || index.row() >= infos.size()) -+ { -+ qCDebug(DIGIKAM_GENERAL_LOG) << "Invalid index" << index; -+ return false; -+ } -+ -+ return true; -+ } -+ inline bool extraValueValid(const QModelIndex& index) -+ { -+ // we assume isValid() being called before, no duplicate checks -+ if (index.row() >= extraValues.size()) -+ { -+ qCDebug(DIGIKAM_GENERAL_LOG) << "Invalid index for extraData" << index; -+ return false; -+ } -+ -+ return true; -+ } -+}; -+ -+typedef QPair<int, int> IntPair; // to make foreach macro happy -+typedef QList<IntPair> IntPairList; -+ -+class ImageModelIncrementalUpdater -+{ -+public: -+ -+ explicit ImageModelIncrementalUpdater(ImageModel::Private* d); -+ -+ void appendInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues); -+ void aboutToBeRemovedInModel(const IntPairList& aboutToBeRemoved); -+ QList<IntPair> oldIndexes(); -+ -+ static QList<IntPair> toContiguousPairs(const QList<int>& ids); -+ -+public: -+ -+ QHash<qlonglong, int> oldIds; -+ QList<QVariant> oldExtraValues; -+ QList<ImageInfo> newInfos; -+ QList<QVariant> newExtraValues; -+ QList<IntPairList> modelRemovals; -+}; -+ -+ImageModel::ImageModel(QObject* parent) -+ : QAbstractListModel(parent), -+ d(new Private) -+{ -+ connect(CoreDbAccess::databaseWatch(), SIGNAL(imageChange(ImageChangeset)), -+ this, SLOT(slotImageChange(ImageChangeset))); -+ -+ connect(CoreDbAccess::databaseWatch(), SIGNAL(imageTagChange(ImageTagChangeset)), -+ this, SLOT(slotImageTagChange(ImageTagChangeset))); -+} -+ -+ImageModel::~ImageModel() -+{ -+ delete d->incrementalUpdater; -+ delete d; -+} -+ -+// ------------ Access methods ------------- -+ -+void ImageModel::setKeepsFilePathCache(bool keepCache) -+{ -+ d->keepFilePathCache = keepCache; -+} -+ -+bool ImageModel::keepsFilePathCache() const -+{ -+ return d->keepFilePathCache; -+} -+ -+bool ImageModel::isEmpty() const -+{ -+ return d->infos.isEmpty(); -+} -+ -+void ImageModel::setWatchFlags(const DatabaseFields::Set& set) -+{ -+ d->watchFlags = set; -+} -+ -+ImageInfo ImageModel::imageInfo(const QModelIndex& index) const -+{ -+ if (!d->isValid(index)) -+ { -+ return ImageInfo(); -+ } -+ -+ return d->infos.at(index.row()); -+} -+ -+ImageInfo& ImageModel::imageInfoRef(const QModelIndex& index) const -+{ -+ return d->infos[index.row()]; -+} -+ -+qlonglong ImageModel::imageId(const QModelIndex& index) const -+{ -+ if (!d->isValid(index)) -+ { -+ return 0; -+ } -+ -+ return d->infos.at(index.row()).id(); -+} -+ -+QList<ImageInfo> ImageModel::imageInfos(const QList<QModelIndex>& indexes) const -+{ -+ QList<ImageInfo> infos; -+ -+ foreach(const QModelIndex& index, indexes) -+ { -+ infos << imageInfo(index); -+ } -+ -+ return infos; -+} -+ -+QList<qlonglong> ImageModel::imageIds(const QList<QModelIndex>& indexes) const -+{ -+ QList<qlonglong> ids; -+ -+ foreach(const QModelIndex& index, indexes) -+ { -+ ids << imageId(index); -+ } -+ -+ return ids; -+} -+ -+ImageInfo ImageModel::imageInfo(int row) const -+{ -+ if (row >= d->infos.size()) -+ { -+ return ImageInfo(); -+ } -+ -+ return d->infos.at(row); -+} -+ -+ImageInfo& ImageModel::imageInfoRef(int row) const -+{ -+ return d->infos[row]; -+} -+ -+qlonglong ImageModel::imageId(int row) const -+{ -+ if (row < 0 || row >= d->infos.size()) -+ { -+ return -1; -+ } -+ -+ return d->infos.at(row).id(); -+} -+ -+QModelIndex ImageModel::indexForImageInfo(const ImageInfo& info) const -+{ -+ return indexForImageId(info.id()); -+} -+ -+QModelIndex ImageModel::indexForImageInfo(const ImageInfo& info, const QVariant& extraValue) const -+{ -+ return indexForImageId(info.id(), extraValue); -+} -+ -+QList<QModelIndex> ImageModel::indexesForImageInfo(const ImageInfo& info) const -+{ -+ return indexesForImageId(info.id()); -+} -+ -+QModelIndex ImageModel::indexForImageId(qlonglong id) const -+{ -+ int index = d->idHash.value(id, -1); -+ -+ if (index != -1) -+ { -+ return createIndex(index, 0); -+ } -+ -+ return QModelIndex(); -+} -+ -+QModelIndex ImageModel::indexForImageId(qlonglong id, const QVariant& extraValue) const -+{ -+ if (d->extraValues.isEmpty()) -+ return indexForImageId(id); -+ -+ QHash<qlonglong, int>::const_iterator it; -+ -+ for (it = d->idHash.constFind(id); it != d->idHash.constEnd() && it.key() == id; ++it) -+ { -+ if (d->extraValues.at(it.value()) == extraValue) -+ return createIndex(it.value(), 0); -+ } -+ -+ return QModelIndex(); -+} -+ -+QList<QModelIndex> ImageModel::indexesForImageId(qlonglong id) const -+{ -+ QList<QModelIndex> indexes; -+ QHash<qlonglong, int>::const_iterator it; -+ -+ for (it = d->idHash.constFind(id); it != d->idHash.constEnd() && it.key() == id; ++it) -+ { -+ indexes << createIndex(it.value(), 0); -+ } -+ -+ return indexes; -+} -+ -+int ImageModel::numberOfIndexesForImageInfo(const ImageInfo& info) const -+{ -+ return numberOfIndexesForImageId(info.id()); -+} -+ -+int ImageModel::numberOfIndexesForImageId(qlonglong id) const -+{ -+ if (d->extraValues.isEmpty()) -+ { -+ return 0; -+ } -+ -+ int count = 0; -+ QHash<qlonglong,int>::const_iterator it; -+ -+ for (it = d->idHash.constFind(id); it != d->idHash.constEnd() && it.key() == id; ++it) -+ { -+ ++count; -+ } -+ -+ return count; -+} -+ -+// static method -+ImageInfo ImageModel::retrieveImageInfo(const QModelIndex& index) -+{ -+ if (!index.isValid()) -+ { -+ return ImageInfo(); -+ } -+ -+ ImageModel* const model = index.data(ImageModelPointerRole).value<ImageModel*>(); -+ int row = index.data(ImageModelInternalId).toInt(); -+ -+ if (!model) -+ { -+ return ImageInfo(); -+ } -+ -+ return model->imageInfo(row); -+} -+ -+// static method -+qlonglong ImageModel::retrieveImageId(const QModelIndex& index) -+{ -+ if (!index.isValid()) -+ { -+ return 0; -+ } -+ -+ ImageModel* const model = index.data(ImageModelPointerRole).value<ImageModel*>(); -+ int row = index.data(ImageModelInternalId).toInt(); -+ -+ if (!model) -+ { -+ return 0; -+ } -+ -+ return model->imageId(row); -+} -+ -+QModelIndex ImageModel::indexForPath(const QString& filePath) const -+{ -+ if (d->keepFilePathCache) -+ { -+ return indexForImageId(d->filePathHash.value(filePath)); -+ } -+ else -+ { -+ const int size = d->infos.size(); -+ -+ for (int i=0; i<size; ++i) -+ { -+ if (d->infos.at(i).filePath() == filePath) -+ { -+ return createIndex(i, 0); -+ } -+ } -+ } -+ -+ return QModelIndex(); -+} -+ -+QList<QModelIndex> ImageModel::indexesForPath(const QString& filePath) const -+{ -+ if (d->keepFilePathCache) -+ { -+ return indexesForImageId(d->filePathHash.value(filePath)); -+ } -+ else -+ { -+ QList<QModelIndex> indexes; -+ const int size = d->infos.size(); -+ -+ for (int i=0; i<size; ++i) -+ { -+ if (d->infos.at(i).filePath() == filePath) -+ { -+ indexes << createIndex(i, 0); -+ } -+ } -+ -+ return indexes; -+ } -+} -+ -+ImageInfo ImageModel::imageInfo(const QString& filePath) const -+{ -+ if (d->keepFilePathCache) -+ { -+ qlonglong id = d->filePathHash.value(filePath); -+ -+ if (id) -+ { -+ int index = d->idHash.value(id, -1); -+ -+ if (index != -1) -+ { -+ return d->infos.at(index); -+ } -+ } -+ } -+ else -+ { -+ foreach(const ImageInfo& info, d->infos) -+ { -+ if (info.filePath() == filePath) -+ { -+ return info; -+ } -+ } -+ } -+ -+ return ImageInfo(); -+} -+ -+QList<ImageInfo> ImageModel::imageInfos(const QString& filePath) const -+{ -+ QList<ImageInfo> infos; -+ -+ if (d->keepFilePathCache) -+ { -+ qlonglong id = d->filePathHash.value(filePath); -+ -+ if (id) -+ { -+ foreach(int index, d->idHash.values(id)) -+ { -+ infos << d->infos.at(index); -+ } -+ } -+ } -+ else -+ { -+ foreach(const ImageInfo& info, d->infos) -+ { -+ if (info.filePath() == filePath) -+ { -+ infos << info; -+ } -+ } -+ } -+ -+ return infos; -+} -+ -+void ImageModel::addImageInfo(const ImageInfo& info) -+{ -+ addImageInfos(QList<ImageInfo>() << info, QList<QVariant>()); -+} -+ -+void ImageModel::addImageInfos(const QList<ImageInfo>& infos) -+{ -+ addImageInfos(infos, QList<QVariant>()); -+} -+ -+void ImageModel::addImageInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues) -+{ -+ if (infos.isEmpty()) -+ { -+ return; -+ } -+ -+ if (d->incrementalUpdater) -+ { -+ d->incrementalUpdater->appendInfos(infos, extraValues); -+ } -+ else -+ { -+ appendInfos(infos, extraValues); -+ } -+} -+ -+void ImageModel::addImageInfoSynchronously(const ImageInfo& info) -+{ -+ addImageInfosSynchronously(QList<ImageInfo>() << info, QList<QVariant>()); -+} -+ -+void ImageModel::addImageInfosSynchronously(const QList<ImageInfo>& infos) -+{ -+ addImageInfos(infos, QList<QVariant>()); -+} -+ -+void ImageModel::addImageInfosSynchronously(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues) -+{ -+ if (infos.isEmpty()) -+ { -+ return; -+ } -+ -+ publiciseInfos(infos, extraValues); -+ emit processAdded(infos, extraValues); -+} -+ -+void ImageModel::ensureHasImageInfo(const ImageInfo& info) -+{ -+ ensureHasImageInfos(QList<ImageInfo>() << info, QList<QVariant>()); -+} -+ -+void ImageModel::ensureHasImageInfos(const QList<ImageInfo>& infos) -+{ -+ ensureHasImageInfos(infos, QList<QVariant>()); -+} -+ -+void ImageModel::ensureHasImageInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues) -+{ -+ if (extraValues.isEmpty()) -+ { -+ if (!d->pendingExtraValues.isEmpty()) -+ { -+ qCDebug(DIGIKAM_GENERAL_LOG) << "ExtraValue / No Extra Value mismatch. Ignoring added infos."; -+ return; -+ } -+ } -+ else -+ { -+ if (d->pendingInfos.size() != d->pendingExtraValues.size()) -+ { -+ qCDebug(DIGIKAM_GENERAL_LOG) << "ExtraValue / No Extra Value mismatch. Ignoring added infos."; -+ return; -+ } -+ } -+ -+ d->pendingInfos << infos; -+ d->pendingExtraValues << extraValues; -+ cleanSituationChecks(); -+} -+ -+void ImageModel::clearImageInfos() -+{ -+ d->infos.clear(); -+ d->extraValues.clear(); -+ d->idHash.clear(); -+ d->filePathHash.clear(); -+ delete d->incrementalUpdater; -+ d->incrementalUpdater = 0; -+ d->pendingInfos.clear(); -+ d->pendingExtraValues.clear(); -+ d->refreshing = false; -+ d->reAdding = false; -+ d->incrementalRefreshRequested = false; -+ -+ beginResetModel(); -+ endResetModel(); -+ -+ imageInfosCleared(); -+} -+ -+void ImageModel::setImageInfos(const QList<ImageInfo>& infos) -+{ -+ clearImageInfos(); -+ addImageInfos(infos); -+} -+ -+QList<ImageInfo> ImageModel::imageInfos() const -+{ -+ return d->infos; -+} -+ -+QList<qlonglong> ImageModel::imageIds() const -+{ -+ return d->idHash.keys(); -+} -+ -+bool ImageModel::hasImage(qlonglong id) const -+{ -+ return d->idHash.contains(id); -+} -+ -+bool ImageModel::hasImage(const ImageInfo& info) const -+{ -+ return d->idHash.contains(info.id()); -+} -+ -+bool ImageModel::hasImage(const ImageInfo& info, const QVariant& extraValue) const -+{ -+ return hasImage(info.id(), extraValue); -+} -+ -+bool ImageModel::hasImage(qlonglong id, const QVariant& extraValue) const -+{ -+ if (d->extraValues.isEmpty()) -+ return hasImage(id); -+ -+ QHash<qlonglong, int>::const_iterator it; -+ -+ for (it = d->idHash.constFind(id); it != d->idHash.constEnd() && it.key() == id; ++it) -+ { -+ if (d->extraValues.at(it.value()) == extraValue) -+ return true; -+ } -+ -+ return false;; -+} -+ -+QList<ImageInfo> ImageModel::uniqueImageInfos() const -+{ -+ if (d->extraValues.isEmpty()) -+ { -+ return d->infos; -+ } -+ -+ QList<ImageInfo> uniqueInfos; -+ const int size = d->infos.size(); -+ -+ for (int i=0; i<size; ++i) -+ { -+ const ImageInfo& info = d->infos.at(i); -+ -+ if (d->idHash.value(info.id()) == i) -+ { -+ uniqueInfos << info; -+ } -+ } -+ -+ return uniqueInfos; -+} -+ -+void ImageModel::emitDataChangedForAll() -+{ -+ if (d->infos.isEmpty()) -+ { -+ return; -+ } -+ -+ QModelIndex first = createIndex(0, 0); -+ QModelIndex last = createIndex(d->infos.size() - 1, 0); -+ emit dataChanged(first, last); -+} -+ -+void ImageModel::emitDataChangedForSelection(const QItemSelection& selection) -+{ -+ if (!selection.isEmpty()) -+ { -+ foreach(const QItemSelectionRange& range, selection) -+ { -+ emit dataChanged(range.topLeft(), range.bottomRight()); -+ } -+ } -+} -+ -+void ImageModel::ensureHasGroupedImages(const ImageInfo& groupLeader) -+{ -+ ensureHasImageInfos(groupLeader.groupedImages()); -+} -+ -+// ------------ Preprocessing ------------- -+ -+void ImageModel::setPreprocessor(QObject* preprocessor) -+{ -+ unsetPreprocessor(d->preprocessor); -+ d->preprocessor = preprocessor; -+} -+ -+void ImageModel::unsetPreprocessor(QObject* preprocessor) -+{ -+ if (preprocessor && d->preprocessor == preprocessor) -+ { -+ disconnect(this, SIGNAL(preprocess(QList<ImageInfo>,QList<QVariant>)), 0, 0); -+ disconnect(d->preprocessor, 0, this, SLOT(reAddImageInfos(QList<ImageInfo>,QList<QVariant>))); -+ disconnect(d->preprocessor, 0, this, SLOT(reAddingFinished())); -+ } -+} -+ -+void ImageModel::appendInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues) -+{ -+ if (infos.isEmpty()) -+ { -+ return; -+ } -+ -+ if (d->preprocessor) -+ { -+ d->reAdding = true; -+ emit preprocess(infos, extraValues); -+ } -+ else -+ { -+ publiciseInfos(infos, extraValues); -+ } -+} -+ -+void ImageModel::appendInfosChecked(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues) -+{ -+ // This method does deduplication. It is private because in context of readding or refreshing it is of no use. -+ -+ if (extraValues.isEmpty()) -+ { -+ QList<ImageInfo> checkedInfos; -+ -+ foreach (const ImageInfo& info, infos) -+ { -+ if (!hasImage(info)) -+ { -+ checkedInfos << info; -+ } -+ } -+ -+ appendInfos(checkedInfos, QList<QVariant>()); -+ } -+ else -+ { -+ QList<ImageInfo> checkedInfos; -+ QList<QVariant> checkedExtraValues; -+ const int size = infos.size(); -+ -+ for (int i=0; i<size; i++) -+ { -+ if (!hasImage(infos[i], extraValues[i])) -+ { -+ checkedInfos << infos[i]; -+ checkedExtraValues << extraValues[i]; -+ } -+ } -+ -+ appendInfos(checkedInfos, checkedExtraValues); -+ } -+} -+ -+void ImageModel::reAddImageInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues) -+{ -+ // addImageInfos -> appendInfos -> preprocessor -> reAddImageInfos -+ publiciseInfos(infos, extraValues); -+} -+ -+void ImageModel::reAddingFinished() -+{ -+ d->reAdding = false; -+ cleanSituationChecks(); -+} -+ -+void ImageModel::startRefresh() -+{ -+ d->refreshing = true; -+} -+ -+void ImageModel::finishRefresh() -+{ -+ d->refreshing = false; -+ cleanSituationChecks(); -+} -+ -+bool ImageModel::isRefreshing() const -+{ -+ return d->refreshing; -+} -+ -+void ImageModel::cleanSituationChecks() -+{ -+ // For starting an incremental refresh we want a clear situation: -+ // Any remaining batches from non-incremental refreshing subclasses have been received in appendInfos(), -+ // any batches sent to preprocessor for re-adding have been re-added. -+ if (d->refreshing || d->reAdding) -+ { -+ return; -+ } -+ -+ if (!d->pendingInfos.isEmpty()) -+ { -+ appendInfosChecked(d->pendingInfos, d->pendingExtraValues); -+ d->pendingInfos.clear(); -+ d->pendingExtraValues.clear(); -+ cleanSituationChecks(); -+ return; -+ } -+ -+ if (d->incrementalRefreshRequested) -+ { -+ d->incrementalRefreshRequested = false; -+ emit readyForIncrementalRefresh(); -+ } -+ else -+ { -+ emit allRefreshingFinished(); -+ } -+} -+ -+void ImageModel::publiciseInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues) -+{ -+ if (infos.isEmpty()) -+ { -+ return; -+ } -+ -+ Q_ASSERT(infos.size() == extraValues.size() || (extraValues.isEmpty() && d->extraValues.isEmpty())); -+ -+ emit imageInfosAboutToBeAdded(infos); -+ const int firstNewIndex = d->infos.size(); -+ const int lastNewIndex = d->infos.size() + infos.size() - 1; -+ beginInsertRows(QModelIndex(), firstNewIndex, lastNewIndex); -+ d->infos << infos; -+ d->extraValues << extraValues; -+ -+ for (int i=firstNewIndex; i<=lastNewIndex; ++i) -+ { -+ const ImageInfo& info = d->infos.at(i); -+ qlonglong id = info.id(); -+ d->idHash.insertMulti(id, i); -+ -+ if (d->keepFilePathCache) -+ { -+ d->filePathHash[info.filePath()] = id; -+ } -+ } -+ -+ endInsertRows(); -+ emit imageInfosAdded(infos); -+} -+ -+void ImageModel::requestIncrementalRefresh() -+{ -+ if (d->reAdding) -+ { -+ d->incrementalRefreshRequested = true; -+ } -+ else -+ { -+ emit readyForIncrementalRefresh(); -+ } -+} -+ -+bool ImageModel::hasIncrementalRefreshPending() const -+{ -+ return d->incrementalRefreshRequested; -+} -+ -+void ImageModel::startIncrementalRefresh() -+{ -+ delete d->incrementalUpdater; -+ -+ d->incrementalUpdater = new ImageModelIncrementalUpdater(d); -+} -+ -+void ImageModel::finishIncrementalRefresh() -+{ -+ if (!d->incrementalUpdater) -+ { -+ return; -+ } -+ -+ // remove old entries -+ QList<QPair<int, int> > pairs = d->incrementalUpdater->oldIndexes(); -+ removeRowPairs(pairs); -+ -+ // add new indexes -+ appendInfos(d->incrementalUpdater->newInfos, d->incrementalUpdater->newExtraValues); -+ -+ delete d->incrementalUpdater; -+ d->incrementalUpdater = 0; -+} -+ -+void ImageModel::removeIndex(const QModelIndex& index) -+{ -+ removeIndexes(QList<QModelIndex>() << index); -+} -+ -+void ImageModel::removeIndexes(const QList<QModelIndex>& indexes) -+{ -+ QList<int> listIndexes; -+ -+ foreach(const QModelIndex& index, indexes) -+ { -+ if (d->isValid(index)) -+ { -+ listIndexes << index.row(); -+ } -+ } -+ -+ if (listIndexes.isEmpty()) -+ { -+ return; -+ } -+ -+ removeRowPairsWithCheck(ImageModelIncrementalUpdater::toContiguousPairs(listIndexes)); -+} -+ -+void ImageModel::removeImageInfo(const ImageInfo& info) -+{ -+ removeImageInfos(QList<ImageInfo>() << info); -+} -+ -+void ImageModel::removeImageInfos(const QList<ImageInfo>& infos) -+{ -+ QList<int> listIndexes; -+ -+ foreach(const ImageInfo& info, infos) -+ { -+ QModelIndex index = indexForImageId(info.id()); -+ -+ if (index.isValid()) -+ { -+ listIndexes << index.row(); -+ } -+ } -+ removeRowPairsWithCheck(ImageModelIncrementalUpdater::toContiguousPairs(listIndexes)); -+} -+ -+void ImageModel::removeImageInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues) -+{ -+ if (extraValues.isEmpty()) -+ { -+ removeImageInfos(infos); -+ return; -+ } -+ -+ QList<int> listIndexes; -+ -+ for (int i=0; i<infos.size(); ++i) -+ { -+ QModelIndex index = indexForImageId(infos.at(i).id(), extraValues.at(i)); -+ -+ if (index.isValid()) -+ { -+ listIndexes << index.row(); -+ } -+ } -+ -+ removeRowPairsWithCheck(ImageModelIncrementalUpdater::toContiguousPairs(listIndexes)); -+} -+ -+void ImageModel::setSendRemovalSignals(bool send) -+{ -+ d->sendRemovalSignals = send; -+} -+ -+template <class List, typename T> -+static bool pairsContain(const List& list, T value) -+{ -+ typename List::const_iterator middle; -+ typename List::const_iterator begin = list.begin(); -+ typename List::const_iterator end = list.end(); -+ int n = int(end - begin); -+ int half; -+ -+ while (n > 0) -+ { -+ half = n >> 1; -+ middle = begin + half; -+ -+ if (middle->first <= value && middle->second >= value) -+ { -+ return true; -+ } -+ else if (middle->second < value) -+ { -+ begin = middle + 1; -+ n -= half + 1; -+ } -+ else -+ { -+ n = half; -+ } -+ } -+ -+ return false; -+} -+ -+void ImageModel::removeRowPairsWithCheck(const QList<QPair<int, int> >& toRemove) -+{ -+ if (d->incrementalUpdater) -+ { -+ d->incrementalUpdater->aboutToBeRemovedInModel(toRemove); -+ } -+ -+ removeRowPairs(toRemove); -+} -+ -+void ImageModel::removeRowPairs(const QList<QPair<int, int> >& toRemove) -+{ -+ if (toRemove.isEmpty()) -+ { -+ return; -+ } -+ -+ // Remove old indexes -+ // Keep in mind that when calling beginRemoveRows all structures announced to be removed -+ // must still be valid, and this includes our hashes as well, which limits what we can optimize -+ -+ int removedRows = 0, offset = 0; -+ typedef QPair<int, int> IntPair; // to make foreach macro happy -+ -+ foreach(const IntPair& pair, toRemove) -+ { -+ const int begin = pair.first - offset; -+ const int end = pair.second - offset; // inclusive -+ removedRows = end - begin + 1; -+ -+ // when removing from the list, all subsequent indexes are affected -+ offset += removedRows; -+ -+ QList<ImageInfo> removedInfos; -+ -+ if (d->sendRemovalSignals) -+ { -+ qCopy(d->infos.begin() + begin, d->infos.begin() + end, removedInfos.begin()); -+ emit imageInfosAboutToBeRemoved(removedInfos); -+ } -+ -+ imageInfosAboutToBeRemoved(begin, end); -+ beginRemoveRows(QModelIndex(), begin, end); -+ -+ // update idHash - which points to indexes of d->infos, and these change now! -+ QHash<qlonglong, int>::iterator it; -+ -+ for (it = d->idHash.begin(); it != d->idHash.end(); ) -+ { -+ if (it.value() >= begin) -+ { -+ if (it.value() > end) -+ { -+ // after the removed interval: adjust index -+ it.value() -= removedRows; -+ } -+ else -+ { -+ // in the removed interval -+ it = d->idHash.erase(it); -+ continue; -+ } -+ } -+ -+ ++it; -+ } -+ -+ // remove from list -+ d->infos.erase(d->infos.begin() + begin, d->infos.begin() + (end + 1)); -+ -+ if (!d->extraValues.isEmpty()) -+ { -+ d->extraValues.erase(d->extraValues.begin() + begin, d->extraValues.begin() + (end + 1)); -+ } -+ -+ endRemoveRows(); -+ -+ if (d->sendRemovalSignals) -+ { -+ emit imageInfosRemoved(removedInfos); -+ } -+ } -+ -+ // tidy up: remove old indexes from file path hash now -+ if (d->keepFilePathCache) -+ { -+ QHash<QString, qlonglong>::iterator it; -+ -+ for (it = d->filePathHash.begin(); it != d->filePathHash.end(); ) -+ { -+ if (pairsContain(toRemove, it.value())) -+ { -+ it = d->filePathHash.erase(it); -+ } -+ else -+ { -+ ++it; -+ } -+ } -+ } -+} -+ -+ImageModelIncrementalUpdater::ImageModelIncrementalUpdater(ImageModel::Private* d) -+{ -+ oldIds = d->idHash; -+ oldExtraValues = d->extraValues; -+} -+ -+void ImageModelIncrementalUpdater::appendInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues) -+{ -+ if (extraValues.isEmpty()) -+ { -+ foreach(const ImageInfo& info, infos) -+ { -+ QHash<qlonglong,int>::iterator it = oldIds.find(info.id()); -+ -+ if (it != oldIds.end()) -+ { -+ oldIds.erase(it); -+ } -+ else -+ { -+ newInfos << info; -+ } -+ } -+ } -+ else -+ { -+ for (int i=0; i<infos.size(); ++i) -+ { -+ const ImageInfo& info = infos.at(i); -+ bool found = false; -+ QHash<qlonglong,int>::iterator it; -+ -+ for (it = oldIds.find(info.id()); it != oldIds.end() && it.key() == info.id(); ++it) -+ { -+ // first check is for bug #262596. Not sure if needed. -+ if (it.value() < oldExtraValues.size() && extraValues.at(i) == oldExtraValues.at(it.value())) -+ { -+ found = true; -+ break; -+ } -+ } -+ -+ if (found) -+ { -+ oldIds.erase(it); -+ // do not erase from oldExtraValues - oldIds is a hash id -> index. -+ } -+ else -+ { -+ newInfos << info; -+ newExtraValues << extraValues.at(i); -+ } -+ } -+ } -+} -+ -+void ImageModelIncrementalUpdater::aboutToBeRemovedInModel(const IntPairList& toRemove) -+{ -+ modelRemovals << toRemove; -+} -+ -+QList<QPair<int, int> > ImageModelIncrementalUpdater::oldIndexes() -+{ -+ // first, apply all changes to indexes by direct removal in model -+ // while the updater was active -+ foreach(const IntPairList& list, modelRemovals) -+ { -+ int removedRows = 0, offset = 0; -+ -+ foreach(const IntPair& pair, list) -+ { -+ const int begin = pair.first - offset; -+ const int end = pair.second - offset; // inclusive -+ removedRows = end - begin + 1; -+ -+ // when removing from the list, all subsequent indexes are affected -+ offset += removedRows; -+ -+ // update idHash - which points to indexes of d->infos, and these change now! -+ QHash<qlonglong, int>::iterator it; -+ -+ for (it = oldIds.begin(); it != oldIds.end(); ) -+ { -+ if (it.value() >= begin) -+ { -+ if (it.value() > end) -+ { -+ // after the removed interval: adjust index -+ it.value() -= removedRows; -+ } -+ else -+ { -+ // in the removed interval -+ it = oldIds.erase(it); -+ continue; -+ } -+ } -+ -+ ++it; -+ } -+ } -+ } -+ -+ modelRemovals.clear(); -+ -+ return toContiguousPairs(oldIds.values()); -+} -+ -+QList<QPair<int, int> > ImageModelIncrementalUpdater::toContiguousPairs(const QList<int>& unsorted) -+{ -+ // Take the given indices and return them as contiguous pairs [begin, end] -+ -+ QList<QPair<int, int> > pairs; -+ -+ if (unsorted.isEmpty()) -+ { -+ return pairs; -+ } -+ -+ QList<int> indices(unsorted); -+ qSort(indices); -+ -+ QPair<int, int> pair(indices.first(), indices.first()); -+ -+ for (int i=1; i<indices.size(); ++i) -+ { -+ const int &index = indices.at(i); -+ -+ if (index == pair.second + 1) -+ { -+ pair.second = index; -+ continue; -+ } -+ -+ pairs << pair; // insert last pair -+ pair.first = index; -+ pair.second = index; -+ } -+ -+ pairs << pair; -+ -+ return pairs; -+} -+ -+// ------------ QAbstractItemModel implementation ------------- -+ -+QVariant ImageModel::data(const QModelIndex& index, int role) const -+{ -+ if (!d->isValid(index)) -+ { -+ return QVariant(); -+ } -+ -+ switch (role) -+ { -+ case Qt::DisplayRole: -+ case Qt::ToolTipRole: -+ return d->infos.at(index.row()).name(); -+ -+ case ImageModelPointerRole: -+ return QVariant::fromValue(const_cast<ImageModel*>(this)); -+ -+ case ImageModelInternalId: -+ return index.row(); -+ -+ case CreationDateRole: -+ return d->infos.at(index.row()).dateTime(); -+ -+ case ExtraDataRole: -+ -+ if (d->extraValueValid(index)) -+ { -+ return d->extraValues.at(index.row()); -+ } -+ else -+ { -+ return QVariant(); -+ } -+ -+ case ExtraDataDuplicateCount: -+ { -+ qlonglong id = d->infos.at(index.row()).id(); -+ return numberOfIndexesForImageId(id); -+ } -+ } -+ -+ return QVariant(); -+} -+ -+QVariant ImageModel::headerData(int section, Qt::Orientation orientation, int role) const -+{ -+ Q_UNUSED(section) -+ Q_UNUSED(orientation) -+ Q_UNUSED(role) -+ return QVariant(); -+} -+ -+int ImageModel::rowCount(const QModelIndex& parent) const -+{ -+ if (parent.isValid()) -+ { -+ return 0; -+ } -+ -+ return d->infos.size(); -+} -+ -+Qt::ItemFlags ImageModel::flags(const QModelIndex& index) const -+{ -+ if (!d->isValid(index)) -+ { -+ return 0; -+ } -+ -+ Qt::ItemFlags f = Qt::ItemIsSelectable | Qt::ItemIsEnabled; -+ -+ f |= dragDropFlags(index); -+ -+ return f; -+} -+ -+QModelIndex ImageModel::index(int row, int column, const QModelIndex& parent) const -+{ -+ if (column != 0 || row < 0 || parent.isValid() || row >= d->infos.size()) -+ { -+ return QModelIndex(); -+ } -+ -+ return createIndex(row, 0); -+} -+ -+// ------------ Database watch ------------- -+ -+void ImageModel::slotImageChange(const ImageChangeset& changeset) -+{ -+ if (d->infos.isEmpty()) -+ { -+ return; -+ } -+ -+ if (d->watchFlags & changeset.changes()) -+ { -+ QItemSelection items; -+ -+ foreach(const qlonglong& id, changeset.ids()) -+ { -+ QModelIndex index = indexForImageId(id); -+ -+ if (index.isValid()) -+ { -+ items.select(index, index); -+ } -+ } -+ -+ if (!items.isEmpty()) -+ { -+ emitDataChangedForSelection(items); -+ emit imageChange(changeset, items); -+ } -+ } -+} -+ -+void ImageModel::slotImageTagChange(const ImageTagChangeset& changeset) -+{ -+ if (d->infos.isEmpty()) -+ { -+ return; -+ } -+ -+ QItemSelection items; -+ -+ foreach(const qlonglong& id, changeset.ids()) -+ { -+ QModelIndex index = indexForImageId(id); -+ -+ if (index.isValid()) -+ { -+ items.select(index, index); -+ } -+ } -+ -+ if (!items.isEmpty()) -+ { -+ emitDataChangedForSelection(items); -+ emit imageTagChange(changeset, items); -+ } -+} -+ -+} // namespace Digikam -diff --git a/libs/database/models/imagemodel.h b/libs/database/models/imagemodel.h -new file mode 100644 -index 0000000..dcf94c2 ---- /dev/null -+++ b/libs/database/models/imagemodel.h -@@ -0,0 +1,364 @@ -+/* ============================================================ -+ * -+ * This file is a part of digiKam project -+ * http://www.digikam.org -+ * -+ * Date : 2009-03-05 -+ * Description : Qt item model for database entries -+ * -+ * Copyright (C) 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -+ * -+ * This program is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU General -+ * Public License as published by the Free Software Foundation; -+ * either version 2, or (at your option) -+ * any later version. -+ * -+ * This program 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 General Public License for more details. -+ * -+ * ============================================================ */ -+ -+#ifndef IMAGEMODEL_H -+#define IMAGEMODEL_H -+ -+// Qt includes -+ -+#include <QAbstractListModel> -+ -+// Local includes -+ -+#include "dragdropimplementations.h" -+#include "imageinfo.h" -+#include "digikam_export.h" -+ -+class QItemSelection; -+ -+namespace Digikam -+{ -+ -+class ImageChangeset; -+class ImageTagChangeset; -+ -+namespace DatabaseFields -+{ -+class Set; -+} -+ -+class DIGIKAM_DATABASE_EXPORT ImageModel : public QAbstractListModel, public DragDropModelImplementation -+{ -+ Q_OBJECT -+ -+public: -+ -+ enum ImageModelRoles -+ { -+ /// An ImageModel* pointer to this model -+ ImageModelPointerRole = Qt::UserRole, -+ ImageModelInternalId = Qt::UserRole + 1, -+ /// Returns a thumbnail pixmap. May be implemented by subclasses. -+ /// Returns either a valid pixmap or a null QVariant. -+ ThumbnailRole = Qt::UserRole + 2, -+ /// Returns a QDateTime with the creation date -+ CreationDateRole = Qt::UserRole + 3, -+ /// Return (optional) extraData field -+ ExtraDataRole = Qt::UserRole + 5, -+ /// Returns the number of duplicate indexes for the same image id -+ ExtraDataDuplicateCount = Qt::UserRole + 6, -+ -+ // Roles which are defined here but not implemented by ImageModel -+ /// Returns position of item in Left Light Table preview. -+ LTLeftPanelRole = Qt::UserRole + 50, -+ /// Returns position of item in Right Light Table preview. -+ LTRightPanelRole = Qt::UserRole + 51, -+ -+ // For use by subclasses -+ SubclassRoles = Qt::UserRole + 100, -+ // For use by filter models -+ FilterModelRoles = Qt::UserRole + 500 -+ }; -+ -+public: -+ -+ explicit ImageModel(QObject* parent = 0); -+ ~ImageModel(); -+ -+ /** If a cache is kept, lookup by file path is fast, -+ * without a cache it is O(n). Default is false. -+ */ -+ void setKeepsFilePathCache(bool keepCache); -+ bool keepsFilePathCache() const; -+ -+ /** Set a set of database fields to watch. -+ * If either of these is changed, dataChanged() will be emitted. -+ * Default is no flag (no signal will be emitted). -+ */ -+ void setWatchFlags(const DatabaseFields::Set& set); -+ -+ /** Returns the ImageInfo object, reference or image id from the underlying data -+ * pointed to by the index. -+ * If the index is not valid, imageInfo will return a null ImageInfo, imageId will -+ * return 0, imageInfoRef must not be called with an invalid index. -+ */ -+ ImageInfo imageInfo(const QModelIndex& index) const; -+ ImageInfo& imageInfoRef(const QModelIndex& index) const; -+ qlonglong imageId(const QModelIndex& index) const; -+ QList<ImageInfo> imageInfos(const QList<QModelIndex>& indexes) const; -+ QList<qlonglong> imageIds(const QList<QModelIndex>& indexes) const; -+ -+ /** Returns the ImageInfo object, reference or image id from the underlying data -+ * of the given row (parent is the invalid QModelIndex, column is 0). -+ * Note that imageInfoRef will crash if index is invalid. -+ */ -+ ImageInfo imageInfo(int row) const; -+ ImageInfo& imageInfoRef(int row) const; -+ qlonglong imageId(int row) const; -+ -+ /** Return the index for the given ImageInfo or id, if contained in this model. -+ */ -+ QModelIndex indexForImageInfo(const ImageInfo& info) const; -+ QModelIndex indexForImageInfo(const ImageInfo& info, const QVariant& extraValue) const; -+ QModelIndex indexForImageId(qlonglong id) const; -+ QModelIndex indexForImageId(qlonglong id, const QVariant& extraValue) const; -+ QList<QModelIndex> indexesForImageInfo(const ImageInfo& info) const; -+ QList<QModelIndex> indexesForImageId(qlonglong id) const; -+ -+ int numberOfIndexesForImageInfo(const ImageInfo& info) const; -+ int numberOfIndexesForImageId(qlonglong id) const; -+ -+ /** Returns the index or ImageInfo object from the underlying data -+ * for the given file path. This is fast if keepsFilePathCache is enabled. -+ * The file path is as returned by ImageInfo.filePath(). -+ * In case of multiple occurrences of the same file, the simpler variants return -+ * any one found first, use the QList methods to retrieve all occurrences. -+ */ -+ QModelIndex indexForPath(const QString& filePath) const; -+ ImageInfo imageInfo(const QString& filePath) const; -+ QList<QModelIndex> indexesForPath(const QString& filePath) const; -+ QList<ImageInfo> imageInfos(const QString& filePath) const; -+ -+ /** Main entry point for subclasses adding image infos to the model. -+ * If you list entries not unique per image id, you must add an extraValue -+ * so that every entry is unique by imageId and extraValues. -+ * Please note that these methods do not prevent addition of duplicate entries. -+ */ -+ void addImageInfo(const ImageInfo& info); -+ void addImageInfos(const QList<ImageInfo>& infos); -+ void addImageInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues); -+ -+ /** Clears image infos and resets model. -+ */ -+ void clearImageInfos(); -+ -+ /** Clears and adds the infos. -+ */ -+ void setImageInfos(const QList<ImageInfo>& infos); -+ -+ /** -+ * Directly remove the given indexes or infos from the model. -+ */ -+ void removeIndex(const QModelIndex& indexes); -+ void removeIndexes(const QList<QModelIndex>& indexes); -+ void removeImageInfo(const ImageInfo& info); -+ void removeImageInfos(const QList<ImageInfo>& infos); -+ void removeImageInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues); -+ -+ /** -+ * addImageInfo() is asynchronous if a prepocessor is set. -+ * This method first adds the info, synchronously. -+ * Only afterwards, the preprocessor will have the opportunity to process it. -+ * This method also bypasses any incremental updates. -+ * Please note that these methods do not prevent addition of duplicate entries. -+ */ -+ void addImageInfoSynchronously(const ImageInfo& info); -+ void addImageInfosSynchronously(const QList<ImageInfo>& infos); -+ void addImageInfosSynchronously(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues); -+ -+ /** -+ * Add the given entries. Method returns immediately, the -+ * addition may happen later asynchronously. -+ * These methods prevent the addition of duplicate entries. -+ */ -+ void ensureHasImageInfo(const ImageInfo& info); -+ void ensureHasImageInfos(const QList<ImageInfo>& infos); -+ void ensureHasImageInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues); -+ -+ /** -+ * Ensure that all images grouped on the given leader are contained in the model. -+ */ -+ void ensureHasGroupedImages(const ImageInfo& groupLeader); -+ -+ QList<ImageInfo> imageInfos() const; -+ QList<qlonglong> imageIds() const; -+ QList<ImageInfo> uniqueImageInfos() const; -+ -+ bool hasImage(qlonglong id) const; -+ bool hasImage(const ImageInfo& info) const; -+ bool hasImage(const ImageInfo& info, const QVariant& extraValue) const; -+ bool hasImage(qlonglong id, const QVariant& extraValue) const; -+ -+ bool isEmpty() const; -+ -+ // Drag and Drop -+ DECLARE_MODEL_DRAG_DROP_METHODS -+ -+ /** -+ * Install an object as a preprocessor for ImageInfos added to this model. -+ * For every QList of ImageInfos added to addImageInfo, the signal preprocess() -+ * will be emitted. The preprocessor may process the items and shall then readd -+ * them by calling reAddImageInfos(). It may take some time to process. -+ * It shall discard any held infos when the modelReset() signal is sent. -+ * It shall call readdFinished() when no reset occurred and all infos on the way have been readded. -+ * This means that only after calling this method, you shall make three connections -+ * (preprocess -> your slot, your signal -> reAddImageInfos, your signal -> reAddingFinished) -+ * and make or already hold a connection modelReset() -> your slot. -+ * There is only one preprocessor at a time, a previously set object will be disconnected. -+ */ -+ void setPreprocessor(QObject* processor); -+ void unsetPreprocessor(QObject* processor); -+ -+ /** -+ * Returns true if this model is currently refreshing. -+ * For a preprocessor this means that, although the preprocessor may currently have -+ * processed all it got, more batches are to be expected. -+ */ -+ bool isRefreshing() const; -+ -+ /** -+ * Enable sending of imageInfosAboutToBeRemoved and imageInfosRemoved signals. -+ * Default: false -+ */ -+ void setSendRemovalSignals(bool send); -+ -+ virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; -+ virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; -+ virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; -+ virtual Qt::ItemFlags flags(const QModelIndex& index) const; -+ virtual QModelIndex index(int row, int column = 0, const QModelIndex& parent = QModelIndex()) const; -+ -+ /** Retrieves the imageInfo object from the data() method of the given index. -+ * The index may be from a QSortFilterProxyModel as long as an ImageModel is at the end. */ -+ static ImageInfo retrieveImageInfo(const QModelIndex& index); -+ static qlonglong retrieveImageId(const QModelIndex& index); -+ -+Q_SIGNALS: -+ -+ /** Informs that ImageInfos will be added to the model. -+ * This signal is sent before the model data is changed and views are informed. -+ */ -+ void imageInfosAboutToBeAdded(const QList<ImageInfo>& infos); -+ -+ /** Informs that ImageInfos have been added to the model. -+ * This signal is sent after the model data is changed and views are informed. -+ */ -+ void imageInfosAdded(const QList<ImageInfo>& infos); -+ -+ /** Informs that ImageInfos will be removed from the model. -+ * This signal is sent before the model data is changed and views are informed. -+ * Note: You need to explicitly enable sending of this signal. It is not sent -+ * in clearImageInfos(). -+ */ -+ void imageInfosAboutToBeRemoved(const QList<ImageInfo>& infos); -+ -+ /** Informs that ImageInfos have been removed from the model. -+ * This signal is sent after the model data is changed and views are informed. * -+ * Note: You need to explicitly enable sending of this signal. It is not sent -+ * in clearImageInfos(). -+ */ -+ void imageInfosRemoved(const QList<ImageInfo>& infos); -+ -+ /** Connect to this signal only if you are the current preprocessor. -+ */ -+ void preprocess(const QList<ImageInfo>& infos, const QList<QVariant>&); -+ void processAdded(const QList<ImageInfo>& infos, const QList<QVariant>&); -+ -+ /** If an ImageChangeset affected indexes of this model with changes as set in watchFlags(), -+ * this signal contains the changeset and the affected indexes. -+ */ -+ void imageChange(const ImageChangeset&, const QItemSelection&); -+ -+ /** If an ImageTagChangeset affected indexes of this model, -+ * this signal contains the changeset and the affected indexes. -+ */ -+ void imageTagChange(const ImageTagChangeset&, const QItemSelection&); -+ -+ /** Signals that the model is right now ready to start an incremental refresh. -+ * This is guaranteed only for the scope of emitting this signal. -+ */ -+ void readyForIncrementalRefresh(); -+ -+ /** Signals that the model has finished currently with all scheduled -+ * refreshing, full or incremental, and all preprocessing. -+ * The model is in polished, clean situation right now. -+ */ -+ void allRefreshingFinished(); -+ -+public Q_SLOTS: -+ -+ void reAddImageInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues); -+ void reAddingFinished(); -+ -+protected: -+ -+ /** Subclasses that add ImageInfos in batches shall call startRefresh() -+ * when they start sending batches and finishRefresh() when they have finished. -+ * No incremental refreshes will be started while listing. -+ * A clearImageInfos() always stops listing, calling finishRefresh() is then not necessary. -+ */ -+ void startRefresh(); -+ void finishRefresh(); -+ -+ /** As soon as the model is ready to start an incremental refresh, the signal -+ * readyForIncrementalRefresh() will be emitted. The signal will be emitted inline -+ * if the model is ready right now. -+ */ -+ void requestIncrementalRefresh(); -+ bool hasIncrementalRefreshPending() const; -+ -+ /** Starts an incremental refresh operation. You shall only call this method from a slot -+ * connected to readyForIncrementalRefresh(). To initiate an incremental refresh, -+ * call requestIncrementalRefresh(). -+ */ -+ void startIncrementalRefresh(); -+ void finishIncrementalRefresh(); -+ -+ void emitDataChangedForAll(); -+ void emitDataChangedForSelection(const QItemSelection& selection); -+ -+ // Called when the internal storage is cleared -+ virtual void imageInfosCleared() {}; -+ -+ // Called before rowsAboutToBeRemoved -+ virtual void imageInfosAboutToBeRemoved(int /*begin*/, int /*end*/) {}; -+ -+protected Q_SLOTS: -+ -+ virtual void slotImageChange(const ImageChangeset& changeset); -+ virtual void slotImageTagChange(const ImageTagChangeset& changeset); -+ -+private: -+ -+ void appendInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues); -+ void appendInfosChecked(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues); -+ void publiciseInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues); -+ void cleanSituationChecks(); -+ void removeRowPairsWithCheck(const QList<QPair<int, int> >& toRemove); -+ void removeRowPairs(const QList<QPair<int, int> >& toRemove); -+ -+public: -+ -+ // Declared public because it's used in ImageModelIncrementalUpdater class -+ class Private; -+ -+private: -+ -+ Private* const d; -+}; -+ -+} // namespace Digikam -+ -+Q_DECLARE_METATYPE(Digikam::ImageModel*) -+ -+#endif // IMAGEMODEL_H -diff --git a/libs/database/models/imagesortsettings.cpp b/libs/database/models/imagesortsettings.cpp -new file mode 100644 -index 0000000..39ee6e1 ---- /dev/null -+++ b/libs/database/models/imagesortsettings.cpp -@@ -0,0 +1,400 @@ -+/* ============================================================ -+ * -+ * This file is a part of digiKam project -+ * http://www.digikam.org -+ * -+ * Date : 2009-03-05 -+ * Description : Filter values for use with ImageFilterModel -+ * -+ * Copyright (C) 2009 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -+ * Copyright (C) 2014 by Mohamed Anwer <m dot anwer at gmx dot com> -+ * -+ * This program is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU General -+ * Public License as published by the Free Software Foundation; -+ * either version 2, or (at your option) -+ * any later version. -+ * -+ * This program 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 General Public License for more details. -+ * -+ * ============================================================ */ -+ -+#include "imagesortsettings.h" -+ -+// Qt includes -+ -+#include <QDateTime> -+#include <QRectF> -+ -+// Local includes -+ -+#include "coredbfields.h" -+#include "imageinfo.h" -+ -+namespace Digikam -+{ -+ -+ImageSortSettings::ImageSortSettings() -+{ -+ categorizationMode = NoCategories; -+ categorizationSortOrder = DefaultOrder; -+ categorizationCaseSensitivity = Qt::CaseSensitive; -+ sortRole = SortByFileName; -+ sortOrder = DefaultOrder; -+ strTypeNatural = true; -+ sortCaseSensitivity = Qt::CaseSensitive; -+ currentCategorizationSortOrder = Qt::AscendingOrder; -+ currentSortOrder = Qt::AscendingOrder; -+} -+ -+bool ImageSortSettings::operator==(const ImageSortSettings& other) const -+{ -+ return -+ categorizationMode == other.categorizationMode && -+ categorizationSortOrder == other.categorizationSortOrder && -+ categorizationCaseSensitivity == other.categorizationCaseSensitivity && -+ sortRole == other.sortRole && -+ sortOrder == other.sortOrder && -+ sortCaseSensitivity == other.sortCaseSensitivity; -+} -+ -+void ImageSortSettings::setCategorizationMode(CategorizationMode mode) -+{ -+ categorizationMode = mode; -+ -+ if (categorizationSortOrder == DefaultOrder) -+ { -+ currentCategorizationSortOrder = defaultSortOrderForCategorizationMode(categorizationMode); -+ } -+} -+ -+void ImageSortSettings::setCategorizationSortOrder(SortOrder order) -+{ -+ categorizationSortOrder = order; -+ -+ if (categorizationSortOrder == DefaultOrder) -+ { -+ currentCategorizationSortOrder = defaultSortOrderForCategorizationMode(categorizationMode); -+ } -+ else -+ { -+ currentCategorizationSortOrder = (Qt::SortOrder)categorizationSortOrder; -+ } -+} -+ -+void ImageSortSettings::setSortRole(SortRole role) -+{ -+ sortRole = role; -+ -+ if (sortOrder == DefaultOrder) -+ { -+ currentSortOrder = defaultSortOrderForSortRole(sortRole); -+ } -+} -+ -+void ImageSortSettings::setSortOrder(SortOrder order) -+{ -+ sortOrder = order; -+ -+ if (sortOrder == DefaultOrder) -+ { -+ currentSortOrder = defaultSortOrderForSortRole(sortRole); -+ } -+ else -+ { -+ currentSortOrder = (Qt::SortOrder)order; -+ } -+} -+ -+void ImageSortSettings::setStringTypeNatural(bool natural) -+{ -+ strTypeNatural = natural; -+} -+ -+Qt::SortOrder ImageSortSettings::defaultSortOrderForCategorizationMode(CategorizationMode mode) -+{ -+ switch (mode) -+ { -+ case NoCategories: -+ case OneCategory: -+ case CategoryByAlbum: -+ case CategoryByFormat: -+ default: -+ return Qt::AscendingOrder; -+ } -+} -+ -+Qt::SortOrder ImageSortSettings::defaultSortOrderForSortRole(SortRole role) -+{ -+ switch (role) -+ { -+ case SortByFileName: -+ case SortByFilePath: -+ return Qt::AscendingOrder; -+ case SortByFileSize: -+ return Qt::DescendingOrder; -+ case SortByModificationDate: -+ case SortByCreationDate: -+ return Qt::AscendingOrder; -+ case SortByRating: -+ case SortByImageSize: -+ return Qt::DescendingOrder; -+ case SortByAspectRatio: -+ return Qt::DescendingOrder; -+ case SortBySimilarity: -+ return Qt::DescendingOrder; -+ default: -+ return Qt::AscendingOrder; -+ } -+} -+ -+int ImageSortSettings::compareCategories(const ImageInfo& left, const ImageInfo& right) const -+{ -+ switch (categorizationMode) -+ { -+ case NoCategories: -+ case OneCategory: -+ return 0; -+ case CategoryByAlbum: -+ { -+ int leftAlbum = left.albumId(); -+ int rightAlbum = right.albumId(); -+ -+ // return comparation result -+ if (leftAlbum == rightAlbum) -+ { -+ return 0; -+ } -+ else if (lessThanByOrder(leftAlbum, rightAlbum, currentCategorizationSortOrder)) -+ { -+ return -1; -+ } -+ else -+ { -+ return 1; -+ } -+ } -+ case CategoryByFormat: -+ { -+ return naturalCompare(left.format(), right.format(), -+ currentCategorizationSortOrder, categorizationCaseSensitivity, strTypeNatural); -+ } -+ default: -+ return 0; -+ } -+} -+ -+bool ImageSortSettings::lessThan(const ImageInfo& left, const ImageInfo& right) const -+{ -+ int result = compare(left, right, sortRole); -+ -+ if (result != 0) -+ { -+ return result < 0; -+ } -+ -+ // are they identical? -+ if (left == right) -+ { -+ return false; -+ } -+ -+ // If left and right equal for first sort order, use a hierarchy of all sort orders -+ if ( (result = compare(left, right, SortByFileName)) != 0) -+ { -+ return result < 0; -+ } -+ -+ if ( (result = compare(left, right, SortByCreationDate)) != 0) -+ { -+ return result < 0; -+ } -+ -+ if ( (result = compare(left, right, SortByModificationDate)) != 0) -+ { -+ return result < 0; -+ } -+ -+ if ( (result = compare(left, right, SortByFilePath)) != 0) -+ { -+ return result < 0; -+ } -+ -+ if ( (result = compare(left, right, SortByFileSize)) != 0) -+ { -+ return result < 0; -+ } -+ -+ if ( (result = compare(left, right, SortBySimilarity)) != 0) -+ { -+ return result < 0; -+ } -+ -+ return false; -+} -+ -+int ImageSortSettings::compare(const ImageInfo& left, const ImageInfo& right) const -+{ -+ return compare(left, right, sortRole); -+} -+ -+int ImageSortSettings::compare(const ImageInfo& left, const ImageInfo& right, SortRole role) const -+{ -+ switch (role) -+ { -+ case SortByFileName: -+ { -+ bool versioning = (left.name().contains(QLatin1String("_v"), Qt::CaseInsensitive) || -+ right.name().contains(QLatin1String("_v"), Qt::CaseInsensitive)); -+ return naturalCompare(left.name(), right.name(), currentSortOrder, sortCaseSensitivity, strTypeNatural, versioning); -+ } -+ case SortByFilePath: -+ return naturalCompare(left.filePath(), right.filePath(), currentSortOrder, sortCaseSensitivity, strTypeNatural); -+ case SortByFileSize: -+ return compareByOrder(left.fileSize(), right.fileSize(), currentSortOrder); -+ case SortByModificationDate: -+ return compareByOrder(left.modDateTime(), right.modDateTime(), currentSortOrder); -+ case SortByCreationDate: -+ return compareByOrder(left.dateTime(), right.dateTime(), currentSortOrder); -+ case SortByRating: -+ // I have the feeling that inverting the sort order for rating is the natural order -+ return - compareByOrder(left.rating(), right.rating(), currentSortOrder); -+ case SortByImageSize: -+ { -+ QSize leftSize = left.dimensions(); -+ QSize rightSize = right.dimensions(); -+ int leftPixels = leftSize.width() * leftSize.height(); -+ int rightPixels = rightSize.width() * rightSize.height(); -+ return compareByOrder(leftPixels, rightPixels, currentSortOrder); -+ } -+ case SortByAspectRatio: -+ { -+ QSize leftSize = left.dimensions(); -+ QSize rightSize = right.dimensions(); -+ int leftAR = (double(leftSize.width()) / double(leftSize.height())) * 1000000; -+ int rightAR = (double(rightSize.width()) / double(rightSize.height())) * 1000000; -+ return compareByOrder(leftAR, rightAR, currentSortOrder); -+ } -+ case SortBySimilarity: -+ { -+ qlonglong leftReferenceImageId = left.currentReferenceImage(); -+ qlonglong rightReferenceImageId = right.currentReferenceImage(); -+ // make sure that the original image has always the highest similarity. -+ double leftSimilarity = left.id() == leftReferenceImageId ? 1.1 : left.currentSimilarity(); -+ double rightSimilarity = right.id() == rightReferenceImageId ? 1.1 : right.currentSimilarity(); -+ return compareByOrder(leftSimilarity, rightSimilarity, currentSortOrder); -+ } -+ default: -+ return 1; -+ } -+} -+ -+bool ImageSortSettings::lessThan(const QVariant& left, const QVariant& right) const -+{ -+ if (left.type() != right.type()) -+ { -+ return false; -+ } -+ -+ switch (left.type()) -+ { -+ case QVariant::Int: -+ return compareByOrder(left.toInt(), right.toInt(), currentSortOrder); -+ case QVariant::UInt: -+ return compareByOrder(left.toUInt(), right.toUInt(), currentSortOrder); -+ case QVariant::LongLong: -+ return compareByOrder(left.toLongLong(), right.toLongLong(), currentSortOrder); -+ case QVariant::ULongLong: -+ return compareByOrder(left.toULongLong(), right.toULongLong(), currentSortOrder); -+ case QVariant::Double: -+ return compareByOrder(left.toDouble(), right.toDouble(), currentSortOrder); -+ case QVariant::Date: -+ return compareByOrder(left.toDate(), right.toDate(), currentSortOrder); -+ case QVariant::DateTime: -+ return compareByOrder(left.toDateTime(), right.toDateTime(), currentSortOrder); -+ case QVariant::Time: -+ return compareByOrder(left.toTime(), right.toTime(), currentSortOrder); -+ case QVariant::Rect: -+ case QVariant::RectF: -+ { -+ QRectF rectLeft = left.toRectF(); -+ QRectF rectRight = right.toRectF(); -+ int result; -+ -+ if ((result = compareByOrder(rectLeft.top(), rectRight.top(), currentSortOrder)) != 0) -+ { -+ return result < 0; -+ } -+ -+ if ((result = compareByOrder(rectLeft.left(), rectRight.left(), currentSortOrder)) != 0) -+ { -+ return result < 0; -+ } -+ -+ QSizeF sizeLeft = rectLeft.size(), sizeRight = rectRight.size(); -+ -+ if ((result = compareByOrder(sizeLeft.width()*sizeLeft.height(), sizeRight.width()*sizeRight.height(), currentSortOrder)) != 0) -+ { -+ return result < 0; -+ } -+ // FIXME: fall through?? If not, add "break" here -+ } -+ default: -+ return naturalCompare(left.toString(), right.toString(), currentSortOrder, sortCaseSensitivity, strTypeNatural); -+ } -+} -+ -+DatabaseFields::Set ImageSortSettings::watchFlags() const -+{ -+ DatabaseFields::Set set; -+ -+ switch (sortRole) -+ { -+ case SortByFileName: -+ set |= DatabaseFields::Name; -+ break; -+ case SortByFilePath: -+ set |= DatabaseFields::Name; -+ break; -+ case SortByFileSize: -+ set |= DatabaseFields::FileSize; -+ break; -+ case SortByModificationDate: -+ set |= DatabaseFields::ModificationDate; -+ break; -+ case SortByCreationDate: -+ set |= DatabaseFields::CreationDate; -+ break; -+ case SortByRating: -+ set |= DatabaseFields::Rating; -+ break; -+ case SortByImageSize: -+ set |= DatabaseFields::Width | DatabaseFields::Height; -+ break; -+ case SortByAspectRatio: -+ set |= DatabaseFields::Width | DatabaseFields::Height; -+ break; -+ case SortBySimilarity: -+ // TODO: Not sure what to do here.... -+ set |= DatabaseFields::Name; -+ break; -+ } -+ -+ switch (categorizationMode) -+ { -+ case NoCategories: -+ case OneCategory: -+ case CategoryByAlbum: -+ break; -+ case CategoryByFormat: -+ set |= DatabaseFields::Format; -+ break; -+ } -+ -+ return set; -+} -+ -+} // namespace Digikam -diff --git a/libs/database/models/imagesortsettings.h b/libs/database/models/imagesortsettings.h -new file mode 100644 -index 0000000..2a5fd8c ---- /dev/null -+++ b/libs/database/models/imagesortsettings.h -@@ -0,0 +1,225 @@ -+/* ============================================================ -+ * -+ * This file is a part of digiKam project -+ * http://www.digikam.org -+ * -+ * Date : 2009-05-31 -+ * Description : Sort settings for use with ImageFilterModel -+ * -+ * Copyright (C) 2009 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -+ * -+ * This program is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU General -+ * Public License as published by the Free Software Foundation; -+ * either version 2, or (at your option) -+ * any later version. -+ * -+ * This program 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 General Public License for more details. -+ * -+ * ============================================================ */ -+ -+#ifndef IMAGESORTSETTINGS_H -+#define IMAGESORTSETTINGS_H -+ -+// Qt includes -+ -+#include <QHash> -+#include <QList> -+#include <QMap> -+#include <QString> -+#include <QCollator> -+ -+// Local includes -+ -+#include "digikam_export.h" -+ -+namespace Digikam -+{ -+ -+class ImageInfo; -+ -+namespace DatabaseFields -+{ -+ class Set; -+} -+ -+class DIGIKAM_DATABASE_EXPORT ImageSortSettings -+{ -+public: -+ -+ ImageSortSettings(); -+ -+ bool operator==(const ImageSortSettings& other) const; -+ -+ /** Compares the categories of left and right. -+ * Return -1 if left is less than right, 0 if both fall in the same category, -+ * and 1 if left is greater than right. -+ * Adheres to set categorization mode and current category sort order. -+ */ -+ int compareCategories(const ImageInfo& left, const ImageInfo& right) const; -+ -+ /** Returns true if left is less than right. -+ * Adheres to current sort role and sort order. -+ */ -+ bool lessThan(const ImageInfo& left, const ImageInfo& right) const; -+ -+ /** Compares the ImageInfos left and right. -+ * Return -1 if left is less than right, 1 if left is greater than right, -+ * and 0 if left equals right comparing the current sort role's value. -+ * Adheres to set sort role and sort order. -+ */ -+ int compare(const ImageInfo& left, const ImageInfo& right) const; -+ -+ /** Returns true if left QVariant is less than right. -+ * Adheres to current sort role and sort order. -+ * Use for extraValue, if necessary. -+ */ -+ bool lessThan(const QVariant& left, const QVariant& right) const; -+ -+ enum SortOrder -+ { -+ AscendingOrder = Qt::AscendingOrder, -+ DescendingOrder = Qt::DescendingOrder, -+ DefaultOrder /// sort order depends on the chosen sort role -+ }; -+ -+ /// --- Categories --- -+ -+ enum CategorizationMode -+ { -+ NoCategories, /// categorization switched off -+ OneCategory, /// all items in one global category -+ CategoryByAlbum, -+ CategoryByFormat -+ }; -+ -+ CategorizationMode categorizationMode; -+ SortOrder categorizationSortOrder; -+ -+ void setCategorizationMode(CategorizationMode mode); -+ void setCategorizationSortOrder(SortOrder order); -+ -+ /// Only Ascending or Descending, never DefaultOrder -+ Qt::SortOrder currentCategorizationSortOrder; -+ Qt::CaseSensitivity categorizationCaseSensitivity; -+ -+ bool isCategorized() const { return categorizationMode >= CategoryByAlbum; } -+ -+ /// --- Image Sorting --- -+ -+ enum SortRole -+ { -+ // Note: For legacy reasons, the order of the first five entries must remain unchanged -+ SortByFileName, -+ SortByFilePath, -+ SortByCreationDate, -+ SortByFileSize, -+ SortByRating, -+ SortByModificationDate, -+ SortByImageSize, // pixel number -+ SortByAspectRatio, // width / height * 100000 -+ SortBySimilarity -+ }; -+ -+ SortRole sortRole; -+ SortOrder sortOrder; -+ bool strTypeNatural; -+ -+ void setSortRole(SortRole role); -+ void setSortOrder(SortOrder order); -+ void setStringTypeNatural(bool natural); -+ -+ Qt::SortOrder currentSortOrder; -+ Qt::CaseSensitivity sortCaseSensitivity; -+ -+ int compare(const ImageInfo& left, const ImageInfo& right, SortRole sortRole) const; -+ -+ // --- --- -+ -+ static Qt::SortOrder defaultSortOrderForCategorizationMode(CategorizationMode mode); -+ static Qt::SortOrder defaultSortOrderForSortRole(SortRole role); -+ -+ /// --- Change notification --- -+ -+ /** Returns database fields a change in which would affect the current sorting. -+ */ -+ DatabaseFields::Set watchFlags() const; -+ -+ /// --- Utilities --- -+ -+ /** Returns a < b if sortOrder is Ascending, or b < a if order is descending. -+ */ -+ template <typename T> -+ static inline bool lessThanByOrder(const T& a, const T& b, Qt::SortOrder sortOrder) -+ { -+ if (sortOrder == Qt::AscendingOrder) -+ { -+ return a < b; -+ } -+ else -+ { -+ return b < a; -+ } -+ } -+ -+ /** Returns the usual compare result of -1, 0, or 1 for lessThan, equals and greaterThan. -+ */ -+ template <typename T> -+ static inline int compareValue(const T& a, const T& b) -+ { -+ if (a == b) -+ { -+ return 0; -+ } -+ -+ if (a < b) -+ { -+ return -1; -+ } -+ else -+ { -+ return 1; -+ } -+ } -+ -+ /** Takes a typical result from a compare method (0 is equal, -1 is less than, 1 is greater than) -+ * and applies the given sort order to it. -+ */ -+ static inline int compareByOrder(int compareResult, Qt::SortOrder sortOrder) -+ { -+ if (sortOrder == Qt::AscendingOrder) -+ { -+ return compareResult; -+ } -+ else -+ { -+ return - compareResult; -+ } -+ } -+ -+ template <typename T> -+ static inline int compareByOrder(const T& a, const T& b, Qt::SortOrder sortOrder) -+ { -+ return compareByOrder(compareValue(a, b), sortOrder); -+ } -+ -+ /** Compares the two string by natural comparison and adheres to given sort order -+ */ -+ static inline int naturalCompare(const QString& a, const QString& b, Qt::SortOrder sortOrder, -+ Qt::CaseSensitivity caseSensitive = Qt::CaseSensitive, -+ bool natural = true, bool versioning = false) -+ { -+ QCollator collator; -+ collator.setNumericMode(natural); -+ collator.setIgnorePunctuation(versioning); -+ collator.setCaseSensitivity(caseSensitive); -+ return (compareByOrder(collator.compare(a, b), sortOrder)); -+ } -+}; -+ -+} // namespace Digikam -+ -+#endif // IMAGESORTSETTINGS_H -diff --git a/libs/database/models/imagethumbnailmodel.cpp b/libs/database/models/imagethumbnailmodel.cpp -new file mode 100644 -index 0000000..b7f5661 ---- /dev/null -+++ b/libs/database/models/imagethumbnailmodel.cpp -@@ -0,0 +1,323 @@ -+/* ============================================================ -+ * -+ * This file is a part of digiKam project -+ * http://www.digikam.org -+ * -+ * Date : 2009-03-05 -+ * Description : Qt item model for database entries with support for thumbnail loading -+ * -+ * Copyright (C) 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -+ * Copyright (C) 2011-2017 by Gilles Caulier <caulier dot gilles at gmail dot com> -+ * -+ * This program is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU General -+ * Public License as published by the Free Software Foundation; -+ * either version 2, or (at your option) -+ * any later version. -+ * -+ * This program 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 General Public License for more details. -+ * -+ * ============================================================ */ -+ -+#include "imagethumbnailmodel.h" -+ -+// Qt includes -+ -+#include <QHash> -+ -+// Local includes -+ -+#include "digikam_debug.h" -+#include "thumbnailloadthread.h" -+#include "digikam_export.h" -+#include "digikam_globals.h" -+ -+namespace Digikam -+{ -+ -+class ImageThumbnailModel::ImageThumbnailModelPriv -+{ -+public: -+ -+ ImageThumbnailModelPriv() : -+ thread(0), -+ preloadThread(0), -+ thumbSize(0), -+ lastGlobalThumbSize(0), -+ preloadThumbSize(0), -+ emitDataChanged(true) -+ { -+ staticListContainingThumbnailRole << ImageModel::ThumbnailRole; -+ } -+ -+ ThumbnailLoadThread* thread; -+ ThumbnailLoadThread* preloadThread; -+ ThumbnailSize thumbSize; -+ ThumbnailSize lastGlobalThumbSize; -+ ThumbnailSize preloadThumbSize; -+ QRect detailRect; -+ QVector<int> staticListContainingThumbnailRole; -+ -+ bool emitDataChanged; -+ -+ int preloadThumbnailSize() const -+ { -+ if (preloadThumbSize.size()) -+ { -+ return preloadThumbSize.size(); -+ } -+ -+ return thumbSize.size(); -+ } -+}; -+ -+ImageThumbnailModel::ImageThumbnailModel(QObject* parent) -+ : ImageModel(parent), d(new ImageThumbnailModelPriv) -+{ -+ setKeepsFilePathCache(true); -+} -+ -+ImageThumbnailModel::~ImageThumbnailModel() -+{ -+ delete d->preloadThread; -+ delete d; -+} -+ -+void ImageThumbnailModel::setThumbnailLoadThread(ThumbnailLoadThread* thread) -+{ -+ d->thread = thread; -+ -+ connect(d->thread, SIGNAL(signalThumbnailLoaded(LoadingDescription,QPixmap)), -+ this, SLOT(slotThumbnailLoaded(LoadingDescription,QPixmap))); -+} -+ -+ThumbnailLoadThread* ImageThumbnailModel::thumbnailLoadThread() const -+{ -+ return d->thread; -+} -+ -+ThumbnailSize ImageThumbnailModel::thumbnailSize() const -+{ -+ return d->thumbSize; -+} -+ -+void ImageThumbnailModel::setThumbnailSize(const ThumbnailSize& size) -+{ -+ d->lastGlobalThumbSize = size; -+ d->thumbSize = size; -+} -+ -+void ImageThumbnailModel::setPreloadThumbnailSize(const ThumbnailSize& size) -+{ -+ d->preloadThumbSize = size; -+} -+ -+void ImageThumbnailModel::setEmitDataChanged(bool emitSignal) -+{ -+ d->emitDataChanged = emitSignal; -+} -+ -+void ImageThumbnailModel::setPreloadThumbnails(bool preload) -+{ -+ if (preload) -+ { -+ if (!d->preloadThread) -+ { -+ d->preloadThread = new ThumbnailLoadThread; -+ d->preloadThread->setPixmapRequested(false); -+ d->preloadThread->setPriority(QThread::LowestPriority); -+ } -+ -+ connect(this, SIGNAL(allRefreshingFinished()), -+ this, SLOT(preloadAllThumbnails())); -+ } -+ else -+ { -+ delete d->preloadThread; -+ d->preloadThread = 0; -+ disconnect(this, SIGNAL(allRefreshingFinished()), -+ this, SLOT(preloadAllThumbnails())); -+ } -+} -+ -+void ImageThumbnailModel::prepareThumbnails(const QList<QModelIndex>& indexesToPrepare) -+{ -+ prepareThumbnails(indexesToPrepare, d->thumbSize); -+} -+ -+void ImageThumbnailModel::prepareThumbnails(const QList<QModelIndex>& indexesToPrepare, const ThumbnailSize& thumbSize) -+{ -+ if (!d->thread) -+ { -+ return; -+ } -+ -+ QList<ThumbnailIdentifier> ids; -+ foreach(const QModelIndex& index, indexesToPrepare) -+ { -+ ids << imageInfoRef(index).thumbnailIdentifier(); -+ } -+ d->thread->findGroup(ids, thumbSize.size()); -+} -+ -+void ImageThumbnailModel::preloadThumbnails(const QList<ImageInfo>& infos) -+{ -+ if (!d->preloadThread) -+ { -+ return; -+ } -+ -+ QList<ThumbnailIdentifier> ids; -+ foreach(const ImageInfo& info, infos) -+ { -+ ids << info.thumbnailIdentifier(); -+ } -+ d->preloadThread->pregenerateGroup(ids, d->preloadThumbnailSize()); -+} -+ -+void ImageThumbnailModel::preloadThumbnails(const QList<QModelIndex>& indexesToPreload) -+{ -+ if (!d->preloadThread) -+ { -+ return; -+ } -+ -+ QList<ThumbnailIdentifier> ids; -+ foreach(const QModelIndex& index, indexesToPreload) -+ { -+ ids << imageInfoRef(index).thumbnailIdentifier(); -+ } -+ d->preloadThread->stopAllTasks(); -+ d->preloadThread->pregenerateGroup(ids, d->preloadThumbnailSize()); -+} -+ -+void ImageThumbnailModel::preloadAllThumbnails() -+{ -+ preloadThumbnails(imageInfos()); -+} -+ -+void ImageThumbnailModel::imageInfosCleared() -+{ -+ if (d->preloadThread) -+ { -+ d->preloadThread->stopAllTasks(); -+ } -+} -+ -+QVariant ImageThumbnailModel::data(const QModelIndex& index, int role) const -+{ -+ if (role == ThumbnailRole && d->thread && index.isValid()) -+ { -+ QPixmap thumbnail; -+ ImageInfo info = imageInfo(index); -+ QString path = info.filePath(); -+ -+ if (info.isNull()) -+ { -+ return QVariant(QVariant::Pixmap); -+ } -+ -+ if (!d->detailRect.isNull()) -+ { -+ if (d->thread->find(info.thumbnailIdentifier(), d->detailRect, thumbnail, d->thumbSize.size())) -+ { -+ return thumbnail; -+ } -+ } -+ else -+ { -+ if (d->thread->find(info.thumbnailIdentifier(), thumbnail, d->thumbSize.size())) -+ { -+ return thumbnail; -+ } -+ } -+ -+ return QVariant(QVariant::Pixmap); -+ } -+ -+ return ImageModel::data(index, role); -+} -+ -+bool ImageThumbnailModel::setData(const QModelIndex& index, const QVariant& value, int role) -+{ -+ if (role == ThumbnailRole) -+ { -+ switch (value.type()) -+ { -+ case QVariant::Invalid: -+ d->thumbSize = d->lastGlobalThumbSize; -+ d->detailRect = QRect(); -+ break; -+ -+ case QVariant::Int: -+ -+ if (value.isNull()) -+ { -+ d->thumbSize = d->lastGlobalThumbSize; -+ } -+ else -+ { -+ d->thumbSize = value.toInt(); -+ } -+ break; -+ -+ case QVariant::Rect: -+ -+ if (value.isNull()) -+ { -+ d->detailRect = QRect(); -+ } -+ else -+ { -+ d->detailRect = value.toRect(); -+ } -+ break; -+ -+ default: -+ break; -+ } -+ } -+ -+ return ImageModel::setData(index, value, role); -+} -+ -+void ImageThumbnailModel::slotThumbnailLoaded(const LoadingDescription& loadingDescription, const QPixmap& thumb) -+{ -+ if (thumb.isNull()) -+ { -+ return; -+ } -+ -+ // In case of multiple occurrence, we currently do not know which thumbnail is this. Signal change on all. -+ QModelIndexList indexes; -+ ThumbnailIdentifier thumbId = loadingDescription.thumbnailIdentifier(); -+ if (thumbId.filePath.isEmpty()) -+ { -+ indexes = indexesForImageId(thumbId.id); -+ } -+ else -+ { -+ indexes = indexesForPath(thumbId.filePath); -+ } -+ foreach(const QModelIndex& index, indexes) -+ { -+ if (thumb.isNull()) -+ { -+ emit thumbnailFailed(index, loadingDescription.previewParameters.size); -+ } -+ else -+ { -+ emit thumbnailAvailable(index, loadingDescription.previewParameters.size); -+ -+ if (d->emitDataChanged) -+ { -+ emit dataChanged(index, index, d->staticListContainingThumbnailRole); -+ } -+ } -+ } -+} -+ -+} // namespace Digikam -diff --git a/libs/database/models/imagethumbnailmodel.h b/libs/database/models/imagethumbnailmodel.h -new file mode 100644 -index 0000000..366ca65 ---- /dev/null -+++ b/libs/database/models/imagethumbnailmodel.h -@@ -0,0 +1,140 @@ -+/* ============================================================ -+ * -+ * This file is a part of digiKam project -+ * http://www.digikam.org -+ * -+ * Date : 2009-03-05 -+ * Description : Qt item model for database entries with support for thumbnail loading -+ * -+ * Copyright (C) 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -+ * Copyright (C) 2011 by Gilles Caulier <caulier dot gilles at gmail dot com> -+ * -+ * This program is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU General -+ * Public License as published by the Free Software Foundation; -+ * either version 2, or (at your option) -+ * any later version. -+ * -+ * This program 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 General Public License for more details. -+ * -+ * ============================================================ */ -+ -+#ifndef IMAGETHUMBNAILMODEL_H -+#define IMAGETHUMBNAILMODEL_H -+ -+// Local includes -+ -+#include "imagemodel.h" -+#include "thumbnailsize.h" -+#include "digikam_export.h" -+ -+namespace Digikam -+{ -+ -+class LoadingDescription; -+class ThumbnailLoadThread; -+ -+class DIGIKAM_DATABASE_EXPORT ImageThumbnailModel : public ImageModel -+{ -+ Q_OBJECT -+ -+public: -+ -+ /** -+ * An ImageModel that supports thumbnail loading. -+ * You need to set a ThumbnailLoadThread to enable thumbnail loading. -+ * Adjust the thumbnail size to your needs. -+ * Note that setKeepsFilePathCache is enabled per default. -+ */ -+ explicit ImageThumbnailModel(QObject* parent); -+ ~ImageThumbnailModel(); -+ -+ /** Enable thumbnail loading and set the thread that shall be used. -+ * The thumbnail size of this thread will be adjusted. -+ */ -+ void setThumbnailLoadThread(ThumbnailLoadThread* thread); -+ ThumbnailLoadThread* thumbnailLoadThread() const; -+ -+ /// Set the thumbnail size to use -+ void setThumbnailSize(const ThumbnailSize& thumbSize); -+ -+ /// If you want to fix a size for preloading, do it here. -+ void setPreloadThumbnailSize(const ThumbnailSize& thumbSize); -+ -+ void setExifRotate(bool rotate); -+ -+ /** -+ * Enable emitting dataChanged() when a thumbnail becomes available. -+ * The thumbnailAvailable() signal will be emitted in any case. -+ * Default is true. -+ */ -+ void setEmitDataChanged(bool emitSignal); -+ -+ /** -+ * Enable preloading of thumbnails: -+ * If preloading is enabled, for every entry in the model a thumbnail generation is started. -+ * Default: false. -+ */ -+ void setPreloadThumbnails(bool preload); -+ -+ ThumbnailSize thumbnailSize() const; -+ -+ /** -+ * Handles the ThumbnailRole. -+ * If the pixmap is available, returns it in the QVariant. -+ * If it still needs to be loaded, returns a null QVariant and emits -+ * thumbnailAvailable() as soon as it is available. -+ */ -+ virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; -+ -+ /** -+ * You can override the current thumbnail size by giving an integer value for ThumbnailRole. -+ * Set a null QVariant to use the thumbnail size set by setThumbnailSize() again. -+ * The index given here is ignored for this purpose. -+ */ -+ virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::DisplayRole); -+ -+public Q_SLOTS: -+ -+ /** Prepare the thumbnail loading for the given indexes -+ */ -+ void prepareThumbnails(const QList<QModelIndex>& indexesToPrepare); -+ void prepareThumbnails(const QList<QModelIndex>& indexesToPrepare, const ThumbnailSize& thumbSize); -+ -+ /** -+ * Preload thumbnail for the given infos resp. indexes. -+ * Note: Use setPreloadThumbnails to automatically preload all entries in the model. -+ * Note: This only ensures thumbnail generation. It is not guaranteed that pixmaps -+ * are stored in the cache. For thumbnails that are expect to be drawn immediately, -+ * include them in prepareThumbnails(). -+ * Note: Stops preloading of previously added thumbnails. -+ */ -+ void preloadThumbnails(const QList<ImageInfo>&); -+ void preloadThumbnails(const QList<QModelIndex>&); -+ void preloadAllThumbnails(); -+ -+Q_SIGNALS: -+ -+ void thumbnailAvailable(const QModelIndex& index, int requestedSize); -+ void thumbnailFailed(const QModelIndex& index, int requestedSize); -+ -+protected: -+ -+ virtual void imageInfosCleared(); -+ -+protected Q_SLOTS: -+ -+ void slotThumbnailLoaded(const LoadingDescription& loadingDescription, const QPixmap& thumb); -+ -+private: -+ -+ class ImageThumbnailModelPriv; -+ ImageThumbnailModelPriv* const d; -+}; -+ -+} // namespace Digikam -+ -+#endif /* IMAGETHUMBNAILMODEL_H */ -diff --git a/libs/database/models/imageversionsmodel.cpp b/libs/database/models/imageversionsmodel.cpp -new file mode 100644 -index 0000000..e6ba582 ---- /dev/null -+++ b/libs/database/models/imageversionsmodel.cpp -@@ -0,0 +1,183 @@ -+/* ============================================================ -+ * -+ * This file is a part of digiKam project -+ * http://www.digikam.org -+ * -+ * Date : 2010-07-13 -+ * Description : Model for image versions -+ * -+ * Copyright (C) 2010 by Martin Klapetek <martin dot klapetek at gmail dot com> -+ * -+ * This program is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU General -+ * Public License as published by the Free Software Foundation; -+ * either version 2, or (at your option) -+ * any later version. -+ * -+ * This program 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 General Public License for more details. -+ * -+ * ============================================================ */ -+ -+#include "imageversionsmodel.h" -+ -+// KDE includes -+ -+#include <klocalizedstring.h> -+ -+// Local includes -+ -+#include "digikam_debug.h" -+#include "workingwidget.h" -+ -+namespace Digikam -+{ -+ -+class ImageVersionsModel::Private -+{ -+public: -+ -+ Private() -+ { -+ data = 0; -+ paintTree = false; -+ } -+ -+ ///Complete paths with filenames and tree level -+ QList<QPair<QString, int> >* data; -+ ///This is for delegate to paint it as selected -+ QString currentSelectedImage; -+ ///If true, the delegate will paint items as a tree -+ ///if false, it will be painted as a list -+ bool paintTree; -+}; -+ -+ImageVersionsModel::ImageVersionsModel(QObject* parent) -+ : QAbstractListModel(parent), -+ d(new Private) -+{ -+ d->data = new QList<QPair<QString, int> >; -+} -+ -+ImageVersionsModel::~ImageVersionsModel() -+{ -+ //qDeleteAll(d->data); -+ delete d; -+} -+ -+Qt::ItemFlags ImageVersionsModel::flags(const QModelIndex& index) const -+{ -+ if (!index.isValid()) -+ { -+ return 0; -+ } -+ -+ return Qt::ItemIsEnabled | Qt::ItemIsSelectable; -+} -+ -+QVariant ImageVersionsModel::data(const QModelIndex& index, int role) const -+{ -+ if (!index.isValid()) -+ { -+ return QVariant(); -+ } -+ -+ if (role == Qt::DisplayRole && !d->data->isEmpty()) -+ { -+ return d->data->at(index.row()).first; -+ } -+ else if (role == Qt::UserRole && !d->data->isEmpty()) -+ { -+ return d->data->at(index.row()).second; -+ } -+ else if (role == Qt::DisplayRole && d->data->isEmpty()) -+ { -+ //TODO: make this text Italic -+ return QVariant(QString(i18n("No image selected"))); -+ } -+ -+ return QVariant(); -+} -+ -+int ImageVersionsModel::rowCount(const QModelIndex& parent) const -+{ -+ Q_UNUSED(parent) -+ return d->data->count(); -+} -+ -+void ImageVersionsModel::setupModelData(QList<QPair<QString, int> >& data) -+{ -+ beginResetModel(); -+ -+ d->data->clear(); -+ -+ if (!data.isEmpty()) -+ { -+ d->data->append(data); -+ } -+ else -+ { -+ d->data->append(qMakePair(QString(i18n("This is the original image")), 0)); -+ } -+ -+ endResetModel(); -+} -+ -+void ImageVersionsModel::clearModelData() -+{ -+ beginResetModel(); -+ -+ if (!d->data->isEmpty()) -+ { -+ d->data->clear(); -+ } -+ -+ endResetModel(); -+} -+ -+void ImageVersionsModel::slotAnimationStep() -+{ -+ emit dataChanged(createIndex(0, 0), createIndex(rowCount()-1, 1)); -+} -+ -+QString ImageVersionsModel::currentSelectedImage() const -+{ -+ return d->currentSelectedImage; -+} -+ -+void ImageVersionsModel::setCurrentSelectedImage(const QString& path) -+{ -+ d->currentSelectedImage = path; -+} -+ -+QModelIndex ImageVersionsModel::currentSelectedImageIndex() const -+{ -+ return index(listIndexOf(d->currentSelectedImage), 0); -+} -+ -+bool ImageVersionsModel::paintTree() const -+{ -+ return d->paintTree; -+} -+ -+void ImageVersionsModel::setPaintTree(bool paint) -+{ -+ d->paintTree = paint; -+} -+ -+int ImageVersionsModel::listIndexOf(const QString& item) const -+{ -+ for (int i = 0; i < d->data->size(); ++i) -+ { -+ if (d->data->at(i).first == item) -+ { -+ return i; -+ } -+ } -+ -+ return -1; -+} -+ -+} // namespace Digikam -diff --git a/libs/database/models/imageversionsmodel.h b/libs/database/models/imageversionsmodel.h -new file mode 100644 -index 0000000..ed08529 ---- /dev/null -+++ b/libs/database/models/imageversionsmodel.h -@@ -0,0 +1,75 @@ -+/* ============================================================ -+ * -+ * This file is a part of digiKam project -+ * http://www.digikam.org -+ * -+ * Date : 2010-07-13 -+ * Description : Model for image versions -+ * -+ * Copyright (C) 2010 by Martin Klapetek <martin dot klapetek at gmail dot com> -+ * -+ * This program is free software; you can redistribute it -+ * and/or modify it under the terms of the GNU General -+ * Public License as published by the Free Software Foundation; -+ * either version 2, or (at your option) -+ * any later version. -+ * -+ * This program 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 General Public License for more details. -+ * -+ * ============================================================ */ -+ -+#ifndef IMAGEVERSIONSMODEL_H -+#define IMAGEVERSIONSMODEL_H -+ -+// Qt includes -+ -+#include <QModelIndex> -+#include <QPixmap> -+ -+// Local includes -+ -+#include "digikam_export.h" -+ -+namespace Digikam -+{ -+ -+class DIGIKAM_DATABASE_EXPORT ImageVersionsModel : public QAbstractListModel -+{ -+ Q_OBJECT -+ -+public: -+ -+ explicit ImageVersionsModel(QObject* parent = 0); -+ ~ImageVersionsModel(); -+ -+ Qt::ItemFlags flags(const QModelIndex& index) const; -+ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; -+ int rowCount(const QModelIndex& parent = QModelIndex()) const; -+ -+ void setupModelData(QList<QPair<QString, int> >& data); -+ void clearModelData(); -+ -+ QString currentSelectedImage() const; -+ void setCurrentSelectedImage(const QString& path); -+ QModelIndex currentSelectedImageIndex() const; -+ -+ bool paintTree() const; -+ int listIndexOf(const QString& item) const; -+ -+public Q_SLOTS: -+ -+ void slotAnimationStep(); -+ void setPaintTree(bool paint); -+ -+private: -+ -+ class Private; -+ Private* const d; -+}; -+ -+} // namespace Digikam -+ -+#endif // IMAGEVERSIONSMODEL_H -diff --git a/libs/models/CMakeLists.txt b/libs/models/CMakeLists.txt -index cbabfaa..804456b 100644 ---- a/libs/models/CMakeLists.txt -+++ b/libs/models/CMakeLists.txt -@@ -9,18 +9,6 @@ if (POLICY CMP0063) - cmake_policy(SET CMP0063 NEW) - endif (POLICY CMP0063) - --set(libdatabasemodels_SRCS -- imagemodel.cpp -- imagefiltermodel.cpp -- imagefiltermodelpriv.cpp -- imagefiltermodelthreads.cpp -- imagefiltersettings.cpp -- imagelistmodel.cpp -- imagesortsettings.cpp -- imagethumbnailmodel.cpp -- imageversionsmodel.cpp --) -- - set(libalbummodels_SRCS - imagealbummodel.cpp - imagealbumfiltermodel.cpp -@@ -52,5 +40,4 @@ endif() - #for digikam core lib - add_library(digikamgenericmodels_src OBJECT ${libgenericmodels_SRCS}) - --add_library(digikamdatabasemodels_src OBJECT ${libdatabasemodels_SRCS}) --add_library(digikammodels_src OBJECT ${libalbummodels_SRCS} ${libgenericmodels_SRCS}) -+add_library(digikammodels_src OBJECT ${libalbummodels_SRCS} ${libgenericmodels_SRCS}) -diff --git a/libs/models/imagefiltermodel.cpp b/libs/models/imagefiltermodel.cpp -deleted file mode 100644 -index 3d57e05..0000000 ---- a/libs/models/imagefiltermodel.cpp -+++ /dev/null -@@ -1,1116 +0,0 @@ --/* ============================================================ -- * -- * This file is a part of digiKam project -- * http://www.digikam.org -- * -- * Date : 2009-03-05 -- * Description : Qt item model for database entries -- * -- * Copyright (C) 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -- * Copyright (C) 2011-2017 by Gilles Caulier <caulier dot gilles at gmail dot com> -- * Copyright (C) 2010 by Andi Clemens <andi dot clemens at gmail dot com> -- * Copyright (C) 2011 by Michael G. Hansen <mike at mghansen dot de> -- * Copyright (C) 2014 by Mohamed Anwer <m dot anwer at gmx dot com> -- * -- * This program is free software; you can redistribute it -- * and/or modify it under the terms of the GNU General -- * Public License as published by the Free Software Foundation; -- * either version 2, or (at your option) -- * any later version. -- * -- * This program 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 General Public License for more details. -- * -- * ============================================================ */ -- --#include "imagefiltermodel.h" --#include "imagefiltermodelpriv.h" --#include "imagefiltermodelthreads.h" -- --// Local includes -- --#include "digikam_debug.h" --#include "coredbaccess.h" --#include "coredbchangesets.h" --#include "coredbwatch.h" --#include "imageinfolist.h" --#include "imagemodel.h" -- --namespace Digikam --{ -- --ImageSortFilterModel::ImageSortFilterModel(QObject* parent) -- : DCategorizedSortFilterProxyModel(parent), m_chainedModel(0) --{ --} -- --void ImageSortFilterModel::setSourceImageModel(ImageModel* source) --{ -- if (m_chainedModel) -- { -- m_chainedModel->setSourceImageModel(source); -- } -- else -- { -- setDirectSourceImageModel(source); -- } --} -- --void ImageSortFilterModel::setSourceFilterModel(ImageSortFilterModel* source) --{ -- if (source) -- { -- ImageModel* const model = sourceImageModel(); -- -- if (model) -- { -- source->setSourceImageModel(model); -- } -- } -- -- m_chainedModel = source; -- setSourceModel(source); --} -- --void ImageSortFilterModel::setDirectSourceImageModel(ImageModel* model) --{ -- setSourceModel(model); --} -- --void ImageSortFilterModel::setSourceModel(QAbstractItemModel* model) --{ -- // made it protected, only setSourceImageModel is public -- DCategorizedSortFilterProxyModel::setSourceModel(model); --} -- --ImageModel* ImageSortFilterModel::sourceImageModel() const --{ -- if (m_chainedModel) -- { -- return m_chainedModel->sourceImageModel(); -- } -- -- return static_cast<ImageModel*>(sourceModel()); --} -- --ImageSortFilterModel* ImageSortFilterModel::sourceFilterModel() const --{ -- return m_chainedModel; --} -- --ImageFilterModel* ImageSortFilterModel::imageFilterModel() const --{ -- // reimplemented in ImageFilterModel -- if (m_chainedModel) -- { -- return m_chainedModel->imageFilterModel(); -- } -- -- return 0; --} -- --QModelIndex ImageSortFilterModel::mapToSourceImageModel(const QModelIndex& index) const --{ -- if (m_chainedModel) -- { -- return m_chainedModel->mapToSourceImageModel(mapToSource(index)); -- } -- -- return mapToSource(index); --} -- --QModelIndex ImageSortFilterModel::mapFromSourceImageModel(const QModelIndex& albummodel_index) const --{ -- if (m_chainedModel) -- { -- return mapFromSource(m_chainedModel->mapFromSourceImageModel(albummodel_index)); -- } -- -- return mapFromSource(albummodel_index); --} -- -- --QModelIndex ImageSortFilterModel::mapFromDirectSourceToSourceImageModel(const QModelIndex& sourceModel_index) const --{ -- if (m_chainedModel) -- { -- return m_chainedModel->mapToSourceImageModel(sourceModel_index); -- } -- return sourceModel_index; --} -- --// -------------- Convenience mappers ------------------------------------------------------------------- -- --QList<QModelIndex> ImageSortFilterModel::mapListToSource(const QList<QModelIndex>& indexes) const --{ -- QList<QModelIndex> sourceIndexes; -- foreach(const QModelIndex& index, indexes) -- { -- sourceIndexes << mapToSourceImageModel(index); -- } -- return sourceIndexes; --} -- --QList<QModelIndex> ImageSortFilterModel::mapListFromSource(const QList<QModelIndex>& sourceIndexes) const --{ -- QList<QModelIndex> indexes; -- foreach(const QModelIndex& index, sourceIndexes) -- { -- indexes << mapFromSourceImageModel(index); -- } -- return indexes; --} -- --ImageInfo ImageSortFilterModel::imageInfo(const QModelIndex& index) const --{ -- return sourceImageModel()->imageInfo(mapToSourceImageModel(index)); --} -- --qlonglong ImageSortFilterModel::imageId(const QModelIndex& index) const --{ -- return sourceImageModel()->imageId(mapToSourceImageModel(index)); --} -- --QList<ImageInfo> ImageSortFilterModel::imageInfos(const QList<QModelIndex>& indexes) const --{ -- QList<ImageInfo> infos; -- ImageModel* const model = sourceImageModel(); -- -- foreach(const QModelIndex& index, indexes) -- { -- infos << model->imageInfo(mapToSourceImageModel(index)); -- } -- -- return infos; --} -- --QList<qlonglong> ImageSortFilterModel::imageIds(const QList<QModelIndex>& indexes) const --{ -- QList<qlonglong> ids; -- ImageModel* const model = sourceImageModel(); -- -- foreach(const QModelIndex& index, indexes) -- { -- ids << model->imageId(mapToSourceImageModel(index)); -- } -- -- return ids; --} -- --QModelIndex ImageSortFilterModel::indexForPath(const QString& filePath) const --{ -- return mapFromSourceImageModel(sourceImageModel()->indexForPath(filePath)); --} -- --QModelIndex ImageSortFilterModel::indexForImageInfo(const ImageInfo& info) const --{ -- return mapFromSourceImageModel(sourceImageModel()->indexForImageInfo(info)); --} -- --QModelIndex ImageSortFilterModel::indexForImageId(qlonglong id) const --{ -- return mapFromSourceImageModel(sourceImageModel()->indexForImageId(id)); --} -- --QList<ImageInfo> ImageSortFilterModel::imageInfosSorted() const --{ -- QList<ImageInfo> infos; -- const int size = rowCount(); -- ImageModel* const model = sourceImageModel(); -- -- for (int i=0; i<size; ++i) -- { -- infos << model->imageInfo(mapToSourceImageModel(index(i, 0))); -- } -- -- return infos; --} -- --// -------------------------------------------------------------------------------------------- -- --ImageFilterModel::ImageFilterModel(QObject* parent) -- : ImageSortFilterModel(parent), -- d_ptr(new ImageFilterModelPrivate) --{ -- d_ptr->init(this); --} -- --ImageFilterModel::ImageFilterModel(ImageFilterModelPrivate& dd, QObject* parent) -- : ImageSortFilterModel(parent), -- d_ptr(&dd) --{ -- d_ptr->init(this); --} -- --ImageFilterModel::~ImageFilterModel() --{ -- Q_D(ImageFilterModel); -- delete d; --} -- --void ImageFilterModel::setDirectSourceImageModel(ImageModel* sourceModel) --{ -- Q_D(ImageFilterModel); -- -- if (d->imageModel) -- { -- d->imageModel->unsetPreprocessor(d); -- disconnect(d->imageModel, SIGNAL(modelReset()), -- this, SLOT(slotModelReset())); -- slotModelReset(); -- } -- -- d->imageModel = sourceModel; -- -- if (d->imageModel) -- { -- d->imageModel->setPreprocessor(d); -- -- connect(d->imageModel, SIGNAL(preprocess(QList<ImageInfo>,QList<QVariant>)), -- d, SLOT(preprocessInfos(QList<ImageInfo>,QList<QVariant>))); -- -- connect(d->imageModel, SIGNAL(processAdded(QList<ImageInfo>,QList<QVariant>)), -- d, SLOT(processAddedInfos(QList<ImageInfo>,QList<QVariant>))); -- -- connect(d, SIGNAL(reAddImageInfos(QList<ImageInfo>,QList<QVariant>)), -- d->imageModel, SLOT(reAddImageInfos(QList<ImageInfo>,QList<QVariant>))); -- -- connect(d, SIGNAL(reAddingFinished()), -- d->imageModel, SLOT(reAddingFinished())); -- -- connect(d->imageModel, SIGNAL(modelReset()), -- this, SLOT(slotModelReset())); -- -- connect(d->imageModel, SIGNAL(imageChange(ImageChangeset,QItemSelection)), -- this, SLOT(slotImageChange(ImageChangeset))); -- -- connect(d->imageModel, SIGNAL(imageTagChange(ImageTagChangeset,QItemSelection)), -- this, SLOT(slotImageTagChange(ImageTagChangeset))); -- } -- -- setSourceModel(d->imageModel); --} -- --QVariant ImageFilterModel::data(const QModelIndex& index, int role) const --{ -- Q_D(const ImageFilterModel); -- -- if (!index.isValid()) -- { -- return QVariant(); -- } -- -- switch (role) -- { -- // Attention: This breaks should there ever be another filter model between this and the ImageModel -- -- case DCategorizedSortFilterProxyModel::CategoryDisplayRole: -- return categoryIdentifier(d->imageModel->imageInfoRef(mapToSource(index))); -- case CategorizationModeRole: -- return d->sorter.categorizationMode; -- case SortOrderRole: -- return d->sorter.sortRole; -- //case CategoryCountRole: -- // return categoryCount(d->imageModel->imageInfoRef(mapToSource(index))); -- case CategoryAlbumIdRole: -- return d->imageModel->imageInfoRef(mapToSource(index)).albumId(); -- case CategoryFormatRole: -- return d->imageModel->imageInfoRef(mapToSource(index)).format(); -- case GroupIsOpenRole: -- return d->groupFilter.isAllOpen() || -- d->groupFilter.isOpen(d->imageModel->imageInfoRef(mapToSource(index)).id()); -- case ImageFilterModelPointerRole: -- return QVariant::fromValue(const_cast<ImageFilterModel*>(this)); -- } -- -- return DCategorizedSortFilterProxyModel::data(index, role); --} -- --ImageFilterModel* ImageFilterModel::imageFilterModel() const --{ -- return const_cast<ImageFilterModel*>(this); --} -- --DatabaseFields::Set ImageFilterModel::suggestedWatchFlags() const --{ -- DatabaseFields::Set watchFlags; -- watchFlags |= DatabaseFields::Name | DatabaseFields::FileSize | DatabaseFields::ModificationDate; -- watchFlags |= DatabaseFields::Rating | DatabaseFields::CreationDate | DatabaseFields::Orientation | -- DatabaseFields::Width | DatabaseFields::Height; -- watchFlags |= DatabaseFields::Comment; -- watchFlags |= DatabaseFields::ImageRelations; -- return watchFlags; --} -- --// -------------- Filter settings -------------- -- --void ImageFilterModel::setDayFilter(const QList<QDateTime>& days) --{ -- Q_D(ImageFilterModel); -- d->filter.setDayFilter(days); -- setImageFilterSettings(d->filter); --} -- --void ImageFilterModel::setTagFilter(const QList<int>& includedTags, const QList<int>& excludedTags, -- ImageFilterSettings::MatchingCondition matchingCond, -- bool showUnTagged, const QList<int>& clTagIds, const QList<int>& plTagIds) --{ -- Q_D(ImageFilterModel); -- d->filter.setTagFilter(includedTags, excludedTags, matchingCond, showUnTagged, clTagIds, plTagIds); -- setImageFilterSettings(d->filter); --} -- --void ImageFilterModel::setRatingFilter(int rating, ImageFilterSettings::RatingCondition ratingCond, bool isUnratedExcluded) --{ -- Q_D(ImageFilterModel); -- d->filter.setRatingFilter(rating, ratingCond, isUnratedExcluded); -- setImageFilterSettings(d->filter); --} -- --void ImageFilterModel::setUrlWhitelist(const QList<QUrl> urlList, const QString& id) --{ -- Q_D(ImageFilterModel); -- d->filter.setUrlWhitelist(urlList, id); -- setImageFilterSettings(d->filter); --} -- --void ImageFilterModel::setIdWhitelist(const QList<qlonglong>& idList, const QString& id) --{ -- Q_D(ImageFilterModel); -- d->filter.setIdWhitelist(idList, id); -- setImageFilterSettings(d->filter); --} -- --void ImageFilterModel::setMimeTypeFilter(int mimeTypeFilter) --{ -- Q_D(ImageFilterModel); -- d->filter.setMimeTypeFilter(mimeTypeFilter); -- setImageFilterSettings(d->filter); --} -- --void ImageFilterModel::setGeolocationFilter(const ImageFilterSettings::GeolocationCondition& condition) --{ -- Q_D(ImageFilterModel); -- d->filter.setGeolocationFilter(condition); -- setImageFilterSettings(d->filter); --} -- --void ImageFilterModel::setTextFilter(const SearchTextFilterSettings& settings) --{ -- Q_D(ImageFilterModel); -- d->filter.setTextFilter(settings); -- setImageFilterSettings(d->filter); --} -- --void ImageFilterModel::setImageFilterSettings(const ImageFilterSettings& settings) --{ -- Q_D(ImageFilterModel); -- -- { -- QMutexLocker lock(&d->mutex); -- d->version++; -- d->filter = settings; -- d->filterCopy = settings; -- d->versionFilterCopy = d->versionFilter; -- d->groupFilterCopy = d->groupFilter; -- -- d->needPrepareComments = settings.isFilteringByText(); -- d->needPrepareTags = settings.isFilteringByTags(); -- d->needPrepareGroups = true; -- d->needPrepare = d->needPrepareComments || d->needPrepareTags || d->needPrepareGroups; -- -- d->hasOneMatch = false; -- d->hasOneMatchForText = false; -- } -- -- d->filterResults.clear(); -- -- //d->categoryCountHashInt.clear(); -- //d->categoryCountHashString.clear(); -- if (d->imageModel) -- { -- d->infosToProcess(d->imageModel->imageInfos()); -- } -- -- emit filterSettingsChanged(settings); --} -- --void ImageFilterModel::setVersionManagerSettings(const VersionManagerSettings& settings) --{ -- Q_D(ImageFilterModel); -- d->versionFilter.setVersionManagerSettings(settings); -- setVersionImageFilterSettings(d->versionFilter); --} -- --void ImageFilterModel::setExceptionList(const QList<qlonglong>& idList, const QString& id) --{ -- Q_D(ImageFilterModel); -- d->versionFilter.setExceptionList(idList, id); -- setVersionImageFilterSettings(d->versionFilter); --} -- --void ImageFilterModel::setVersionImageFilterSettings(const VersionImageFilterSettings& settings) --{ -- Q_D(ImageFilterModel); -- d->versionFilter = settings; -- slotUpdateFilter(); --} -- --bool ImageFilterModel::isGroupOpen(qlonglong group) const --{ -- Q_D(const ImageFilterModel); -- return d->groupFilter.isOpen(group); --} -- --bool ImageFilterModel::isAllGroupsOpen() const --{ -- Q_D(const ImageFilterModel); -- return d->groupFilter.isAllOpen(); --} -- --void ImageFilterModel::setGroupOpen(qlonglong group, bool open) --{ -- Q_D(ImageFilterModel); -- d->groupFilter.setOpen(group, open); -- setGroupImageFilterSettings(d->groupFilter); --} -- --void ImageFilterModel::toggleGroupOpen(qlonglong group) --{ -- setGroupOpen(group, !isGroupOpen(group)); --} -- --void ImageFilterModel::setAllGroupsOpen(bool open) --{ -- Q_D(ImageFilterModel); -- d->groupFilter.setAllOpen(open); -- setGroupImageFilterSettings(d->groupFilter); --} -- --void ImageFilterModel::setGroupImageFilterSettings(const GroupImageFilterSettings& settings) --{ -- Q_D(ImageFilterModel); -- d->groupFilter = settings; -- slotUpdateFilter(); --} -- --void ImageFilterModel::slotUpdateFilter() --{ -- Q_D(ImageFilterModel); -- setImageFilterSettings(d->filter); --} -- --ImageFilterSettings ImageFilterModel::imageFilterSettings() const --{ -- Q_D(const ImageFilterModel); -- return d->filter; --} -- --ImageSortSettings ImageFilterModel::imageSortSettings() const --{ -- Q_D(const ImageFilterModel); -- return d->sorter; --} -- --VersionImageFilterSettings ImageFilterModel::versionImageFilterSettings() const --{ -- Q_D(const ImageFilterModel); -- return d->versionFilter; --} -- --GroupImageFilterSettings ImageFilterModel::groupImageFilterSettings() const --{ -- Q_D(const ImageFilterModel); -- return d->groupFilter; --} -- --void ImageFilterModel::slotModelReset() --{ -- Q_D(ImageFilterModel); -- { -- QMutexLocker lock(&d->mutex); -- // discard all packages on the way that are marked as send out for re-add -- d->lastDiscardVersion = d->version; -- d->sentOutForReAdd = 0; -- // discard all packages on the way -- d->version++; -- d->sentOut = 0; -- -- d->hasOneMatch = false; -- d->hasOneMatchForText = false; -- } -- d->filterResults.clear(); --} -- --bool ImageFilterModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const --{ -- Q_D(const ImageFilterModel); -- -- if (source_parent.isValid()) -- { -- return false; -- } -- -- qlonglong id = d->imageModel->imageId(source_row); -- QHash<qlonglong, bool>::const_iterator it = d->filterResults.constFind(id); -- -- if (it != d->filterResults.constEnd()) -- { -- return it.value(); -- } -- -- // usually done in thread and cache, unless source model changed -- ImageInfo info = d->imageModel->imageInfo(source_row); -- bool match = d->filter.matches(info); -- match = match ? d->versionFilter.matches(info) : false; -- -- return match ? d->groupFilter.matches(info) : false; --} -- --void ImageFilterModel::setSendImageInfoSignals(bool sendSignals) --{ -- if (sendSignals) -- { -- connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), -- this, SLOT(slotRowsInserted(QModelIndex,int,int))); -- -- connect(this, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), -- this, SLOT(slotRowsAboutToBeRemoved(QModelIndex,int,int))); -- } -- else -- { -- disconnect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), -- this, SLOT(slotRowsInserted(QModelIndex,int,int))); -- -- disconnect(this, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), -- this, SLOT(slotRowsAboutToBeRemoved(QModelIndex,int,int))); -- } --} -- --void ImageFilterModel::slotRowsInserted(const QModelIndex& /*parent*/, int start, int end) --{ -- QList<ImageInfo> infos; -- -- for (int i=start; i<=end; ++i) -- { -- infos << imageInfo(index(i, 0)); -- } -- -- emit imageInfosAdded(infos); --} -- --void ImageFilterModel::slotRowsAboutToBeRemoved(const QModelIndex& /*parent*/, int start, int end) --{ -- QList<ImageInfo> infos; -- -- for (int i=start; i<=end; ++i) -- { -- infos << imageInfo(index(i, 0)); -- } -- -- emit imageInfosAboutToBeRemoved(infos); --} -- --// -------------- Threaded preparation & filtering -------------- -- --void ImageFilterModel::addPrepareHook(ImageFilterModelPrepareHook* hook) --{ -- Q_D(ImageFilterModel); -- QMutexLocker lock(&d->mutex); -- d->prepareHooks << hook; --} -- --void ImageFilterModel::removePrepareHook(ImageFilterModelPrepareHook* hook) --{ -- Q_D(ImageFilterModel); -- QMutexLocker lock(&d->mutex); -- d->prepareHooks.removeAll(hook); --} -- --void ImageFilterModelPreparer::process(ImageFilterModelTodoPackage package) --{ -- if (!checkVersion(package)) -- { -- emit discarded(package); -- return; -- } -- -- // get thread-local copy -- bool needPrepareTags, needPrepareComments, needPrepareGroups; -- QList<ImageFilterModelPrepareHook*> prepareHooks; -- { -- QMutexLocker lock(&d->mutex); -- needPrepareTags = d->needPrepareTags; -- needPrepareComments = d->needPrepareComments; -- needPrepareGroups = d->needPrepareGroups; -- prepareHooks = d->prepareHooks; -- } -- -- //TODO: Make efficient!! -- if (needPrepareComments) -- { -- foreach(const ImageInfo& info, package.infos) -- { -- info.comment(); -- } -- } -- -- if (!checkVersion(package)) -- { -- emit discarded(package); -- return; -- } -- -- // The downside of QVector: At some point, we may need a QList for an API. -- // Nonetheless, QList and ImageInfo is fast. We could as well -- // reimplement ImageInfoList to ImageInfoVector (internally with templates?) -- ImageInfoList infoList; -- -- if (needPrepareTags || needPrepareGroups) -- { -- infoList = package.infos.toList(); -- } -- -- if (needPrepareTags) -- { -- infoList.loadTagIds(); -- } -- -- if (needPrepareGroups) -- { -- infoList.loadGroupImageIds(); -- } -- -- foreach(ImageFilterModelPrepareHook* hook, prepareHooks) -- { -- hook->prepare(package.infos); -- } -- -- emit processed(package); --} -- --void ImageFilterModelFilterer::process(ImageFilterModelTodoPackage package) --{ -- if (!checkVersion(package)) -- { -- emit discarded(package); -- return; -- } -- -- // get thread-local copy -- ImageFilterSettings localFilter; -- VersionImageFilterSettings localVersionFilter; -- GroupImageFilterSettings localGroupFilter; -- bool hasOneMatch; -- bool hasOneMatchForText; -- { -- QMutexLocker lock(&d->mutex); -- localFilter = d->filterCopy; -- localVersionFilter = d->versionFilterCopy; -- localGroupFilter = d->groupFilterCopy; -- hasOneMatch = d->hasOneMatch; -- hasOneMatchForText = d->hasOneMatchForText; -- } -- -- // Actual filtering. The variants to spare checking hasOneMatch over and over again. -- if (hasOneMatch && hasOneMatchForText) -- { -- foreach(const ImageInfo& info, package.infos) -- { -- package.filterResults[info.id()] = localFilter.matches(info) && -- localVersionFilter.matches(info) && -- localGroupFilter.matches(info); -- } -- } -- else if (hasOneMatch) -- { -- bool matchForText; -- -- foreach(const ImageInfo& info, package.infos) -- { -- package.filterResults[info.id()] = localFilter.matches(info, &matchForText) && -- localVersionFilter.matches(info) && -- localGroupFilter.matches(info); -- -- if (matchForText) -- { -- hasOneMatchForText = true; -- } -- } -- } -- else -- { -- bool result, matchForText; -- -- foreach(const ImageInfo& info, package.infos) -- { -- result = localFilter.matches(info, &matchForText) && -- localVersionFilter.matches(info) && -- localGroupFilter.matches(info); -- package.filterResults[info.id()] = result; -- -- if (result) -- { -- hasOneMatch = true; -- } -- -- if (matchForText) -- { -- hasOneMatchForText = true; -- } -- } -- } -- -- if (checkVersion(package)) -- { -- QMutexLocker lock(&d->mutex); -- d->hasOneMatch = hasOneMatch; -- d->hasOneMatchForText = hasOneMatchForText; -- } -- -- emit processed(package); --} -- --// -------------- Sorting and Categorization ------------------------------------------------------- -- --void ImageFilterModel::setImageSortSettings(const ImageSortSettings& sorter) --{ -- Q_D(ImageFilterModel); -- d->sorter = sorter; -- setCategorizedModel(d->sorter.categorizationMode != ImageSortSettings::NoCategories); -- invalidate(); --} -- --void ImageFilterModel::setCategorizationMode(ImageSortSettings::CategorizationMode mode) --{ -- Q_D(ImageFilterModel); -- d->sorter.setCategorizationMode(mode); -- setImageSortSettings(d->sorter); --} -- --void ImageFilterModel::setCategorizationSortOrder(ImageSortSettings::SortOrder order) --{ -- Q_D(ImageFilterModel); -- d->sorter.setCategorizationSortOrder(order); -- setImageSortSettings(d->sorter); --} -- --void ImageFilterModel::setSortRole(ImageSortSettings::SortRole role) --{ -- Q_D(ImageFilterModel); -- d->sorter.setSortRole(role); -- setImageSortSettings(d->sorter); --} -- --void ImageFilterModel::setSortOrder(ImageSortSettings::SortOrder order) --{ -- Q_D(ImageFilterModel); -- d->sorter.setSortOrder(order); -- setImageSortSettings(d->sorter); --} -- --void ImageFilterModel::setStringTypeNatural(bool natural) --{ -- Q_D(ImageFilterModel); -- d->sorter.setStringTypeNatural(natural); -- setImageSortSettings(d->sorter); --} -- --int ImageFilterModel::compareCategories(const QModelIndex& left, const QModelIndex& right) const --{ -- // source indexes -- Q_D(const ImageFilterModel); -- -- if (!d->sorter.isCategorized()) -- { -- return 0; -- } -- -- if (!left.isValid() || !right.isValid()) -- { -- return -1; -- } -- -- const ImageInfo& leftInfo = d->imageModel->imageInfoRef(left); -- const ImageInfo& rightInfo = d->imageModel->imageInfoRef(right); -- -- // Check grouping -- qlonglong leftGroupImageId = leftInfo.groupImageId(); -- qlonglong rightGroupImageId = rightInfo.groupImageId(); -- -- return compareInfosCategories(leftGroupImageId == -1 ? leftInfo : ImageInfo(leftGroupImageId), -- rightGroupImageId == -1 ? rightInfo : ImageInfo(rightGroupImageId)); --} -- --bool ImageFilterModel::subSortLessThan(const QModelIndex& left, const QModelIndex& right) const --{ -- // source indexes -- Q_D(const ImageFilterModel); -- -- if (!left.isValid() || !right.isValid()) -- { -- return true; -- } -- -- if (left == right) -- { -- return false; -- } -- -- const ImageInfo& leftInfo = d->imageModel->imageInfoRef(left); -- const ImageInfo& rightInfo = d->imageModel->imageInfoRef(right); -- -- if (leftInfo == rightInfo) -- { -- return d->sorter.lessThan(left.data(ImageModel::ExtraDataRole), right.data(ImageModel::ExtraDataRole)); -- } -- -- // Check grouping -- qlonglong leftGroupImageId = leftInfo.groupImageId(); -- qlonglong rightGroupImageId = rightInfo.groupImageId(); -- -- // Either no grouping (-1), or same group image, or same image -- if (leftGroupImageId == rightGroupImageId) -- { -- return infosLessThan(leftInfo, rightInfo); -- } -- -- // We have grouping to handle -- -- // Is one grouped on the other? Sort behind leader. -- if (leftGroupImageId == rightInfo.id()) -- { -- return false; -- } -- if (rightGroupImageId == leftInfo.id()) -- { -- return true; -- } -- -- // Use the group leader for sorting -- return infosLessThan(leftGroupImageId == -1 ? leftInfo : ImageInfo(leftGroupImageId), -- rightGroupImageId == -1 ? rightInfo : ImageInfo(rightGroupImageId)); --} -- --int ImageFilterModel::compareInfosCategories(const ImageInfo& left, const ImageInfo& right) const --{ -- // Note: reimplemented in ImageAlbumFilterModel -- Q_D(const ImageFilterModel); -- return d->sorter.compareCategories(left, right); --} -- --// Feel free to optimize. QString::number is 3x slower. --static inline QString fastNumberToString(int id) --{ -- const int size = sizeof(int) * 2; -- char c[size+1]; -- c[size] = '\0'; -- char* p = c; -- int number = id; -- -- for (int i=0; i<size; ++i) -- { -- *p = 'a' + (number & 0xF); -- number >>= 4; -- ++p; -- } -- -- return QString::fromLatin1(c); --} -- --QString ImageFilterModel::categoryIdentifier(const ImageInfo& i) const --{ -- Q_D(const ImageFilterModel); -- -- if (!d->sorter.isCategorized()) -- { -- return QString(); -- } -- -- qlonglong groupedImageId = i.groupImageId(); -- ImageInfo info = groupedImageId == -1 ? i : ImageInfo(groupedImageId); -- -- switch (d->sorter.categorizationMode) -- { -- case ImageSortSettings::NoCategories: -- return QString(); -- case ImageSortSettings::OneCategory: -- return QString(); -- case ImageSortSettings::CategoryByAlbum: -- return fastNumberToString(info.albumId()); -- case ImageSortSettings::CategoryByFormat: -- return info.format(); -- default: -- return QString(); -- } --} -- --bool ImageFilterModel::infosLessThan(const ImageInfo& left, const ImageInfo& right) const --{ -- Q_D(const ImageFilterModel); -- return d->sorter.lessThan(left, right); --} -- --// -------------- Watching changes ----------------------------------------------------------------- -- --void ImageFilterModel::slotImageTagChange(const ImageTagChangeset& changeset) --{ -- Q_D(ImageFilterModel); -- -- if (!d->imageModel || d->imageModel->isEmpty()) -- { -- return; -- } -- -- // already scheduled to re-filter? -- if (d->updateFilterTimer->isActive()) -- { -- return; -- } -- -- // do we filter at all? -- if (!d->versionFilter.isFilteringByTags() && -- !d->filter.isFilteringByTags() && -- !d->filter.isFilteringByText()) -- { -- return; -- } -- -- // is one of our images affected? -- foreach(const qlonglong& id, changeset.ids()) -- { -- // if one matching image id is found, trigger a refresh -- if (d->imageModel->hasImage(id)) -- { -- d->updateFilterTimer->start(); -- return; -- } -- } --} -- --void ImageFilterModel::slotImageChange(const ImageChangeset& changeset) --{ -- Q_D(ImageFilterModel); -- -- if (!d->imageModel || d->imageModel->isEmpty()) -- { -- return; -- } -- -- // already scheduled to re-filter? -- if (d->updateFilterTimer->isActive()) -- { -- return; -- } -- -- // is one of the values affected that we filter or sort by? -- DatabaseFields::Set set = changeset.changes(); -- bool sortAffected = (set & d->sorter.watchFlags()); -- bool filterAffected = (set & d->filter.watchFlags()) || (set & d->groupFilter.watchFlags()); -- -- if (!sortAffected && !filterAffected) -- { -- return; -- } -- -- // is one of our images affected? -- bool imageAffected = false; -- -- foreach(const qlonglong& id, changeset.ids()) -- { -- // if one matching image id is found, trigger a refresh -- if (d->imageModel->hasImage(id)) -- { -- imageAffected = true; -- break; -- } -- } -- -- if (!imageAffected) -- { -- return; -- } -- -- if (filterAffected) -- { -- d->updateFilterTimer->start(); -- } -- else -- { -- invalidate(); // just resort, reuse filter results -- } --} -- --// ------------------------------------------------------------------------------------------------------- -- --NoDuplicatesImageFilterModel::NoDuplicatesImageFilterModel(QObject* parent) -- : ImageSortFilterModel(parent) --{ --} -- --bool NoDuplicatesImageFilterModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const --{ -- QModelIndex index = sourceModel()->index(source_row, 0, source_parent); -- -- if (index.data(ImageModel::ExtraDataDuplicateCount).toInt() <= 1) -- { -- return true; -- } -- -- QModelIndex previousIndex = sourceModel()->index(source_row - 1, 0, source_parent); -- -- if (!previousIndex.isValid()) -- { -- return true; -- } -- -- if (sourceImageModel()->imageId(mapFromDirectSourceToSourceImageModel(index)) == sourceImageModel()->imageId(mapFromDirectSourceToSourceImageModel(previousIndex))) -- { -- return false; -- } -- return true; --} -- --/* --void NoDuplicatesImageFilterModel::setSourceModel(QAbstractItemModel* model) --{ -- if (sourceModel()) -- { -- } -- -- ImageSortFilterModel::setSourceModel(model); -- -- if (sourceModel()) -- { -- connect(sourceModel(), SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), -- this, SLOT(slotRowsAboutToBeRemoved(QModelIndex,int,int))); -- } --} -- --void NoDuplicatesImageFilterModel::slotRowsAboutToBeRemoved(const QModelIndex& parent, int begin, int end) --{ -- bool needInvalidate = false; -- -- for (int i = begin; i<=end; ++i) -- { -- QModelIndex index = sourceModel()->index(i, 0, parent); -- -- // filtered out by us? -- if (!mapFromSource(index).isValid()) -- { -- continue; -- } -- -- QModelIndex sourceIndex = mapFromDirectSourceToSourceImageModel(index); -- qlonglong id = sourceImageModel()->imageId(sourceIndex); -- -- if (sourceImageModel()->numberOfIndexesForImageId(id) > 1) -- { -- needInvalidate = true; -- } -- } --}*/ -- --} // namespace Digikam -diff --git a/libs/models/imagefiltermodel.h b/libs/models/imagefiltermodel.h -deleted file mode 100644 -index d131b3e..0000000 ---- a/libs/models/imagefiltermodel.h -+++ /dev/null -@@ -1,299 +0,0 @@ --/* ============================================================ -- * -- * This file is a part of digiKam project -- * http://www.digikam.org -- * -- * Date : 2009-03-05 -- * Description : Qt item model for database entries -- * -- * Copyright (C) 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -- * Copyright (C) 2011 by Gilles Caulier <caulier dot gilles at gmail dot com> -- * Copyright (C) 2010 by Andi Clemens <andi dot clemens at gmail dot com> -- * Copyright (C) 2011 by Michael G. Hansen <mike at mghansen dot de> -- * Copyright (C) 2014 by Mohamed Anwer <m dot anwer at gmx dot com> -- * -- * This program is free software; you can redistribute it -- * and/or modify it under the terms of the GNU General -- * Public License as published by the Free Software Foundation; -- * either version 2, or (at your option) -- * any later version. -- * -- * This program 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 General Public License for more details. -- * -- * ============================================================ */ -- --#ifndef IMAGEFILTERMODEL_H --#define IMAGEFILTERMODEL_H -- --// Local includes -- --#include "dcategorizedsortfilterproxymodel.h" --#include "textfilter.h" --#include "imagefiltersettings.h" --#include "imagemodel.h" --#include "imagesortsettings.h" --#include "digikam_export.h" -- --namespace Digikam --{ -- --class ImageChangeset; --class ImageFilterModel; --class ImageTagChangeset; -- --class DIGIKAM_DATABASE_EXPORT ImageFilterModelPrepareHook --{ --public: -- -- virtual ~ImageFilterModelPrepareHook() {}; -- virtual void prepare(const QVector<ImageInfo>& infos) = 0; --}; -- --// ----------------------------------------------------------------------------------------------- -- --class DIGIKAM_DATABASE_EXPORT ImageSortFilterModel : public DCategorizedSortFilterProxyModel --{ -- Q_OBJECT -- --public: -- -- explicit ImageSortFilterModel(QObject* parent = 0); -- -- void setSourceImageModel(ImageModel* model); -- ImageModel* sourceImageModel() const; -- -- void setSourceFilterModel(ImageSortFilterModel* model); -- ImageSortFilterModel* sourceFilterModel() const; -- -- QModelIndex mapToSourceImageModel(const QModelIndex& index) const; -- QModelIndex mapFromSourceImageModel(const QModelIndex& imagemodel_index) const; -- QModelIndex mapFromDirectSourceToSourceImageModel(const QModelIndex& sourceModel_index) const; -- -- /// Convenience methods mapped to ImageModel. -- /// Mentioned indexes returned come from the source image model. -- QList<QModelIndex> mapListToSource(const QList<QModelIndex>& indexes) const; -- QList<QModelIndex> mapListFromSource(const QList<QModelIndex>& sourceIndexes) const; -- -- ImageInfo imageInfo(const QModelIndex& index) const; -- qlonglong imageId(const QModelIndex& index) const; -- QList<ImageInfo> imageInfos(const QList<QModelIndex>& indexes) const; -- QList<qlonglong> imageIds(const QList<QModelIndex>& indexes) const; -- -- QModelIndex indexForPath(const QString& filePath) const; -- QModelIndex indexForImageInfo(const ImageInfo& info) const; -- QModelIndex indexForImageId(qlonglong id) const; -- -- /** Returns a list of all image infos, sorted according to this model. -- * If you do not need a sorted list, use ImageModel's imageInfos() method. -- */ -- QList<ImageInfo> imageInfosSorted() const; -- -- /// Returns this, any chained ImageFilterModel, or 0. -- virtual ImageFilterModel* imageFilterModel() const; -- --protected: -- -- /// Reimplement if needed. Called only when model shall be set as (direct) sourceModel. -- virtual void setDirectSourceImageModel(ImageModel* model); -- -- // made protected -- virtual void setSourceModel(QAbstractItemModel* model); -- --protected: -- -- ImageSortFilterModel* m_chainedModel; --}; -- --// ----------------------------------------------------------------------------------------------- -- --class DIGIKAM_DATABASE_EXPORT ImageFilterModel : public ImageSortFilterModel --{ -- Q_OBJECT -- --public: -- -- enum ImageFilterModelRoles -- { -- /// Returns the current categorization mode -- CategorizationModeRole = ImageModel::FilterModelRoles + 1, -- /// Returns the current sort order -- SortOrderRole = ImageModel::FilterModelRoles + 2, -- // / Returns the number of items in the index' category -- //CategoryCountRole = ImageModel::FilterModelRoles + 3, -- /// Returns the id of the PAlbum of the index which is used for category -- CategoryAlbumIdRole = ImageModel::FilterModelRoles + 3, -- /// Returns the format of the index which is used for category -- CategoryFormatRole = ImageModel::FilterModelRoles + 4, -- /// Returns true if the given image is a group leader, and the group is opened -- GroupIsOpenRole = ImageModel::FilterModelRoles + 5, -- ImageFilterModelPointerRole = ImageModel::FilterModelRoles + 50 -- }; -- --public: -- -- explicit ImageFilterModel(QObject* parent = 0); -- ~ImageFilterModel(); -- -- /** Add a hook to get added images for preparation tasks before they are added in the model */ -- void addPrepareHook(ImageFilterModelPrepareHook* hook); -- void removePrepareHook(ImageFilterModelPrepareHook* hook); -- -- /** Returns a set of DatabaseFields suggested to set as watch flags on the source ImageModel. -- * The contained flags will be those that this model can sort or filter by. */ -- DatabaseFields::Set suggestedWatchFlags() const; -- -- ImageFilterSettings imageFilterSettings() const; -- VersionImageFilterSettings versionImageFilterSettings() const; -- GroupImageFilterSettings groupImageFilterSettings() const; -- ImageSortSettings imageSortSettings() const; -- -- // group is identified by the id of its group leader -- bool isGroupOpen(qlonglong group) const; -- bool isAllGroupsOpen() const; -- -- /// Enables sending imageInfosAdded and imageInfosAboutToBeRemoved -- void setSendImageInfoSignals(bool sendSignals); -- -- virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; -- virtual ImageFilterModel* imageFilterModel() const; -- --public Q_SLOTS: -- -- /** Changes the current version image filter settings and refilters. */ -- void setVersionImageFilterSettings(const VersionImageFilterSettings& settings); -- -- /** Changes the current version image filter settings and refilters. */ -- void setGroupImageFilterSettings(const GroupImageFilterSettings& settings); -- -- /** Adjust the current ImageFilterSettings. -- * Equivalent to retrieving the current filter settings, adjusting the parameter -- * and calling setImageFilterSettings. -- * Provided for convenience. -- * It is encouraged to use setImageFilterSettings if you change more than one -- * parameter at a time. -- */ -- void setDayFilter(const QList<QDateTime>& days); -- void setTagFilter(const QList<int>& includedTags, const QList<int>& excludedTags, -- ImageFilterSettings::MatchingCondition matchingCond, bool showUnTagged, -- const QList<int>& clTagIds, const QList<int>& plTagIds); -- void setRatingFilter(int rating, ImageFilterSettings::RatingCondition ratingCond, bool isUnratedExcluded); -- void setMimeTypeFilter(int mimeTypeFilter); -- void setGeolocationFilter(const ImageFilterSettings::GeolocationCondition& condition); -- void setTextFilter(const SearchTextFilterSettings& settings); -- -- void setCategorizationMode(ImageSortSettings::CategorizationMode mode); -- void setCategorizationSortOrder(ImageSortSettings::SortOrder order); -- void setSortRole(ImageSortSettings::SortRole role); -- void setSortOrder(ImageSortSettings::SortOrder order); -- void setStringTypeNatural(bool natural); -- void setUrlWhitelist(const QList<QUrl> urlList, const QString& id); -- void setIdWhitelist(const QList<qlonglong>& idList, const QString& id); -- -- void setVersionManagerSettings(const VersionManagerSettings& settings); -- void setExceptionList(const QList<qlonglong>& idlist, const QString& id); -- -- void setGroupOpen(qlonglong group, bool open); -- void toggleGroupOpen(qlonglong group); -- void setAllGroupsOpen(bool open); -- -- /** Changes the current image filter settings and refilters. */ -- virtual void setImageFilterSettings(const ImageFilterSettings& settings); -- -- /** Changes the current image sort settings and resorts. */ -- virtual void setImageSortSettings(const ImageSortSettings& settings); -- --Q_SIGNALS: -- -- /// Signals that the set filter matches at least one index -- void filterMatches(bool matches); -- -- /** Signals that the set text filter matches at least one entry. -- If no text filter is set, this signal is emitted -- with 'false' when filterMatches() is emitted. -- */ -- void filterMatchesForText(bool matchesByText); -- -- /** Emitted when the filter settings have been changed -- (the model may not yet have been updated) -- */ -- void filterSettingsChanged(const ImageFilterSettings& settings); -- -- /** These signals need to be explicitly enabled with setSendImageInfoSignals() -- */ -- void imageInfosAdded(const QList<ImageInfo>& infos); -- void imageInfosAboutToBeRemoved(const QList<ImageInfo>& infos); -- --public: -- -- // Declared as public because of use in sub-classes. -- class ImageFilterModelPrivate; -- --protected: -- -- ImageFilterModelPrivate* const d_ptr; -- --protected: -- -- ImageFilterModel(ImageFilterModelPrivate& dd, QObject* parent); -- -- virtual void setDirectSourceImageModel(ImageModel* model); -- -- virtual bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const; -- -- virtual int compareCategories(const QModelIndex& left, const QModelIndex& right) const; -- virtual bool subSortLessThan(const QModelIndex& left, const QModelIndex& right) const; -- //virtual int categoryCount(const ImageInfo& info) const; -- -- /** Reimplement to customize category sorting, -- * Return negative if category of left < category right, -- * Return 0 if left and right are in the same category, else return positive. -- */ -- virtual int compareInfosCategories(const ImageInfo& left, const ImageInfo& right) const; -- -- /** Reimplement to customize sorting. Do not take categories into account here. -- */ -- virtual bool infosLessThan(const ImageInfo& left, const ImageInfo& right) const; -- -- /** Returns a unique identifier for the category if info. The string need not be for user display. -- */ -- virtual QString categoryIdentifier(const ImageInfo& info) const; -- --protected Q_SLOTS: -- -- void slotModelReset(); -- void slotUpdateFilter(); -- -- void slotImageTagChange(const ImageTagChangeset& changeset); -- void slotImageChange(const ImageChangeset& changeset); -- -- void slotRowsInserted(const QModelIndex& parent, int start, int end); -- void slotRowsAboutToBeRemoved(const QModelIndex& parent, int start, int end); -- --private: -- -- Q_DECLARE_PRIVATE(ImageFilterModel) --}; -- --// ----------------------------------------------------------------------------------------------------- -- --class DIGIKAM_DATABASE_EXPORT NoDuplicatesImageFilterModel : public ImageSortFilterModel --{ -- Q_OBJECT -- --public: -- -- explicit NoDuplicatesImageFilterModel(QObject* parent = 0); -- --protected: -- -- virtual bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const; --}; -- --} // namespace Digikam -- --Q_DECLARE_METATYPE(Digikam::ImageFilterModel*) -- --#endif // IMAGEMODEL_H -diff --git a/libs/models/imagefiltermodelpriv.cpp b/libs/models/imagefiltermodelpriv.cpp -deleted file mode 100644 -index 07d9e79..0000000 ---- a/libs/models/imagefiltermodelpriv.cpp -+++ /dev/null -@@ -1,258 +0,0 @@ --/* ============================================================ -- * -- * This file is a part of digiKam project -- * http://www.digikam.org -- * -- * Date : 2009-03-05 -- * Description : Qt item model for database entries -- * -- * Copyright (C) 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -- * Copyright (C) 2011-2017 by Gilles Caulier <caulier dot gilles at gmail dot com> -- * Copyright (C) 2010 by Andi Clemens <andi dot clemens at gmail dot com> -- * Copyright (C) 2011 by Michael G. Hansen <mike at mghansen dot de> -- * Copyright (C) 2014 by Mohamed Anwer <m dot anwer at gmx dot com> -- * -- * This program is free software; you can redistribute it -- * and/or modify it under the terms of the GNU General -- * Public License as published by the Free Software Foundation; -- * either version 2, or (at your option) -- * any later version. -- * -- * This program 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 General Public License for more details. -- * -- * ============================================================ */ -- --#include "imagefiltermodelpriv.h" -- --// Local includes -- --#include "digikam_debug.h" --#include "imagefiltermodelthreads.h" -- --namespace Digikam --{ -- --ImageFilterModel::ImageFilterModelPrivate::ImageFilterModelPrivate() --{ -- imageModel = 0; -- version = 0; -- lastDiscardVersion = 0; -- sentOut = 0; -- sentOutForReAdd = 0; -- updateFilterTimer = 0; -- needPrepare = false; -- needPrepareComments = false; -- needPrepareTags = false; -- needPrepareGroups = false; -- preparer = 0; -- filterer = 0; -- hasOneMatch = false; -- hasOneMatchForText = false; -- -- setupWorkers(); --} -- --ImageFilterModel::ImageFilterModelPrivate::~ImageFilterModelPrivate() --{ -- // facilitate thread stopping -- ++version; -- preparer->deactivate(); -- filterer->deactivate(); -- delete preparer; -- delete filterer; --} -- --void ImageFilterModel::ImageFilterModelPrivate::init(ImageFilterModel* _q) --{ -- q = _q; -- -- updateFilterTimer = new QTimer(this); -- updateFilterTimer->setSingleShot(true); -- updateFilterTimer->setInterval(250); -- -- connect(updateFilterTimer, SIGNAL(timeout()), -- q, SLOT(slotUpdateFilter())); -- -- // inter-thread redirection -- qRegisterMetaType<ImageFilterModelTodoPackage>("ImageFilterModelTodoPackage"); --} -- --void ImageFilterModel::ImageFilterModelPrivate::preprocessInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues) --{ -- infosToProcess(infos, extraValues, true); --} -- --void ImageFilterModel::ImageFilterModelPrivate::processAddedInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues) --{ -- // These have already been added, we just process them afterwards -- infosToProcess(infos, extraValues, false); --} -- --void ImageFilterModel::ImageFilterModelPrivate::setupWorkers() --{ -- preparer = new ImageFilterModelPreparer(this); -- filterer = new ImageFilterModelFilterer(this); -- -- // A package in constructed in infosToProcess. -- // Normal flow is infosToProcess -> preparer::process -> filterer::process -> packageFinished. -- // If no preparation is needed, the first step is skipped. -- // If filter version changes, both will discard old package and send them to packageDiscarded. -- -- connect(this, SIGNAL(packageToPrepare(ImageFilterModelTodoPackage)), -- preparer, SLOT(process(ImageFilterModelTodoPackage))); -- -- connect(this, SIGNAL(packageToFilter(ImageFilterModelTodoPackage)), -- filterer, SLOT(process(ImageFilterModelTodoPackage))); -- -- connect(preparer, SIGNAL(processed(ImageFilterModelTodoPackage)), -- filterer, SLOT(process(ImageFilterModelTodoPackage))); -- -- connect(filterer, SIGNAL(processed(ImageFilterModelTodoPackage)), -- this, SLOT(packageFinished(ImageFilterModelTodoPackage))); -- -- connect(preparer, SIGNAL(discarded(ImageFilterModelTodoPackage)), -- this, SLOT(packageDiscarded(ImageFilterModelTodoPackage))); -- -- connect(filterer, SIGNAL(discarded(ImageFilterModelTodoPackage)), -- this, SLOT(packageDiscarded(ImageFilterModelTodoPackage))); --} -- --void ImageFilterModel::ImageFilterModelPrivate::infosToProcess(const QList<ImageInfo>& infos) --{ -- infosToProcess(infos, QList<QVariant>(), false); --} -- --void ImageFilterModel::ImageFilterModelPrivate::infosToProcess(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues, bool forReAdd) --{ -- if (infos.isEmpty()) -- { -- return; -- } -- -- filterer->schedule(); -- -- if (needPrepare) -- { -- preparer->schedule(); -- } -- -- Q_ASSERT(extraValues.isEmpty() || infos.size() == extraValues.size()); -- -- // prepare and filter in chunks -- const int size = infos.size(); -- const int maxChunkSize = needPrepare ? PrepareChunkSize : FilterChunkSize; -- const bool hasExtraValues = !extraValues.isEmpty(); -- QList<ImageInfo>::const_iterator it = infos.constBegin(), end; -- QList<QVariant>::const_iterator xit = extraValues.constBegin(), xend; -- int index = 0; -- QVector<ImageInfo> infoVector; -- QVector<QVariant> extraValueVector; -- -- while (it != infos.constEnd()) -- { -- const int chunkSize = qMin(maxChunkSize, size - index); -- infoVector.resize(chunkSize); -- end = it + chunkSize; -- qCopy(it, end, infoVector.begin()); -- -- if (hasExtraValues) -- { -- extraValueVector.resize(chunkSize); -- xend = xit + chunkSize; -- qCopy(xit, xend, extraValueVector.begin()); -- xit = xend; -- } -- -- it = end; -- index += chunkSize; -- -- ++sentOut; -- -- if (forReAdd) -- { -- ++sentOutForReAdd; -- } -- -- if (needPrepare) -- { -- emit packageToPrepare(ImageFilterModelTodoPackage(infoVector, extraValueVector, version, forReAdd)); -- } -- else -- { -- emit packageToFilter(ImageFilterModelTodoPackage(infoVector, extraValueVector, version, forReAdd)); -- } -- } --} -- --void ImageFilterModel::ImageFilterModelPrivate::packageFinished(const ImageFilterModelTodoPackage& package) --{ -- // check if it got discarded on the journey -- if (package.version != version) -- { -- packageDiscarded(package); -- return; -- } -- -- // incorporate result -- QHash<qlonglong, bool>::const_iterator it = package.filterResults.constBegin(); -- -- for (; it != package.filterResults.constEnd(); ++it) -- { -- filterResults.insert(it.key(), it.value()); -- } -- -- // re-add if necessary -- if (package.isForReAdd) -- { -- emit reAddImageInfos(package.infos.toList(), package.extraValues.toList()); -- -- if (sentOutForReAdd == 1) // last package -- { -- emit reAddingFinished(); -- } -- } -- -- // decrement counters -- --sentOut; -- -- if (package.isForReAdd) -- { -- --sentOutForReAdd; -- } -- -- // If all packages have returned, filtered and readded, and no more are expected, -- // and there is need to tell the filter result to the view, do that -- if (sentOut == 0 && sentOutForReAdd == 0 && !imageModel->isRefreshing()) -- { -- q->invalidate(); // use invalidate, not invalidateFilter only. Sorting may have changed as well. -- emit (q->filterMatches(hasOneMatch)); -- emit (q->filterMatchesForText(hasOneMatchForText)); -- filterer->deactivate(); -- preparer->deactivate(); -- } --} -- --void ImageFilterModel::ImageFilterModelPrivate::packageDiscarded(const ImageFilterModelTodoPackage& package) --{ -- // Either, the model was reset, or the filter changed -- // In the former case throw all away, in the latter case, recycle -- if (package.version > lastDiscardVersion) -- { -- // Recycle packages: Send again with current version -- // Do not increment sentOut or sentOutForReAdd here: it was not decremented! -- -- if (needPrepare) -- { -- emit packageToPrepare(ImageFilterModelTodoPackage(package.infos, package.extraValues, version, package.isForReAdd)); -- } -- else -- { -- emit packageToFilter(ImageFilterModelTodoPackage(package.infos, package.extraValues, version, package.isForReAdd)); -- } -- } --} -- --} // namespace Digikam -diff --git a/libs/models/imagefiltermodelpriv.h b/libs/models/imagefiltermodelpriv.h -deleted file mode 100644 -index a9e3f22..0000000 ---- a/libs/models/imagefiltermodelpriv.h -+++ /dev/null -@@ -1,159 +0,0 @@ --/* ============================================================ -- * -- * This file is a part of digiKam project -- * http://www.digikam.org -- * -- * Date : 2009-03-11 -- * Description : Qt item model for database entries - private shared header -- * -- * Copyright (C) 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -- * -- * This program is free software; you can redistribute it -- * and/or modify it under the terms of the GNU General -- * Public License as published by the Free Software Foundation; -- * either version 2, or (at your option) -- * any later version. -- * -- * This program 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 General Public License for more details. -- * -- * ============================================================ */ -- --#ifndef IMAGEFILTERMODELPRIV_H --#define IMAGEFILTERMODELPRIV_H -- --// Qt includes -- --#include <QHash> --#include <QMutex> --#include <QMutexLocker> --#include <QSet> --#include <QThread> --#include <QTimer> --#include <QWaitCondition> -- --// Local includes -- --#include "imageinfo.h" --#include "imagefiltermodel.h" -- --#include "digikam_export.h" --// Yes, we need the EXPORT macro in a private header because --// this private header is shared across binary objects. --// This does NOT make this classes here any more public! -- --namespace Digikam --{ -- --const int PrepareChunkSize = 101; --const int FilterChunkSize = 2001; -- --class ImageFilterModelTodoPackage --{ --public: -- -- ImageFilterModelTodoPackage() -- : version(0), isForReAdd(false) -- { -- } -- -- ImageFilterModelTodoPackage(const QVector<ImageInfo>& infos, const QVector<QVariant>& extraValues, int version, bool isForReAdd) -- : infos(infos), extraValues(extraValues), version(version), isForReAdd(isForReAdd) -- { -- } -- -- QVector<ImageInfo> infos; -- QVector<QVariant> extraValues; -- unsigned int version; -- bool isForReAdd; -- QHash<qlonglong, bool> filterResults; --}; -- --// ------------------------------------------------------------------------------------------------ -- --class ImageFilterModelPreparer; --class ImageFilterModelFilterer; -- --class DIGIKAM_DATABASE_EXPORT ImageFilterModel::ImageFilterModelPrivate : public QObject --{ -- Q_OBJECT -- --public: -- -- ImageFilterModelPrivate(); -- ~ImageFilterModelPrivate(); -- -- void init(ImageFilterModel* q); -- void setupWorkers(); -- void infosToProcess(const QList<ImageInfo>& infos); -- void infosToProcess(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues, bool forReAdd = true); -- --public: -- -- ImageFilterModel* q; -- -- ImageModel* imageModel; -- -- ImageFilterSettings filter; -- ImageSortSettings sorter; -- VersionImageFilterSettings versionFilter; -- GroupImageFilterSettings groupFilter; -- -- volatile unsigned int version; -- unsigned int lastDiscardVersion; -- unsigned int lastFilteredVersion; -- int sentOut; -- int sentOutForReAdd; -- -- QTimer* updateFilterTimer; -- -- bool needPrepare; -- bool needPrepareComments; -- bool needPrepareTags; -- bool needPrepareGroups; -- -- QMutex mutex; -- ImageFilterSettings filterCopy; -- VersionImageFilterSettings versionFilterCopy; -- GroupImageFilterSettings groupFilterCopy; -- ImageFilterModelPreparer* preparer; -- ImageFilterModelFilterer* filterer; -- -- QHash<qlonglong, bool> filterResults; -- bool hasOneMatch; -- bool hasOneMatchForText; -- -- QList<ImageFilterModelPrepareHook*> prepareHooks; -- --/* -- QHash<int, QSet<qlonglong> > categoryCountHashInt; -- QHash<QString, QSet<qlonglong> > categoryCountHashString; -- --public: -- -- void cacheCategoryCount(int id, qlonglong imageid) const -- { const_cast<ImageFilterModelPrivate*>(this)->categoryCountHashInt[id].insert(imageid); } -- void cacheCategoryCount(const QString& id, qlonglong imageid) const -- { const_cast<ImageFilterModelPrivate*>(this)->categoryCountHashString[id].insert(imageid); } --*/ -- --public Q_SLOTS: -- -- void preprocessInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues); -- void processAddedInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues); -- void packageFinished(const ImageFilterModelTodoPackage& package); -- void packageDiscarded(const ImageFilterModelTodoPackage& package); -- --Q_SIGNALS: -- -- void packageToPrepare(const ImageFilterModelTodoPackage& package); -- void packageToFilter(const ImageFilterModelTodoPackage& package); -- void reAddImageInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues); -- void reAddingFinished(); --}; -- --} // namespace Digikam -- --#endif // IMAGEFILTERMODELPRIV_H -diff --git a/libs/models/imagefiltermodelthreads.cpp b/libs/models/imagefiltermodelthreads.cpp -deleted file mode 100644 -index aa5c462..0000000 ---- a/libs/models/imagefiltermodelthreads.cpp -+++ /dev/null -@@ -1,40 +0,0 @@ --/* ============================================================ -- * -- * This file is a part of digiKam project -- * http://www.digikam.org -- * -- * Date : 2009-03-05 -- * Description : Qt item model for database entries -- * -- * Copyright (C) 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -- * Copyright (C) 2011-2017 by Gilles Caulier <caulier dot gilles at gmail dot com> -- * Copyright (C) 2010 by Andi Clemens <andi dot clemens at gmail dot com> -- * Copyright (C) 2011 by Michael G. Hansen <mike at mghansen dot de> -- * Copyright (C) 2014 by Mohamed Anwer <m dot anwer at gmx dot com> -- * -- * This program is free software; you can redistribute it -- * and/or modify it under the terms of the GNU General -- * Public License as published by the Free Software Foundation; -- * either version 2, or (at your option) -- * any later version. -- * -- * This program 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 General Public License for more details. -- * -- * ============================================================ */ -- --#include "imagefiltermodel.h" --#include "imagefiltermodelpriv.h" --#include "imagefiltermodelthreads.h" -- --namespace Digikam --{ -- --ImageFilterModelWorker::ImageFilterModelWorker(ImageFilterModel::ImageFilterModelPrivate* const d) -- : d(d) --{ --} -- --} // namespace Digikam -diff --git a/libs/models/imagefiltermodelthreads.h b/libs/models/imagefiltermodelthreads.h -deleted file mode 100644 -index 83fa987..0000000 ---- a/libs/models/imagefiltermodelthreads.h -+++ /dev/null -@@ -1,100 +0,0 @@ --/* ============================================================ -- * -- * This file is a part of digiKam project -- * http://www.digikam.org -- * -- * Date : 2009-03-11 -- * Description : Qt item model for database entries - private header -- * -- * Copyright (C) 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -- * -- * This program is free software; you can redistribute it -- * and/or modify it under the terms of the GNU General -- * Public License as published by the Free Software Foundation; -- * either version 2, or (at your option) -- * any later version. -- * -- * This program 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 General Public License for more details. -- * -- * ============================================================ */ -- --#ifndef IMAGEFILTERMODELTHREADS_H --#define IMAGEFILTERMODELTHREADS_H -- --// Qt includes -- --#include <QThread> -- --// Local includes -- --#include "digikam_export.h" --#include "workerobject.h" -- --namespace Digikam --{ -- --class DIGIKAM_DATABASE_EXPORT ImageFilterModelWorker : public WorkerObject --{ -- Q_OBJECT -- --public: -- -- explicit ImageFilterModelWorker(ImageFilterModel::ImageFilterModelPrivate* const d); -- -- bool checkVersion(const ImageFilterModelTodoPackage& package) -- { -- return d->version == package.version; -- } -- --public Q_SLOTS: -- -- virtual void process(ImageFilterModelTodoPackage package) = 0; -- --Q_SIGNALS: -- -- void processed(const ImageFilterModelTodoPackage& package); -- void discarded(const ImageFilterModelTodoPackage& package); -- --protected: -- -- ImageFilterModel::ImageFilterModelPrivate* d; --}; -- --// ----------------------------------------------------------------------------------------- -- --class DIGIKAM_DATABASE_EXPORT ImageFilterModelPreparer : public ImageFilterModelWorker --{ -- Q_OBJECT -- --public: -- -- explicit ImageFilterModelPreparer(ImageFilterModel::ImageFilterModelPrivate* const d) -- : ImageFilterModelWorker(d) -- { -- } -- -- void process(ImageFilterModelTodoPackage package); --}; -- --// ---------------------------------------------------------------------------------------- -- --class DIGIKAM_DATABASE_EXPORT ImageFilterModelFilterer : public ImageFilterModelWorker --{ -- Q_OBJECT -- --public: -- -- explicit ImageFilterModelFilterer(ImageFilterModel::ImageFilterModelPrivate* const d) -- : ImageFilterModelWorker(d) -- { -- } -- -- void process(ImageFilterModelTodoPackage package); --}; -- --} // namespace Digikam -- --#endif // IMAGEFILTERMODELTHREADS_H -diff --git a/libs/models/imagefiltersettings.cpp b/libs/models/imagefiltersettings.cpp -deleted file mode 100644 -index b61e7f9..0000000 ---- a/libs/models/imagefiltersettings.cpp -+++ /dev/null -@@ -1,952 +0,0 @@ --/* ============================================================ -- * -- * This file is a part of digiKam project -- * http://www.digikam.org -- * -- * Date : 2009-03-05 -- * Description : Filter values for use with ImageFilterModel -- * -- * Copyright (C) 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -- * Copyright (C) 2011-2017 by Gilles Caulier <caulier dot gilles at gmail dot com> -- * Copyright (C) 2010 by Andi Clemens <andi dot clemens at gmail dot com> -- * Copyright (C) 2011 by Michael G. Hansen <mike at mghansen dot de> -- * Copyright (C) 2014 by Mohamed Anwer <m dot anwer at gmx dot com> -- * -- * This program is free software; you can redistribute it -- * and/or modify it under the terms of the GNU General -- * Public License as published by the Free Software Foundation; -- * either version 2, or (at your option) -- * any later version. -- * -- * This program 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 General Public License for more details. -- * -- * ============================================================ */ -- --#include "imagefiltersettings.h" -- --// C++ includes -- --#include <cmath> -- --// Qt includes -- --#include <QDateTime> -- --// Local includes -- --#include "digikam_debug.h" --#include "coredbfields.h" --#include "digikam_globals.h" --#include "imageinfo.h" --#include "tagscache.h" --#include "versionmanagersettings.h" -- --namespace Digikam --{ -- --ImageFilterSettings::ImageFilterSettings() --{ -- m_untaggedFilter = false; -- m_isUnratedExcluded = false; -- m_ratingFilter = 0; -- m_mimeTypeFilter = MimeFilter::AllFiles; -- m_ratingCond = GreaterEqualCondition; -- m_matchingCond = OrCondition; -- m_geolocationCondition = GeolocationNoFilter; --} -- --DatabaseFields::Set ImageFilterSettings::watchFlags() const --{ -- DatabaseFields::Set set; -- -- if (isFilteringByDay()) -- { -- set |= DatabaseFields::CreationDate; -- } -- -- if (isFilteringByText()) -- { -- set |= DatabaseFields::Name; -- set |= DatabaseFields::Comment; -- } -- -- if (isFilteringByRating()) -- { -- set |= DatabaseFields::Rating; -- } -- -- if (isFilteringByTypeMime()) -- { -- set |= DatabaseFields::Category; -- set |= DatabaseFields::Format; -- } -- -- if (isFilteringByGeolocation()) -- { -- set |= DatabaseFields::ImagePositionsAll; -- } -- -- if (isFilteringByColorLabels()) -- { -- set |= DatabaseFields::ColorLabel; -- } -- -- if (isFilteringByPickLabels()) -- { -- set |= DatabaseFields::PickLabel; -- } -- -- return set; --} -- --bool ImageFilterSettings::isFilteringByDay() const --{ -- if (!m_dayFilter.isEmpty()) -- { -- return true; -- } -- -- return false; --} -- --bool ImageFilterSettings::isFilteringByTags() const --{ -- if (!m_includeTagFilter.isEmpty() || !m_excludeTagFilter.isEmpty() || m_untaggedFilter) -- { -- return true; -- } -- -- return false; --} -- --bool ImageFilterSettings::isFilteringByColorLabels() const --{ -- if (!m_colorLabelTagFilter.isEmpty()) -- { -- return true; -- } -- -- return false; --} -- --bool ImageFilterSettings::isFilteringByPickLabels() const --{ -- if (!m_pickLabelTagFilter.isEmpty()) -- { -- return true; -- } -- -- return false; --} -- --bool ImageFilterSettings::isFilteringByText() const --{ -- if (!m_textFilterSettings.text.isEmpty()) -- { -- return true; -- } -- -- return false; --} -- --bool ImageFilterSettings::isFilteringByTypeMime() const --{ -- if (m_mimeTypeFilter != MimeFilter::AllFiles) -- { -- return true; -- } -- -- return false; --} -- --bool ImageFilterSettings::isFilteringByGeolocation() const --{ -- return (m_geolocationCondition != GeolocationNoFilter); --} -- --bool ImageFilterSettings::isFilteringByRating() const --{ -- if (m_ratingFilter != 0 || m_ratingCond != GreaterEqualCondition || m_isUnratedExcluded) -- { -- return true; -- } -- -- return false; --} -- --bool ImageFilterSettings::isFilteringInternally() const --{ -- return (isFiltering() || !m_urlWhitelists.isEmpty() || !m_idWhitelists.isEmpty()); --} -- --bool ImageFilterSettings::isFiltering() const --{ -- return isFilteringByDay() || -- isFilteringByTags() || -- isFilteringByText() || -- isFilteringByRating() || -- isFilteringByTypeMime() || -- isFilteringByColorLabels() || -- isFilteringByPickLabels() || -- isFilteringByGeolocation(); --} -- --void ImageFilterSettings::setDayFilter(const QList<QDateTime>& days) --{ -- m_dayFilter.clear(); -- -- for (QList<QDateTime>::const_iterator it = days.constBegin(); it != days.constEnd(); ++it) -- { -- m_dayFilter.insert(*it, true); -- } --} -- --void ImageFilterSettings::setTagFilter(const QList<int>& includedTags, -- const QList<int>& excludedTags, -- MatchingCondition matchingCondition, -- bool showUnTagged, -- const QList<int>& clTagIds, -- const QList<int>& plTagIds) --{ -- m_includeTagFilter = includedTags; -- m_excludeTagFilter = excludedTags; -- m_matchingCond = matchingCondition; -- m_untaggedFilter = showUnTagged; -- m_colorLabelTagFilter = clTagIds; -- m_pickLabelTagFilter = plTagIds; --} -- --void ImageFilterSettings::setRatingFilter(int rating, RatingCondition ratingCondition, bool isUnratedExcluded) --{ -- m_ratingFilter = rating; -- m_ratingCond = ratingCondition; -- m_isUnratedExcluded = isUnratedExcluded; --} -- --void ImageFilterSettings::setMimeTypeFilter(int mime) --{ -- m_mimeTypeFilter = (MimeFilter::TypeMimeFilter)mime; --} -- --void ImageFilterSettings::setGeolocationFilter(const GeolocationCondition& condition) --{ -- m_geolocationCondition = condition; --} -- --void ImageFilterSettings::setTextFilter(const SearchTextFilterSettings& settings) --{ -- m_textFilterSettings = settings; --} -- --void ImageFilterSettings::setTagNames(const QHash<int, QString>& hash) --{ -- m_tagNameHash = hash; --} -- --void ImageFilterSettings::setAlbumNames(const QHash<int, QString>& hash) --{ -- m_albumNameHash = hash; --} -- --void ImageFilterSettings::setUrlWhitelist(const QList<QUrl>& urlList, const QString& id) --{ -- if (urlList.isEmpty()) -- { -- m_urlWhitelists.remove(id); -- } -- else -- { -- m_urlWhitelists.insert(id, urlList); -- } --} -- --void ImageFilterSettings::setIdWhitelist(const QList<qlonglong>& idList, const QString& id) --{ -- if (idList.isEmpty()) -- { -- m_idWhitelists.remove(id); -- } -- else -- { -- m_idWhitelists.insert(id, idList); -- } --} -- --template <class ContainerA, class ContainerB> --bool containsAnyOf(const ContainerA& listA, const ContainerB& listB) --{ -- foreach (const typename ContainerA::value_type& a, listA) -- { -- if (listB.contains(a)) -- { -- return true; -- } -- } -- return false; --} -- --template <class ContainerA, typename Value, class ContainerB> --bool containsNoneOfExcept(const ContainerA& list, const ContainerB& noneOfList, const Value& exception) --{ -- foreach (const typename ContainerB::value_type& n, noneOfList) -- { -- if (n != exception && list.contains(n)) -- { -- return false; -- } -- } -- return true; --} -- --bool ImageFilterSettings::matches(const ImageInfo& info, bool* const foundText) const --{ -- if (foundText) -- { -- *foundText = false; -- } -- -- if (!isFilteringInternally()) -- { -- return true; -- } -- -- bool match = false; -- -- if (!m_includeTagFilter.isEmpty() || !m_excludeTagFilter.isEmpty()) -- { -- QList<int> tagIds = info.tagIds(); -- QList<int>::const_iterator it; -- -- match = m_includeTagFilter.isEmpty(); -- -- if (m_matchingCond == OrCondition) -- { -- for (it = m_includeTagFilter.begin(); it != m_includeTagFilter.end(); ++it) -- { -- if (tagIds.contains(*it)) -- { -- match = true; -- break; -- } -- } -- -- match |= (m_untaggedFilter && tagIds.isEmpty()); -- } -- else // AND matching condition... -- { -- // m_untaggedFilter and non-empty tag filter, combined with AND, is logically no match -- if (!m_untaggedFilter) -- { -- for (it = m_includeTagFilter.begin(); it != m_includeTagFilter.end(); ++it) -- { -- if (!tagIds.contains(*it)) -- { -- break; -- } -- } -- -- if (it == m_includeTagFilter.end()) -- { -- match = true; -- } -- } -- } -- -- for (it = m_excludeTagFilter.begin(); it != m_excludeTagFilter.end(); ++it) -- { -- if (tagIds.contains(*it)) -- { -- match = false; -- break; -- } -- } -- } -- else if (m_untaggedFilter) -- { -- match = !TagsCache::instance()->containsPublicTags(info.tagIds()); -- } -- else -- { -- match = true; -- } -- -- //-- Filter by pick labels ------------------------------------------------ -- -- if (!m_pickLabelTagFilter.isEmpty()) -- { -- QList<int> tagIds = info.tagIds(); -- bool matchPL = false; -- -- if (containsAnyOf(m_pickLabelTagFilter, tagIds)) -- { -- matchPL = true; -- } -- else if (!matchPL) -- { -- int noPickLabelTagId = TagsCache::instance()->tagForPickLabel(NoPickLabel); -- -- if (m_pickLabelTagFilter.contains(noPickLabelTagId)) -- { -- // Searching for "has no ColorLabel" requires special handling: -- // Scan that the tag ids contains none of the ColorLabel tags, except maybe the NoColorLabel tag -- matchPL = containsNoneOfExcept(tagIds, TagsCache::instance()->pickLabelTags(), noPickLabelTagId); -- } -- } -- -- match &= matchPL; -- } -- -- //-- Filter by color labels ------------------------------------------------ -- -- if (!m_colorLabelTagFilter.isEmpty()) -- { -- QList<int> tagIds = info.tagIds(); -- bool matchCL = false; -- -- if (containsAnyOf(m_colorLabelTagFilter, tagIds)) -- { -- matchCL = true; -- } -- else if (!matchCL) -- { -- int noColorLabelTagId = TagsCache::instance()->tagForColorLabel(NoColorLabel); -- -- if (m_colorLabelTagFilter.contains(noColorLabelTagId)) -- { -- // Searching for "has no ColorLabel" requires special handling: -- // Scan that the tag ids contains none of the ColorLabel tags, except maybe the NoColorLabel tag -- matchCL = containsNoneOfExcept(tagIds, TagsCache::instance()->colorLabelTags(), noColorLabelTagId); -- } -- } -- -- match &= matchCL; -- } -- -- //-- Filter by date ----------------------------------------------------------- -- -- if (!m_dayFilter.isEmpty()) -- { -- match &= m_dayFilter.contains(QDateTime(info.dateTime().date(), QTime())); -- } -- -- //-- Filter by rating --------------------------------------------------------- -- -- if (m_ratingFilter >= 0) -- { -- // for now we treat -1 (no rating) just like a rating of 0. -- int rating = info.rating(); -- -- if (rating == -1) -- { -- rating = 0; -- } -- -- if(m_isUnratedExcluded && rating == 0) -- { -- match = false; -- } -- else -- { -- if (m_ratingCond == GreaterEqualCondition) -- { -- // If the rating is not >=, i.e it is <, then it does not match. -- if (rating < m_ratingFilter) -- { -- match = false; -- } -- } -- else if (m_ratingCond == EqualCondition) -- { -- // If the rating is not =, i.e it is !=, then it does not match. -- if (rating != m_ratingFilter) -- { -- match = false; -- } -- } -- else -- { -- // If the rating is not <=, i.e it is >, then it does not match. -- if (rating > m_ratingFilter) -- { -- match = false; -- } -- } -- } -- } -- -- // -- Filter by mime type ----------------------------------------------------- -- -- switch (m_mimeTypeFilter) -- { -- // info.format is a standardized string: Only one possibility per mime type -- case MimeFilter::ImageFiles: -- { -- if (info.category() != DatabaseItem::Image) -- { -- match = false; -- } -- -- break; -- } -- case MimeFilter::JPGFiles: -- { -- if (info.format() != QLatin1String("JPG")) -- { -- match = false; -- } -- -- break; -- } -- case MimeFilter::PNGFiles: -- { -- if (info.format() != QLatin1String("PNG")) -- { -- match = false; -- } -- -- break; -- } -- case MimeFilter::TIFFiles: -- { -- if (info.format() != QLatin1String("TIFF")) -- { -- match = false; -- } -- -- break; -- } -- case MimeFilter::DNGFiles: -- { -- if (info.format() != QLatin1String("RAW-DNG")) -- { -- match = false; -- } -- -- break; -- } -- case MimeFilter::NoRAWFiles: -- { -- if (info.format().startsWith(QLatin1String("RAW"))) -- { -- match = false; -- } -- -- break; -- } -- case MimeFilter::RAWFiles: -- { -- if (!info.format().startsWith(QLatin1String("RAW"))) -- { -- match = false; -- } -- -- break; -- } -- case MimeFilter::MoviesFiles: -- { -- if (info.category() != DatabaseItem::Video) -- { -- match = false; -- } -- -- break; -- } -- case MimeFilter::AudioFiles: -- { -- if (info.category() != DatabaseItem::Audio) -- { -- match = false; -- } -- -- break; -- } -- case MimeFilter::RasterFiles: -- { -- if (info.format() != QLatin1String("PSD") && // Adobe Photoshop Document -- info.format() != QLatin1String("PSB") && // Adobe Photoshop Big -- info.format() != QLatin1String("XCF") && // Gimp -- info.format() != QLatin1String("KRA") && // Krita -- info.format() != QLatin1String("ORA") // Open Raster -- ) -- { -- match = false; -- } -- -- break; -- } -- default: -- { -- // All Files: do nothing... -- break; -- } -- } -- -- //-- Filter by geolocation ---------------------------------------------------- -- -- if (m_geolocationCondition!=GeolocationNoFilter) -- { -- if (m_geolocationCondition==GeolocationNoCoordinates) -- { -- if (info.hasCoordinates()) -- { -- match = false; -- } -- } -- else if (m_geolocationCondition==GeolocationHasCoordinates) -- { -- if (!info.hasCoordinates()) -- { -- match = false; -- } -- } -- } -- -- //-- Filter by text ----------------------------------------------------------- -- -- if (!m_textFilterSettings.text.isEmpty()) -- { -- bool textMatch = false; -- -- // Image name -- if (m_textFilterSettings.textFields & SearchTextFilterSettings::ImageName && -- info.name().contains(m_textFilterSettings.text, m_textFilterSettings.caseSensitive)) -- { -- textMatch = true; -- } -- -- // Image title -- if (m_textFilterSettings.textFields & SearchTextFilterSettings::ImageTitle && -- info.title().contains(m_textFilterSettings.text, m_textFilterSettings.caseSensitive)) -- { -- textMatch = true; -- } -- -- // Image comment -- if (m_textFilterSettings.textFields & SearchTextFilterSettings::ImageComment && -- info.comment().contains(m_textFilterSettings.text, m_textFilterSettings.caseSensitive)) -- { -- textMatch = true; -- } -- -- // Tag names -- foreach(int id, info.tagIds()) -- { -- if (m_textFilterSettings.textFields & SearchTextFilterSettings::TagName && -- m_tagNameHash.value(id).contains(m_textFilterSettings.text, m_textFilterSettings.caseSensitive)) -- { -- textMatch = true; -- } -- } -- -- // Album names -- if (m_textFilterSettings.textFields & SearchTextFilterSettings::AlbumName && -- m_albumNameHash.value(info.albumId()).contains(m_textFilterSettings.text, m_textFilterSettings.caseSensitive)) -- { -- textMatch = true; -- } -- -- // Image Aspect Ratio -- if (m_textFilterSettings.textFields & SearchTextFilterSettings::ImageAspectRatio) -- { -- QRegExp expRatio (QLatin1String("^\\d+:\\d+$")); -- QRegExp expFloat (QLatin1String("^\\d+(.\\d+)?$")); -- -- if (expRatio.indexIn(m_textFilterSettings.text) > -1 && m_textFilterSettings.text.contains(QRegExp(QLatin1String(":\\d+")))) -- { -- QString trimmedTextFilterSettingsText = m_textFilterSettings.text; -- QStringList numberStringList = trimmedTextFilterSettingsText.split(QLatin1String(":"), QString::SkipEmptyParts); -- -- if (numberStringList.length() == 2) -- { -- QString numString = (QString)numberStringList.at(0), denomString = (QString)numberStringList.at(1); -- bool canConverseNum = false; -- bool canConverseDenom = false; -- int num = numString.toInt(&canConverseNum, 10), denom = denomString.toInt(&canConverseDenom, 10); -- -- if (canConverseNum && canConverseDenom) -- { -- if (fabs(info.aspectRatio() - (double)num / denom) < 0.1) -- textMatch = true; -- } -- } -- } -- else if (expFloat.indexIn(m_textFilterSettings.text) > -1) -- { -- QString trimmedTextFilterSettingsText = m_textFilterSettings.text; -- bool canConverse = false; -- double ratio = trimmedTextFilterSettingsText.toDouble(&canConverse); -- -- if (canConverse) -- { -- if (fabs(info.aspectRatio() - ratio) < 0.1) -- textMatch = true; -- } -- } -- } -- -- // Image Pixel Size -- // See bug #341053 for details. -- -- if (m_textFilterSettings.textFields & SearchTextFilterSettings::ImagePixelSize) -- { -- QSize size = info.dimensions(); -- int pixelSize = size.height()*size.width(); -- QString text = m_textFilterSettings.text; -- -- if(text.contains(QRegExp(QLatin1String("^>\\d{1,15}$"))) && pixelSize > (text.remove(0,1)).toInt()) -- { -- textMatch = true; -- } -- else if(text.contains(QRegExp(QLatin1String("^<\\d{1,15}$"))) && pixelSize < (text.remove(0,1)).toInt()) -- { -- textMatch = true; -- } -- else if(text.contains(QRegExp(QLatin1String("^\\d+$"))) && pixelSize == text.toInt()) -- { -- textMatch = true; -- } -- } -- -- match &= textMatch; -- -- if (foundText) -- { -- *foundText = textMatch; -- } -- } -- -- // -- filter by URL-whitelists ------------------------------------------------ -- // NOTE: whitelists are always AND for now. -- -- if (match) -- { -- const QUrl url = info.fileUrl(); -- -- for (QHash<QString, QList<QUrl>>::const_iterator it = m_urlWhitelists.constBegin(); -- it!=m_urlWhitelists.constEnd(); ++it) -- { -- match = it->contains(url); -- -- if (!match) -- { -- break; -- } -- } -- } -- -- if (match) -- { -- const qlonglong id = info.id(); -- -- for (QHash<QString, QList<qlonglong> >::const_iterator it = m_idWhitelists.constBegin(); -- it!=m_idWhitelists.constEnd(); ++it) -- { -- match = it->contains(id); -- -- if (!match) -- { -- break; -- } -- } -- } -- -- return match; --} -- --// ------------------------------------------------------------------------------------------------- -- --VersionImageFilterSettings::VersionImageFilterSettings() --{ -- m_includeTagFilter = 0; -- m_exceptionTagFilter = 0; --} -- --VersionImageFilterSettings::VersionImageFilterSettings(const VersionManagerSettings& settings) --{ -- setVersionManagerSettings(settings); --} -- --bool VersionImageFilterSettings::operator==(const VersionImageFilterSettings& other) const --{ -- return m_excludeTagFilter == other.m_excludeTagFilter && -- m_exceptionLists == other.m_exceptionLists; --} -- --bool VersionImageFilterSettings::matches(const ImageInfo& info) const --{ -- if (!isFiltering()) -- { -- return true; -- } -- -- const qlonglong id = info.id(); -- -- for (QHash<QString, QList<qlonglong> >::const_iterator it = m_exceptionLists.constBegin(); -- it != m_exceptionLists.constEnd(); ++it) -- { -- if (it->contains(id)) -- { -- return true; -- } -- } -- -- bool match = true; -- QList<int> tagIds = info.tagIds(); -- -- if (!tagIds.contains(m_includeTagFilter)) -- { -- for (QList<int>::const_iterator it = m_excludeTagFilter.begin(); -- it != m_excludeTagFilter.end(); ++it) -- { -- if (tagIds.contains(*it)) -- { -- match = false; -- break; -- } -- } -- } -- -- if (!match) -- { -- if (tagIds.contains(m_exceptionTagFilter)) -- { -- match = true; -- } -- } -- -- return match; --} -- --bool VersionImageFilterSettings::isHiddenBySettings(const ImageInfo& info) const --{ -- QList<int> tagIds = info.tagIds(); -- -- foreach(int tagId, m_excludeTagFilter) -- { -- if (tagIds.contains(tagId)) -- { -- return true; -- } -- } -- -- return false; --} -- --bool VersionImageFilterSettings::isExemptedBySettings(const ImageInfo& info) const --{ -- return info.tagIds().contains(m_exceptionTagFilter); --} -- --void VersionImageFilterSettings::setVersionManagerSettings(const VersionManagerSettings& settings) --{ -- m_excludeTagFilter.clear(); -- -- if (!settings.enabled) -- { -- return; -- } -- -- if (!(settings.showInViewFlags & VersionManagerSettings::ShowOriginal)) -- { -- m_excludeTagFilter << TagsCache::instance()->getOrCreateInternalTag(InternalTagName::originalVersion()); -- } -- -- if (!(settings.showInViewFlags & VersionManagerSettings::ShowIntermediates)) -- { -- m_excludeTagFilter << TagsCache::instance()->getOrCreateInternalTag(InternalTagName::intermediateVersion()); -- } -- -- m_includeTagFilter = TagsCache::instance()->getOrCreateInternalTag(InternalTagName::currentVersion()); -- m_exceptionTagFilter = TagsCache::instance()->getOrCreateInternalTag(InternalTagName::versionAlwaysVisible()); --} -- --void VersionImageFilterSettings::setExceptionList(const QList<qlonglong>& idList, const QString& id) --{ -- if (idList.isEmpty()) -- { -- m_exceptionLists.remove(id); -- } -- else -- { -- m_exceptionLists.insert(id, idList); -- } --} -- --bool VersionImageFilterSettings::isFiltering() const --{ -- return !m_excludeTagFilter.isEmpty(); --} -- --bool VersionImageFilterSettings::isFilteringByTags() const --{ -- return isFiltering(); --} -- --// ------------------------------------------------------------------------------------------------- -- --GroupImageFilterSettings::GroupImageFilterSettings() -- : m_allOpen(false) --{ --} -- --bool GroupImageFilterSettings::operator==(const GroupImageFilterSettings& other) const --{ -- return (m_allOpen == other.m_allOpen && -- m_openGroups == other.m_openGroups); --} -- --bool GroupImageFilterSettings::matches(const ImageInfo& info) const --{ -- if (m_allOpen) -- { -- return true; -- } -- -- if (info.isGrouped()) -- { -- return m_openGroups.contains(info.groupImage().id()); -- } -- return true; --} -- --void GroupImageFilterSettings::setOpen(qlonglong group, bool open) --{ -- if (open) -- { -- m_openGroups << group; -- } -- else -- { -- m_openGroups.remove(group); -- } --} -- --bool GroupImageFilterSettings::isOpen(qlonglong group) const --{ -- return m_openGroups.contains(group); --} -- --void GroupImageFilterSettings::setAllOpen(bool open) --{ -- m_allOpen = open; --} -- --bool GroupImageFilterSettings::isAllOpen() const --{ -- return m_allOpen; --} -- --bool GroupImageFilterSettings::isFiltering() const --{ -- return !m_allOpen; --} -- --DatabaseFields::Set GroupImageFilterSettings::watchFlags() const --{ -- return DatabaseFields::ImageRelations; --} -- --} // namespace Digikam -diff --git a/libs/models/imagefiltersettings.h b/libs/models/imagefiltersettings.h -deleted file mode 100644 -index 0e7beae..0000000 ---- a/libs/models/imagefiltersettings.h -+++ /dev/null -@@ -1,349 +0,0 @@ --/* ============================================================ -- * -- * This file is a part of digiKam project -- * http://www.digikam.org -- * -- * Date : 2009-03-05 -- * Description : Filter values for use with ImageFilterModel -- * -- * Copyright (C) 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -- * Copyright (C) 2011-2017 by Gilles Caulier <caulier dot gilles at gmail dot com> -- * Copyright (C) 2010 by Andi Clemens <andi dot clemens at gmail dot com> -- * Copyright (C) 2011 by Michael G. Hansen <mike at mghansen dot de> -- * Copyright (C) 2014 by Mohamed Anwer <m dot anwer at gmx dot com> -- * -- * This program is free software; you can redistribute it -- * and/or modify it under the terms of the GNU General -- * Public License as published by the Free Software Foundation; -- * either version 2, or (at your option) -- * any later version. -- * -- * This program 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 General Public License for more details. -- * -- * ============================================================ */ -- --#ifndef IMAGEFILTERSETTINGS_H --#define IMAGEFILTERSETTINGS_H -- --// Qt includes -- --#include <QHash> --#include <QList> --#include <QMap> --#include <QString> --#include <QSet> --#include <QUrl> -- --// Local includes -- --#include "searchtextbar.h" --#include "mimefilter.h" --#include "digikam_export.h" -- --namespace Digikam --{ -- --class ImageInfo; --class VersionManagerSettings; -- --namespace DatabaseFields --{ -- class Set; --} -- --// --------------------------------------------------------------------------------------- -- --class DIGIKAM_DATABASE_EXPORT SearchTextFilterSettings : public SearchTextSettings --{ -- --public: -- -- enum TextFilterFields -- { -- None = 0x00, -- ImageName = 0x01, -- ImageTitle = 0x02, -- ImageComment = 0x04, -- TagName = 0x08, -- AlbumName = 0x10, -- ImageAspectRatio = 0x20, -- ImagePixelSize = 0x40, -- All = ImageName | ImageTitle | ImageComment | TagName | AlbumName | ImageAspectRatio | ImagePixelSize -- }; -- --public: -- -- SearchTextFilterSettings() -- { -- textFields = None; -- } -- -- explicit SearchTextFilterSettings(const SearchTextSettings& settings) -- { -- caseSensitive = settings.caseSensitive; -- text = settings.text; -- textFields = None; -- } -- -- TextFilterFields textFields; --}; -- --// --------------------------------------------------------------------------------------- -- --class DIGIKAM_DATABASE_EXPORT ImageFilterSettings --{ --public: -- -- ImageFilterSettings(); -- -- /** -- * Returns true if the given ImageInfo matches the filter criteria. -- * Optionally, foundText is set to true if it matched by text search. -- */ -- bool matches(const ImageInfo& info, bool* const foundText = 0) const; -- --public: -- -- /// --- Tags filter --- -- -- /// Possible logical matching condition used to sort tags id. -- enum MatchingCondition -- { -- OrCondition, -- AndCondition -- }; -- -- void setTagFilter(const QList<int>& includedTags, -- const QList<int>& excludedTags, -- MatchingCondition matchingCond, -- bool showUnTagged, -- const QList<int>& clTagIds, -- const QList<int>& plTagIds); -- --public: -- -- /// --- Rating filter --- -- -- /// Possible conditions used to filter rating: >=, =, <= -- enum RatingCondition -- { -- GreaterEqualCondition, -- EqualCondition, -- LessEqualCondition -- }; -- -- void setRatingFilter(int rating, RatingCondition ratingCond, bool isUnratedExcluded); -- --public: -- -- /// --- Date filter --- -- void setDayFilter(const QList<QDateTime>& days); -- --public: -- -- /// --- Text filter --- -- void setTextFilter(const SearchTextFilterSettings& settings); -- void setTagNames(const QHash<int, QString>& tagNameHash); -- void setAlbumNames(const QHash<int, QString>& albumNameHash); -- --public: -- -- /// --- Mime filter --- -- void setMimeTypeFilter(int mimeTypeFilter); -- --public: -- -- /// --- Geolocation filter -- enum GeolocationCondition -- { -- GeolocationNoFilter = 0, -- GeolocationNoCoordinates = 1 << 1, -- GeolocationHasCoordinates = 1 << 2 -- }; -- -- void setGeolocationFilter(const GeolocationCondition& condition); -- --public: -- -- /// Returns if the day is a filter criteria -- bool isFilteringByDay() const; -- -- /// Returns if the type mime is a filter criteria -- bool isFilteringByTypeMime() const; -- -- /// Returns whether geolocation is a filter criteria -- bool isFilteringByGeolocation() const; -- -- /// Returns if the rating is a filter criteria -- bool isFilteringByRating() const; -- -- /// Returns if the pick labels is a filter criteria -- bool isFilteringByPickLabels() const; -- -- /// Returns if the color labels is a filter criteria -- bool isFilteringByColorLabels() const; -- -- /// Returns if the tag is a filter criteria -- bool isFilteringByTags() const; -- -- /// Returns if the text (including comment) is a filter criteria -- bool isFilteringByText() const; -- -- /// Returns if images will be filtered by these criteria at all -- bool isFiltering() const; -- --public: -- -- /// --- URL whitelist filter -- void setUrlWhitelist(const QList<QUrl>& urlList, const QString& id); -- --public: -- -- /// --- ID whitelist filter -- void setIdWhitelist(const QList<qlonglong>& idList, const QString& id); -- --public: -- -- /// --- Change notification --- -- -- /** Returns database fields a change in which would affect the current filtering. -- * To find out if an image tag change affects filtering, test isFilteringByTags(). -- * The text filter will also be affected by changes in tags and album names. -- */ -- DatabaseFields::Set watchFlags() const; -- --private: -- -- /** -- * @brief Returns whether some internal filtering (whitelist by id or URL) or normal filtering is going on -- */ -- bool isFilteringInternally() const; -- --private: -- -- /// --- Tags filter --- -- bool m_untaggedFilter; -- QList<int> m_includeTagFilter; -- QList<int> m_excludeTagFilter; -- MatchingCondition m_matchingCond; -- QList<int> m_colorLabelTagFilter; -- QList<int> m_pickLabelTagFilter; -- -- /// --- Rating filter --- -- int m_ratingFilter; -- RatingCondition m_ratingCond; -- bool m_isUnratedExcluded; -- -- /// --- Date filter --- -- QMap<QDateTime, bool> m_dayFilter; -- -- /// --- Text filter --- -- SearchTextFilterSettings m_textFilterSettings; -- -- /// Helpers for text search: Set these if you want to search album or tag names with text search -- QHash<int, QString> m_tagNameHash; -- QHash<int, QString> m_albumNameHash; -- -- /// --- Mime filter --- -- MimeFilter::TypeMimeFilter m_mimeTypeFilter; -- -- /// --- Geolocation filter -- GeolocationCondition m_geolocationCondition; -- -- /// --- URL whitelist filter -- QHash<QString,QList<QUrl>> m_urlWhitelists; -- -- /// --- ID whitelist filter -- QHash<QString,QList<qlonglong> > m_idWhitelists; --}; -- --// --------------------------------------------------------------------------------------- -- --class DIGIKAM_DATABASE_EXPORT VersionImageFilterSettings --{ --public: -- -- VersionImageFilterSettings(); -- explicit VersionImageFilterSettings(const VersionManagerSettings& settings); -- -- bool operator==(const VersionImageFilterSettings& other) const; -- -- /** -- * Returns true if the given ImageInfo matches the filter criteria. -- */ -- bool matches(const ImageInfo& info) const; -- -- bool isHiddenBySettings(const ImageInfo& info) const; -- bool isExemptedBySettings(const ImageInfo& info) const; -- -- /// --- Tags filter --- -- -- void setVersionManagerSettings(const VersionManagerSettings& settings); -- -- /** -- * Add list with exceptions: These images will be exempted from filtering by this filter -- */ -- void setExceptionList(const QList<qlonglong>& idlist, const QString& id); -- -- /// Returns if images will be filtered by these criteria at all -- bool isFiltering() const; -- -- /// Returns if the tag is a filter criteria -- bool isFilteringByTags() const; -- -- /// DatabaseFields::Set watchFlags() const: Would return 0 -- --protected: -- -- QList<int> m_excludeTagFilter; -- int m_includeTagFilter; -- int m_exceptionTagFilter; -- QHash<QString,QList<qlonglong> > m_exceptionLists; --}; -- --// --------------------------------------------------------------------------------------- -- --class DIGIKAM_DATABASE_EXPORT GroupImageFilterSettings --{ --public: -- -- GroupImageFilterSettings(); -- -- bool operator==(const GroupImageFilterSettings& other) const; -- -- /** -- * Returns true if the given ImageInfo matches the filter criteria. -- */ -- bool matches(const ImageInfo& info) const; -- -- /** -- * Open or close a group. -- */ -- void setOpen(qlonglong group, bool open); -- bool isOpen(qlonglong group) const; -- -- /** -- * Open all groups -- */ -- void setAllOpen(bool open); -- bool isAllOpen() const; -- -- /// Returns if images will be filtered by these criteria at all -- bool isFiltering() const; -- -- DatabaseFields::Set watchFlags() const; -- --protected: -- -- bool m_allOpen; -- QSet<qlonglong> m_openGroups; --}; -- --} // namespace Digikam -- --Q_DECLARE_METATYPE(Digikam::ImageFilterSettings::GeolocationCondition) -- --#endif // IMAGEFILTERSETTINGS_H -diff --git a/libs/models/imagelistmodel.cpp b/libs/models/imagelistmodel.cpp -deleted file mode 100644 -index fafce34..0000000 ---- a/libs/models/imagelistmodel.cpp -+++ /dev/null -@@ -1,70 +0,0 @@ --/* ============================================================ -- * -- * This file is a part of digiKam project -- * http://www.digikam.org -- * -- * Date : 2010-12-06 -- * Description : An image model based on a static list -- * -- * Copyright (C) 2010-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -- * -- * This program is free software; you can redistribute it -- * and/or modify it under the terms of the GNU General -- * Public License as published by the Free Software Foundation; -- * either version 2, or (at your option) -- * any later version. -- * -- * This program 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 General Public License for more details. -- * -- * ============================================================ */ -- --#include "imagelistmodel.h" -- --// Local includes -- --#include "digikam_debug.h" --#include "coredbaccess.h" --#include "coredbchangesets.h" --#include "coredbwatch.h" --#include "imageinfo.h" --#include "imageinfolist.h" -- --namespace Digikam --{ -- --ImageListModel::ImageListModel(QObject* parent) -- : ImageThumbnailModel(parent) --{ -- connect(CoreDbAccess::databaseWatch(), SIGNAL(collectionImageChange(CollectionImageChangeset)), -- this, SLOT(slotCollectionImageChange(CollectionImageChangeset))); --} -- --ImageListModel::~ImageListModel() --{ --} -- --void ImageListModel::slotCollectionImageChange(const CollectionImageChangeset& changeset) --{ -- if (isEmpty()) -- { -- return; -- } -- -- switch (changeset.operation()) -- { -- case CollectionImageChangeset::Added: -- break; -- case CollectionImageChangeset::Removed: -- case CollectionImageChangeset::RemovedAll: -- removeImageInfos(ImageInfoList(changeset.ids())); -- break; -- -- default: -- break; -- } --} -- --} // namespace Digikam -diff --git a/libs/models/imagelistmodel.h b/libs/models/imagelistmodel.h -deleted file mode 100644 -index a225b1b..0000000 ---- a/libs/models/imagelistmodel.h -+++ /dev/null -@@ -1,63 +0,0 @@ --/* ============================================================ -- * -- * This file is a part of digiKam project -- * http://www.digikam.org -- * -- * Date : 2010-12-06 -- * Description : An image model based on a static list -- * -- * Copyright (C) 2010-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -- * -- * This program is free software; you can redistribute it -- * and/or modify it under the terms of the GNU General -- * Public License as published by the Free Software Foundation; -- * either version 2, or (at your option) -- * any later version. -- * -- * This program 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 General Public License for more details. -- * -- * ============================================================ */ -- --#ifndef IMAGELISTMODEL_H --#define IMAGELISTMODEL_H -- --// Local includes -- --#include "imagethumbnailmodel.h" --#include "digikam_export.h" -- --namespace Digikam --{ -- --class ImageChangeset; --class CollectionImageChangeset; -- --class DIGIKAM_DATABASE_EXPORT ImageListModel : public ImageThumbnailModel --{ -- Q_OBJECT -- --public: -- -- explicit ImageListModel(QObject* parent = 0); -- ~ImageListModel(); -- -- // NOTE: necessary methods to add and remove ImageInfos to the model are inherited from ImageModel -- --Q_SIGNALS: -- -- /** -- * Emitted when images are removed from the model because they are removed in the database -- */ -- void imageInfosRemoved(const QList<ImageInfo>& infos); -- --protected Q_SLOTS: -- -- void slotCollectionImageChange(const CollectionImageChangeset& changeset); --}; -- --} // namespace Digikam -- --#endif // IMAGELISTMODEL_H -diff --git a/libs/models/imagemodel.cpp b/libs/models/imagemodel.cpp -deleted file mode 100644 -index 41b43cf..0000000 ---- a/libs/models/imagemodel.cpp -+++ /dev/null -@@ -1,1368 +0,0 @@ --/* ============================================================ -- * -- * This file is a part of digiKam project -- * http://www.digikam.org -- * -- * Date : 2009-03-05 -- * Description : Qt item model for database entries -- * -- * Copyright (C) 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -- * -- * This program is free software; you can redistribute it -- * and/or modify it under the terms of the GNU General -- * Public License as published by the Free Software Foundation; -- * either version 2, or (at your option) -- * any later version. -- * -- * This program 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 General Public License for more details. -- * -- * ============================================================ */ -- --#include "imagemodel.h" -- --// Qt includes -- --#include <QHash> --#include <QItemSelection> -- --// Local includes -- --#include "digikam_debug.h" --#include "coredbchangesets.h" --#include "coredbfields.h" --#include "coredbwatch.h" --#include "imageinfo.h" --#include "imageinfolist.h" --#include "abstractitemdragdrophandler.h" -- --namespace Digikam --{ -- --class ImageModel::Private --{ --public: -- -- Private() -- { -- preprocessor = 0; -- keepFilePathCache = false; -- sendRemovalSignals = false; -- incrementalUpdater = 0; -- refreshing = false; -- reAdding = false; -- incrementalRefreshRequested = false; -- } -- -- ImageInfoList infos; -- QList<QVariant> extraValues; -- QHash<qlonglong, int> idHash; -- -- bool keepFilePathCache; -- QHash<QString, qlonglong> filePathHash; -- -- bool sendRemovalSignals; -- -- QObject* preprocessor; -- bool refreshing; -- bool reAdding; -- bool incrementalRefreshRequested; -- -- DatabaseFields::Set watchFlags; -- -- class ImageModelIncrementalUpdater* incrementalUpdater; -- -- ImageInfoList pendingInfos; -- QList<QVariant> pendingExtraValues; -- -- inline bool isValid(const QModelIndex& index) -- { -- if (!index.isValid()) -- { -- return false; -- } -- -- if (index.row() < 0 || index.row() >= infos.size()) -- { -- qCDebug(DIGIKAM_GENERAL_LOG) << "Invalid index" << index; -- return false; -- } -- -- return true; -- } -- inline bool extraValueValid(const QModelIndex& index) -- { -- // we assume isValid() being called before, no duplicate checks -- if (index.row() >= extraValues.size()) -- { -- qCDebug(DIGIKAM_GENERAL_LOG) << "Invalid index for extraData" << index; -- return false; -- } -- -- return true; -- } --}; -- --typedef QPair<int, int> IntPair; // to make foreach macro happy --typedef QList<IntPair> IntPairList; -- --class ImageModelIncrementalUpdater --{ --public: -- -- explicit ImageModelIncrementalUpdater(ImageModel::Private* d); -- -- void appendInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues); -- void aboutToBeRemovedInModel(const IntPairList& aboutToBeRemoved); -- QList<IntPair> oldIndexes(); -- -- static QList<IntPair> toContiguousPairs(const QList<int>& ids); -- --public: -- -- QHash<qlonglong, int> oldIds; -- QList<QVariant> oldExtraValues; -- QList<ImageInfo> newInfos; -- QList<QVariant> newExtraValues; -- QList<IntPairList> modelRemovals; --}; -- --ImageModel::ImageModel(QObject* parent) -- : QAbstractListModel(parent), -- d(new Private) --{ -- connect(CoreDbAccess::databaseWatch(), SIGNAL(imageChange(ImageChangeset)), -- this, SLOT(slotImageChange(ImageChangeset))); -- -- connect(CoreDbAccess::databaseWatch(), SIGNAL(imageTagChange(ImageTagChangeset)), -- this, SLOT(slotImageTagChange(ImageTagChangeset))); --} -- --ImageModel::~ImageModel() --{ -- delete d->incrementalUpdater; -- delete d; --} -- --// ------------ Access methods ------------- -- --void ImageModel::setKeepsFilePathCache(bool keepCache) --{ -- d->keepFilePathCache = keepCache; --} -- --bool ImageModel::keepsFilePathCache() const --{ -- return d->keepFilePathCache; --} -- --bool ImageModel::isEmpty() const --{ -- return d->infos.isEmpty(); --} -- --void ImageModel::setWatchFlags(const DatabaseFields::Set& set) --{ -- d->watchFlags = set; --} -- --ImageInfo ImageModel::imageInfo(const QModelIndex& index) const --{ -- if (!d->isValid(index)) -- { -- return ImageInfo(); -- } -- -- return d->infos.at(index.row()); --} -- --ImageInfo& ImageModel::imageInfoRef(const QModelIndex& index) const --{ -- return d->infos[index.row()]; --} -- --qlonglong ImageModel::imageId(const QModelIndex& index) const --{ -- if (!d->isValid(index)) -- { -- return 0; -- } -- -- return d->infos.at(index.row()).id(); --} -- --QList<ImageInfo> ImageModel::imageInfos(const QList<QModelIndex>& indexes) const --{ -- QList<ImageInfo> infos; -- -- foreach(const QModelIndex& index, indexes) -- { -- infos << imageInfo(index); -- } -- -- return infos; --} -- --QList<qlonglong> ImageModel::imageIds(const QList<QModelIndex>& indexes) const --{ -- QList<qlonglong> ids; -- -- foreach(const QModelIndex& index, indexes) -- { -- ids << imageId(index); -- } -- -- return ids; --} -- --ImageInfo ImageModel::imageInfo(int row) const --{ -- if (row >= d->infos.size()) -- { -- return ImageInfo(); -- } -- -- return d->infos.at(row); --} -- --ImageInfo& ImageModel::imageInfoRef(int row) const --{ -- return d->infos[row]; --} -- --qlonglong ImageModel::imageId(int row) const --{ -- if (row < 0 || row >= d->infos.size()) -- { -- return -1; -- } -- -- return d->infos.at(row).id(); --} -- --QModelIndex ImageModel::indexForImageInfo(const ImageInfo& info) const --{ -- return indexForImageId(info.id()); --} -- --QModelIndex ImageModel::indexForImageInfo(const ImageInfo& info, const QVariant& extraValue) const --{ -- return indexForImageId(info.id(), extraValue); --} -- --QList<QModelIndex> ImageModel::indexesForImageInfo(const ImageInfo& info) const --{ -- return indexesForImageId(info.id()); --} -- --QModelIndex ImageModel::indexForImageId(qlonglong id) const --{ -- int index = d->idHash.value(id, -1); -- -- if (index != -1) -- { -- return createIndex(index, 0); -- } -- -- return QModelIndex(); --} -- --QModelIndex ImageModel::indexForImageId(qlonglong id, const QVariant& extraValue) const --{ -- if (d->extraValues.isEmpty()) -- return indexForImageId(id); -- -- QHash<qlonglong, int>::const_iterator it; -- -- for (it = d->idHash.constFind(id); it != d->idHash.constEnd() && it.key() == id; ++it) -- { -- if (d->extraValues.at(it.value()) == extraValue) -- return createIndex(it.value(), 0); -- } -- -- return QModelIndex(); --} -- --QList<QModelIndex> ImageModel::indexesForImageId(qlonglong id) const --{ -- QList<QModelIndex> indexes; -- QHash<qlonglong, int>::const_iterator it; -- -- for (it = d->idHash.constFind(id); it != d->idHash.constEnd() && it.key() == id; ++it) -- { -- indexes << createIndex(it.value(), 0); -- } -- -- return indexes; --} -- --int ImageModel::numberOfIndexesForImageInfo(const ImageInfo& info) const --{ -- return numberOfIndexesForImageId(info.id()); --} -- --int ImageModel::numberOfIndexesForImageId(qlonglong id) const --{ -- if (d->extraValues.isEmpty()) -- { -- return 0; -- } -- -- int count = 0; -- QHash<qlonglong,int>::const_iterator it; -- -- for (it = d->idHash.constFind(id); it != d->idHash.constEnd() && it.key() == id; ++it) -- { -- ++count; -- } -- -- return count; --} -- --// static method --ImageInfo ImageModel::retrieveImageInfo(const QModelIndex& index) --{ -- if (!index.isValid()) -- { -- return ImageInfo(); -- } -- -- ImageModel* const model = index.data(ImageModelPointerRole).value<ImageModel*>(); -- int row = index.data(ImageModelInternalId).toInt(); -- -- if (!model) -- { -- return ImageInfo(); -- } -- -- return model->imageInfo(row); --} -- --// static method --qlonglong ImageModel::retrieveImageId(const QModelIndex& index) --{ -- if (!index.isValid()) -- { -- return 0; -- } -- -- ImageModel* const model = index.data(ImageModelPointerRole).value<ImageModel*>(); -- int row = index.data(ImageModelInternalId).toInt(); -- -- if (!model) -- { -- return 0; -- } -- -- return model->imageId(row); --} -- --QModelIndex ImageModel::indexForPath(const QString& filePath) const --{ -- if (d->keepFilePathCache) -- { -- return indexForImageId(d->filePathHash.value(filePath)); -- } -- else -- { -- const int size = d->infos.size(); -- -- for (int i=0; i<size; ++i) -- { -- if (d->infos.at(i).filePath() == filePath) -- { -- return createIndex(i, 0); -- } -- } -- } -- -- return QModelIndex(); --} -- --QList<QModelIndex> ImageModel::indexesForPath(const QString& filePath) const --{ -- if (d->keepFilePathCache) -- { -- return indexesForImageId(d->filePathHash.value(filePath)); -- } -- else -- { -- QList<QModelIndex> indexes; -- const int size = d->infos.size(); -- -- for (int i=0; i<size; ++i) -- { -- if (d->infos.at(i).filePath() == filePath) -- { -- indexes << createIndex(i, 0); -- } -- } -- -- return indexes; -- } --} -- --ImageInfo ImageModel::imageInfo(const QString& filePath) const --{ -- if (d->keepFilePathCache) -- { -- qlonglong id = d->filePathHash.value(filePath); -- -- if (id) -- { -- int index = d->idHash.value(id, -1); -- -- if (index != -1) -- { -- return d->infos.at(index); -- } -- } -- } -- else -- { -- foreach(const ImageInfo& info, d->infos) -- { -- if (info.filePath() == filePath) -- { -- return info; -- } -- } -- } -- -- return ImageInfo(); --} -- --QList<ImageInfo> ImageModel::imageInfos(const QString& filePath) const --{ -- QList<ImageInfo> infos; -- -- if (d->keepFilePathCache) -- { -- qlonglong id = d->filePathHash.value(filePath); -- -- if (id) -- { -- foreach(int index, d->idHash.values(id)) -- { -- infos << d->infos.at(index); -- } -- } -- } -- else -- { -- foreach(const ImageInfo& info, d->infos) -- { -- if (info.filePath() == filePath) -- { -- infos << info; -- } -- } -- } -- -- return infos; --} -- --void ImageModel::addImageInfo(const ImageInfo& info) --{ -- addImageInfos(QList<ImageInfo>() << info, QList<QVariant>()); --} -- --void ImageModel::addImageInfos(const QList<ImageInfo>& infos) --{ -- addImageInfos(infos, QList<QVariant>()); --} -- --void ImageModel::addImageInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues) --{ -- if (infos.isEmpty()) -- { -- return; -- } -- -- if (d->incrementalUpdater) -- { -- d->incrementalUpdater->appendInfos(infos, extraValues); -- } -- else -- { -- appendInfos(infos, extraValues); -- } --} -- --void ImageModel::addImageInfoSynchronously(const ImageInfo& info) --{ -- addImageInfosSynchronously(QList<ImageInfo>() << info, QList<QVariant>()); --} -- --void ImageModel::addImageInfosSynchronously(const QList<ImageInfo>& infos) --{ -- addImageInfos(infos, QList<QVariant>()); --} -- --void ImageModel::addImageInfosSynchronously(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues) --{ -- if (infos.isEmpty()) -- { -- return; -- } -- -- publiciseInfos(infos, extraValues); -- emit processAdded(infos, extraValues); --} -- --void ImageModel::ensureHasImageInfo(const ImageInfo& info) --{ -- ensureHasImageInfos(QList<ImageInfo>() << info, QList<QVariant>()); --} -- --void ImageModel::ensureHasImageInfos(const QList<ImageInfo>& infos) --{ -- ensureHasImageInfos(infos, QList<QVariant>()); --} -- --void ImageModel::ensureHasImageInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues) --{ -- if (extraValues.isEmpty()) -- { -- if (!d->pendingExtraValues.isEmpty()) -- { -- qCDebug(DIGIKAM_GENERAL_LOG) << "ExtraValue / No Extra Value mismatch. Ignoring added infos."; -- return; -- } -- } -- else -- { -- if (d->pendingInfos.size() != d->pendingExtraValues.size()) -- { -- qCDebug(DIGIKAM_GENERAL_LOG) << "ExtraValue / No Extra Value mismatch. Ignoring added infos."; -- return; -- } -- } -- -- d->pendingInfos << infos; -- d->pendingExtraValues << extraValues; -- cleanSituationChecks(); --} -- --void ImageModel::clearImageInfos() --{ -- d->infos.clear(); -- d->extraValues.clear(); -- d->idHash.clear(); -- d->filePathHash.clear(); -- delete d->incrementalUpdater; -- d->incrementalUpdater = 0; -- d->pendingInfos.clear(); -- d->pendingExtraValues.clear(); -- d->refreshing = false; -- d->reAdding = false; -- d->incrementalRefreshRequested = false; -- -- beginResetModel(); -- endResetModel(); -- -- imageInfosCleared(); --} -- --void ImageModel::setImageInfos(const QList<ImageInfo>& infos) --{ -- clearImageInfos(); -- addImageInfos(infos); --} -- --QList<ImageInfo> ImageModel::imageInfos() const --{ -- return d->infos; --} -- --QList<qlonglong> ImageModel::imageIds() const --{ -- return d->idHash.keys(); --} -- --bool ImageModel::hasImage(qlonglong id) const --{ -- return d->idHash.contains(id); --} -- --bool ImageModel::hasImage(const ImageInfo& info) const --{ -- return d->idHash.contains(info.id()); --} -- --bool ImageModel::hasImage(const ImageInfo& info, const QVariant& extraValue) const --{ -- return hasImage(info.id(), extraValue); --} -- --bool ImageModel::hasImage(qlonglong id, const QVariant& extraValue) const --{ -- if (d->extraValues.isEmpty()) -- return hasImage(id); -- -- QHash<qlonglong, int>::const_iterator it; -- -- for (it = d->idHash.constFind(id); it != d->idHash.constEnd() && it.key() == id; ++it) -- { -- if (d->extraValues.at(it.value()) == extraValue) -- return true; -- } -- -- return false;; --} -- --QList<ImageInfo> ImageModel::uniqueImageInfos() const --{ -- if (d->extraValues.isEmpty()) -- { -- return d->infos; -- } -- -- QList<ImageInfo> uniqueInfos; -- const int size = d->infos.size(); -- -- for (int i=0; i<size; ++i) -- { -- const ImageInfo& info = d->infos.at(i); -- -- if (d->idHash.value(info.id()) == i) -- { -- uniqueInfos << info; -- } -- } -- -- return uniqueInfos; --} -- --void ImageModel::emitDataChangedForAll() --{ -- if (d->infos.isEmpty()) -- { -- return; -- } -- -- QModelIndex first = createIndex(0, 0); -- QModelIndex last = createIndex(d->infos.size() - 1, 0); -- emit dataChanged(first, last); --} -- --void ImageModel::emitDataChangedForSelection(const QItemSelection& selection) --{ -- if (!selection.isEmpty()) -- { -- foreach(const QItemSelectionRange& range, selection) -- { -- emit dataChanged(range.topLeft(), range.bottomRight()); -- } -- } --} -- --void ImageModel::ensureHasGroupedImages(const ImageInfo& groupLeader) --{ -- ensureHasImageInfos(groupLeader.groupedImages()); --} -- --// ------------ Preprocessing ------------- -- --void ImageModel::setPreprocessor(QObject* preprocessor) --{ -- unsetPreprocessor(d->preprocessor); -- d->preprocessor = preprocessor; --} -- --void ImageModel::unsetPreprocessor(QObject* preprocessor) --{ -- if (preprocessor && d->preprocessor == preprocessor) -- { -- disconnect(this, SIGNAL(preprocess(QList<ImageInfo>,QList<QVariant>)), 0, 0); -- disconnect(d->preprocessor, 0, this, SLOT(reAddImageInfos(QList<ImageInfo>,QList<QVariant>))); -- disconnect(d->preprocessor, 0, this, SLOT(reAddingFinished())); -- } --} -- --void ImageModel::appendInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues) --{ -- if (infos.isEmpty()) -- { -- return; -- } -- -- if (d->preprocessor) -- { -- d->reAdding = true; -- emit preprocess(infos, extraValues); -- } -- else -- { -- publiciseInfos(infos, extraValues); -- } --} -- --void ImageModel::appendInfosChecked(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues) --{ -- // This method does deduplication. It is private because in context of readding or refreshing it is of no use. -- -- if (extraValues.isEmpty()) -- { -- QList<ImageInfo> checkedInfos; -- -- foreach (const ImageInfo& info, infos) -- { -- if (!hasImage(info)) -- { -- checkedInfos << info; -- } -- } -- -- appendInfos(checkedInfos, QList<QVariant>()); -- } -- else -- { -- QList<ImageInfo> checkedInfos; -- QList<QVariant> checkedExtraValues; -- const int size = infos.size(); -- -- for (int i=0; i<size; i++) -- { -- if (!hasImage(infos[i], extraValues[i])) -- { -- checkedInfos << infos[i]; -- checkedExtraValues << extraValues[i]; -- } -- } -- -- appendInfos(checkedInfos, checkedExtraValues); -- } --} -- --void ImageModel::reAddImageInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues) --{ -- // addImageInfos -> appendInfos -> preprocessor -> reAddImageInfos -- publiciseInfos(infos, extraValues); --} -- --void ImageModel::reAddingFinished() --{ -- d->reAdding = false; -- cleanSituationChecks(); --} -- --void ImageModel::startRefresh() --{ -- d->refreshing = true; --} -- --void ImageModel::finishRefresh() --{ -- d->refreshing = false; -- cleanSituationChecks(); --} -- --bool ImageModel::isRefreshing() const --{ -- return d->refreshing; --} -- --void ImageModel::cleanSituationChecks() --{ -- // For starting an incremental refresh we want a clear situation: -- // Any remaining batches from non-incremental refreshing subclasses have been received in appendInfos(), -- // any batches sent to preprocessor for re-adding have been re-added. -- if (d->refreshing || d->reAdding) -- { -- return; -- } -- -- if (!d->pendingInfos.isEmpty()) -- { -- appendInfosChecked(d->pendingInfos, d->pendingExtraValues); -- d->pendingInfos.clear(); -- d->pendingExtraValues.clear(); -- cleanSituationChecks(); -- return; -- } -- -- if (d->incrementalRefreshRequested) -- { -- d->incrementalRefreshRequested = false; -- emit readyForIncrementalRefresh(); -- } -- else -- { -- emit allRefreshingFinished(); -- } --} -- --void ImageModel::publiciseInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues) --{ -- if (infos.isEmpty()) -- { -- return; -- } -- -- Q_ASSERT(infos.size() == extraValues.size() || (extraValues.isEmpty() && d->extraValues.isEmpty())); -- -- emit imageInfosAboutToBeAdded(infos); -- const int firstNewIndex = d->infos.size(); -- const int lastNewIndex = d->infos.size() + infos.size() - 1; -- beginInsertRows(QModelIndex(), firstNewIndex, lastNewIndex); -- d->infos << infos; -- d->extraValues << extraValues; -- -- for (int i=firstNewIndex; i<=lastNewIndex; ++i) -- { -- const ImageInfo& info = d->infos.at(i); -- qlonglong id = info.id(); -- d->idHash.insertMulti(id, i); -- -- if (d->keepFilePathCache) -- { -- d->filePathHash[info.filePath()] = id; -- } -- } -- -- endInsertRows(); -- emit imageInfosAdded(infos); --} -- --void ImageModel::requestIncrementalRefresh() --{ -- if (d->reAdding) -- { -- d->incrementalRefreshRequested = true; -- } -- else -- { -- emit readyForIncrementalRefresh(); -- } --} -- --bool ImageModel::hasIncrementalRefreshPending() const --{ -- return d->incrementalRefreshRequested; --} -- --void ImageModel::startIncrementalRefresh() --{ -- delete d->incrementalUpdater; -- -- d->incrementalUpdater = new ImageModelIncrementalUpdater(d); --} -- --void ImageModel::finishIncrementalRefresh() --{ -- if (!d->incrementalUpdater) -- { -- return; -- } -- -- // remove old entries -- QList<QPair<int, int> > pairs = d->incrementalUpdater->oldIndexes(); -- removeRowPairs(pairs); -- -- // add new indexes -- appendInfos(d->incrementalUpdater->newInfos, d->incrementalUpdater->newExtraValues); -- -- delete d->incrementalUpdater; -- d->incrementalUpdater = 0; --} -- --void ImageModel::removeIndex(const QModelIndex& index) --{ -- removeIndexes(QList<QModelIndex>() << index); --} -- --void ImageModel::removeIndexes(const QList<QModelIndex>& indexes) --{ -- QList<int> listIndexes; -- -- foreach(const QModelIndex& index, indexes) -- { -- if (d->isValid(index)) -- { -- listIndexes << index.row(); -- } -- } -- -- if (listIndexes.isEmpty()) -- { -- return; -- } -- -- removeRowPairsWithCheck(ImageModelIncrementalUpdater::toContiguousPairs(listIndexes)); --} -- --void ImageModel::removeImageInfo(const ImageInfo& info) --{ -- removeImageInfos(QList<ImageInfo>() << info); --} -- --void ImageModel::removeImageInfos(const QList<ImageInfo>& infos) --{ -- QList<int> listIndexes; -- -- foreach(const ImageInfo& info, infos) -- { -- QModelIndex index = indexForImageId(info.id()); -- -- if (index.isValid()) -- { -- listIndexes << index.row(); -- } -- } -- removeRowPairsWithCheck(ImageModelIncrementalUpdater::toContiguousPairs(listIndexes)); --} -- --void ImageModel::removeImageInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues) --{ -- if (extraValues.isEmpty()) -- { -- removeImageInfos(infos); -- return; -- } -- -- QList<int> listIndexes; -- -- for (int i=0; i<infos.size(); ++i) -- { -- QModelIndex index = indexForImageId(infos.at(i).id(), extraValues.at(i)); -- -- if (index.isValid()) -- { -- listIndexes << index.row(); -- } -- } -- -- removeRowPairsWithCheck(ImageModelIncrementalUpdater::toContiguousPairs(listIndexes)); --} -- --void ImageModel::setSendRemovalSignals(bool send) --{ -- d->sendRemovalSignals = send; --} -- --template <class List, typename T> --static bool pairsContain(const List& list, T value) --{ -- typename List::const_iterator middle; -- typename List::const_iterator begin = list.begin(); -- typename List::const_iterator end = list.end(); -- int n = int(end - begin); -- int half; -- -- while (n > 0) -- { -- half = n >> 1; -- middle = begin + half; -- -- if (middle->first <= value && middle->second >= value) -- { -- return true; -- } -- else if (middle->second < value) -- { -- begin = middle + 1; -- n -= half + 1; -- } -- else -- { -- n = half; -- } -- } -- -- return false; --} -- --void ImageModel::removeRowPairsWithCheck(const QList<QPair<int, int> >& toRemove) --{ -- if (d->incrementalUpdater) -- { -- d->incrementalUpdater->aboutToBeRemovedInModel(toRemove); -- } -- -- removeRowPairs(toRemove); --} -- --void ImageModel::removeRowPairs(const QList<QPair<int, int> >& toRemove) --{ -- if (toRemove.isEmpty()) -- { -- return; -- } -- -- // Remove old indexes -- // Keep in mind that when calling beginRemoveRows all structures announced to be removed -- // must still be valid, and this includes our hashes as well, which limits what we can optimize -- -- int removedRows = 0, offset = 0; -- typedef QPair<int, int> IntPair; // to make foreach macro happy -- -- foreach(const IntPair& pair, toRemove) -- { -- const int begin = pair.first - offset; -- const int end = pair.second - offset; // inclusive -- removedRows = end - begin + 1; -- -- // when removing from the list, all subsequent indexes are affected -- offset += removedRows; -- -- QList<ImageInfo> removedInfos; -- -- if (d->sendRemovalSignals) -- { -- qCopy(d->infos.begin() + begin, d->infos.begin() + end, removedInfos.begin()); -- emit imageInfosAboutToBeRemoved(removedInfos); -- } -- -- imageInfosAboutToBeRemoved(begin, end); -- beginRemoveRows(QModelIndex(), begin, end); -- -- // update idHash - which points to indexes of d->infos, and these change now! -- QHash<qlonglong, int>::iterator it; -- -- for (it = d->idHash.begin(); it != d->idHash.end(); ) -- { -- if (it.value() >= begin) -- { -- if (it.value() > end) -- { -- // after the removed interval: adjust index -- it.value() -= removedRows; -- } -- else -- { -- // in the removed interval -- it = d->idHash.erase(it); -- continue; -- } -- } -- -- ++it; -- } -- -- // remove from list -- d->infos.erase(d->infos.begin() + begin, d->infos.begin() + (end + 1)); -- -- if (!d->extraValues.isEmpty()) -- { -- d->extraValues.erase(d->extraValues.begin() + begin, d->extraValues.begin() + (end + 1)); -- } -- -- endRemoveRows(); -- -- if (d->sendRemovalSignals) -- { -- emit imageInfosRemoved(removedInfos); -- } -- } -- -- // tidy up: remove old indexes from file path hash now -- if (d->keepFilePathCache) -- { -- QHash<QString, qlonglong>::iterator it; -- -- for (it = d->filePathHash.begin(); it != d->filePathHash.end(); ) -- { -- if (pairsContain(toRemove, it.value())) -- { -- it = d->filePathHash.erase(it); -- } -- else -- { -- ++it; -- } -- } -- } --} -- --ImageModelIncrementalUpdater::ImageModelIncrementalUpdater(ImageModel::Private* d) --{ -- oldIds = d->idHash; -- oldExtraValues = d->extraValues; --} -- --void ImageModelIncrementalUpdater::appendInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues) --{ -- if (extraValues.isEmpty()) -- { -- foreach(const ImageInfo& info, infos) -- { -- QHash<qlonglong,int>::iterator it = oldIds.find(info.id()); -- -- if (it != oldIds.end()) -- { -- oldIds.erase(it); -- } -- else -- { -- newInfos << info; -- } -- } -- } -- else -- { -- for (int i=0; i<infos.size(); ++i) -- { -- const ImageInfo& info = infos.at(i); -- bool found = false; -- QHash<qlonglong,int>::iterator it; -- -- for (it = oldIds.find(info.id()); it != oldIds.end() && it.key() == info.id(); ++it) -- { -- // first check is for bug #262596. Not sure if needed. -- if (it.value() < oldExtraValues.size() && extraValues.at(i) == oldExtraValues.at(it.value())) -- { -- found = true; -- break; -- } -- } -- -- if (found) -- { -- oldIds.erase(it); -- // do not erase from oldExtraValues - oldIds is a hash id -> index. -- } -- else -- { -- newInfos << info; -- newExtraValues << extraValues.at(i); -- } -- } -- } --} -- --void ImageModelIncrementalUpdater::aboutToBeRemovedInModel(const IntPairList& toRemove) --{ -- modelRemovals << toRemove; --} -- --QList<QPair<int, int> > ImageModelIncrementalUpdater::oldIndexes() --{ -- // first, apply all changes to indexes by direct removal in model -- // while the updater was active -- foreach(const IntPairList& list, modelRemovals) -- { -- int removedRows = 0, offset = 0; -- -- foreach(const IntPair& pair, list) -- { -- const int begin = pair.first - offset; -- const int end = pair.second - offset; // inclusive -- removedRows = end - begin + 1; -- -- // when removing from the list, all subsequent indexes are affected -- offset += removedRows; -- -- // update idHash - which points to indexes of d->infos, and these change now! -- QHash<qlonglong, int>::iterator it; -- -- for (it = oldIds.begin(); it != oldIds.end(); ) -- { -- if (it.value() >= begin) -- { -- if (it.value() > end) -- { -- // after the removed interval: adjust index -- it.value() -= removedRows; -- } -- else -- { -- // in the removed interval -- it = oldIds.erase(it); -- continue; -- } -- } -- -- ++it; -- } -- } -- } -- -- modelRemovals.clear(); -- -- return toContiguousPairs(oldIds.values()); --} -- --QList<QPair<int, int> > ImageModelIncrementalUpdater::toContiguousPairs(const QList<int>& unsorted) --{ -- // Take the given indices and return them as contiguous pairs [begin, end] -- -- QList<QPair<int, int> > pairs; -- -- if (unsorted.isEmpty()) -- { -- return pairs; -- } -- -- QList<int> indices(unsorted); -- qSort(indices); -- -- QPair<int, int> pair(indices.first(), indices.first()); -- -- for (int i=1; i<indices.size(); ++i) -- { -- const int &index = indices.at(i); -- -- if (index == pair.second + 1) -- { -- pair.second = index; -- continue; -- } -- -- pairs << pair; // insert last pair -- pair.first = index; -- pair.second = index; -- } -- -- pairs << pair; -- -- return pairs; --} -- --// ------------ QAbstractItemModel implementation ------------- -- --QVariant ImageModel::data(const QModelIndex& index, int role) const --{ -- if (!d->isValid(index)) -- { -- return QVariant(); -- } -- -- switch (role) -- { -- case Qt::DisplayRole: -- case Qt::ToolTipRole: -- return d->infos.at(index.row()).name(); -- -- case ImageModelPointerRole: -- return QVariant::fromValue(const_cast<ImageModel*>(this)); -- -- case ImageModelInternalId: -- return index.row(); -- -- case CreationDateRole: -- return d->infos.at(index.row()).dateTime(); -- -- case ExtraDataRole: -- -- if (d->extraValueValid(index)) -- { -- return d->extraValues.at(index.row()); -- } -- else -- { -- return QVariant(); -- } -- -- case ExtraDataDuplicateCount: -- { -- qlonglong id = d->infos.at(index.row()).id(); -- return numberOfIndexesForImageId(id); -- } -- } -- -- return QVariant(); --} -- --QVariant ImageModel::headerData(int section, Qt::Orientation orientation, int role) const --{ -- Q_UNUSED(section) -- Q_UNUSED(orientation) -- Q_UNUSED(role) -- return QVariant(); --} -- --int ImageModel::rowCount(const QModelIndex& parent) const --{ -- if (parent.isValid()) -- { -- return 0; -- } -- -- return d->infos.size(); --} -- --Qt::ItemFlags ImageModel::flags(const QModelIndex& index) const --{ -- if (!d->isValid(index)) -- { -- return 0; -- } -- -- Qt::ItemFlags f = Qt::ItemIsSelectable | Qt::ItemIsEnabled; -- -- f |= dragDropFlags(index); -- -- return f; --} -- --QModelIndex ImageModel::index(int row, int column, const QModelIndex& parent) const --{ -- if (column != 0 || row < 0 || parent.isValid() || row >= d->infos.size()) -- { -- return QModelIndex(); -- } -- -- return createIndex(row, 0); --} -- --// ------------ Database watch ------------- -- --void ImageModel::slotImageChange(const ImageChangeset& changeset) --{ -- if (d->infos.isEmpty()) -- { -- return; -- } -- -- if (d->watchFlags & changeset.changes()) -- { -- QItemSelection items; -- -- foreach(const qlonglong& id, changeset.ids()) -- { -- QModelIndex index = indexForImageId(id); -- -- if (index.isValid()) -- { -- items.select(index, index); -- } -- } -- -- if (!items.isEmpty()) -- { -- emitDataChangedForSelection(items); -- emit imageChange(changeset, items); -- } -- } --} -- --void ImageModel::slotImageTagChange(const ImageTagChangeset& changeset) --{ -- if (d->infos.isEmpty()) -- { -- return; -- } -- -- QItemSelection items; -- -- foreach(const qlonglong& id, changeset.ids()) -- { -- QModelIndex index = indexForImageId(id); -- -- if (index.isValid()) -- { -- items.select(index, index); -- } -- } -- -- if (!items.isEmpty()) -- { -- emitDataChangedForSelection(items); -- emit imageTagChange(changeset, items); -- } --} -- --} // namespace Digikam -diff --git a/libs/models/imagemodel.h b/libs/models/imagemodel.h -deleted file mode 100644 -index dcf94c2..0000000 ---- a/libs/models/imagemodel.h -+++ /dev/null -@@ -1,364 +0,0 @@ --/* ============================================================ -- * -- * This file is a part of digiKam project -- * http://www.digikam.org -- * -- * Date : 2009-03-05 -- * Description : Qt item model for database entries -- * -- * Copyright (C) 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -- * -- * This program is free software; you can redistribute it -- * and/or modify it under the terms of the GNU General -- * Public License as published by the Free Software Foundation; -- * either version 2, or (at your option) -- * any later version. -- * -- * This program 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 General Public License for more details. -- * -- * ============================================================ */ -- --#ifndef IMAGEMODEL_H --#define IMAGEMODEL_H -- --// Qt includes -- --#include <QAbstractListModel> -- --// Local includes -- --#include "dragdropimplementations.h" --#include "imageinfo.h" --#include "digikam_export.h" -- --class QItemSelection; -- --namespace Digikam --{ -- --class ImageChangeset; --class ImageTagChangeset; -- --namespace DatabaseFields --{ --class Set; --} -- --class DIGIKAM_DATABASE_EXPORT ImageModel : public QAbstractListModel, public DragDropModelImplementation --{ -- Q_OBJECT -- --public: -- -- enum ImageModelRoles -- { -- /// An ImageModel* pointer to this model -- ImageModelPointerRole = Qt::UserRole, -- ImageModelInternalId = Qt::UserRole + 1, -- /// Returns a thumbnail pixmap. May be implemented by subclasses. -- /// Returns either a valid pixmap or a null QVariant. -- ThumbnailRole = Qt::UserRole + 2, -- /// Returns a QDateTime with the creation date -- CreationDateRole = Qt::UserRole + 3, -- /// Return (optional) extraData field -- ExtraDataRole = Qt::UserRole + 5, -- /// Returns the number of duplicate indexes for the same image id -- ExtraDataDuplicateCount = Qt::UserRole + 6, -- -- // Roles which are defined here but not implemented by ImageModel -- /// Returns position of item in Left Light Table preview. -- LTLeftPanelRole = Qt::UserRole + 50, -- /// Returns position of item in Right Light Table preview. -- LTRightPanelRole = Qt::UserRole + 51, -- -- // For use by subclasses -- SubclassRoles = Qt::UserRole + 100, -- // For use by filter models -- FilterModelRoles = Qt::UserRole + 500 -- }; -- --public: -- -- explicit ImageModel(QObject* parent = 0); -- ~ImageModel(); -- -- /** If a cache is kept, lookup by file path is fast, -- * without a cache it is O(n). Default is false. -- */ -- void setKeepsFilePathCache(bool keepCache); -- bool keepsFilePathCache() const; -- -- /** Set a set of database fields to watch. -- * If either of these is changed, dataChanged() will be emitted. -- * Default is no flag (no signal will be emitted). -- */ -- void setWatchFlags(const DatabaseFields::Set& set); -- -- /** Returns the ImageInfo object, reference or image id from the underlying data -- * pointed to by the index. -- * If the index is not valid, imageInfo will return a null ImageInfo, imageId will -- * return 0, imageInfoRef must not be called with an invalid index. -- */ -- ImageInfo imageInfo(const QModelIndex& index) const; -- ImageInfo& imageInfoRef(const QModelIndex& index) const; -- qlonglong imageId(const QModelIndex& index) const; -- QList<ImageInfo> imageInfos(const QList<QModelIndex>& indexes) const; -- QList<qlonglong> imageIds(const QList<QModelIndex>& indexes) const; -- -- /** Returns the ImageInfo object, reference or image id from the underlying data -- * of the given row (parent is the invalid QModelIndex, column is 0). -- * Note that imageInfoRef will crash if index is invalid. -- */ -- ImageInfo imageInfo(int row) const; -- ImageInfo& imageInfoRef(int row) const; -- qlonglong imageId(int row) const; -- -- /** Return the index for the given ImageInfo or id, if contained in this model. -- */ -- QModelIndex indexForImageInfo(const ImageInfo& info) const; -- QModelIndex indexForImageInfo(const ImageInfo& info, const QVariant& extraValue) const; -- QModelIndex indexForImageId(qlonglong id) const; -- QModelIndex indexForImageId(qlonglong id, const QVariant& extraValue) const; -- QList<QModelIndex> indexesForImageInfo(const ImageInfo& info) const; -- QList<QModelIndex> indexesForImageId(qlonglong id) const; -- -- int numberOfIndexesForImageInfo(const ImageInfo& info) const; -- int numberOfIndexesForImageId(qlonglong id) const; -- -- /** Returns the index or ImageInfo object from the underlying data -- * for the given file path. This is fast if keepsFilePathCache is enabled. -- * The file path is as returned by ImageInfo.filePath(). -- * In case of multiple occurrences of the same file, the simpler variants return -- * any one found first, use the QList methods to retrieve all occurrences. -- */ -- QModelIndex indexForPath(const QString& filePath) const; -- ImageInfo imageInfo(const QString& filePath) const; -- QList<QModelIndex> indexesForPath(const QString& filePath) const; -- QList<ImageInfo> imageInfos(const QString& filePath) const; -- -- /** Main entry point for subclasses adding image infos to the model. -- * If you list entries not unique per image id, you must add an extraValue -- * so that every entry is unique by imageId and extraValues. -- * Please note that these methods do not prevent addition of duplicate entries. -- */ -- void addImageInfo(const ImageInfo& info); -- void addImageInfos(const QList<ImageInfo>& infos); -- void addImageInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues); -- -- /** Clears image infos and resets model. -- */ -- void clearImageInfos(); -- -- /** Clears and adds the infos. -- */ -- void setImageInfos(const QList<ImageInfo>& infos); -- -- /** -- * Directly remove the given indexes or infos from the model. -- */ -- void removeIndex(const QModelIndex& indexes); -- void removeIndexes(const QList<QModelIndex>& indexes); -- void removeImageInfo(const ImageInfo& info); -- void removeImageInfos(const QList<ImageInfo>& infos); -- void removeImageInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues); -- -- /** -- * addImageInfo() is asynchronous if a prepocessor is set. -- * This method first adds the info, synchronously. -- * Only afterwards, the preprocessor will have the opportunity to process it. -- * This method also bypasses any incremental updates. -- * Please note that these methods do not prevent addition of duplicate entries. -- */ -- void addImageInfoSynchronously(const ImageInfo& info); -- void addImageInfosSynchronously(const QList<ImageInfo>& infos); -- void addImageInfosSynchronously(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues); -- -- /** -- * Add the given entries. Method returns immediately, the -- * addition may happen later asynchronously. -- * These methods prevent the addition of duplicate entries. -- */ -- void ensureHasImageInfo(const ImageInfo& info); -- void ensureHasImageInfos(const QList<ImageInfo>& infos); -- void ensureHasImageInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues); -- -- /** -- * Ensure that all images grouped on the given leader are contained in the model. -- */ -- void ensureHasGroupedImages(const ImageInfo& groupLeader); -- -- QList<ImageInfo> imageInfos() const; -- QList<qlonglong> imageIds() const; -- QList<ImageInfo> uniqueImageInfos() const; -- -- bool hasImage(qlonglong id) const; -- bool hasImage(const ImageInfo& info) const; -- bool hasImage(const ImageInfo& info, const QVariant& extraValue) const; -- bool hasImage(qlonglong id, const QVariant& extraValue) const; -- -- bool isEmpty() const; -- -- // Drag and Drop -- DECLARE_MODEL_DRAG_DROP_METHODS -- -- /** -- * Install an object as a preprocessor for ImageInfos added to this model. -- * For every QList of ImageInfos added to addImageInfo, the signal preprocess() -- * will be emitted. The preprocessor may process the items and shall then readd -- * them by calling reAddImageInfos(). It may take some time to process. -- * It shall discard any held infos when the modelReset() signal is sent. -- * It shall call readdFinished() when no reset occurred and all infos on the way have been readded. -- * This means that only after calling this method, you shall make three connections -- * (preprocess -> your slot, your signal -> reAddImageInfos, your signal -> reAddingFinished) -- * and make or already hold a connection modelReset() -> your slot. -- * There is only one preprocessor at a time, a previously set object will be disconnected. -- */ -- void setPreprocessor(QObject* processor); -- void unsetPreprocessor(QObject* processor); -- -- /** -- * Returns true if this model is currently refreshing. -- * For a preprocessor this means that, although the preprocessor may currently have -- * processed all it got, more batches are to be expected. -- */ -- bool isRefreshing() const; -- -- /** -- * Enable sending of imageInfosAboutToBeRemoved and imageInfosRemoved signals. -- * Default: false -- */ -- void setSendRemovalSignals(bool send); -- -- virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; -- virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; -- virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; -- virtual Qt::ItemFlags flags(const QModelIndex& index) const; -- virtual QModelIndex index(int row, int column = 0, const QModelIndex& parent = QModelIndex()) const; -- -- /** Retrieves the imageInfo object from the data() method of the given index. -- * The index may be from a QSortFilterProxyModel as long as an ImageModel is at the end. */ -- static ImageInfo retrieveImageInfo(const QModelIndex& index); -- static qlonglong retrieveImageId(const QModelIndex& index); -- --Q_SIGNALS: -- -- /** Informs that ImageInfos will be added to the model. -- * This signal is sent before the model data is changed and views are informed. -- */ -- void imageInfosAboutToBeAdded(const QList<ImageInfo>& infos); -- -- /** Informs that ImageInfos have been added to the model. -- * This signal is sent after the model data is changed and views are informed. -- */ -- void imageInfosAdded(const QList<ImageInfo>& infos); -- -- /** Informs that ImageInfos will be removed from the model. -- * This signal is sent before the model data is changed and views are informed. -- * Note: You need to explicitly enable sending of this signal. It is not sent -- * in clearImageInfos(). -- */ -- void imageInfosAboutToBeRemoved(const QList<ImageInfo>& infos); -- -- /** Informs that ImageInfos have been removed from the model. -- * This signal is sent after the model data is changed and views are informed. * -- * Note: You need to explicitly enable sending of this signal. It is not sent -- * in clearImageInfos(). -- */ -- void imageInfosRemoved(const QList<ImageInfo>& infos); -- -- /** Connect to this signal only if you are the current preprocessor. -- */ -- void preprocess(const QList<ImageInfo>& infos, const QList<QVariant>&); -- void processAdded(const QList<ImageInfo>& infos, const QList<QVariant>&); -- -- /** If an ImageChangeset affected indexes of this model with changes as set in watchFlags(), -- * this signal contains the changeset and the affected indexes. -- */ -- void imageChange(const ImageChangeset&, const QItemSelection&); -- -- /** If an ImageTagChangeset affected indexes of this model, -- * this signal contains the changeset and the affected indexes. -- */ -- void imageTagChange(const ImageTagChangeset&, const QItemSelection&); -- -- /** Signals that the model is right now ready to start an incremental refresh. -- * This is guaranteed only for the scope of emitting this signal. -- */ -- void readyForIncrementalRefresh(); -- -- /** Signals that the model has finished currently with all scheduled -- * refreshing, full or incremental, and all preprocessing. -- * The model is in polished, clean situation right now. -- */ -- void allRefreshingFinished(); -- --public Q_SLOTS: -- -- void reAddImageInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues); -- void reAddingFinished(); -- --protected: -- -- /** Subclasses that add ImageInfos in batches shall call startRefresh() -- * when they start sending batches and finishRefresh() when they have finished. -- * No incremental refreshes will be started while listing. -- * A clearImageInfos() always stops listing, calling finishRefresh() is then not necessary. -- */ -- void startRefresh(); -- void finishRefresh(); -- -- /** As soon as the model is ready to start an incremental refresh, the signal -- * readyForIncrementalRefresh() will be emitted. The signal will be emitted inline -- * if the model is ready right now. -- */ -- void requestIncrementalRefresh(); -- bool hasIncrementalRefreshPending() const; -- -- /** Starts an incremental refresh operation. You shall only call this method from a slot -- * connected to readyForIncrementalRefresh(). To initiate an incremental refresh, -- * call requestIncrementalRefresh(). -- */ -- void startIncrementalRefresh(); -- void finishIncrementalRefresh(); -- -- void emitDataChangedForAll(); -- void emitDataChangedForSelection(const QItemSelection& selection); -- -- // Called when the internal storage is cleared -- virtual void imageInfosCleared() {}; -- -- // Called before rowsAboutToBeRemoved -- virtual void imageInfosAboutToBeRemoved(int /*begin*/, int /*end*/) {}; -- --protected Q_SLOTS: -- -- virtual void slotImageChange(const ImageChangeset& changeset); -- virtual void slotImageTagChange(const ImageTagChangeset& changeset); -- --private: -- -- void appendInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues); -- void appendInfosChecked(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues); -- void publiciseInfos(const QList<ImageInfo>& infos, const QList<QVariant>& extraValues); -- void cleanSituationChecks(); -- void removeRowPairsWithCheck(const QList<QPair<int, int> >& toRemove); -- void removeRowPairs(const QList<QPair<int, int> >& toRemove); -- --public: -- -- // Declared public because it's used in ImageModelIncrementalUpdater class -- class Private; -- --private: -- -- Private* const d; --}; -- --} // namespace Digikam -- --Q_DECLARE_METATYPE(Digikam::ImageModel*) -- --#endif // IMAGEMODEL_H -diff --git a/libs/models/imagesortsettings.cpp b/libs/models/imagesortsettings.cpp -deleted file mode 100644 -index 39ee6e1..0000000 ---- a/libs/models/imagesortsettings.cpp -+++ /dev/null -@@ -1,400 +0,0 @@ --/* ============================================================ -- * -- * This file is a part of digiKam project -- * http://www.digikam.org -- * -- * Date : 2009-03-05 -- * Description : Filter values for use with ImageFilterModel -- * -- * Copyright (C) 2009 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -- * Copyright (C) 2014 by Mohamed Anwer <m dot anwer at gmx dot com> -- * -- * This program is free software; you can redistribute it -- * and/or modify it under the terms of the GNU General -- * Public License as published by the Free Software Foundation; -- * either version 2, or (at your option) -- * any later version. -- * -- * This program 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 General Public License for more details. -- * -- * ============================================================ */ -- --#include "imagesortsettings.h" -- --// Qt includes -- --#include <QDateTime> --#include <QRectF> -- --// Local includes -- --#include "coredbfields.h" --#include "imageinfo.h" -- --namespace Digikam --{ -- --ImageSortSettings::ImageSortSettings() --{ -- categorizationMode = NoCategories; -- categorizationSortOrder = DefaultOrder; -- categorizationCaseSensitivity = Qt::CaseSensitive; -- sortRole = SortByFileName; -- sortOrder = DefaultOrder; -- strTypeNatural = true; -- sortCaseSensitivity = Qt::CaseSensitive; -- currentCategorizationSortOrder = Qt::AscendingOrder; -- currentSortOrder = Qt::AscendingOrder; --} -- --bool ImageSortSettings::operator==(const ImageSortSettings& other) const --{ -- return -- categorizationMode == other.categorizationMode && -- categorizationSortOrder == other.categorizationSortOrder && -- categorizationCaseSensitivity == other.categorizationCaseSensitivity && -- sortRole == other.sortRole && -- sortOrder == other.sortOrder && -- sortCaseSensitivity == other.sortCaseSensitivity; --} -- --void ImageSortSettings::setCategorizationMode(CategorizationMode mode) --{ -- categorizationMode = mode; -- -- if (categorizationSortOrder == DefaultOrder) -- { -- currentCategorizationSortOrder = defaultSortOrderForCategorizationMode(categorizationMode); -- } --} -- --void ImageSortSettings::setCategorizationSortOrder(SortOrder order) --{ -- categorizationSortOrder = order; -- -- if (categorizationSortOrder == DefaultOrder) -- { -- currentCategorizationSortOrder = defaultSortOrderForCategorizationMode(categorizationMode); -- } -- else -- { -- currentCategorizationSortOrder = (Qt::SortOrder)categorizationSortOrder; -- } --} -- --void ImageSortSettings::setSortRole(SortRole role) --{ -- sortRole = role; -- -- if (sortOrder == DefaultOrder) -- { -- currentSortOrder = defaultSortOrderForSortRole(sortRole); -- } --} -- --void ImageSortSettings::setSortOrder(SortOrder order) --{ -- sortOrder = order; -- -- if (sortOrder == DefaultOrder) -- { -- currentSortOrder = defaultSortOrderForSortRole(sortRole); -- } -- else -- { -- currentSortOrder = (Qt::SortOrder)order; -- } --} -- --void ImageSortSettings::setStringTypeNatural(bool natural) --{ -- strTypeNatural = natural; --} -- --Qt::SortOrder ImageSortSettings::defaultSortOrderForCategorizationMode(CategorizationMode mode) --{ -- switch (mode) -- { -- case NoCategories: -- case OneCategory: -- case CategoryByAlbum: -- case CategoryByFormat: -- default: -- return Qt::AscendingOrder; -- } --} -- --Qt::SortOrder ImageSortSettings::defaultSortOrderForSortRole(SortRole role) --{ -- switch (role) -- { -- case SortByFileName: -- case SortByFilePath: -- return Qt::AscendingOrder; -- case SortByFileSize: -- return Qt::DescendingOrder; -- case SortByModificationDate: -- case SortByCreationDate: -- return Qt::AscendingOrder; -- case SortByRating: -- case SortByImageSize: -- return Qt::DescendingOrder; -- case SortByAspectRatio: -- return Qt::DescendingOrder; -- case SortBySimilarity: -- return Qt::DescendingOrder; -- default: -- return Qt::AscendingOrder; -- } --} -- --int ImageSortSettings::compareCategories(const ImageInfo& left, const ImageInfo& right) const --{ -- switch (categorizationMode) -- { -- case NoCategories: -- case OneCategory: -- return 0; -- case CategoryByAlbum: -- { -- int leftAlbum = left.albumId(); -- int rightAlbum = right.albumId(); -- -- // return comparation result -- if (leftAlbum == rightAlbum) -- { -- return 0; -- } -- else if (lessThanByOrder(leftAlbum, rightAlbum, currentCategorizationSortOrder)) -- { -- return -1; -- } -- else -- { -- return 1; -- } -- } -- case CategoryByFormat: -- { -- return naturalCompare(left.format(), right.format(), -- currentCategorizationSortOrder, categorizationCaseSensitivity, strTypeNatural); -- } -- default: -- return 0; -- } --} -- --bool ImageSortSettings::lessThan(const ImageInfo& left, const ImageInfo& right) const --{ -- int result = compare(left, right, sortRole); -- -- if (result != 0) -- { -- return result < 0; -- } -- -- // are they identical? -- if (left == right) -- { -- return false; -- } -- -- // If left and right equal for first sort order, use a hierarchy of all sort orders -- if ( (result = compare(left, right, SortByFileName)) != 0) -- { -- return result < 0; -- } -- -- if ( (result = compare(left, right, SortByCreationDate)) != 0) -- { -- return result < 0; -- } -- -- if ( (result = compare(left, right, SortByModificationDate)) != 0) -- { -- return result < 0; -- } -- -- if ( (result = compare(left, right, SortByFilePath)) != 0) -- { -- return result < 0; -- } -- -- if ( (result = compare(left, right, SortByFileSize)) != 0) -- { -- return result < 0; -- } -- -- if ( (result = compare(left, right, SortBySimilarity)) != 0) -- { -- return result < 0; -- } -- -- return false; --} -- --int ImageSortSettings::compare(const ImageInfo& left, const ImageInfo& right) const --{ -- return compare(left, right, sortRole); --} -- --int ImageSortSettings::compare(const ImageInfo& left, const ImageInfo& right, SortRole role) const --{ -- switch (role) -- { -- case SortByFileName: -- { -- bool versioning = (left.name().contains(QLatin1String("_v"), Qt::CaseInsensitive) || -- right.name().contains(QLatin1String("_v"), Qt::CaseInsensitive)); -- return naturalCompare(left.name(), right.name(), currentSortOrder, sortCaseSensitivity, strTypeNatural, versioning); -- } -- case SortByFilePath: -- return naturalCompare(left.filePath(), right.filePath(), currentSortOrder, sortCaseSensitivity, strTypeNatural); -- case SortByFileSize: -- return compareByOrder(left.fileSize(), right.fileSize(), currentSortOrder); -- case SortByModificationDate: -- return compareByOrder(left.modDateTime(), right.modDateTime(), currentSortOrder); -- case SortByCreationDate: -- return compareByOrder(left.dateTime(), right.dateTime(), currentSortOrder); -- case SortByRating: -- // I have the feeling that inverting the sort order for rating is the natural order -- return - compareByOrder(left.rating(), right.rating(), currentSortOrder); -- case SortByImageSize: -- { -- QSize leftSize = left.dimensions(); -- QSize rightSize = right.dimensions(); -- int leftPixels = leftSize.width() * leftSize.height(); -- int rightPixels = rightSize.width() * rightSize.height(); -- return compareByOrder(leftPixels, rightPixels, currentSortOrder); -- } -- case SortByAspectRatio: -- { -- QSize leftSize = left.dimensions(); -- QSize rightSize = right.dimensions(); -- int leftAR = (double(leftSize.width()) / double(leftSize.height())) * 1000000; -- int rightAR = (double(rightSize.width()) / double(rightSize.height())) * 1000000; -- return compareByOrder(leftAR, rightAR, currentSortOrder); -- } -- case SortBySimilarity: -- { -- qlonglong leftReferenceImageId = left.currentReferenceImage(); -- qlonglong rightReferenceImageId = right.currentReferenceImage(); -- // make sure that the original image has always the highest similarity. -- double leftSimilarity = left.id() == leftReferenceImageId ? 1.1 : left.currentSimilarity(); -- double rightSimilarity = right.id() == rightReferenceImageId ? 1.1 : right.currentSimilarity(); -- return compareByOrder(leftSimilarity, rightSimilarity, currentSortOrder); -- } -- default: -- return 1; -- } --} -- --bool ImageSortSettings::lessThan(const QVariant& left, const QVariant& right) const --{ -- if (left.type() != right.type()) -- { -- return false; -- } -- -- switch (left.type()) -- { -- case QVariant::Int: -- return compareByOrder(left.toInt(), right.toInt(), currentSortOrder); -- case QVariant::UInt: -- return compareByOrder(left.toUInt(), right.toUInt(), currentSortOrder); -- case QVariant::LongLong: -- return compareByOrder(left.toLongLong(), right.toLongLong(), currentSortOrder); -- case QVariant::ULongLong: -- return compareByOrder(left.toULongLong(), right.toULongLong(), currentSortOrder); -- case QVariant::Double: -- return compareByOrder(left.toDouble(), right.toDouble(), currentSortOrder); -- case QVariant::Date: -- return compareByOrder(left.toDate(), right.toDate(), currentSortOrder); -- case QVariant::DateTime: -- return compareByOrder(left.toDateTime(), right.toDateTime(), currentSortOrder); -- case QVariant::Time: -- return compareByOrder(left.toTime(), right.toTime(), currentSortOrder); -- case QVariant::Rect: -- case QVariant::RectF: -- { -- QRectF rectLeft = left.toRectF(); -- QRectF rectRight = right.toRectF(); -- int result; -- -- if ((result = compareByOrder(rectLeft.top(), rectRight.top(), currentSortOrder)) != 0) -- { -- return result < 0; -- } -- -- if ((result = compareByOrder(rectLeft.left(), rectRight.left(), currentSortOrder)) != 0) -- { -- return result < 0; -- } -- -- QSizeF sizeLeft = rectLeft.size(), sizeRight = rectRight.size(); -- -- if ((result = compareByOrder(sizeLeft.width()*sizeLeft.height(), sizeRight.width()*sizeRight.height(), currentSortOrder)) != 0) -- { -- return result < 0; -- } -- // FIXME: fall through?? If not, add "break" here -- } -- default: -- return naturalCompare(left.toString(), right.toString(), currentSortOrder, sortCaseSensitivity, strTypeNatural); -- } --} -- --DatabaseFields::Set ImageSortSettings::watchFlags() const --{ -- DatabaseFields::Set set; -- -- switch (sortRole) -- { -- case SortByFileName: -- set |= DatabaseFields::Name; -- break; -- case SortByFilePath: -- set |= DatabaseFields::Name; -- break; -- case SortByFileSize: -- set |= DatabaseFields::FileSize; -- break; -- case SortByModificationDate: -- set |= DatabaseFields::ModificationDate; -- break; -- case SortByCreationDate: -- set |= DatabaseFields::CreationDate; -- break; -- case SortByRating: -- set |= DatabaseFields::Rating; -- break; -- case SortByImageSize: -- set |= DatabaseFields::Width | DatabaseFields::Height; -- break; -- case SortByAspectRatio: -- set |= DatabaseFields::Width | DatabaseFields::Height; -- break; -- case SortBySimilarity: -- // TODO: Not sure what to do here.... -- set |= DatabaseFields::Name; -- break; -- } -- -- switch (categorizationMode) -- { -- case NoCategories: -- case OneCategory: -- case CategoryByAlbum: -- break; -- case CategoryByFormat: -- set |= DatabaseFields::Format; -- break; -- } -- -- return set; --} -- --} // namespace Digikam -diff --git a/libs/models/imagesortsettings.h b/libs/models/imagesortsettings.h -deleted file mode 100644 -index 2a5fd8c..0000000 ---- a/libs/models/imagesortsettings.h -+++ /dev/null -@@ -1,225 +0,0 @@ --/* ============================================================ -- * -- * This file is a part of digiKam project -- * http://www.digikam.org -- * -- * Date : 2009-05-31 -- * Description : Sort settings for use with ImageFilterModel -- * -- * Copyright (C) 2009 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -- * -- * This program is free software; you can redistribute it -- * and/or modify it under the terms of the GNU General -- * Public License as published by the Free Software Foundation; -- * either version 2, or (at your option) -- * any later version. -- * -- * This program 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 General Public License for more details. -- * -- * ============================================================ */ -- --#ifndef IMAGESORTSETTINGS_H --#define IMAGESORTSETTINGS_H -- --// Qt includes -- --#include <QHash> --#include <QList> --#include <QMap> --#include <QString> --#include <QCollator> -- --// Local includes -- --#include "digikam_export.h" -- --namespace Digikam --{ -- --class ImageInfo; -- --namespace DatabaseFields --{ -- class Set; --} -- --class DIGIKAM_DATABASE_EXPORT ImageSortSettings --{ --public: -- -- ImageSortSettings(); -- -- bool operator==(const ImageSortSettings& other) const; -- -- /** Compares the categories of left and right. -- * Return -1 if left is less than right, 0 if both fall in the same category, -- * and 1 if left is greater than right. -- * Adheres to set categorization mode and current category sort order. -- */ -- int compareCategories(const ImageInfo& left, const ImageInfo& right) const; -- -- /** Returns true if left is less than right. -- * Adheres to current sort role and sort order. -- */ -- bool lessThan(const ImageInfo& left, const ImageInfo& right) const; -- -- /** Compares the ImageInfos left and right. -- * Return -1 if left is less than right, 1 if left is greater than right, -- * and 0 if left equals right comparing the current sort role's value. -- * Adheres to set sort role and sort order. -- */ -- int compare(const ImageInfo& left, const ImageInfo& right) const; -- -- /** Returns true if left QVariant is less than right. -- * Adheres to current sort role and sort order. -- * Use for extraValue, if necessary. -- */ -- bool lessThan(const QVariant& left, const QVariant& right) const; -- -- enum SortOrder -- { -- AscendingOrder = Qt::AscendingOrder, -- DescendingOrder = Qt::DescendingOrder, -- DefaultOrder /// sort order depends on the chosen sort role -- }; -- -- /// --- Categories --- -- -- enum CategorizationMode -- { -- NoCategories, /// categorization switched off -- OneCategory, /// all items in one global category -- CategoryByAlbum, -- CategoryByFormat -- }; -- -- CategorizationMode categorizationMode; -- SortOrder categorizationSortOrder; -- -- void setCategorizationMode(CategorizationMode mode); -- void setCategorizationSortOrder(SortOrder order); -- -- /// Only Ascending or Descending, never DefaultOrder -- Qt::SortOrder currentCategorizationSortOrder; -- Qt::CaseSensitivity categorizationCaseSensitivity; -- -- bool isCategorized() const { return categorizationMode >= CategoryByAlbum; } -- -- /// --- Image Sorting --- -- -- enum SortRole -- { -- // Note: For legacy reasons, the order of the first five entries must remain unchanged -- SortByFileName, -- SortByFilePath, -- SortByCreationDate, -- SortByFileSize, -- SortByRating, -- SortByModificationDate, -- SortByImageSize, // pixel number -- SortByAspectRatio, // width / height * 100000 -- SortBySimilarity -- }; -- -- SortRole sortRole; -- SortOrder sortOrder; -- bool strTypeNatural; -- -- void setSortRole(SortRole role); -- void setSortOrder(SortOrder order); -- void setStringTypeNatural(bool natural); -- -- Qt::SortOrder currentSortOrder; -- Qt::CaseSensitivity sortCaseSensitivity; -- -- int compare(const ImageInfo& left, const ImageInfo& right, SortRole sortRole) const; -- -- // --- --- -- -- static Qt::SortOrder defaultSortOrderForCategorizationMode(CategorizationMode mode); -- static Qt::SortOrder defaultSortOrderForSortRole(SortRole role); -- -- /// --- Change notification --- -- -- /** Returns database fields a change in which would affect the current sorting. -- */ -- DatabaseFields::Set watchFlags() const; -- -- /// --- Utilities --- -- -- /** Returns a < b if sortOrder is Ascending, or b < a if order is descending. -- */ -- template <typename T> -- static inline bool lessThanByOrder(const T& a, const T& b, Qt::SortOrder sortOrder) -- { -- if (sortOrder == Qt::AscendingOrder) -- { -- return a < b; -- } -- else -- { -- return b < a; -- } -- } -- -- /** Returns the usual compare result of -1, 0, or 1 for lessThan, equals and greaterThan. -- */ -- template <typename T> -- static inline int compareValue(const T& a, const T& b) -- { -- if (a == b) -- { -- return 0; -- } -- -- if (a < b) -- { -- return -1; -- } -- else -- { -- return 1; -- } -- } -- -- /** Takes a typical result from a compare method (0 is equal, -1 is less than, 1 is greater than) -- * and applies the given sort order to it. -- */ -- static inline int compareByOrder(int compareResult, Qt::SortOrder sortOrder) -- { -- if (sortOrder == Qt::AscendingOrder) -- { -- return compareResult; -- } -- else -- { -- return - compareResult; -- } -- } -- -- template <typename T> -- static inline int compareByOrder(const T& a, const T& b, Qt::SortOrder sortOrder) -- { -- return compareByOrder(compareValue(a, b), sortOrder); -- } -- -- /** Compares the two string by natural comparison and adheres to given sort order -- */ -- static inline int naturalCompare(const QString& a, const QString& b, Qt::SortOrder sortOrder, -- Qt::CaseSensitivity caseSensitive = Qt::CaseSensitive, -- bool natural = true, bool versioning = false) -- { -- QCollator collator; -- collator.setNumericMode(natural); -- collator.setIgnorePunctuation(versioning); -- collator.setCaseSensitivity(caseSensitive); -- return (compareByOrder(collator.compare(a, b), sortOrder)); -- } --}; -- --} // namespace Digikam -- --#endif // IMAGESORTSETTINGS_H -diff --git a/libs/models/imagethumbnailmodel.cpp b/libs/models/imagethumbnailmodel.cpp -deleted file mode 100644 -index b7f5661..0000000 ---- a/libs/models/imagethumbnailmodel.cpp -+++ /dev/null -@@ -1,323 +0,0 @@ --/* ============================================================ -- * -- * This file is a part of digiKam project -- * http://www.digikam.org -- * -- * Date : 2009-03-05 -- * Description : Qt item model for database entries with support for thumbnail loading -- * -- * Copyright (C) 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -- * Copyright (C) 2011-2017 by Gilles Caulier <caulier dot gilles at gmail dot com> -- * -- * This program is free software; you can redistribute it -- * and/or modify it under the terms of the GNU General -- * Public License as published by the Free Software Foundation; -- * either version 2, or (at your option) -- * any later version. -- * -- * This program 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 General Public License for more details. -- * -- * ============================================================ */ -- --#include "imagethumbnailmodel.h" -- --// Qt includes -- --#include <QHash> -- --// Local includes -- --#include "digikam_debug.h" --#include "thumbnailloadthread.h" --#include "digikam_export.h" --#include "digikam_globals.h" -- --namespace Digikam --{ -- --class ImageThumbnailModel::ImageThumbnailModelPriv --{ --public: -- -- ImageThumbnailModelPriv() : -- thread(0), -- preloadThread(0), -- thumbSize(0), -- lastGlobalThumbSize(0), -- preloadThumbSize(0), -- emitDataChanged(true) -- { -- staticListContainingThumbnailRole << ImageModel::ThumbnailRole; -- } -- -- ThumbnailLoadThread* thread; -- ThumbnailLoadThread* preloadThread; -- ThumbnailSize thumbSize; -- ThumbnailSize lastGlobalThumbSize; -- ThumbnailSize preloadThumbSize; -- QRect detailRect; -- QVector<int> staticListContainingThumbnailRole; -- -- bool emitDataChanged; -- -- int preloadThumbnailSize() const -- { -- if (preloadThumbSize.size()) -- { -- return preloadThumbSize.size(); -- } -- -- return thumbSize.size(); -- } --}; -- --ImageThumbnailModel::ImageThumbnailModel(QObject* parent) -- : ImageModel(parent), d(new ImageThumbnailModelPriv) --{ -- setKeepsFilePathCache(true); --} -- --ImageThumbnailModel::~ImageThumbnailModel() --{ -- delete d->preloadThread; -- delete d; --} -- --void ImageThumbnailModel::setThumbnailLoadThread(ThumbnailLoadThread* thread) --{ -- d->thread = thread; -- -- connect(d->thread, SIGNAL(signalThumbnailLoaded(LoadingDescription,QPixmap)), -- this, SLOT(slotThumbnailLoaded(LoadingDescription,QPixmap))); --} -- --ThumbnailLoadThread* ImageThumbnailModel::thumbnailLoadThread() const --{ -- return d->thread; --} -- --ThumbnailSize ImageThumbnailModel::thumbnailSize() const --{ -- return d->thumbSize; --} -- --void ImageThumbnailModel::setThumbnailSize(const ThumbnailSize& size) --{ -- d->lastGlobalThumbSize = size; -- d->thumbSize = size; --} -- --void ImageThumbnailModel::setPreloadThumbnailSize(const ThumbnailSize& size) --{ -- d->preloadThumbSize = size; --} -- --void ImageThumbnailModel::setEmitDataChanged(bool emitSignal) --{ -- d->emitDataChanged = emitSignal; --} -- --void ImageThumbnailModel::setPreloadThumbnails(bool preload) --{ -- if (preload) -- { -- if (!d->preloadThread) -- { -- d->preloadThread = new ThumbnailLoadThread; -- d->preloadThread->setPixmapRequested(false); -- d->preloadThread->setPriority(QThread::LowestPriority); -- } -- -- connect(this, SIGNAL(allRefreshingFinished()), -- this, SLOT(preloadAllThumbnails())); -- } -- else -- { -- delete d->preloadThread; -- d->preloadThread = 0; -- disconnect(this, SIGNAL(allRefreshingFinished()), -- this, SLOT(preloadAllThumbnails())); -- } --} -- --void ImageThumbnailModel::prepareThumbnails(const QList<QModelIndex>& indexesToPrepare) --{ -- prepareThumbnails(indexesToPrepare, d->thumbSize); --} -- --void ImageThumbnailModel::prepareThumbnails(const QList<QModelIndex>& indexesToPrepare, const ThumbnailSize& thumbSize) --{ -- if (!d->thread) -- { -- return; -- } -- -- QList<ThumbnailIdentifier> ids; -- foreach(const QModelIndex& index, indexesToPrepare) -- { -- ids << imageInfoRef(index).thumbnailIdentifier(); -- } -- d->thread->findGroup(ids, thumbSize.size()); --} -- --void ImageThumbnailModel::preloadThumbnails(const QList<ImageInfo>& infos) --{ -- if (!d->preloadThread) -- { -- return; -- } -- -- QList<ThumbnailIdentifier> ids; -- foreach(const ImageInfo& info, infos) -- { -- ids << info.thumbnailIdentifier(); -- } -- d->preloadThread->pregenerateGroup(ids, d->preloadThumbnailSize()); --} -- --void ImageThumbnailModel::preloadThumbnails(const QList<QModelIndex>& indexesToPreload) --{ -- if (!d->preloadThread) -- { -- return; -- } -- -- QList<ThumbnailIdentifier> ids; -- foreach(const QModelIndex& index, indexesToPreload) -- { -- ids << imageInfoRef(index).thumbnailIdentifier(); -- } -- d->preloadThread->stopAllTasks(); -- d->preloadThread->pregenerateGroup(ids, d->preloadThumbnailSize()); --} -- --void ImageThumbnailModel::preloadAllThumbnails() --{ -- preloadThumbnails(imageInfos()); --} -- --void ImageThumbnailModel::imageInfosCleared() --{ -- if (d->preloadThread) -- { -- d->preloadThread->stopAllTasks(); -- } --} -- --QVariant ImageThumbnailModel::data(const QModelIndex& index, int role) const --{ -- if (role == ThumbnailRole && d->thread && index.isValid()) -- { -- QPixmap thumbnail; -- ImageInfo info = imageInfo(index); -- QString path = info.filePath(); -- -- if (info.isNull()) -- { -- return QVariant(QVariant::Pixmap); -- } -- -- if (!d->detailRect.isNull()) -- { -- if (d->thread->find(info.thumbnailIdentifier(), d->detailRect, thumbnail, d->thumbSize.size())) -- { -- return thumbnail; -- } -- } -- else -- { -- if (d->thread->find(info.thumbnailIdentifier(), thumbnail, d->thumbSize.size())) -- { -- return thumbnail; -- } -- } -- -- return QVariant(QVariant::Pixmap); -- } -- -- return ImageModel::data(index, role); --} -- --bool ImageThumbnailModel::setData(const QModelIndex& index, const QVariant& value, int role) --{ -- if (role == ThumbnailRole) -- { -- switch (value.type()) -- { -- case QVariant::Invalid: -- d->thumbSize = d->lastGlobalThumbSize; -- d->detailRect = QRect(); -- break; -- -- case QVariant::Int: -- -- if (value.isNull()) -- { -- d->thumbSize = d->lastGlobalThumbSize; -- } -- else -- { -- d->thumbSize = value.toInt(); -- } -- break; -- -- case QVariant::Rect: -- -- if (value.isNull()) -- { -- d->detailRect = QRect(); -- } -- else -- { -- d->detailRect = value.toRect(); -- } -- break; -- -- default: -- break; -- } -- } -- -- return ImageModel::setData(index, value, role); --} -- --void ImageThumbnailModel::slotThumbnailLoaded(const LoadingDescription& loadingDescription, const QPixmap& thumb) --{ -- if (thumb.isNull()) -- { -- return; -- } -- -- // In case of multiple occurrence, we currently do not know which thumbnail is this. Signal change on all. -- QModelIndexList indexes; -- ThumbnailIdentifier thumbId = loadingDescription.thumbnailIdentifier(); -- if (thumbId.filePath.isEmpty()) -- { -- indexes = indexesForImageId(thumbId.id); -- } -- else -- { -- indexes = indexesForPath(thumbId.filePath); -- } -- foreach(const QModelIndex& index, indexes) -- { -- if (thumb.isNull()) -- { -- emit thumbnailFailed(index, loadingDescription.previewParameters.size); -- } -- else -- { -- emit thumbnailAvailable(index, loadingDescription.previewParameters.size); -- -- if (d->emitDataChanged) -- { -- emit dataChanged(index, index, d->staticListContainingThumbnailRole); -- } -- } -- } --} -- --} // namespace Digikam -diff --git a/libs/models/imagethumbnailmodel.h b/libs/models/imagethumbnailmodel.h -deleted file mode 100644 -index 366ca65..0000000 ---- a/libs/models/imagethumbnailmodel.h -+++ /dev/null -@@ -1,140 +0,0 @@ --/* ============================================================ -- * -- * This file is a part of digiKam project -- * http://www.digikam.org -- * -- * Date : 2009-03-05 -- * Description : Qt item model for database entries with support for thumbnail loading -- * -- * Copyright (C) 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> -- * Copyright (C) 2011 by Gilles Caulier <caulier dot gilles at gmail dot com> -- * -- * This program is free software; you can redistribute it -- * and/or modify it under the terms of the GNU General -- * Public License as published by the Free Software Foundation; -- * either version 2, or (at your option) -- * any later version. -- * -- * This program 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 General Public License for more details. -- * -- * ============================================================ */ -- --#ifndef IMAGETHUMBNAILMODEL_H --#define IMAGETHUMBNAILMODEL_H -- --// Local includes -- --#include "imagemodel.h" --#include "thumbnailsize.h" --#include "digikam_export.h" -- --namespace Digikam --{ -- --class LoadingDescription; --class ThumbnailLoadThread; -- --class DIGIKAM_DATABASE_EXPORT ImageThumbnailModel : public ImageModel --{ -- Q_OBJECT -- --public: -- -- /** -- * An ImageModel that supports thumbnail loading. -- * You need to set a ThumbnailLoadThread to enable thumbnail loading. -- * Adjust the thumbnail size to your needs. -- * Note that setKeepsFilePathCache is enabled per default. -- */ -- explicit ImageThumbnailModel(QObject* parent); -- ~ImageThumbnailModel(); -- -- /** Enable thumbnail loading and set the thread that shall be used. -- * The thumbnail size of this thread will be adjusted. -- */ -- void setThumbnailLoadThread(ThumbnailLoadThread* thread); -- ThumbnailLoadThread* thumbnailLoadThread() const; -- -- /// Set the thumbnail size to use -- void setThumbnailSize(const ThumbnailSize& thumbSize); -- -- /// If you want to fix a size for preloading, do it here. -- void setPreloadThumbnailSize(const ThumbnailSize& thumbSize); -- -- void setExifRotate(bool rotate); -- -- /** -- * Enable emitting dataChanged() when a thumbnail becomes available. -- * The thumbnailAvailable() signal will be emitted in any case. -- * Default is true. -- */ -- void setEmitDataChanged(bool emitSignal); -- -- /** -- * Enable preloading of thumbnails: -- * If preloading is enabled, for every entry in the model a thumbnail generation is started. -- * Default: false. -- */ -- void setPreloadThumbnails(bool preload); -- -- ThumbnailSize thumbnailSize() const; -- -- /** -- * Handles the ThumbnailRole. -- * If the pixmap is available, returns it in the QVariant. -- * If it still needs to be loaded, returns a null QVariant and emits -- * thumbnailAvailable() as soon as it is available. -- */ -- virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; -- -- /** -- * You can override the current thumbnail size by giving an integer value for ThumbnailRole. -- * Set a null QVariant to use the thumbnail size set by setThumbnailSize() again. -- * The index given here is ignored for this purpose. -- */ -- virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::DisplayRole); -- --public Q_SLOTS: -- -- /** Prepare the thumbnail loading for the given indexes -- */ -- void prepareThumbnails(const QList<QModelIndex>& indexesToPrepare); -- void prepareThumbnails(const QList<QModelIndex>& indexesToPrepare, const ThumbnailSize& thumbSize); -- -- /** -- * Preload thumbnail for the given infos resp. indexes. -- * Note: Use setPreloadThumbnails to automatically preload all entries in the model. -- * Note: This only ensures thumbnail generation. It is not guaranteed that pixmaps -- * are stored in the cache. For thumbnails that are expect to be drawn immediately, -- * include them in prepareThumbnails(). -- * Note: Stops preloading of previously added thumbnails. -- */ -- void preloadThumbnails(const QList<ImageInfo>&); -- void preloadThumbnails(const QList<QModelIndex>&); -- void preloadAllThumbnails(); -- --Q_SIGNALS: -- -- void thumbnailAvailable(const QModelIndex& index, int requestedSize); -- void thumbnailFailed(const QModelIndex& index, int requestedSize); -- --protected: -- -- virtual void imageInfosCleared(); -- --protected Q_SLOTS: -- -- void slotThumbnailLoaded(const LoadingDescription& loadingDescription, const QPixmap& thumb); -- --private: -- -- class ImageThumbnailModelPriv; -- ImageThumbnailModelPriv* const d; --}; -- --} // namespace Digikam -- --#endif /* IMAGETHUMBNAILMODEL_H */ -diff --git a/libs/models/imageversionsmodel.cpp b/libs/models/imageversionsmodel.cpp -deleted file mode 100644 -index e6ba582..0000000 ---- a/libs/models/imageversionsmodel.cpp -+++ /dev/null -@@ -1,183 +0,0 @@ --/* ============================================================ -- * -- * This file is a part of digiKam project -- * http://www.digikam.org -- * -- * Date : 2010-07-13 -- * Description : Model for image versions -- * -- * Copyright (C) 2010 by Martin Klapetek <martin dot klapetek at gmail dot com> -- * -- * This program is free software; you can redistribute it -- * and/or modify it under the terms of the GNU General -- * Public License as published by the Free Software Foundation; -- * either version 2, or (at your option) -- * any later version. -- * -- * This program 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 General Public License for more details. -- * -- * ============================================================ */ -- --#include "imageversionsmodel.h" -- --// KDE includes -- --#include <klocalizedstring.h> -- --// Local includes -- --#include "digikam_debug.h" --#include "workingwidget.h" -- --namespace Digikam --{ -- --class ImageVersionsModel::Private --{ --public: -- -- Private() -- { -- data = 0; -- paintTree = false; -- } -- -- ///Complete paths with filenames and tree level -- QList<QPair<QString, int> >* data; -- ///This is for delegate to paint it as selected -- QString currentSelectedImage; -- ///If true, the delegate will paint items as a tree -- ///if false, it will be painted as a list -- bool paintTree; --}; -- --ImageVersionsModel::ImageVersionsModel(QObject* parent) -- : QAbstractListModel(parent), -- d(new Private) --{ -- d->data = new QList<QPair<QString, int> >; --} -- --ImageVersionsModel::~ImageVersionsModel() --{ -- //qDeleteAll(d->data); -- delete d; --} -- --Qt::ItemFlags ImageVersionsModel::flags(const QModelIndex& index) const --{ -- if (!index.isValid()) -- { -- return 0; -- } -- -- return Qt::ItemIsEnabled | Qt::ItemIsSelectable; --} -- --QVariant ImageVersionsModel::data(const QModelIndex& index, int role) const --{ -- if (!index.isValid()) -- { -- return QVariant(); -- } -- -- if (role == Qt::DisplayRole && !d->data->isEmpty()) -- { -- return d->data->at(index.row()).first; -- } -- else if (role == Qt::UserRole && !d->data->isEmpty()) -- { -- return d->data->at(index.row()).second; -- } -- else if (role == Qt::DisplayRole && d->data->isEmpty()) -- { -- //TODO: make this text Italic -- return QVariant(QString(i18n("No image selected"))); -- } -- -- return QVariant(); --} -- --int ImageVersionsModel::rowCount(const QModelIndex& parent) const --{ -- Q_UNUSED(parent) -- return d->data->count(); --} -- --void ImageVersionsModel::setupModelData(QList<QPair<QString, int> >& data) --{ -- beginResetModel(); -- -- d->data->clear(); -- -- if (!data.isEmpty()) -- { -- d->data->append(data); -- } -- else -- { -- d->data->append(qMakePair(QString(i18n("This is the original image")), 0)); -- } -- -- endResetModel(); --} -- --void ImageVersionsModel::clearModelData() --{ -- beginResetModel(); -- -- if (!d->data->isEmpty()) -- { -- d->data->clear(); -- } -- -- endResetModel(); --} -- --void ImageVersionsModel::slotAnimationStep() --{ -- emit dataChanged(createIndex(0, 0), createIndex(rowCount()-1, 1)); --} -- --QString ImageVersionsModel::currentSelectedImage() const --{ -- return d->currentSelectedImage; --} -- --void ImageVersionsModel::setCurrentSelectedImage(const QString& path) --{ -- d->currentSelectedImage = path; --} -- --QModelIndex ImageVersionsModel::currentSelectedImageIndex() const --{ -- return index(listIndexOf(d->currentSelectedImage), 0); --} -- --bool ImageVersionsModel::paintTree() const --{ -- return d->paintTree; --} -- --void ImageVersionsModel::setPaintTree(bool paint) --{ -- d->paintTree = paint; --} -- --int ImageVersionsModel::listIndexOf(const QString& item) const --{ -- for (int i = 0; i < d->data->size(); ++i) -- { -- if (d->data->at(i).first == item) -- { -- return i; -- } -- } -- -- return -1; --} -- --} // namespace Digikam -diff --git a/libs/models/imageversionsmodel.h b/libs/models/imageversionsmodel.h -deleted file mode 100644 -index ed08529..0000000 ---- a/libs/models/imageversionsmodel.h -+++ /dev/null -@@ -1,75 +0,0 @@ --/* ============================================================ -- * -- * This file is a part of digiKam project -- * http://www.digikam.org -- * -- * Date : 2010-07-13 -- * Description : Model for image versions -- * -- * Copyright (C) 2010 by Martin Klapetek <martin dot klapetek at gmail dot com> -- * -- * This program is free software; you can redistribute it -- * and/or modify it under the terms of the GNU General -- * Public License as published by the Free Software Foundation; -- * either version 2, or (at your option) -- * any later version. -- * -- * This program 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 General Public License for more details. -- * -- * ============================================================ */ -- --#ifndef IMAGEVERSIONSMODEL_H --#define IMAGEVERSIONSMODEL_H -- --// Qt includes -- --#include <QModelIndex> --#include <QPixmap> -- --// Local includes -- --#include "digikam_export.h" -- --namespace Digikam --{ -- --class DIGIKAM_DATABASE_EXPORT ImageVersionsModel : public QAbstractListModel --{ -- Q_OBJECT -- --public: -- -- explicit ImageVersionsModel(QObject* parent = 0); -- ~ImageVersionsModel(); -- -- Qt::ItemFlags flags(const QModelIndex& index) const; -- QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; -- int rowCount(const QModelIndex& parent = QModelIndex()) const; -- -- void setupModelData(QList<QPair<QString, int> >& data); -- void clearModelData(); -- -- QString currentSelectedImage() const; -- void setCurrentSelectedImage(const QString& path); -- QModelIndex currentSelectedImageIndex() const; -- -- bool paintTree() const; -- int listIndexOf(const QString& item) const; -- --public Q_SLOTS: -- -- void slotAnimationStep(); -- void setPaintTree(bool paint); -- --private: -- -- class Private; -- Private* const d; --}; -- --} // namespace Digikam -- --#endif // IMAGEVERSIONSMODEL_H --- -cgit v0.11.2 - diff --git a/kde/patch/digikam/digikam_imagemagick7.patch b/kde/patch/digikam/digikam_imagemagick7.patch deleted file mode 100644 index 04a7752..0000000 --- a/kde/patch/digikam/digikam_imagemagick7.patch +++ /dev/null @@ -1,40 +0,0 @@ -From: Antonio Rojas <arojas@archlinux.org> -Date: Thu, 7 Nov 2019 09:25:02 +0100 -Subject: Properly initialize ExceptionInfo in libMagick - -Otherwise it will crash if some plugins can't be loaded. - -diff --git a/core/dplugins/dimg/imagemagick/dimgimagemagickplugin.cpp b/core/dplugins/dimg/imagemagick/dimgimagemagickplugin.cpp -index 1858b4d..20ef01b 100644 ---- a/core/dplugins/dimg/imagemagick/dimgimagemagickplugin.cpp -+++ b/core/dplugins/dimg/imagemagick/dimgimagemagickplugin.cpp -@@ -125,7 +125,7 @@ QMap<QString, QString> DImgImageMagickPlugin::extraAboutData() const - QString mimes = typeMimes(); - - QMap<QString, QString> map; -- ExceptionInfo ex; -+ ExceptionInfo ex = *AcquireExceptionInfo(); - size_t n = 0; - const MagickInfo** inflst = GetMagickInfoList("*", &n, &ex); - -@@ -219,7 +219,7 @@ int DImgImageMagickPlugin::canRead(const QFileInfo& fileInfo, bool magic) const - int DImgImageMagickPlugin::canWrite(const QString& format) const - { - QStringList formats; -- ExceptionInfo ex; -+ ExceptionInfo ex = *AcquireExceptionInfo(); - size_t n = 0; - const MagickInfo** inflst = GetMagickInfoList("*", &n, &ex); - -@@ -266,7 +266,7 @@ DImgLoader* DImgImageMagickPlugin::loader(DImg* const image, const DRawDecoding& - QStringList DImgImageMagickPlugin::decoderFormats() const - { - QStringList formats; -- ExceptionInfo ex; -+ ExceptionInfo ex = *AcquireExceptionInfo(); - size_t n = 0; - const MagickInfo** inflst = GetMagickInfoList("*", &n, &ex); - --- -cgit v1.1 - diff --git a/kde/patch/dolphin.patch b/kde/patch/dolphin.patch index dfe3a2f..02a7950 100644 --- a/kde/patch/dolphin.patch +++ b/kde/patch/dolphin.patch @@ -1,3 +1,2 @@ # Let the user decide whether she wants to run Dolphin as root: cat $CWD/patch/dolphin/dolphin_revert_noroot.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - diff --git a/kde/patch/gwenview.patch b/kde/patch/gwenview.patch deleted file mode 100644 index 04dfe50..0000000 --- a/kde/patch/gwenview.patch +++ /dev/null @@ -1,4 +0,0 @@ -# Prevent dataloss when importing pictures; -# Will be fixed in 17.04.2: -#cat $CWD/patch/gwenview/gwenview-17.04.1_dataloss.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - diff --git a/kde/patch/gwenview/gwenview-17.04.1_dataloss.patch b/kde/patch/gwenview/gwenview-17.04.1_dataloss.patch deleted file mode 100644 index fa93428..0000000 --- a/kde/patch/gwenview/gwenview-17.04.1_dataloss.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 6ce5d2f8d82f83c5a3d726ee5807ebaf7a6e3c6c Mon Sep 17 00:00:00 2001 -From: Henrik Fehlauer <rkflx@lab12.net> -Date: Thu, 11 May 2017 22:40:15 +0200 -Subject: Avoid data loss when importing pictures - -Summary: -Fix porting regressions, which left users of Gwenview Importer with: -- failed import (import destination still empty) -- additionally (when choosing "Delete" instead of "Keep" after import): - pictures also removed from import source, with no way to recover - -Correct additional problems remaining after fixing the import failure: -- hang on duplicate filenames -- identically named files with different content are never imported -- error dialog when deleting pictures from import source - -BUG: 379615 - -In detail: - -1st problem (introduced in 017b4fe5dc7f4b6e876cfd7b108dcebbf609ae94): - - Initially, pictures are copied to a temporary folder - (e.g. "foo/.gwenview_importer-IcQqvo/"), before being moved/renamed - to the final destination (e.g. "foo/"), which is determined by - calling "cd .." on the temporary folder. - - However, mistakenly this path contains a superfluous '/' - (e.g. "foo/.gwenview_importer-IcQqvo//"), resulting in the final - destination reading "foo/.gwenview_importer-IcQqvo/" instead of - "foo/". On cleanup, the temporary folder is removed, simultaneously - deleting all new pictures. - - Fix: Omit '/' where appropriate. - -2nd problem (broken by a3262e9b197ee97323ef8bf3a9dca1e13f61a74c): - - When trying to find a unique filename, the while loop "stat"ing the - file repeats forever. - - Fix: Call "KIO::stat" and "KJobWidgets::setWindow" - also inside the loop. - -3rd problem (introduced in 017b4fe5dc7f4b6e876cfd7b108dcebbf609ae94): - - If the destination directory already contains an identically named - file, we try to find a different name by appending a number. For - this, we need to strip the old filename from the full path. - Unfortunately, only calling "path()" is incorrect, giving - "foo/pict0001.jpg/pict0001_1.jpg", rather than "foo/pict0001_1.jpg". - - Fix: Use "adjusted(QUrl::RemoveFilename)". - -4th problem (broken by a3262e9b197ee97323ef8bf3a9dca1e13f61a74c): - - Although deletion works, we show a warning dialog stating failure. - - Fix: Invert the logic of "job->exec()", as the error handling should - be skipped by "break"ing out of the while loop. - -Test Plan: -Steps to reproduce (see https://bugs.kde.org/show_bug.cgi?id=379615) no longer result in data loss. - -Autotests for importer (separate review request in D5750) pass. Hopefully, this helps catching any future porting regressions. - -Reviewers: ltoscano, sandsmark, gateau - -Reviewed By: ltoscano - -Differential Revision: https://phabricator.kde.org/D5749 ---- - importer/fileutils.cpp | 5 ++++- - importer/importdialog.cpp | 2 +- - importer/importer.cpp | 4 ++-- - 3 files changed, 7 insertions(+), 4 deletions(-) - -diff --git a/importer/fileutils.cpp b/importer/fileutils.cpp -index 5293d56..a51a18c 100644 ---- a/importer/fileutils.cpp -+++ b/importer/fileutils.cpp -@@ -128,7 +128,10 @@ RenameResult rename(const QUrl& src, const QUrl& dst_, QWidget* authWindow) - } - result = RenamedUnderNewName; - -- dst.setPath(dst.path() + '/' + prefix + QString::number(count) + suffix); -+ dst.setPath(dst.adjusted(QUrl::RemoveFilename).path() + prefix + QString::number(count) + suffix); -+ statJob = KIO::stat(dst); -+ KJobWidgets::setWindow(statJob, authWindow); -+ - ++count; - } - -diff --git a/importer/importdialog.cpp b/importer/importdialog.cpp -index ee6f7cd..5e9e847 100644 ---- a/importer/importdialog.cpp -+++ b/importer/importdialog.cpp -@@ -121,7 +121,7 @@ public: - QList<QUrl> urls = importedUrls + skippedUrls; - while (true) { - KIO::Job* job = KIO::del(urls); -- if (!job->exec()) { -+ if (job->exec()) { - break; - } - // Deleting failed -diff --git a/importer/importer.cpp b/importer/importer.cpp -index 51c4b96..a7e1d4e 100644 ---- a/importer/importer.cpp -+++ b/importer/importer.cpp -@@ -98,7 +98,7 @@ struct ImporterPrivate - } - mCurrentUrl = mUrlList.takeFirst(); - QUrl dst = mTempImportDirUrl; -- dst.setPath(dst.path() + '/' + mCurrentUrl.fileName()); -+ dst.setPath(dst.path() + mCurrentUrl.fileName()); - KIO::Job* job = KIO::copy(mCurrentUrl, dst, KIO::HideProgressInfo); - KJobWidgets::setWindow(job, mAuthWindow); - QObject::connect(job, SIGNAL(result(KJob*)), -@@ -122,7 +122,7 @@ struct ImporterPrivate - } else { - fileName = src.fileName(); - } -- dst.setPath(dst.path() + '/' + fileName); -+ dst.setPath(dst.path() + fileName); - - FileUtils::RenameResult result = FileUtils::rename(src, dst, mAuthWindow); - switch (result) { --- -cgit v0.11.2 - - diff --git a/kde/patch/kaccounts-integration.patch b/kde/patch/kaccounts-integration.patch deleted file mode 100644 index 26b87d4..0000000 --- a/kde/patch/kaccounts-integration.patch +++ /dev/null @@ -1,4 +0,0 @@ -# A bug with 15.08.2/.3 breaks KDE Telepathy accounts connection . -# Will be fixed in 15.12.0: -#cat $CWD/patch/kaccounts-integration/kaccounts-integration-15.08.3_service.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - diff --git a/kde/patch/kaccounts-integration/kaccounts-integration-15.08.3_service.patch b/kde/patch/kaccounts-integration/kaccounts-integration-15.08.3_service.patch deleted file mode 100644 index e41d58b..0000000 --- a/kde/patch/kaccounts-integration/kaccounts-integration-15.08.3_service.patch +++ /dev/null @@ -1,28 +0,0 @@ ---- a/src/jobs/createaccount.cpp -+++ b/src/jobs/createaccount.cpp -@@ -141,8 +141,8 @@ - - m_done = true; - -+ connect(m_identity, &SignOn::Identity::credentialsStored, m_identity, &SignOn::Identity::queryInfo); - m_identity->storeCredentials(); -- connect(m_identity, &SignOn::Identity::credentialsStored, m_identity, &SignOn::Identity::queryInfo); - } - - void CreateAccount::pluginError(const QString &error) -@@ -177,12 +177,12 @@ - return; - } - -+ m_account->selectService(); -+ - if (m_account->displayName().isEmpty()) { - m_account->setDisplayName(info.userName()); - } - m_account->setValue("username", info.userName()); -- -- m_account->selectService(); - m_account->setCredentialsId(info.id()); - - Accounts::AuthData authData = m_accInfo->authData(); - diff --git a/kde/patch/kalgebra.patch b/kde/patch/kalgebra.patch index 8365ff3..d17f482 100644 --- a/kde/patch/kalgebra.patch +++ b/kde/patch/kalgebra.patch @@ -2,4 +2,3 @@ # on other, it's not, requiring you to link both Curses and Readline libraries # manually. cat $CWD/patch/kalgebra/kalgebra_ncurses_linking.diff | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - diff --git a/kde/patch/kalzium.patch b/kde/patch/kalzium.patch deleted file mode 100644 index 6593e9d..0000000 --- a/kde/patch/kalzium.patch +++ /dev/null @@ -1,3 +0,0 @@ -# Fix build against KF 5.31.0 (repaired in 16.12.3): -#cat $CWD/patch/kalzium/kalzium_kf_5.31.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - diff --git a/kde/patch/kalzium/kalzium_kf_5.31.patch b/kde/patch/kalzium/kalzium_kf_5.31.patch deleted file mode 100644 index a3d4e00..0000000 --- a/kde/patch/kalzium/kalzium_kf_5.31.patch +++ /dev/null @@ -1,156 +0,0 @@ -Patch taken from: -https://gitweb.gentoo.org/repo/gentoo.git/plain/kde-apps/kalzium/files/kalzium-16.12.2-kf-5.31.patch - -From f233d458959548ab371e3faeca7313f746625afc Mon Sep 17 00:00:00 2001 -From: Heiko Becker <heirecka@exherbo.org> -Date: Sun, 22 Jan 2017 14:46:24 +0100 -Subject: Fix build with extra-cmake-modules > 5.30 - -Since a5f3a76e14799c68b5e8f74e375baa5f6f6ab4dc in -extra-cmake-modules.git -fno-operator-names is passed to the build -(when supported), causing a build error for kalzium. - -REVIEW: 129873 ---- - src/calculator/titrationCalculator.cpp | 39 +++++++++++++++------------------- - 1 file changed, 17 insertions(+), 22 deletions(-) - -diff --git a/src/calculator/titrationCalculator.cpp b/src/calculator/titrationCalculator.cpp -index 44ea152..6ea9ac9 100644 ---- a/src/calculator/titrationCalculator.cpp -+++ b/src/calculator/titrationCalculator.cpp -@@ -41,11 +41,6 @@ - - using namespace std; - --#ifdef _MSC_VER --#define and && --#define or || --#endif -- - titrationCalculator::titrationCalculator(QWidget * parent) : QWidget(parent) - { - xmin = 0; -@@ -112,7 +107,7 @@ void titrationCalculator::plot() - } - QString mreporto; - int iter = 0; -- if (uid.xaxis->text() == "" or uid.xaxis->text() == " ") { -+ if (uid.xaxis->text() == "" || uid.xaxis->text() == " ") { - uid.xaxis->setText(i18n("nothing")); - } - if (tmpy == 0) { -@@ -121,11 +116,11 @@ void titrationCalculator::plot() - //now we have to solve the system of equations NOTE:yvalue contains the equation of Y-axis variable - //we iterates the process until you have an equation in one only unknown variable or a numeric expression - mreporto = solve(yvalue); -- while (end == 0 or lettere == 1) { -+ while (end == 0 || lettere == 1) { - QByteArray ba = mreporto.toLatin1(); - char *tmreport = ba.data(); - ++iter; -- if (end == 1 or lettere == 0) { -+ if (end == 1 || lettere == 0) { - break; - } - if (iter > 100) { -@@ -273,13 +268,13 @@ QString titrationCalculator::solve(char *yvalue) - QString tempyval; - QString ptem; - for (int i = 0; strlen(yvalue) + 1; ++i) { -- if (!(yvalue[i]=='q' or yvalue[i]=='w' or yvalue[i]=='e' or yvalue[i]=='r' or yvalue[i]=='t' or yvalue[i]=='y' or yvalue[i]=='u' or yvalue[i]=='i' or yvalue[i]=='o' or yvalue[i]=='p' or yvalue[i]=='a' or yvalue[i]=='s' or yvalue[i]=='d' or yvalue[i]=='f' or yvalue[i]=='g' or yvalue[i]=='h' or yvalue[i]=='j' or yvalue[i]=='k' or yvalue[i]=='l' or yvalue[i]=='z' or yvalue[i]=='x' or yvalue[i]=='c' or yvalue[i]=='v' or yvalue[i]=='b' or yvalue[i]=='n' or yvalue[i]=='m' or yvalue[i]=='+' or yvalue[i]=='-' or yvalue[i]=='^' or yvalue[i]=='*' or yvalue[i]=='/' or yvalue[i]=='(' or yvalue[i]==')' or yvalue[i]=='Q' or yvalue[i]=='W' or yvalue[i]=='E' or yvalue[i]=='R' or yvalue[i]=='T' or yvalue[i]=='Y' or yvalue[i]=='U' or yvalue[i]=='I' or yvalue[i]=='O' or yvalue[i]=='P' or yvalue[i]=='A' or yvalue[i]=='S' or yvalue[i]=='D' or yvalue[i]=='F' or yvalue[i]=='G' or yvalue[i]=='H' or yvalue[i]=='J' or yvalue[i]=='K' or yvalue[i]=='L' or yvalue[i]=='Z' or yvalue[i]=='X' or yvalue[i]=='C' or yvalue[i]=='V' or yvalue[i]=='B' or yvalue[i]=='N' or yvalue[i]=='M' or yvalue[i]=='1' or yvalue[i]=='2' or yvalue[i]=='3' or yvalue[i]=='4' or yvalue[i]=='5' or yvalue[i]=='6' or yvalue[i]=='7' or yvalue[i]=='8' or yvalue[i]=='9' or yvalue[i]=='0' or yvalue[i]=='.' or yvalue[i]==',')) { -+ if (!(yvalue[i]=='q' || yvalue[i]=='w' || yvalue[i]=='e' || yvalue[i]=='r' || yvalue[i]=='t' || yvalue[i]=='y' || yvalue[i]=='u' || yvalue[i]=='i' || yvalue[i]=='o' || yvalue[i]=='p' || yvalue[i]=='a' || yvalue[i]=='s' || yvalue[i]=='d' || yvalue[i]=='f' || yvalue[i]=='g' || yvalue[i]=='h' || yvalue[i]=='j' || yvalue[i]=='k' || yvalue[i]=='l' || yvalue[i]=='z' || yvalue[i]=='x' || yvalue[i]=='c' || yvalue[i]=='v' || yvalue[i]=='b' || yvalue[i]=='n' || yvalue[i]=='m' || yvalue[i]=='+' || yvalue[i]=='-' || yvalue[i]=='^' || yvalue[i]=='*' || yvalue[i]=='/' || yvalue[i]=='(' || yvalue[i]==')' || yvalue[i]=='Q' || yvalue[i]=='W' || yvalue[i]=='E' || yvalue[i]=='R' || yvalue[i]=='T' || yvalue[i]=='Y' || yvalue[i]=='U' || yvalue[i]=='I' || yvalue[i]=='O' || yvalue[i]=='P' || yvalue[i]=='A' || yvalue[i]=='S' || yvalue[i]=='D' || yvalue[i]=='F' || yvalue[i]=='G' || yvalue[i]=='H' || yvalue[i]=='J' || yvalue[i]=='K' || yvalue[i]=='L' || yvalue[i]=='Z' || yvalue[i]=='X' || yvalue[i]=='C' || yvalue[i]=='V' || yvalue[i]=='B' || yvalue[i]=='N' || yvalue[i]=='M' || yvalue[i]=='1' || yvalue[i]=='2' || yvalue[i]=='3' || yvalue[i]=='4' || yvalue[i]=='5' || yvalue[i]=='6' || yvalue[i]=='7' || yvalue[i]=='8' || yvalue[i]=='9' || yvalue[i]=='0' || yvalue[i]=='.' || yvalue[i]==',')) { - break; //if current value is not a permitted value, this means that something is wrong - } -- if (yvalue[i]=='q' or yvalue[i]=='w' or yvalue[i]=='e' or yvalue[i]=='r' or yvalue[i]=='t' or yvalue[i]=='y' or yvalue[i]=='u' or yvalue[i]=='i' or yvalue[i]=='o' or yvalue[i]=='p' or yvalue[i]=='a' or yvalue[i]=='s' or yvalue[i]=='d' or yvalue[i]=='f' or yvalue[i]=='g' or yvalue[i]=='h' or yvalue[i]=='j' or yvalue[i]=='k' or yvalue[i]=='l' or yvalue[i]=='z' or yvalue[i]=='x' or yvalue[i]=='c' or yvalue[i]=='v' or yvalue[i]=='b' or yvalue[i]=='n' or yvalue[i]=='m' or yvalue[i]=='Q' or yvalue[i]=='W' or yvalue[i]=='E' or yvalue[i]=='R' or yvalue[i]=='T' or yvalue[i]=='Y' or yvalue[i]=='U' or yvalue[i]=='I' or yvalue[i]=='O' or yvalue[i]=='P' or yvalue[i]=='A' or yvalue[i]=='S' or yvalue[i]=='D' or yvalue[i]=='F' or yvalue[i]=='G' or yvalue[i]=='H' or yvalue[i]=='J' or yvalue[i]=='K' or yvalue[i]=='L' or yvalue[i]=='Z' or yvalue[i]=='X' or yvalue[i]=='C' or yvalue[i]=='V' or yvalue[i]=='B' or yvalue[i]=='N' or yvalue[i]=='M' or yvalue[i]=='.' or yvalue[i]==',') { -+ if (yvalue[i]=='q' || yvalue[i]=='w' || yvalue[i]=='e' || yvalue[i]=='r' || yvalue[i]=='t' || yvalue[i]=='y' || yvalue[i]=='u' || yvalue[i]=='i' || yvalue[i]=='o' || yvalue[i]=='p' || yvalue[i]=='a' || yvalue[i]=='s' || yvalue[i]=='d' || yvalue[i]=='f' || yvalue[i]=='g' || yvalue[i]=='h' || yvalue[i]=='j' || yvalue[i]=='k' || yvalue[i]=='l' || yvalue[i]=='z' || yvalue[i]=='x' || yvalue[i]=='c' || yvalue[i]=='v' || yvalue[i]=='b' || yvalue[i]=='n' || yvalue[i]=='m' || yvalue[i]=='Q' || yvalue[i]=='W' || yvalue[i]=='E' || yvalue[i]=='R' || yvalue[i]=='T' || yvalue[i]=='Y' || yvalue[i]=='U' || yvalue[i]=='I' || yvalue[i]=='O' || yvalue[i]=='P' || yvalue[i]=='A' || yvalue[i]=='S' || yvalue[i]=='D' || yvalue[i]=='F' || yvalue[i]=='G' || yvalue[i]=='H' || yvalue[i]=='J' || yvalue[i]=='K' || yvalue[i]=='L' || yvalue[i]=='Z' || yvalue[i]=='X' || yvalue[i]=='C' || yvalue[i]=='V' || yvalue[i]=='B' || yvalue[i]=='N' || yvalue[i]=='M' || yvalue[i]=='.' || yvalue[i]==',') { - lettere = 1; //if lettere == 0 then the equation contains only mnumbers - } -- if (yvalue[i]=='+' or yvalue[i]=='-' or yvalue[i]=='^' or yvalue[i]=='*' or yvalue[i]=='/' or yvalue[i]=='(' or yvalue[i]==')' or yvalue[i]=='1' or yvalue[i]=='2' or yvalue[i]=='3' or yvalue[i]=='4' or yvalue[i]=='5' or yvalue[i]=='6' or yvalue[i]=='7' or yvalue[i]=='8' or yvalue[i]=='9' or yvalue[i]=='0' or yvalue[i]=='.' or yvalue[i]==',') { -+ if (yvalue[i]=='+' || yvalue[i]=='-' || yvalue[i]=='^' || yvalue[i]=='*' || yvalue[i]=='/' || yvalue[i]=='(' || yvalue[i]==')' || yvalue[i]=='1' || yvalue[i]=='2' || yvalue[i]=='3' || yvalue[i]=='4' || yvalue[i]=='5' || yvalue[i]=='6' || yvalue[i]=='7' || yvalue[i]=='8' || yvalue[i]=='9' || yvalue[i]=='0' || yvalue[i]=='.' || yvalue[i]==',') { - tempyval = tempyval + QString(yvalue[i]); - } else { - tempy = tempy + QString(yvalue[i]); -@@ -302,7 +297,7 @@ QString titrationCalculator::solve(char *yvalue) - end = 1; - } - if (tempy!=uid.xaxis->text()) { -- if (yvalue[i]=='+' or yvalue[i]=='-' or yvalue[i]=='^' or yvalue[i]=='*' or yvalue[i]=='/' or yvalue[i]=='(' or yvalue[i]==')' or yvalue[i]=='1' or yvalue[i]=='2' or yvalue[i]=='3' or yvalue[i]=='4' or yvalue[i]=='5' or yvalue[i]=='6' or yvalue[i]=='7' or yvalue[i]=='8' or yvalue[i]=='9' or yvalue[i]=='0' or yvalue[i]=='.' or yvalue[i]==',') { -+ if (yvalue[i]=='+' || yvalue[i]=='-' || yvalue[i]=='^' || yvalue[i]=='*' || yvalue[i]=='/' || yvalue[i]=='(' || yvalue[i]==')' || yvalue[i]=='1' || yvalue[i]=='2' || yvalue[i]=='3' || yvalue[i]=='4' || yvalue[i]=='5' || yvalue[i]=='6' || yvalue[i]=='7' || yvalue[i]=='8' || yvalue[i]=='9' || yvalue[i]=='0' || yvalue[i]=='.' || yvalue[i]==',') { - //actually nothing - } else { - end = 0; -@@ -335,13 +330,13 @@ QString titrationCalculator::solvex(char *yvalue, QString dnum) { - QString tempyval; - tempy = ""; - for (int i = 0; strlen(yvalue) + 1; ++i) { -- if (!(yvalue[i]=='q' or yvalue[i]=='w' or yvalue[i]=='e' or yvalue[i]=='r' or yvalue[i]=='t' or yvalue[i]=='y' or yvalue[i]=='u' or yvalue[i]=='i' or yvalue[i]=='o' or yvalue[i]=='p' or yvalue[i]=='a' or yvalue[i]=='s' or yvalue[i]=='d' or yvalue[i]=='f' or yvalue[i]=='g' or yvalue[i]=='h' or yvalue[i]=='j' or yvalue[i]=='k' or yvalue[i]=='l' or yvalue[i]=='z' or yvalue[i]=='x' or yvalue[i]=='c' or yvalue[i]=='v' or yvalue[i]=='b' or yvalue[i]=='n' or yvalue[i]=='m' or yvalue[i]=='+' or yvalue[i]=='-' or yvalue[i]=='^' or yvalue[i]=='*' or yvalue[i]=='/' or yvalue[i]=='(' or yvalue[i]==')' or yvalue[i]=='Q' or yvalue[i]=='W' or yvalue[i]=='E' or yvalue[i]=='R' or yvalue[i]=='T' or yvalue[i]=='Y' or yvalue[i]=='U' or yvalue[i]=='I' or yvalue[i]=='O' or yvalue[i]=='P' or yvalue[i]=='A' or yvalue[i]=='S' or yvalue[i]=='D' or yvalue[i]=='F' or yvalue[i]=='G' or yvalue[i]=='H' or yvalue[i]=='J' or yvalue[i]=='K' or yvalue[i]=='L' or yvalue[i]=='Z' or yvalue[i]=='X' or yvalue[i]=='C' or yvalue[i]=='V' or yvalue[i]=='B' or yvalue[i]=='N' or yvalue[i]=='M' or yvalue[i]=='1' or yvalue[i]=='2' or yvalue[i]=='3' or yvalue[i]=='4' or yvalue[i]=='5' or yvalue[i]=='6' or yvalue[i]=='7' or yvalue[i]=='8' or yvalue[i]=='9' or yvalue[i]=='0' or yvalue[i]=='.' or yvalue[i]==',')) { -+ if (!(yvalue[i]=='q' || yvalue[i]=='w' || yvalue[i]=='e' || yvalue[i]=='r' || yvalue[i]=='t' || yvalue[i]=='y' || yvalue[i]=='u' || yvalue[i]=='i' || yvalue[i]=='o' || yvalue[i]=='p' || yvalue[i]=='a' || yvalue[i]=='s' || yvalue[i]=='d' || yvalue[i]=='f' || yvalue[i]=='g' || yvalue[i]=='h' || yvalue[i]=='j' || yvalue[i]=='k' || yvalue[i]=='l' || yvalue[i]=='z' || yvalue[i]=='x' || yvalue[i]=='c' || yvalue[i]=='v' || yvalue[i]=='b' || yvalue[i]=='n' || yvalue[i]=='m' || yvalue[i]=='+' || yvalue[i]=='-' || yvalue[i]=='^' || yvalue[i]=='*' || yvalue[i]=='/' || yvalue[i]=='(' || yvalue[i]==')' || yvalue[i]=='Q' || yvalue[i]=='W' || yvalue[i]=='E' || yvalue[i]=='R' || yvalue[i]=='T' || yvalue[i]=='Y' || yvalue[i]=='U' || yvalue[i]=='I' || yvalue[i]=='O' || yvalue[i]=='P' || yvalue[i]=='A' || yvalue[i]=='S' || yvalue[i]=='D' || yvalue[i]=='F' || yvalue[i]=='G' || yvalue[i]=='H' || yvalue[i]=='J' || yvalue[i]=='K' || yvalue[i]=='L' || yvalue[i]=='Z' || yvalue[i]=='X' || yvalue[i]=='C' || yvalue[i]=='V' || yvalue[i]=='B' || yvalue[i]=='N' || yvalue[i]=='M' || yvalue[i]=='1' || yvalue[i]=='2' || yvalue[i]=='3' || yvalue[i]=='4' || yvalue[i]=='5' || yvalue[i]=='6' || yvalue[i]=='7' || yvalue[i]=='8' || yvalue[i]=='9' || yvalue[i]=='0' || yvalue[i]=='.' || yvalue[i]==',')) { - break; //if current value is not a permitted value, this means that something is wrong - } -- if (yvalue[i]=='q' or yvalue[i]=='w' or yvalue[i]=='e' or yvalue[i]=='r' or yvalue[i]=='t' or yvalue[i]=='y' or yvalue[i]=='u' or yvalue[i]=='i' or yvalue[i]=='o' or yvalue[i]=='p' or yvalue[i]=='a' or yvalue[i]=='s' or yvalue[i]=='d' or yvalue[i]=='f' or yvalue[i]=='g' or yvalue[i]=='h' or yvalue[i]=='j' or yvalue[i]=='k' or yvalue[i]=='l' or yvalue[i]=='z' or yvalue[i]=='x' or yvalue[i]=='c' or yvalue[i]=='v' or yvalue[i]=='b' or yvalue[i]=='n' or yvalue[i]=='m' or yvalue[i]=='Q' or yvalue[i]=='W' or yvalue[i]=='E' or yvalue[i]=='R' or yvalue[i]=='T' or yvalue[i]=='Y' or yvalue[i]=='U' or yvalue[i]=='I' or yvalue[i]=='O' or yvalue[i]=='P' or yvalue[i]=='A' or yvalue[i]=='S' or yvalue[i]=='D' or yvalue[i]=='F' or yvalue[i]=='G' or yvalue[i]=='H' or yvalue[i]=='J' or yvalue[i]=='K' or yvalue[i]=='L' or yvalue[i]=='Z' or yvalue[i]=='X' or yvalue[i]=='C' or yvalue[i]=='V' or yvalue[i]=='B' or yvalue[i]=='N' or yvalue[i]=='M' or yvalue[i]=='.' or yvalue[i]==',') { -+ if (yvalue[i]=='q' || yvalue[i]=='w' || yvalue[i]=='e' || yvalue[i]=='r' || yvalue[i]=='t' || yvalue[i]=='y' || yvalue[i]=='u' || yvalue[i]=='i' || yvalue[i]=='o' || yvalue[i]=='p' || yvalue[i]=='a' || yvalue[i]=='s' || yvalue[i]=='d' || yvalue[i]=='f' || yvalue[i]=='g' || yvalue[i]=='h' || yvalue[i]=='j' || yvalue[i]=='k' || yvalue[i]=='l' || yvalue[i]=='z' || yvalue[i]=='x' || yvalue[i]=='c' || yvalue[i]=='v' || yvalue[i]=='b' || yvalue[i]=='n' || yvalue[i]=='m' || yvalue[i]=='Q' || yvalue[i]=='W' || yvalue[i]=='E' || yvalue[i]=='R' || yvalue[i]=='T' || yvalue[i]=='Y' || yvalue[i]=='U' || yvalue[i]=='I' || yvalue[i]=='O' || yvalue[i]=='P' || yvalue[i]=='A' || yvalue[i]=='S' || yvalue[i]=='D' || yvalue[i]=='F' || yvalue[i]=='G' || yvalue[i]=='H' || yvalue[i]=='J' || yvalue[i]=='K' || yvalue[i]=='L' || yvalue[i]=='Z' || yvalue[i]=='X' || yvalue[i]=='C' || yvalue[i]=='V' || yvalue[i]=='B' || yvalue[i]=='N' || yvalue[i]=='M' || yvalue[i]=='.' || yvalue[i]==',') { - tempy = tempy + yvalue[i]; //if lettere == 0 then the equation contains only mnumbers - } -- if (yvalue[i]=='+' or yvalue[i]=='-' or yvalue[i]=='^' or yvalue[i]=='*' or yvalue[i]=='/' or yvalue[i]=='(' or yvalue[i]==')' or yvalue[i]=='1' or yvalue[i]=='2' or yvalue[i]=='3' or yvalue[i]=='4' or yvalue[i]=='5' or yvalue[i]=='6' or yvalue[i]=='7' or yvalue[i]=='8' or yvalue[i]=='9' or yvalue[i]=='0' or yvalue[i]=='.' or yvalue[i]==',') { -+ if (yvalue[i]=='+' || yvalue[i]=='-' || yvalue[i]=='^' || yvalue[i]=='*' || yvalue[i]=='/' || yvalue[i]=='(' || yvalue[i]==')' || yvalue[i]=='1' || yvalue[i]=='2' || yvalue[i]=='3' || yvalue[i]=='4' || yvalue[i]=='5' || yvalue[i]=='6' || yvalue[i]=='7' || yvalue[i]=='8' || yvalue[i]=='9' || yvalue[i]=='0' || yvalue[i]=='.' || yvalue[i]==',') { - if (!tempyolda.isEmpty()) { - tempy = tempy + yvalue[i]; - if (tempyolda == uid.xaxis->text()) { -@@ -359,7 +354,7 @@ QString titrationCalculator::solvex(char *yvalue, QString dnum) { - tempyolda = tempyold; - } else { - tempyold = ""; -- if (((olda != 1) and (yvalue[i + 1] != '^')) or (yvalue[i] == '+' or yvalue[i] == '-' or yvalue[i] == '^' or yvalue[i] == '*' or yvalue[i] == '/' or yvalue[i] == '(' or yvalue[i] == ')')) { -+ if (((olda != 1) && (yvalue[i + 1] != '^')) || (yvalue[i] == '+' || yvalue[i] == '-' || yvalue[i] == '^' || yvalue[i] == '*' || yvalue[i] == '/' || yvalue[i] == '(' || yvalue[i] == ')')) { - tempyval = tempyval + QString(yvalue[i]); - } - } -@@ -374,7 +369,7 @@ QString titrationCalculator::solvex(char *yvalue, QString dnum) { - tempyold = ""; - olda = 1; - } -- if ((tempy==uid.xaxis->text()) and (!tempyolda.isEmpty())) { -+ if ((tempy==uid.xaxis->text()) && (!tempyolda.isEmpty())) { - if (yvalue[i + 1] != '^') { - tempyval = tempyval + dnum; - } -@@ -611,7 +606,7 @@ void titrationCalculator::on_actionOpen_triggered() - if (tmpchr != '|') { - tempyval = tempyval + tmpchr; - } else { -- if ((tablea == 1) and (tempyval != QString("table1")) and (tempyval != QString("table2")) and (tempyval != QString("xaxis")) and (tempyval != QString("yaxis")) and (tempyval != QString("note"))) { -+ if ((tablea == 1) && (tempyval != QString("table1")) && (tempyval != QString("table2")) && (tempyval != QString("xaxis")) && (tempyval != QString("yaxis")) && (tempyval != QString("note"))) { - if ((i % 2) != 0) { - QTableWidgetItem *titemo = uid.tableWidget->item((i - 1) / 2, 1); - if (titemo) { -@@ -626,7 +621,7 @@ void titrationCalculator::on_actionOpen_triggered() - ++i; - } - -- if ((tableb == 1) and (tempyval != QString("table1")) and (tempyval != QString("table2")) and (tempyval != QString("xaxis")) and (tempyval != QString("yaxis")) and (tempyval != QString("note"))) { -+ if ((tableb == 1) && (tempyval != QString("table1")) && (tempyval != QString("table2")) && (tempyval != QString("xaxis")) && (tempyval != QString("yaxis")) && (tempyval != QString("note"))) { - if ((i % 2) != 0) { - QTableWidgetItem *titemo = uid.tableWidget_2->item((i - 1) / 2, 1); - if (titemo) { -@@ -641,13 +636,13 @@ void titrationCalculator::on_actionOpen_triggered() - } - ++i; - } -- if ((xax == 1) and (tempyval != QString("table1")) and (tempyval != QString("table2")) and (tempyval != QString("xaxis")) and (tempyval != QString("yaxis")) and (tempyval != QString("note"))) { -+ if ((xax == 1) && (tempyval != QString("table1")) && (tempyval != QString("table2")) && (tempyval != QString("xaxis")) && (tempyval != QString("yaxis")) && (tempyval != QString("note"))) { - uid.xaxis->setText(tempyval); - } -- if ((yax == 1) and (tempyval != QString("table1")) and (tempyval != QString("table2")) and (tempyval != QString("xaxis")) and (tempyval != QString("yaxis")) and (tempyval != QString("note"))) { -+ if ((yax == 1) && (tempyval != QString("table1")) && (tempyval != QString("table2")) && (tempyval != QString("xaxis")) && (tempyval != QString("yaxis")) && (tempyval != QString("note"))) { - uid.yaxis->setText(tempyval); - } -- if ((notea == 1) and (tempyval != QString("table1")) and (tempyval != QString("table2")) and (tempyval != QString("xaxis")) and (tempyval != QString("yaxis")) and (tempyval != QString("note"))) { -+ if ((notea == 1) && (tempyval != QString("table1")) && (tempyval != QString("table2")) && (tempyval != QString("xaxis")) && (tempyval != QString("yaxis")) && (tempyval != QString("note"))) { - uid.note->setText(tempyval); - } - --- -cgit v0.11.2 - - diff --git a/kde/patch/kate.patch b/kde/patch/kate.patch index 45c2f53..59df062 100644 --- a/kde/patch/kate.patch +++ b/kde/patch/kate.patch @@ -1,8 +1,3 @@ -# Last-minute fixes for opening and closing files: -# Should be fixed after 15.12.0. -#cat $CWD/patch/kate/kate-15.12.0.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - # Allow Kate to be started by the root user; disallowing this is not # a decision that a developer should make for the user, it is patronizing: cat $CWD/patch/kate/kate_runasroot.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - diff --git a/kde/patch/kate/kate-15.12.0.patch b/kde/patch/kate/kate-15.12.0.patch deleted file mode 100644 index 25067f4..0000000 --- a/kde/patch/kate/kate-15.12.0.patch +++ /dev/null @@ -1,31 +0,0 @@ -From: Michal Humpula <michal.humpula@hudrydum.cz> -Date: Sun, 29 Nov 2015 10:24:42 +0000 -Subject: fix opening new files trough dbus -X-Git-Url: http://quickgit.kde.org/?p=kate.git&a=commitdiff&h=d61b121264d7b43d41c1c6417a18bbfb9078eb9d ---- -fix opening new files trough dbus - -REVIEW: 126197 ---- - - ---- a/urlinfo.h -+++ b/urlinfo.h -@@ -33,7 +33,7 @@ - : cursor(KTextEditor::Cursor::invalid()) - { - // convert to an url -- const QRegularExpression withProtocol(QStringLiteral("^[a-zA-Z]+:")); // TODO: remove after Qt supports this on its own -+ const QRegularExpression withProtocol(QStringLiteral("^[a-zA-Z]+://")); // TODO: remove after Qt supports this on its own - if (withProtocol.match(path).hasMatch()) { - url = QUrl::fromUserInput(path); - } else { -@@ -50,7 +50,7 @@ - int line = match.captured(1).toInt() - 1; - // don't use an invalid column when the line is valid - int column = qMax(0, match.captured(2).toInt() - 1); -- url = QUrl::fromLocalFile(path); -+ url = QUrl::fromLocalFile(QDir::current().absoluteFilePath(path)); - cursor = {line, column}; - } - } diff --git a/kde/patch/kcalc.patch b/kde/patch/kcalc.patch deleted file mode 100644 index 8cc3873..0000000 --- a/kde/patch/kcalc.patch +++ /dev/null @@ -1,5 +0,0 @@ -# Fix issue where kcalc has a zero-sized window and appears not to start, -# in combination with Qt 5.6. -# Should be fixed after 16.04.0. -#cat $CWD/patch/kcalc/kcalc-kdebug_360105.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - diff --git a/kde/patch/kcalc/kcalc-kdebug_360105.patch b/kde/patch/kcalc/kcalc-kdebug_360105.patch deleted file mode 100644 index a2ff272..0000000 --- a/kde/patch/kcalc/kcalc-kdebug_360105.patch +++ /dev/null @@ -1,15 +0,0 @@ -Fix issue where kcalc has a zero-sized window and appears not to start. - -Patch-by: Rex Dieter <rdieter@math.unl.edu> -Gentoo-bug: 577782 -KDE-bug: 360105 - ---- a/kcalc.cpp -+++ b/kcalc.cpp -@@ -124,5 +124,5 @@ KCalculator::KCalculator(QWidget *parent - updateGeometry(); - -- setFixedSize(minimumSize()); -+ if ( ! minimumSize().isEmpty() ) setFixedSize(minimumSize()); - - updateDisplay(UPDATE_FROM_CORE); diff --git a/kde/patch/kcalcore.patch b/kde/patch/kcalcore.patch deleted file mode 100644 index 051150d..0000000 --- a/kde/patch/kcalcore.patch +++ /dev/null @@ -1,4 +0,0 @@ -# Fix compile error against new libical 3: -# Fixed in Applications 17.12.0: -#cat $CWD/patch/kcalcore/kcalcore_libical3.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - diff --git a/kde/patch/kcalcore/kcalcore_libical3.patch b/kde/patch/kcalcore/kcalcore_libical3.patch deleted file mode 100644 index 0a5155f..0000000 --- a/kde/patch/kcalcore/kcalcore_libical3.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 27eaa211b23a6bb0bcba5a91cf7cadfc1e888e21 Mon Sep 17 00:00:00 2001 -From: Allen Winter <winter@kde.org> -Date: Fri, 6 Oct 2017 10:39:20 -0400 -Subject: icalformat_p.cpp, icaltimezones.cpp - follow API changes in libical3 - ---- - src/icalformat_p.cpp | 11 ++++++----- - src/icaltimezones.cpp | 10 ++++------ - 2 files changed, 10 insertions(+), 11 deletions(-) - -diff --git a/src/icalformat_p.cpp b/src/icalformat_p.cpp -index bd1d8a3..c2e4548 100644 ---- a/src/icalformat_p.cpp -+++ b/src/icalformat_p.cpp -@@ -2355,7 +2355,6 @@ icaltimetype ICalFormatImpl::writeICalDate(const QDate &date) - t.second = 0; - - t.is_date = 1; -- t.is_utc = 0; - t.zone = nullptr; - - return t; -@@ -2377,7 +2376,9 @@ icaltimetype ICalFormatImpl::writeICalDateTime(const QDateTime &datetime, bool d - t.second = datetime.time().second(); - } - t.zone = nullptr; // zone is NOT set -- t.is_utc = datetime.isUtc() ? 1 : 0; -+ if ( datetime.isUtc() ) { -+ t = icaltime_convert_to_zone(t, icaltimezone_get_utc_timezone()); -+ } - - // _dumpIcaltime( t ); - -@@ -2450,7 +2452,7 @@ icalproperty *ICalFormatImpl::writeICalDateTimeProperty(const icalproperty_kind - } - - KTimeZone ktz; -- if (!t.is_utc) { -+ if (!icaltime_is_utc(t)) { - ktz = dt.timeZone(); - } - -@@ -2483,7 +2484,7 @@ QDateTime ICalFormatImpl::readICalDateTime(icalproperty *p, const icaltimetype & - // _dumpIcaltime( t ); - - KDateTime::Spec timeSpec; -- if (t.is_utc || t.zone == icaltimezone_get_utc_timezone()) { -+ if (icaltime_is_utc(t) || t.zone == icaltimezone_get_utc_timezone()) { - timeSpec = KDateTime::UTC; // the time zone is UTC - utc = false; // no need to convert to UTC - } else { -diff --git a/src/icaltimezones.cpp b/src/icaltimezones.cpp -index 2f6d42f..f8f8d5d 100644 ---- a/src/icaltimezones.cpp -+++ b/src/icaltimezones.cpp -@@ -54,7 +54,7 @@ static QDateTime toQDateTime(const icaltimetype &t) - { - return QDateTime(QDate(t.year, t.month, t.day), - QTime(t.hour, t.minute, t.second), -- (t.is_utc ? Qt::UTC : Qt::LocalTime)); -+ (icaltime_is_utc(t) ? Qt::UTC : Qt::LocalTime)); - } - - // Maximum date for time zone data. -@@ -81,7 +81,6 @@ static icaltimetype writeLocalICalDateTime(const QDateTime &utc, int offset) - t.second = local.time().second(); - t.is_date = 0; - t.zone = nullptr; -- t.is_utc = 0; - return t; - } - -@@ -888,7 +887,7 @@ - } - case ICAL_LASTMODIFIED_PROPERTY: { - const icaltimetype t = icalproperty_get_lastmodified(p); -- if (t.is_utc) { -+ if (icaltime_is_utc(t)) { - data->d->lastModified = toQDateTime(t); - } else { - qCDebug(KCALCORE_LOG) << "LAST-MODIFIED not UTC"; -@@ -1261,7 +1260,7 @@ bool ICalTimeZoneParser::parsePhase(icalcomponent *c, ICalTimeZonePhase &phase) - // Convert DTSTART to QDateTime, and from local time to UTC - const QDateTime localStart = toQDateTime(dtstart); // local time - dtstart.second -= prevOffset; -- dtstart.is_utc = 1; -+ dtstart = icaltime_convert_to_zone(dtstart, icaltimezone_get_utc_timezone()); - const QDateTime utcStart = toQDateTime(icaltime_normalize(dtstart)); // UTC - - transitions += utcStart; -@@ -1286,13 +1285,12 @@ bool ICalTimeZoneParser::parsePhase(icalcomponent *c, ICalTimeZonePhase &phase) - t.minute = dtstart.minute; - t.second = dtstart.second; - t.is_date = 0; -- t.is_utc = 0; // dtstart is in local time - } - // RFC2445 states that RDATE must be in local time, - // but we support UTC as well to be safe. -- if (!t.is_utc) { -+ if (!icaltime_is_utc(t)) { - t.second -= prevOffset; // convert to UTC -- t.is_utc = 1; -+ t = icaltime_convert_to_zone(t, icaltimezone_get_utc_timezone()); - t = icaltime_normalize(t); - } - transitions += toQDateTime(t); --- -cgit v0.11.2 - diff --git a/kde/patch/kcoreaddons.patch b/kde/patch/kcoreaddons.patch deleted file mode 100644 index 5cd190c..0000000 --- a/kde/patch/kcoreaddons.patch +++ /dev/null @@ -1,5 +0,0 @@ -# KDEBUG #362161 (fixed in Frameworks 5.22.0): -# Fixes regression introduced in 9ae6d765b37135bbfe3a8b936e5a88b8a435e424 -# Since the rand() was not seeded, the numbers generated were predictable. -#cat $CWD/patch/kcoreaddons/kcoreaddons.kdebug_362161.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - diff --git a/kde/patch/kcoreaddons/kcoreaddons.kdebug_362161.patch b/kde/patch/kcoreaddons/kcoreaddons.kdebug_362161.patch deleted file mode 100644 index 31bbcf7..0000000 --- a/kde/patch/kcoreaddons/kcoreaddons.kdebug_362161.patch +++ /dev/null @@ -1,27 +0,0 @@ -From: Albert Astals Cid <aacid@kde.org> -Date: Tue, 26 Apr 2016 21:41:27 +0000 -Subject: Missing rand() -> qrand -X-Git-Url: http://quickgit.kde.org/?p=kcoreaddons.git&a=commitdiff&h=78212436643af95779facd9593c82fb149c2213d ---- -Missing rand() -> qrand - -Fixes regression introduced in 9ae6d765b37135bbfe3a8b936e5a88b8a435e424 - -Reviewed by Aleix - -BUGS: 362161 ---- - - ---- a/src/lib/randomness/krandom.cpp -+++ b/src/lib/randomness/krandom.cpp -@@ -51,7 +51,7 @@ - } - qsrand(seed); - } -- return rand(); -+ return qrand(); - } - - QString KRandom::randomString(int length) - diff --git a/kde/patch/kde-baseapps.patch b/kde/patch/kde-baseapps.patch deleted file mode 100644 index 988504d..0000000 --- a/kde/patch/kde-baseapps.patch +++ /dev/null @@ -1,5 +0,0 @@ -# Fix for bug https://bugs.kde.org/show_bug.cgi?id=327224 -# "Regression: Dolphin doesn't accept URLs containing a kio-slave as parameter" -# Fixed in KDE 4.11.4. -#cat $CWD/patch/kde-baseapps/dolphin_kdebug_327224.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - diff --git a/kde/patch/kde-baseapps/dolphin_kdebug_327224.patch b/kde/patch/kde-baseapps/dolphin_kdebug_327224.patch deleted file mode 100644 index 8210d87..0000000 --- a/kde/patch/kde-baseapps/dolphin_kdebug_327224.patch +++ /dev/null @@ -1,57 +0,0 @@ -Revert "Files passed as arguments: Ignore unsupported files" - -This reverts commit cd9e50ae4f3ded5a78d0cfb09a67684a9c15d726. - -See bug#327224 for details. - ---- a/dolphin/src/dolphinmainwindow.cpp -+++ b/dolphin/src/dolphinmainwindow.cpp -@@ -31,7 +31,6 @@ - #include "panels/information/informationpanel.h" - #include "settings/dolphinsettingsdialog.h" - #include "statusbar/dolphinstatusbar.h" --#include "views/dolphinview.h" - #include "views/dolphinviewactionhandler.h" - #include "views/dolphinremoteencoding.h" - #include "views/draganddrophelper.h" -@@ -244,20 +243,8 @@ - return; - } - -- // dirs could contain URLs that actually point to archives or other files. -- // Replace them by URLs we can open where possible and filter the rest out. -- QList<KUrl> urlsToOpen; -- foreach (const KUrl& rawUrl, dirs) { -- const KFileItem& item = KFileItem(KFileItem::Unknown, KFileItem::Unknown, rawUrl); -- item.determineMimeType(); -- const KUrl& url = DolphinView::openItemAsFolderUrl(item); -- if (!url.isEmpty()) { -- urlsToOpen.append(url); -- } -- } -- -- if (urlsToOpen.count() == 1) { -- m_activeViewContainer->setUrl(urlsToOpen.first()); -+ if (dirs.count() == 1) { -+ m_activeViewContainer->setUrl(dirs.first()); - return; - } - -@@ -267,12 +254,12 @@ - - // Open each directory inside a new tab. If the "split view" option has been enabled, - // always show two directories within one tab. -- QList<KUrl>::const_iterator it = urlsToOpen.begin(); -- while (it != urlsToOpen.end()) { -+ QList<KUrl>::const_iterator it = dirs.begin(); -+ while (it != dirs.end()) { - openNewTab(*it); - ++it; - -- if (hasSplitView && (it != urlsToOpen.end())) { -+ if (hasSplitView && (it != dirs.end())) { - const int tabIndex = m_viewTab.count() - 1; - m_viewTab[tabIndex].secondaryView->setUrl(*it); - ++it; - - diff --git a/kde/patch/kde-cli-tools.patch b/kde/patch/kde-cli-tools.patch deleted file mode 100644 index a76227d..0000000 --- a/kde/patch/kde-cli-tools.patch +++ /dev/null @@ -1,6 +0,0 @@ -# Remove CONFIG argument from find_package(KF5); -# This is no longer wanted, since ECM has a FindKF5 module. -#cat $CWD/patch/kde-cli-tools/kde-cli-tools_ecm.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - -# Adjust for the change in KAboutData: -#cat $CWD/patch/kde-cli-tools/kde-cli-tools_kaboutdata.diff | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } diff --git a/kde/patch/kde-cli-tools/kde-cli-tools_ecm.patch b/kde/patch/kde-cli-tools/kde-cli-tools_ecm.patch deleted file mode 100644 index 1ff1f84..0000000 --- a/kde/patch/kde-cli-tools/kde-cli-tools_ecm.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- kde-cli-tools-20140602git/CMakeLists.txt.orig 2014-06-02 13:45:49.000000000 +0200 -+++ kde-cli-tools-20140602git/CMakeLists.txt 2014-06-02 23:45:22.337682384 +0200 -@@ -21,7 +21,7 @@ - Test - ) - --find_package(KF5 CONFIG REQUIRED COMPONENTS -+find_package(KF5 REQUIRED COMPONENTS - Config - Init - KCMUtils diff --git a/kde/patch/kde-cli-tools/kde-cli-tools_kaboutdata.diff b/kde/patch/kde-cli-tools/kde-cli-tools_kaboutdata.diff deleted file mode 100644 index e88a512..0000000 --- a/kde/patch/kde-cli-tools/kde-cli-tools_kaboutdata.diff +++ /dev/null @@ -1,59 +0,0 @@ -diff -uar kde-cli-tools-20140602git.orig/kdesu/kdesu.cpp kde-cli-tools-20140602git/kdesu/kdesu.cpp ---- kde-cli-tools-20140602git.orig/kdesu/kdesu.cpp 2014-06-02 13:45:49.000000000 +0200 -+++ kde-cli-tools-20140602git/kdesu/kdesu.cpp 2014-06-03 00:41:16.998697492 +0200 -@@ -81,9 +81,9 @@ - if (duser.isEmpty()) - duser = "root"; - -- KAboutData aboutData("kdesu", 0, i18n("KDE su"), -+ KAboutData aboutData("kdesu", i18n("KDE su"), - Version, i18n("Runs a program with elevated privileges."), -- KAboutData::License_Artistic, -+ KAboutLicense::Artistic, - i18n("Copyright (c) 1998-2000 Geert Jansen, Pietro Iglio")); - aboutData.addAuthor(i18n("Geert Jansen"), i18n("Maintainer"), - "jansen@kde.org", "http://www.stack.nl/~geertj/"); -diff -uar kde-cli-tools-20140602git.orig/kioclient/kioclient.cpp kde-cli-tools-20140602git/kioclient/kioclient.cpp ---- kde-cli-tools-20140602git.orig/kioclient/kioclient.cpp 2014-06-02 13:45:49.000000000 +0200 -+++ kde-cli-tools-20140602git/kioclient/kioclient.cpp 2014-06-03 00:41:50.446696159 +0200 -@@ -133,7 +133,7 @@ - QString programName = i18n("KIO Client"); - QString description = i18n("Command-line tool for network-transparent operations"); - QString version = "2.0"; -- KAboutData data(appName, appName, programName, version, description, KAboutData::License_LGPL_V2); -+ KAboutData data(appName, programName, version, description, KAboutLicense::LGPL_V2); - - QCommandLineParser parser; - parser.addOption(QCommandLineOption("noninteractive", i18n("Non-interactive use: no message boxes. If you don't want a" -diff -uar kde-cli-tools-20140602git.orig/kreadconfig/kreadconfig.cpp kde-cli-tools-20140602git/kreadconfig/kreadconfig.cpp ---- kde-cli-tools-20140602git.orig/kreadconfig/kreadconfig.cpp 2014-06-02 13:45:49.000000000 +0200 -+++ kde-cli-tools-20140602git/kreadconfig/kreadconfig.cpp 2014-06-03 00:40:33.820702023 +0200 -@@ -53,10 +53,10 @@ - int main(int argc, char **argv) - { - QCoreApplication app(argc, argv); -- KAboutData aboutData("kreadconfig", 0, i18n("KReadConfig"), -+ KAboutData aboutData("kreadconfig", i18n("KReadConfig"), - "1.0.1", - i18n("Read KConfig entries - for use in shell scripts"), -- KAboutData::License_GPL, -+ KAboutLicense::GPL, - i18n("(c) 2001 Red Hat, Inc.")); - aboutData.addAuthor(i18n("Bernhard Rosenkraenzer"), QString(), "bero@redhat.com"); - -diff -uar kde-cli-tools-20140602git.orig/kreadconfig/kwriteconfig.cpp kde-cli-tools-20140602git/kreadconfig/kwriteconfig.cpp ---- kde-cli-tools-20140602git.orig/kreadconfig/kwriteconfig.cpp 2014-06-02 13:45:49.000000000 +0200 -+++ kde-cli-tools-20140602git/kreadconfig/kwriteconfig.cpp 2014-06-03 00:39:54.811701204 +0200 -@@ -31,10 +31,10 @@ - int main(int argc, char **argv) - { - QCoreApplication app(argc, argv); -- KAboutData aboutData("kwriteconfig", 0, i18n("KWriteConfig"), -+ KAboutData aboutData("kwriteconfig", i18n("KWriteConfig"), - "1.0.0", - i18n("Write KConfig entries - for use in shell scripts"), -- KAboutData::License_GPL, -+ KAboutLicense::GPL, - i18n("(c) 2001 Red Hat, Inc. & LuÃs Pedro Coelho")); - aboutData.addAuthor("LuÃs Pedro Coelho", QString(), "luis_pedro@netcabo.pt"); - aboutData.addAuthor("Bernhard Rosenkraenzer", i18n("Wrote kreadconfig on which this is based"), "bero@redhat.com"); diff --git a/kde/patch/kde-dev-utils.patch b/kde/patch/kde-dev-utils.patch deleted file mode 100644 index c5cbc92..0000000 --- a/kde/patch/kde-dev-utils.patch +++ /dev/null @@ -1,3 +0,0 @@ -# Fix build against KF 5.48.0 (only relevant for 18.04.3): -#cat $CWD/patch/kde-dev-utils/build_with_kf548.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - diff --git a/kde/patch/kde-dev-utils/build_with_kf548.patch b/kde/patch/kde-dev-utils/build_with_kf548.patch deleted file mode 100644 index e75838d..0000000 --- a/kde/patch/kde-dev-utils/build_with_kf548.patch +++ /dev/null @@ -1,156 +0,0 @@ -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 369699a..00e1413 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -1,15 +1,18 @@ - cmake_minimum_required(VERSION 2.8.12) - - find_package(ECM 5.14 REQUIRED NO_MODULE) - set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) - - include(FeatureSummary) - include(ECMInstallIcons) - include(KDEInstallDirs) - include(KDECMakeSettings) - include(KDECompilerSettings NO_POLICY_SCOPE) - include(ECMQtDeclareLoggingCategory) - -+# Required for ki18n_install(po) added on tarball generation -+find_package(KF5 REQUIRED COMPONENTS I18n) -+ - add_subdirectory(kpartloader) - add_subdirectory(kuiviewer) - ki18n_install(po) -diff --git a/kpartloader/CMakeLists.txt b/kpartloader/CMakeLists.txt -index 4e54d94..1fe4136 100644 ---- a/kpartloader/CMakeLists.txt -+++ b/kpartloader/CMakeLists.txt -@@ -1,27 +1,26 @@ - project(kpartloader) - ########### kpartloader ############### - - set(QT_MIN_VERSION "5.5.0") - - find_package(Qt5 ${QT_MIN_VERSION} REQUIRED NO_MODULE - COMPONENTS - Core - ) - - find_package(KF5 REQUIRED - COMPONENTS - CoreAddons -- I18n - Parts - WidgetsAddons - ) - - set(kpartloader_SRCS - kpartloader.cpp - ) - - add_executable(kpartloader ${kpartloader_SRCS}) - target_link_libraries(kpartloader KF5::Parts) - install(TARGETS kpartloader ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) - install(FILES kpartloaderui.rc DESTINATION ${KDE_INSTALL_KXMLGUI5DIR}/kpartloader) - -diff --git a/kuiviewer/CMakeLists.txt b/kuiviewer/CMakeLists.txt -index fa72c59..3fe987e 100644 ---- a/kuiviewer/CMakeLists.txt -+++ b/kuiviewer/CMakeLists.txt -@@ -1,96 +1,95 @@ - project(kuiviewer) - - set(QT_MIN_VERSION "5.5.0") - - include(ECMAddAppIcon) - - find_package(Qt5 ${QT_MIN_VERSION} REQUIRED NO_MODULE - COMPONENTS - Core - Designer - UiTools - ) - - find_package(KF5 REQUIRED - COMPONENTS - CoreAddons - KIO -- I18n - Parts - ) - - add_definitions( - -DQT_DEPRECATED_WARNINGS - -DQT_DISABLE_DEPRECATED_BEFORE=0x050500 - -DQT_NO_SIGNALS_SLOTS_KEYWORDS - -DQT_STRICT_ITERATORS - -DQT_USE_QSTRINGBUILDER - -DQT_NO_CAST_TO_ASCII - -DQT_NO_CAST_FROM_ASCII - -DQT_NO_CAST_FROM_BYTEARRAY - -DQT_NO_URL_CAST_FROM_STRING - ) - - ########### next target ############### - - set(kuiviewer_SRCS main.cpp kuiviewer.cpp ) - - file(GLOB ICONS_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/*-apps-kuiviewer.png") - ecm_add_app_icon(kuiviewer_SRCS ICONS ${ICONS_SRCS}) - - add_executable(kuiviewer ${kuiviewer_SRCS}) - - target_link_libraries(kuiviewer KF5::Parts ) - - install(TARGETS kuiviewer ${KDE_INSTALL_TARGETS_DEFAULT_ARGS} ) - - - ########### next target ############### - - set(kuiviewerpart_PART_SRCS kuiviewer_part.cpp ) - - ecm_qt_declare_logging_category(kuiviewerpart_PART_SRCS - HEADER kuiviewer_part_debug.h - IDENTIFIER KUIVIEWERPART - CATEGORY_NAME "kuiviewerpart" - ) - - add_library(kuiviewerpart MODULE ${kuiviewerpart_PART_SRCS}) - - target_link_libraries(kuiviewerpart KF5::Parts Qt5::Designer Qt5::UiTools) - - install(TARGETS kuiviewerpart DESTINATION ${KDE_INSTALL_PLUGINDIR} ) - - - ########### next target ############### - - set(quithumbnail_PART_SRCS quicreator.cpp ) - - add_library(quithumbnail MODULE ${quithumbnail_PART_SRCS}) - - target_link_libraries(quithumbnail - KF5::KIOWidgets - Qt5::Designer - Qt5::UiTools - ) - - install(TARGETS quithumbnail DESTINATION ${KDE_INSTALL_PLUGINDIR} ) - - - ########### install files ############### - - install( PROGRAMS org.kde.kuiviewer.desktop DESTINATION ${KDE_INSTALL_APPDIR} ) - install( FILES designerthumbnail.desktop kuiviewer_part.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR} ) - install( FILES kuiviewer_part.rc DESTINATION ${KDE_INSTALL_KXMLGUI5DIR}/kuiviewerpart ) - install( FILES kuiviewerui.rc DESTINATION ${KDE_INSTALL_KXMLGUI5DIR}/kuiviewer ) - - ecm_install_icons(ICONS - 16-apps-kuiviewer.png - 32-apps-kuiviewer.png - 48-apps-kuiviewer.png - 64-apps-kuiviewer.png - 128-apps-kuiviewer.png - sc-apps-kuiviewer.svg - DESTINATION ${KDE_INSTALL_ICONDIR} - THEME hicolor - ) diff --git a/kde/patch/kde-gtk-config.patch b/kde/patch/kde-gtk-config.patch deleted file mode 100644 index a62e649..0000000 --- a/kde/patch/kde-gtk-config.patch +++ /dev/null @@ -1,4 +0,0 @@ -# Make the kde-gtk-config load the current config first: -# Fixed in 5.11.2 -#cat $CWD/patch/kde-gtk-config/kde-gtk-config_loadcurrentsettings.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - diff --git a/kde/patch/kde-gtk-config/kde-gtk-config_loadcurrentsettings.patch b/kde/patch/kde-gtk-config/kde-gtk-config_loadcurrentsettings.patch deleted file mode 100644 index b5b074d..0000000 --- a/kde/patch/kde-gtk-config/kde-gtk-config_loadcurrentsettings.patch +++ /dev/null @@ -1,622 +0,0 @@ -From 0d0f812a1704c62c014bc87162b1280224b64f93 Mon Sep 17 00:00:00 2001 -From: Fabian Vogt <fabian@ritter-vogt.de> -Date: Tue, 24 Oct 2017 13:25:32 +0200 -Subject: Revert "Make the kde-gtk-config kcm better at checking global gtk - settings" - -Summary: -This reverts commit 34357f74ee2d98128ff423b0ec6ddcbf4232c475. - -Reverting this fixes loading of the actually used GTK settings. - -BUG: 382291 - -Test Plan: -Opened kcmshell5 kde-gtk-config with and without this revert. -Without, it shows Adwaita as theme, with it shows breeze. -GTK uses breeze, so the behaviour with the revert is correct. - -Reviewers: #plasma, apol - -Subscribers: plasma-devel - -Tags: #plasma - -Differential Revision: https://phabricator.kde.org/D8443 ---- - CMakeLists.txt | 2 +- - src/abstractappearance.h | 5 +- - src/appearancegtk2.cpp | 103 +++++++++++++--------------------- - src/appearancegtk2.h | 11 +--- - src/appearancegtk3.cpp | 143 +++++++++++++++++++++-------------------------- - src/appearancegtk3.h | 10 +--- - src/appearencegtk.cpp | 4 +- - tests/CMakeLists.txt | 2 +- - tests/configsavetest.cpp | 75 ++++++++++--------------- - tests/configsavetest.h | 8 +-- - 10 files changed, 144 insertions(+), 219 deletions(-) - -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 181cfc9..bf1ba29 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -51,7 +51,7 @@ ki18n_wrap_ui(kcm_SRCS - ) - add_library(kcm_kdegtkconfig MODULE ${kcm_SRCS}) - target_compile_definitions(kcm_kdegtkconfig PRIVATE -DPROJECT_VERSION="${PROJECT_VERSION}") --target_link_libraries(kcm_kdegtkconfig ${X11_Xcursor_LIB} KF5::ConfigCore KF5::I18n KF5::KIOWidgets KF5::NewStuff KF5::Archive KF5::NewStuff KF5::ConfigWidgets KF5::IconThemes) -+target_link_libraries(kcm_kdegtkconfig ${X11_Xcursor_LIB} KF5::I18n KF5::KIOWidgets KF5::NewStuff KF5::Archive KF5::NewStuff KF5::ConfigWidgets KF5::IconThemes) - - kcoreaddons_desktop_to_json(kcm_kdegtkconfig kde-gtk-config.desktop) - -diff --git a/src/abstractappearance.h b/src/abstractappearance.h -index 208342e..2961a09 100644 ---- a/src/abstractappearance.h -+++ b/src/abstractappearance.h -@@ -30,11 +30,10 @@ class AbstractAppearance - { - public: - virtual ~AbstractAppearance() {} -- virtual bool loadSettings() = 0; -- virtual bool saveSettings() const = 0; -+ virtual QString defaultConfigFile() const = 0; - virtual bool loadSettings(const QString& path) = 0; - virtual bool saveSettings(const QString& path) const = 0; -- -+ - /** @returns the installed themes' paths*/ - virtual QStringList installedThemes() const = 0; - -diff --git a/src/appearancegtk2.cpp b/src/appearancegtk2.cpp -index 92cbee3..44a2239 100644 ---- a/src/appearancegtk2.cpp -+++ b/src/appearancegtk2.cpp -@@ -30,38 +30,48 @@ - #include <QStandardPaths> - #include <config.h> - --bool AppearanceGTK2::loadSettingsPrivate(const QString& path) -+bool AppearanceGTK2::loadSettings(const QString& path) - { - QFile configFile(path); - -- if (!configFile.open(QIODevice::ReadOnly | QIODevice::Text)) -- return false; -+ bool canRead = configFile.open(QIODevice::ReadOnly | QIODevice::Text); - -- const QMap<QString, QString> foundSettings = readSettingsTuples(&configFile); -- -- for(auto it = foundSettings.constBegin(), itEnd = foundSettings.constEnd(); it!=itEnd; ++it) { -- if (it.key() == "gtk-theme-name") -- m_settings["theme"] = *it; -- else if (it.key() == "gtk-icon-theme-name") -- m_settings["icon"] = *it; -- else if (it.key() == "gtk-fallback-icon-theme") -- m_settings["icon_fallback"] = *it; -- else if (it.key() == "gtk-cursor-theme-name") -- m_settings["cursor"] = *it; -- else if (it.key() == "gtk-font-name") -- m_settings["font"] = *it; -- else if (it.key() == "gtk-toolbar-style") -- m_settings["toolbar_style"] = *it; -- else if (it.key() == "gtk-button-images") -- m_settings["show_icons_buttons"] = *it; -- else if(it.key() == "gtk-menu-images") -- m_settings["show_icons_menus"] = *it; -- else if (it.key() == "gtk-primary-button-warps-slider") -- m_settings["primary_button_warps_slider"] = *it; -- else -- qWarning() << "unknown field" << it.key(); -+ if(canRead) { -+// qDebug() << "The gtk2 config file exists..."; -+ const QMap<QString, QString> foundSettings = readSettingsTuples(&configFile); -+ m_settings = QMap<QString, QString> { -+ {"toolbar_style", "GTK_TOOLBAR_ICONS"}, -+ {"show_icons_buttons", "0"}, -+ {"show_icons_menus", "0"}, -+ {"primary_button_warps_slider", "false"} -+ }; -+ -+ for(auto it = foundSettings.constBegin(), itEnd = foundSettings.constEnd(); it!=itEnd; ++it) { -+ if (it.key() == "gtk-theme-name") -+ m_settings["theme"] = *it; -+ else if (it.key() == "gtk-icon-theme-name") -+ m_settings["icon"] = *it; -+ else if (it.key() == "gtk-fallback-icon-theme") -+ m_settings["icon_fallback"] = *it; -+ else if (it.key() == "gtk-cursor-theme-name") -+ m_settings["cursor"] = *it; -+ else if (it.key() == "gtk-font-name") -+ m_settings["font"] = *it; -+ else if (it.key() == "gtk-toolbar-style") -+ m_settings["toolbar_style"] = *it; -+ else if (it.key() == "gtk-button-images") -+ m_settings["show_icons_buttons"] = *it; -+ else if(it.key() == "gtk-menu-images") -+ m_settings["show_icons_menus"] = *it; -+ else if (it.key() == "gtk-primary-button-warps-slider") -+ m_settings["primary_button_warps_slider"] = *it; -+ else -+ qWarning() << "unknown field" << it.key(); -+ } -+ - } -- return true; -+ -+ return canRead; - } - - QString AppearanceGTK2::themesGtkrcFile(const QString& themeName) const -@@ -82,7 +92,7 @@ QString AppearanceGTK2::themesGtkrcFile(const QString& themeName) const - return QString(); - } - --bool AppearanceGTK2::saveSettingsPrivate(const QString& gtkrcFile) const -+bool AppearanceGTK2::saveSettings(const QString& gtkrcFile) const - { - QFile gtkrc(gtkrcFile); - gtkrc.remove(); -@@ -107,14 +117,14 @@ bool AppearanceGTK2::saveSettingsPrivate(const QString& gtkrcFile) const - flow << "include \"/etc/gtk-2.0/gtkrc\"\n"; //We include the /etc's config file - - int nameEnd = m_settings["font"].lastIndexOf(QRegExp(" ([0-9]+|bold|italic)")); -- const auto fontFamily = m_settings["font"].leftRef(nameEnd); -+ QString fontFamily = m_settings["font"].left(nameEnd); - - //TODO: is this really needed? - flow << "style \"user-font\" \n" - << "{\n" - << "\tfont_name=\""<< fontFamily << "\"\n" - << "}\n"; -- -+ - flow << "widget_class \"*\" style \"user-font\"\n"; - flow << "gtk-font-name=\"" << m_settings["font"] << "\"\n"; - flow << "gtk-theme-name=\"" << m_settings["theme"] << "\"\n"; -@@ -144,16 +154,6 @@ bool AppearanceGTK2::saveSettingsPrivate(const QString& gtkrcFile) const - return true; - } - --void AppearanceGTK2::reset() --{ -- m_settings = QMap<QString, QString> { -- {"toolbar_style", "GTK_TOOLBAR_ICONS"}, -- {"show_icons_buttons", "0"}, -- {"show_icons_menus", "0"}, -- {"primary_button_warps_slider", "false"} -- }; --} -- - QString AppearanceGTK2::defaultConfigFile() const - { - return QDir::homePath()+"/.gtkrc-2.0"; -@@ -183,26 +183,3 @@ QStringList AppearanceGTK2::installedThemes() const - - return paths; - } -- --bool AppearanceGTK2::loadSettings() --{ -- reset(); -- -- return loadSettingsPrivate("/etc/gtk-2.0/gtkrc") && loadSettingsPrivate(defaultConfigFile()); --} -- --bool AppearanceGTK2::saveSettings() const --{ -- return saveSettings(defaultConfigFile()); --} -- --bool AppearanceGTK2::loadSettings(const QString& gtkrcFile) --{ -- reset(); -- return loadSettingsPrivate(gtkrcFile); --} -- --bool AppearanceGTK2::saveSettings(const QString& gtkrcFile) const --{ -- return saveSettingsPrivate(gtkrcFile); --} -diff --git a/src/appearancegtk2.h b/src/appearancegtk2.h -index 7df49bf..8bc28ee 100644 ---- a/src/appearancegtk2.h -+++ b/src/appearancegtk2.h -@@ -29,17 +29,10 @@ class AppearanceGTK2 : public AbstractAppearance - { - bool loadSettings(const QString& path) override; - bool saveSettings(const QString& path) const override; -- bool loadSettings() override; -- bool saveSettings() const override; -+ QString defaultConfigFile() const override; - QStringList installedThemes() const override; -- -+ - QString themesGtkrcFile(const QString& themeName) const; -- --private: -- void reset(); -- QString defaultConfigFile() const; -- bool loadSettingsPrivate(const QString& path); -- bool saveSettingsPrivate(const QString& path) const; - }; - - #endif // APPEARANCEGTK2_H -diff --git a/src/appearancegtk3.cpp b/src/appearancegtk3.cpp -index 7df48c3..fa1bde5 100644 ---- a/src/appearancegtk3.cpp -+++ b/src/appearancegtk3.cpp -@@ -25,8 +25,6 @@ - #include <QDir> - #include <QDebug> - #include <QStandardPaths> --#include <KSharedConfig> --#include <KConfigGroup> - - QStringList AppearanceGTK3::installedThemes() const - { -@@ -53,65 +51,76 @@ QStringList AppearanceGTK3::installedThemes() const - return themes; - } - --bool AppearanceGTK3::saveSettings(const KSharedConfig::Ptr& file) const --{ -- KConfigGroup group(file, "Settings"); -- -- group.writeEntry("gtk-font-name", m_settings["font"]); -- group.writeEntry("gtk-theme-name", m_settings["theme"]); -- group.writeEntry("gtk-icon-theme-name", m_settings["icon"]); -- group.writeEntry("gtk-fallback-icon-theme", m_settings["icon_fallback"]); -- group.writeEntry("gtk-cursor-theme-name", m_settings["cursor"]); -- group.writeEntry("gtk-toolbar-style", m_settings["toolbar_style"]); -- group.writeEntry("gtk-menu-images", m_settings["show_icons_menus"]); -- group.writeEntry("gtk-button-images", m_settings["show_icons_buttons"]); -- group.writeEntry("gtk-primary-button-warps-slider", m_settings["primary_button_warps_slider"]); -- group.writeEntry("gtk-application-prefer-dark-theme", m_settings["application_prefer_dark_theme"]); -- -- const bool sync = group.sync(); -- Q_ASSERT(sync); -- return true; --} -- --bool AppearanceGTK3::loadSettings(const KSharedConfig::Ptr& file) -+bool AppearanceGTK3::saveSettings(const QString& file) const - { -- KConfigGroup group(file, "Settings"); -- -- if (!file || !group.isValid()) { -- qWarning() << "Cannot open the GTK3 config file" << file; -+ //Opening GTK3 config file $ENV{XDG_CONFIG_HOME}/gtk-3.0/m_settings.ini -+ QDir::home().mkpath(file.left(file.lastIndexOf('/'))); //we make sure the path exists -+ QFile file_gtk3(file); -+ -+ if(!file_gtk3.open(QIODevice::WriteOnly | QIODevice::Text)) { -+ qWarning() << "Couldn't open GTK3 config file for writing at:" << file_gtk3.fileName(); - return false; - } -+ QTextStream flow3(&file_gtk3); -+ flow3 << "[Settings]\n"; -+ flow3 << "gtk-font-name=" << m_settings["font"] << "\n"; -+ flow3 << "gtk-theme-name=" << m_settings["theme"] << "\n"; -+ flow3 << "gtk-icon-theme-name="<< m_settings["icon"] << "\n"; -+ flow3 << "gtk-fallback-icon-theme=" << m_settings["icon_fallback"] << "\n"; -+ flow3 << "gtk-cursor-theme-name=" << m_settings["cursor"] << "\n"; -+ flow3 << "gtk-toolbar-style=" << m_settings["toolbar_style"] << "\n"; -+ flow3 << "gtk-menu-images=" << m_settings["show_icons_menus"] << "\n"; -+ flow3 << "gtk-button-images=" << m_settings["show_icons_buttons"] << "\n"; -+ flow3 << "gtk-primary-button-warps-slider=" << m_settings["primary_button_warps_slider"] << "\n"; -+ flow3 << "gtk-application-prefer-dark-theme=" << m_settings["application_prefer_dark_theme"] << "\n"; - -- m_settings = QMap<QString, QString> { -- {"toolbar_style", "GTK_TOOLBAR_ICONS"}, -- {"show_icons_buttons", "0"}, -- {"show_icons_menus", "0"}, -- {"primary_button_warps_slider", "false"}, -- {"application_prefer_dark_theme", "false"} -- }; -- -- m_settings["theme"] = group.readEntry("gtk-theme-name"); -- m_settings["icon"] = group.readEntry("gtk-icon-theme-name"); -- m_settings["icon_fallback"] = group.readEntry("gtk-fallback-icon-theme"); -- m_settings["cursor"] = group.readEntry("gtk-cursor-theme-name"); -- m_settings["font"] = group.readEntry("gtk-font-name"); -- m_settings["toolbar_style"] = group.readEntry("gtk-toolbar-style"); -- m_settings["show_icons_buttons"] = group.readEntry("gtk-button-images"); -- m_settings["show_icons_menus"] = group.readEntry("gtk-menu-images"); -- m_settings["primary_button_warps_slider"] = group.readEntry("gtk-primary-button-warps-slider"); -- m_settings["application_prefer_dark_theme"] = group.readEntry("gtk-application-prefer-dark-theme"); -- for(auto it = m_settings.begin(); it != m_settings.end(); ) { -- if (it.value().isEmpty()) -- it = m_settings.erase(it); -- else -- ++it; -- } - return true; - } - --QString AppearanceGTK3::configFileName() const -+bool AppearanceGTK3::loadSettings(const QString& path) - { -- return QStringLiteral("gtk-3.0/settings.ini"); -+ QFile fileGtk3(path); -+ bool canRead=fileGtk3.open(QIODevice::ReadOnly | QIODevice::Text); -+ -+ if(canRead) { -+ const QMap<QString, QString> foundSettings = readSettingsTuples(&fileGtk3); -+ -+ m_settings = QMap<QString, QString> { -+ {"toolbar_style", "GTK_TOOLBAR_ICONS"}, -+ {"show_icons_buttons", "0"}, -+ {"show_icons_menus", "0"}, -+ {"primary_button_warps_slider", "false"}, -+ {"application_prefer_dark_theme", "false"} -+ }; -+ -+ for(auto it = foundSettings.constBegin(), itEnd = foundSettings.constEnd(); it!=itEnd; ++it) { -+ if (it.key() == "gtk-theme-name") -+ m_settings["theme"] = *it; -+ else if (it.key() == "gtk-icon-theme-name") -+ m_settings["icon"] = *it; -+ else if (it.key() == "gtk-fallback-icon-theme") -+ m_settings["icon_fallback"] = *it; -+ else if (it.key() == "gtk-cursor-theme-name") -+ m_settings["cursor"] = *it; -+ else if (it.key() == "gtk-font-name") -+ m_settings["font"] = *it; -+ else if (it.key() == "gtk-toolbar-style") -+ m_settings["toolbar_style"] = *it; -+ else if (it.key() == "gtk-button-images") -+ m_settings["show_icons_buttons"] = *it; -+ else if (it.key() == "gtk-menu-images") -+ m_settings["show_icons_menus"] = *it; -+ else if (it.key() == "gtk-primary-button-warps-slider") -+ m_settings["primary_button_warps_slider"] = *it; -+ else if (it.key() == "gtk-application-prefer-dark-theme") -+ m_settings["application_prefer_dark_theme"] = *it; -+ else -+ qWarning() << "unknown field" << it.key(); -+ } -+ } else -+ qWarning() << "Cannot open the GTK3 config file" << path; -+ -+ return canRead; - } - - QString AppearanceGTK3::defaultConfigFile() const -@@ -120,7 +129,7 @@ QString AppearanceGTK3::defaultConfigFile() const - if(root.isEmpty()) - root = QFileInfo(QDir::home(), ".config").absoluteFilePath(); - -- return root + '/' + configFileName(); -+ return root+"/gtk-3.0/settings.ini"; - } - - bool AppearanceGTK3::getApplicationPreferDarkTheme() const -@@ -132,29 +141,3 @@ void AppearanceGTK3::setApplicationPreferDarkTheme(const bool& enable) - { - m_settings["application_prefer_dark_theme"] = enable ? "true" : "false"; - } -- --bool AppearanceGTK3::saveSettings(const QString& file) const --{ -- auto cfg = KSharedConfig::openConfig(file); -- return saveSettings(cfg); --} -- --bool AppearanceGTK3::loadSettings(const QString& path) --{ -- auto cfg = KSharedConfig::openConfig(path); -- return loadSettings(cfg); --} -- --bool AppearanceGTK3::loadSettings() --{ -- auto cfg = KSharedConfig::openConfig(configFileName()); -- cfg->setReadDefaults(true); -- return loadSettings(cfg); --} -- --bool AppearanceGTK3::saveSettings() const --{ -- auto cfg = KSharedConfig::openConfig(configFileName()); -- cfg->setReadDefaults(true); -- return saveSettings(cfg); --} -diff --git a/src/appearancegtk3.h b/src/appearancegtk3.h -index 3ce5a05..d4562b1 100644 ---- a/src/appearancegtk3.h -+++ b/src/appearancegtk3.h -@@ -23,7 +23,6 @@ - #ifndef APPEARANCEGTK3_H - #define APPEARANCEGTK3_H - --#include <KSharedConfig> - #include "abstractappearance.h" - - class AppearanceGTK3 : public AbstractAppearance -@@ -31,18 +30,11 @@ class AppearanceGTK3 : public AbstractAppearance - - public: - QStringList installedThemes() const override; -- bool saveSettings() const override; -- bool loadSettings() override; - bool saveSettings(const QString& file) const override; - bool loadSettings(const QString& path) override; -+ QString defaultConfigFile() const override; - bool getApplicationPreferDarkTheme() const; - void setApplicationPreferDarkTheme(const bool& enable); -- --private: -- QString defaultConfigFile() const; -- QString configFileName() const; -- bool saveSettings(const KSharedConfig::Ptr& file) const; -- bool loadSettings(const KSharedConfig::Ptr& file); - }; - - #endif // APPEARANCEGTK3_H -diff --git a/src/appearencegtk.cpp b/src/appearencegtk.cpp -index 95a6604..2e26a5a 100644 ---- a/src/appearencegtk.cpp -+++ b/src/appearencegtk.cpp -@@ -64,7 +64,7 @@ bool AppearenceGTK::loadFileConfig() - { - bool correct = false; - foreach(AbstractAppearance* app, m_app) { -- bool c = app->loadSettings(); -+ bool c = app->loadSettings(app->defaultConfigFile()); - correct = correct || c; - } - // qDebug() << "loading..." << correct; -@@ -75,7 +75,7 @@ bool AppearenceGTK::saveFileConfig() - { - bool correct = true; - foreach(AbstractAppearance* app, m_app) { -- bool c = app->saveSettings(); -+ bool c = app->saveSettings(app->defaultConfigFile()); - correct = correct && c; - } - // qDebug() << "saving..." << correct; -diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt -index 151725d..05bf8f1 100644 ---- a/tests/CMakeLists.txt -+++ b/tests/CMakeLists.txt -@@ -2,7 +2,7 @@ macro(add_kgc_test name) - add_executable(${name} ${name}.cpp ${ARGV}) - add_test(${name} ${name}) - ecm_mark_as_test(${name}) -- target_link_libraries(${name} Qt5::Core Qt5::Gui Qt5::Test KF5::ConfigCore) -+ target_link_libraries(${name} Qt5::Core Qt5::Gui Qt5::Test) - target_include_directories(${name} PRIVATE ${CMAKE_BINARY_DIR}) - endmacro(add_kgc_test) - -diff --git a/tests/configsavetest.cpp b/tests/configsavetest.cpp -index 1fe8f4f..d5d8460 100644 ---- a/tests/configsavetest.cpp -+++ b/tests/configsavetest.cpp -@@ -9,40 +9,33 @@ - - QTEST_GUILESS_MAIN(ConfigSaveTest); - --ConfigSaveTest::ConfigSaveTest() --{ -- QStandardPaths::setTestModeEnabled(true); --} -- --static void fillValues(QScopedPointer<AbstractAppearance>& a) -+void ConfigSaveTest::fillValues(AbstractAppearance* a) - { - a->setFont("a"); - a->setIcon("a"); - a->setTheme("a"); - a->setToolbarStyle("a"); - a->setIconFallback("a"); -- a->setCursor("a"); - a->setShowIconsInButtons(true); - a->setShowIconsInMenus(true); - a->setPrimaryButtonWarpsSlider(true); - -- auto a3 = dynamic_cast<AppearanceGTK3*>(a.data()); -+ auto a3 = dynamic_cast<AppearanceGTK3*>(a); - if (a3) { - a3->setApplicationPreferDarkTheme(false); - } - } - --void compareAppearances(QScopedPointer<AbstractAppearance>& reloaded, QScopedPointer<AbstractAppearance>& instance) -+bool compareAppearances(AbstractAppearance* a, AbstractAppearance* b) - { -- QCOMPARE(reloaded->getFont(), instance->getFont()); -- QCOMPARE(reloaded->getIcon(), instance->getIcon()); -- QCOMPARE(reloaded->getTheme(), instance->getTheme()); -- QCOMPARE(reloaded->getCursor(), instance->getCursor()); -- QCOMPARE(reloaded->getToolbarStyle(), instance->getToolbarStyle()); -- QCOMPARE(reloaded->getIconFallback(), instance->getIconFallback()); -- QCOMPARE(reloaded->getShowIconsInButtons(), instance->getShowIconsInButtons()); -- QCOMPARE(reloaded->getShowIconsInMenus(), instance->getShowIconsInMenus()); -- QCOMPARE(reloaded->getPrimaryButtonWarpsSlider(), instance->getPrimaryButtonWarpsSlider()); -+ return a->getFont() == b->getFont() -+ && a->getIcon() == b->getIcon() -+ && a->getTheme() == b->getTheme() -+ && a->getToolbarStyle() == b->getToolbarStyle() -+ && a->getIconFallback() == b->getIconFallback() -+ && a->getShowIconsInButtons() == b->getShowIconsInButtons() -+ && a->getShowIconsInMenus() == b->getShowIconsInMenus() -+ && a->getPrimaryButtonWarpsSlider() == b->getPrimaryButtonWarpsSlider(); - } - - QByteArray readFile(const QString& path) -@@ -53,35 +46,23 @@ QByteArray readFile(const QString& path) - return f.readAll(); - } - --void ConfigSaveTest::testGtk2() -+void ConfigSaveTest::testOpen() - { -- const QString pathA = QDir::current().absoluteFilePath("test-gtk2") -- , pathB = QDir::current().absoluteFilePath("testB-gtk2"); -- -- QScopedPointer<AbstractAppearance> instance(new AppearanceGTK2); -- fillValues(instance); -- QVERIFY(instance->saveSettings(pathA)); -- -- QScopedPointer<AbstractAppearance> reloaded(new AppearanceGTK2); -- QVERIFY(reloaded->loadSettings(pathA)); -- compareAppearances(reloaded, instance); -- QVERIFY(reloaded->saveSettings(pathB)); -- QCOMPARE(readFile(pathA), readFile(pathB)); --} -- --void ConfigSaveTest::testGtk3() --{ -- QScopedPointer<AbstractAppearance> instance(new AppearanceGTK3); -- fillValues(instance); -- const QString pathA = QDir::current().absoluteFilePath("test-gtk3") -- , pathB = QDir::current().absoluteFilePath("testB-gtk3"); -- QVERIFY(instance->saveSettings(pathA)); -- -- QScopedPointer<AbstractAppearance> reloaded(new AppearanceGTK3); -- QVERIFY(QFile::exists(pathA)); -- QVERIFY(reloaded->loadSettings(pathA)); -- compareAppearances(reloaded, instance); -- QVERIFY(reloaded->saveSettings(pathB)); -+ QVector<AbstractAppearance*> instances; -+ instances << new AppearanceGTK2 << new AppearanceGTK3; -+ fillValues(instances[0]); -+ fillValues(instances[1]); -+ QVERIFY(instances[0]->saveSettings("test-gtk2")); -+ QVERIFY(instances[1]->saveSettings("test-gtk3")); - -- QCOMPARE(readFile(pathA), readFile(pathB)); -+ QVector<AbstractAppearance*> reloaded; -+ reloaded << new AppearanceGTK2 << new AppearanceGTK3; -+ QVERIFY(reloaded[0]->loadSettings("test-gtk2")); -+ QVERIFY(reloaded[1]->loadSettings("test-gtk3")); -+ QVERIFY(compareAppearances(reloaded[0], instances[0])); -+ QVERIFY(compareAppearances(reloaded[1], instances[1])); -+ QVERIFY(reloaded[0]->saveSettings("testB-gtk2")); -+ QVERIFY(reloaded[1]->saveSettings("testB-gtk3")); -+ QCOMPARE(readFile("test-gtk2"), readFile("testB-gtk2")); -+ QCOMPARE(readFile("test-gtk3"), readFile("testB-gtk3")); - } -diff --git a/tests/configsavetest.h b/tests/configsavetest.h -index 342b408..39fb4c2 100644 ---- a/tests/configsavetest.h -+++ b/tests/configsavetest.h -@@ -11,11 +11,11 @@ class AbstractAppearance; - class ConfigSaveTest : public QObject - { - Q_OBJECT --public: -- ConfigSaveTest(); - private slots: -- void testGtk2(); -- void testGtk3(); -+ void testOpen(); -+ -+private: -+ void fillValues(AbstractAppearance* a); - }; - - #endif // CONFIGSAVETEST_H --- -cgit v0.11.2 - diff --git a/kde/patch/kde-runtime.patch b/kde/patch/kde-runtime.patch index c3b6101..3201d76 100644 --- a/kde/patch/kde-runtime.patch +++ b/kde/patch/kde-runtime.patch @@ -1,10 +1,2 @@ -# Fix KDE bug 324470 - solved in KDE 4.11.2. -# - Minimize/maximize by clicking taskbar entries requires double click. -#cat $CWD/patch/kde-runtime/kde-runtime.kdebug324470.diff | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - # Fix compilation against NetworkManager 1.0.6: cat $CWD/patch/kde-runtime/kde-runtime_networkmanager.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - -## Fix compilation against gpgme 1.7+: -#cat $CWD/patch/kde-runtime/kde-runtime_gpgme.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - diff --git a/kde/patch/kde-runtime/kde-runtime.kdebug324470.diff b/kde/patch/kde-runtime/kde-runtime.kdebug324470.diff deleted file mode 100644 index 4269df8..0000000 --- a/kde/patch/kde-runtime/kde-runtime.kdebug324470.diff +++ /dev/null @@ -1,49 +0,0 @@ -commit be1a5d484c70f4f6a383150810afbfbb367db2ac -Author: Eike Hein <hein@kde.org> -Date: Tue Sep 3 20:29:23 2013 +0200 - - Discard the recorded events in the item-local handlers. - - Solves problems with identical events being ignored due to - QGraphicsView's reuse of QGraphicsSceneMouseEvent instances. - - CCMAIL:rdieter@fedoraproject.org - BUG:324470 - BUG:324471 - -diff --git a/plasma/declarativeimports/qtextracomponents/mouseeventlistener.cpp b/plasma/declarativeimports/qtextracomponents/mouseeventlistener.cpp -index b534845..36530e0 100644 ---- a/plasma/declarativeimports/qtextracomponents/mouseeventlistener.cpp -+++ b/plasma/declarativeimports/qtextracomponents/mouseeventlistener.cpp -@@ -90,6 +90,7 @@ bool MouseEventListener::containsMouse() const - void MouseEventListener::mousePressEvent(QGraphicsSceneMouseEvent *me) - { - if (m_lastEvent == me) { -+ m_lastEvent = 0; - return; - } - -@@ -112,6 +113,7 @@ void MouseEventListener::mousePressEvent(QGraphicsSceneMouseEvent *me) - void MouseEventListener::mouseMoveEvent(QGraphicsSceneMouseEvent *me) - { - if (m_lastEvent == me) { -+ m_lastEvent = 0; - return; - } - -@@ -122,6 +124,7 @@ void MouseEventListener::mouseMoveEvent(QGraphicsSceneMouseEvent *me) - void MouseEventListener::mouseReleaseEvent(QGraphicsSceneMouseEvent *me) - { - if (m_lastEvent == me) { -+ m_lastEvent = 0; - return; - } - -@@ -138,6 +141,7 @@ void MouseEventListener::mouseReleaseEvent(QGraphicsSceneMouseEvent *me) - void MouseEventListener::wheelEvent(QGraphicsSceneWheelEvent *we) - { - if (m_lastEvent == we) { -+ m_lastEvent = 0; - return; - } - diff --git a/kde/patch/kde-runtime/kde-runtime_gpgme.patch b/kde/patch/kde-runtime/kde-runtime_gpgme.patch deleted file mode 100644 index b1703ed..0000000 --- a/kde/patch/kde-runtime/kde-runtime_gpgme.patch +++ /dev/null @@ -1,133 +0,0 @@ -commit 1b80d1d0b961f8e28186928ede2b87af292c3de4 -Author: Antonio Rojas <arojas@archlinux.org> -Date: Thu Nov 10 16:58:10 2016 +0100 - - Allow building kwalletd against gpgme++ from gpgme 1.7 - - REVIEW: 129339 - -diff --git a/kwalletd/CMakeLists.txt b/kwalletd/CMakeLists.txt -index 73aec82..ae8c745 100644 ---- a/kwalletd/CMakeLists.txt -+++ b/kwalletd/CMakeLists.txt -@@ -5,11 +5,18 @@ find_package(Gpgme) # Called by FindQGpgme, but since we call some gpgme - # functions ourselves we need to link against it directly. - find_package(QGpgme) # provided by kdepimlibs - --if (GPGME_FOUND AND QGPGME_FOUND) -+if (NOT QGPGME_FOUND) -+find_package(Gpgmepp) # provided by gpgme 1.7 -+endif (NOT QGPGME_FOUND) -+ -+if ((GPGME_FOUND AND QGPGME_FOUND) OR Gpgmepp_FOUND) - add_definitions(-DHAVE_QGPGME) -- include_directories(${GPGME_INCLUDES} ${QGPGME_INCLUDE_DIR}) -+ include_directories(${GPGME_INCLUDES}) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KDE4_ENABLE_EXCEPTIONS}") --endif(GPGME_FOUND AND QGPGME_FOUND) -+endif((GPGME_FOUND AND QGPGME_FOUND) OR Gpgmepp_FOUND) -+if (GPGME_FOUND AND QGPGME_FOUND) -+ include_directories(${QGPGME_INCLUDE_DIR}) -+endif (GPGME_FOUND AND QGPGME_FOUND) - - ########### build backends ######### - add_subdirectory(backend) -@@ -37,7 +44,7 @@ kde4_add_ui_files(kwalletd_KDEINIT_SRCS - kwalletwizardpagepassword.ui - ) - --if (GPGME_FOUND AND QGPGME_FOUND) -+if ((GPGME_FOUND AND QGPGME_FOUND) OR Gpgmepp_FOUND) - set(kwalletd_KDEINIT_SRCS - ${kwalletd_KDEINIT_SRCS} - knewwalletdialog.cpp -@@ -48,7 +55,7 @@ if (GPGME_FOUND AND QGPGME_FOUND) - knewwalletdialogintro.ui - knewwalletdialoggpg.ui - ) --endif(GPGME_FOUND AND QGPGME_FOUND) -+endif((GPGME_FOUND AND QGPGME_FOUND) OR Gpgmepp_FOUND) - - find_file(kwallet_xml org.kde.KWallet.xml HINTS ${KDE4_DBUS_INTERFACES_DIR} ) - -@@ -57,8 +64,12 @@ qt4_add_dbus_adaptor( kwalletd_KDEINIT_SRCS ${kwallet_xml} kwalletd.h KWalletD ) - kde4_add_kdeinit_executable( kwalletd NOGUI ${kwalletd_KDEINIT_SRCS} ) - - target_link_libraries(kdeinit_kwalletd ${KDE4_KDEUI_LIBS} kwalletbackend ) --if (GPGME_FOUND AND QGPGME_FOUND) -- target_link_libraries(kdeinit_kwalletd ${QGPGME_LIBRARIES} ) -+if(GPGME_FOUND AND QGPGME_FOUND) -+target_link_libraries(kdeinit_kwalletd ${QGPGME_LIBRARIES} ) -+else(GPGME_FOUND AND QGPGME_FOUND) -+if(Gpgmepp_FOUND) -+target_link_libraries(kdeinit_kwalletd Gpgmepp) -+endif(Gpgmepp_FOUND) - endif(GPGME_FOUND AND QGPGME_FOUND) - - install(TARGETS kdeinit_kwalletd ${INSTALL_TARGETS_DEFAULT_ARGS}) -@@ -73,4 +84,4 @@ install( FILES kwalletd.notifyrc DESTINATION ${DATA_INSTALL_DIR}/kwalletd ) - install( FILES kwallet-4.13.upd DESTINATION ${DATA_INSTALL_DIR}/kconf_update) - - add_subdirectory(tests) --add_subdirectory(autotests) -\ No newline at end of file -+add_subdirectory(autotests) -diff --git a/kwalletd/backend/CMakeLists.txt b/kwalletd/backend/CMakeLists.txt -index 4db348f..7347b12 100644 ---- a/kwalletd/backend/CMakeLists.txt -+++ b/kwalletd/backend/CMakeLists.txt -@@ -22,6 +22,10 @@ kde4_add_library(kwalletbackend SHARED ${kwalletbackend_LIB_SRCS}) - target_link_libraries(kwalletbackend ${KDE4_KDEUI_LIBS} ${LIBGCRYPT_LIBRARIES}) - if(QGPGME_FOUND) - target_link_libraries(kwalletbackend ${QGPGME_LIBRARIES} ) -+else(QGPGME_FOUND) -+if(Gpgmepp_FOUND) -+target_link_libraries(kwalletbackend Gpgmepp) -+endif(Gpgmepp_FOUND) - endif(QGPGME_FOUND) - - # link with advapi32 on windows -diff --git a/kwalletd/backend/backendpersisthandler.cpp b/kwalletd/backend/backendpersisthandler.cpp -index b7f63f8..9608af0 100644 ---- a/kwalletd/backend/backendpersisthandler.cpp -+++ b/kwalletd/backend/backendpersisthandler.cpp -@@ -33,6 +33,7 @@ - #include <gpgme++/data.h> - #include <gpgme++/encryptionresult.h> - #include <gpgme++/decryptionresult.h> -+#include <boost/shared_ptr.hpp> - #endif - #include "backendpersisthandler.h" - #include "kwalletbackend.h" -diff --git a/kwalletd/kwalletwizard.cpp b/kwalletd/kwalletwizard.cpp -index 78de78d..821b666 100644 ---- a/kwalletd/kwalletwizard.cpp -+++ b/kwalletd/kwalletwizard.cpp -@@ -40,6 +40,7 @@ - #include <kdebug.h> - #include <kmessagebox.h> - #include <gpgme.h> -+#include <boost/shared_ptr.hpp> - #endif - - class PageIntro : public QWizardPage -commit cf28801cd34730da07a2c01704ca3114630f4fe7 -Author: Antonio Rojas <arojas@archlinux.org> -Date: Thu Nov 10 18:54:41 2016 +0100 - - Compiling against gmgpe 1.7 requires c++11 - -diff --git a/kwalletd/CMakeLists.txt b/kwalletd/CMakeLists.txt -index ae8c745..88d944e 100644 ---- a/kwalletd/CMakeLists.txt -+++ b/kwalletd/CMakeLists.txt -@@ -17,6 +17,9 @@ endif((GPGME_FOUND AND QGPGME_FOUND) OR Gpgmepp_FOUND) - if (GPGME_FOUND AND QGPGME_FOUND) - include_directories(${QGPGME_INCLUDE_DIR}) - endif (GPGME_FOUND AND QGPGME_FOUND) -+if (Gpgmepp_FOUND) -+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") -+endif (Gpgmepp_FOUND) - - ########### build backends ######### - add_subdirectory(backend) diff --git a/kde/patch/kde-workspace.patch b/kde/patch/kde-workspace.patch index 4a355d1..bebecfe 100644 --- a/kde/patch/kde-workspace.patch +++ b/kde/patch/kde-workspace.patch @@ -4,9 +4,5 @@ cat $CWD/patch/kde-workspace/kde-workspace.kdm.server.timeout.diff | patch -p1 - # Always show 'remaining time' in the popup of the battery plasmoid: cat $CWD/patch/kde-workspace/kde-workspace.batteryapplet.diff | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } -# Fix crash when DesktopNames isn't set (fixed in 4.11.10): -#cat $CWD/patch/kde-workspace/kde-workspace.desktopnames.diff | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - # In Plasma 5 we do not need the Plasma 4 core apps, they conflict. cat $CWD/patch/kde-workspace/kde-workspace.no.plasma4.diff | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - diff --git a/kde/patch/kde-workspace/kde-workspace.desktopnames.diff b/kde/patch/kde-workspace/kde-workspace.desktopnames.diff deleted file mode 100644 index 59aef1c..0000000 --- a/kde/patch/kde-workspace/kde-workspace.desktopnames.diff +++ /dev/null @@ -1,34 +0,0 @@ -commit e1724800ecf3c6a7035dfa7bcaa50b2a8f48688f -Author: David Faure <faure@kde.org> -Date: Fri May 2 10:26:38 2014 +0200 - - Fix crash when DesktopNames isn't set - - BUG: 334159 - FIXED-IN: 4.11.10 - -diff --git a/kdm/backend/client.c b/kdm/backend/client.c -index 335cc3e..a2d06c2 100644 ---- a/kdm/backend/client.c -+++ b/kdm/backend/client.c -@@ -1810,12 +1810,14 @@ startClient(volatile int *pid) - !(sessargs = iniEntry(str, "Desktop Entry", "Exec", 0))) - sessargs = ""; - buf = iniEntry(str, "Desktop Entry", "DesktopNames", 0); -- for (buf2 = buf; *buf2; ++buf2) { -- if (*buf2 == ';') -- *buf2 = ':'; -+ if (buf) { -+ for (buf2 = buf; *buf2; ++buf2) { -+ if (*buf2 == ';') -+ *buf2 = ':'; -+ } -+ userEnviron = setEnv(userEnviron, "XDG_CURRENT_DESKTOP", buf); -+ free(buf); - } -- userEnviron = setEnv(userEnviron, "XDG_CURRENT_DESKTOP", buf); -- free(buf); - free(str); - free(fname); - goto gotit; - diff --git a/kde/patch/kdeconnect-kde.patch b/kde/patch/kdeconnect-kde.patch index 47f98f5..122440d 100644 --- a/kde/patch/kdeconnect-kde.patch +++ b/kde/patch/kdeconnect-kde.patch @@ -1,3 +1,2 @@ # Fix remote device browsing with openssh 8.2: cat $CWD/patch/kdeconnect-kde/kdeconnect-kde_openssh-8.2.diff | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - diff --git a/kde/patch/kdelibs4support.patch b/kde/patch/kdelibs4support.patch index 8e9fe7b..7d6626e 100644 --- a/kde/patch/kdelibs4support.patch +++ b/kde/patch/kdelibs4support.patch @@ -1,6 +1,2 @@ -# Make FindGettext compatible with the one provided by CMake: -# Fixed in 5.1.0. -#cat $CWD/patch/kdelibs4support/update-FindGettext.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - # Allow cmake to find our doctools: cat $CWD/patch/kdelibs4support/FindDocBookXML4.cmake.diff | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } diff --git a/kde/patch/kdelibs4support/update-FindGettext.patch b/kde/patch/kdelibs4support/update-FindGettext.patch deleted file mode 100644 index 1b75cd8..0000000 --- a/kde/patch/kdelibs4support/update-FindGettext.patch +++ /dev/null @@ -1,36 +0,0 @@ -From: Alex Merry <alex.merry@kde.org> -Date: Fri, 04 Jul 2014 10:10:27 +0000 -Subject: Make FindGettext compatible with the one provided by CMake -X-Git-Url: http://quickgit.kde.org/?p=kdelibs4support.git&a=commitdiff&h=581ee6b370d8b5627196c8d6d8760d3655f6daea ---- -Make FindGettext compatible with the one provided by CMake - -This version will accept the old GETTEXT_PROCESS_PO_FILES() syntax (no -PO_FILES argument), but will also accept the new syntax required by -CMake's version of this file. It will also warn when PO_FILES is not -given. - -REVIEW: 119111 ---- - - ---- a/cmake/modules/FindGettext.cmake -+++ b/cmake/modules/FindGettext.cmake -@@ -212,7 +212,16 @@ - LIST(REMOVE_AT _args 0 1) - ENDIF("${_tmp}" STREQUAL "INSTALL_DESTINATION") - --# message(STATUS "2 all ${_addToAll} dest ${_installDest} args: ${_args}") -+ LIST(GET _args 0 _tmp) -+ IF("${_tmp}" STREQUAL "PO_FILES") -+ LIST(REMOVE_AT _args 0) -+ ELSE() -+ SET(_deprecation_arg DEPRECATION) -+ IF(CMAKE_VERSION VERSION_LESS 3.0.0) -+ SET(_deprecation_arg AUTHOR_WARNING) -+ ENDIF() -+ MESSAGE(${_deprecation_arg} "GETTEXT_PROCESS_PO_FILES without a PO_FILES argument is deprecated") -+ ENDIF() - - FOREACH(_current_PO_FILE ${_args}) - GET_FILENAME_COMPONENT(_name ${_current_PO_FILE} NAME) diff --git a/kde/patch/kdenlive.patch b/kde/patch/kdenlive.patch deleted file mode 100644 index 9065c4d..0000000 --- a/kde/patch/kdenlive.patch +++ /dev/null @@ -1,4 +0,0 @@ -# Fix compilation with gcc7. -# Should have been fixed in 17.04.2... -#cat $CWD/patch/kdenlive/kdenlive_gcc7.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - diff --git a/kde/patch/kdenlive/kdenlive_gcc7.patch b/kde/patch/kdenlive/kdenlive_gcc7.patch deleted file mode 100644 index a7ddb90..0000000 --- a/kde/patch/kdenlive/kdenlive_gcc7.patch +++ /dev/null @@ -1,32 +0,0 @@ -# Make kdenlive compile with gcc7 - ---- kdenlive-17.04.1/src/profiles/tree/profiletreemodel.cpp.orig 2017-05-08 19:52:35.000000000 +0200 -+++ kdenlive-17.04.1/src/profiles/tree/profiletreemodel.cpp 2017-05-19 08:09:04.986909338 +0200 -@@ -27,6 +27,7 @@ - #include <QVector> - #include <array> - #include <KLocalizedString> -+#include <functional> - - - class ProfileItem ---- kdenlive-17.04.1/src/scopes/audioscopes/spectrogram.cpp.orig 2017-05-08 19:52:35.000000000 +0200 -+++ kdenlive-17.04.1/src/scopes/audioscopes/spectrogram.cpp 2017-05-19 08:09:04.993910503 +0200 -@@ -241,7 +241,7 @@ - x = leftDist + (m_innerScopeRect.width() - 1) * ((float)hz) / m_freqMax; - - // Hide text if it would overlap with the text drawn at the mouse position -- hideText = m_aTrackMouse->isChecked() && m_mouseWithinWidget && abs(x - (leftDist + mouseX + 20)) < (int) minDistX + 16 -+ hideText = m_aTrackMouse->isChecked() && m_mouseWithinWidget && abs(x - ((int)leftDist + mouseX + 20)) < (int) minDistX + 16 - && mouseX < m_innerScopeRect.width() && mouseX >= 0; - - if (x <= rightBorder) { -@@ -268,7 +268,7 @@ - } - // Draw the line at the very right (maximum frequency) - x = leftDist + m_innerScopeRect.width() - 1; -- hideText = m_aTrackMouse->isChecked() && m_mouseWithinWidget && abs(x - (leftDist + mouseX + 30)) < (int) minDistX -+ hideText = m_aTrackMouse->isChecked() && m_mouseWithinWidget && abs(x - ((int)leftDist + mouseX + 30)) < (int) minDistX - && mouseX < m_innerScopeRect.width() && mouseX >= 0; - davinci.drawLine(x, topDist, x, topDist + m_innerScopeRect.height() + 6); - if (!hideText) { diff --git a/kde/patch/kdepim.patch b/kde/patch/kdepim.patch deleted file mode 100644 index c5aeb9c..0000000 --- a/kde/patch/kdepim.patch +++ /dev/null @@ -1,4 +0,0 @@ -# Install Kleopatra headers, needed by kopete-cryptography: -# This used to be fixed? -#cat $CWD/patch/kdepim/kdepim-install_kleopatra_headers.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - diff --git a/kde/patch/kdepim/kdepim-install_kleopatra_headers.patch b/kde/patch/kdepim/kdepim-install_kleopatra_headers.patch deleted file mode 100644 index 18662fd..0000000 --- a/kde/patch/kdepim/kdepim-install_kleopatra_headers.patch +++ /dev/null @@ -1,129 +0,0 @@ -diff -uarN kdepim-15.08.0.orig/kleopatra/libkleopatraclient/CMakeLists.txt kdepim-15.08.0/kleopatra/libkleopatraclient/CMakeLists.txt ---- kdepim-15.08.0.orig/kleopatra/libkleopatraclient/CMakeLists.txt 2015-08-10 21:56:00.000000000 +0200 -+++ kdepim-15.08.0/kleopatra/libkleopatraclient/CMakeLists.txt 2015-08-24 23:05:07.650076668 +0200 -@@ -4,6 +4,11 @@ - add_subdirectory(core) - add_subdirectory(gui) - -+install( -+ FILES kleopatraclient_export.h -+ DESTINATION ${INCLUDE_INSTALL_DIR}/libkleopatraclient -+ ) -+ - if(BUILD_TESTING) - add_subdirectory(tests) - endif() -diff -uarN kdepim-15.08.0.orig/kleopatra/libkleopatraclient/core/CMakeLists.txt kdepim-15.08.0/kleopatra/libkleopatraclient/core/CMakeLists.txt ---- kdepim-15.08.0.orig/kleopatra/libkleopatraclient/core/CMakeLists.txt 2015-08-10 21:56:00.000000000 +0200 -+++ kdepim-15.08.0/kleopatra/libkleopatraclient/core/CMakeLists.txt 2015-08-24 22:52:15.613045160 +0200 -@@ -67,3 +67,13 @@ - target_link_libraries(kleopatraclientcore Qt5::Widgets KF5::I18n) - - install(TARGETS kleopatraclientcore ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) -+ -+install( -+ FILES -+ initialization.h -+ command.h -+ selectcertificatecommand.h -+ signencryptfilescommand.h -+ decryptverifyfilescommand.h -+ DESTINATION ${INCLUDE_INSTALL_DIR}/libkleopatraclient/core -+ ) -diff -uarN kdepim-15.08.0.orig/kleopatra/libkleopatraclient/gui/CMakeLists.txt kdepim-15.08.0/kleopatra/libkleopatraclient/gui/CMakeLists.txt ---- kdepim-15.08.0.orig/kleopatra/libkleopatraclient/gui/CMakeLists.txt 2015-08-10 21:56:00.000000000 +0200 -+++ kdepim-15.08.0/kleopatra/libkleopatraclient/gui/CMakeLists.txt 2015-08-24 22:52:15.613045160 +0200 -@@ -16,3 +16,9 @@ - ) - - install(TARGETS kleopatraclientgui ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) -+ -+install( -+ FILES -+ certificaterequester.h -+ DESTINATION ${INCLUDE_INSTALL_DIR}/libkleopatraclient/gui -+ ) -diff -uarN kdepim-15.08.0.orig/libkleo/CMakeLists.txt kdepim-15.08.0/libkleo/CMakeLists.txt ---- kdepim-15.08.0.orig/libkleo/CMakeLists.txt 2015-08-10 21:56:00.000000000 +0200 -+++ kdepim-15.08.0/libkleo/CMakeLists.txt 2015-08-24 22:52:15.613045160 +0200 -@@ -126,3 +126,61 @@ - else () - install ( FILES libkleopatrarc.desktop DESTINATION ${KDE_INSTALL_CONFDIR} RENAME libkleopatrarc ) - endif () -+ -+install( FILES -+ kleo/kleo_export.h -+ kleo/enum.h -+ kleo/oidmap.h -+ kleo/cryptobackend.h -+ kleo/cryptobackendfactory.h -+ kleo/cryptoconfig.h -+ kleo/dn.h -+ kleo/job.h -+ kleo/keylistjob.h -+ kleo/keygenerationjob.h -+ kleo/abstractimportjob.h -+ kleo/importjob.h -+ kleo/importfromkeyserverjob.h -+ kleo/exportjob.h -+ kleo/changeexpiryjob.h -+ kleo/changeownertrustjob.h -+ kleo/downloadjob.h -+ kleo/deletejob.h -+ kleo/encryptjob.h -+ kleo/decryptjob.h -+ kleo/signjob.h -+ kleo/specialjob.h -+ kleo/verifydetachedjob.h -+ kleo/verifyopaquejob.h -+ kleo/decryptverifyjob.h -+ kleo/signencryptjob.h -+ kleo/signkeyjob.h -+ kleo/adduseridjob.h -+ kleo/refreshkeysjob.h -+ kleo/multideletejob.h -+ kleo/hierarchicalkeylistjob.h -+ kleo/keyfilter.h -+ kleo/keyfiltermanager.h -+ kleo/changepasswdjob.h -+ kleo/checksumdefinition.h -+ kleo/exception.h -+ kleo/kconfigbasedkeyfilter.h -+ kleo/listallkeysjob.h -+ kleo/stl_util.h -+ DESTINATION ${INCLUDE_INSTALL_DIR}/kleo COMPONENT Devel) -+ -+install ( FILES -+ ui/kdhorizontalline.h -+ ui/messagebox.h -+ ui/progressbar.h -+ ui/progressdialog.h -+ ui/keylistview.h -+ ui/keyselectiondialog.h -+ ui/keyrequester.h -+ ui/keyapprovaldialog.h -+ ui/dnattributeorderconfigwidget.h -+ ui/cryptoconfigmodule.h -+ ui/cryptoconfigdialog.h -+ ui/directoryserviceswidget.h -+ ui/filenamerequester.h -+ DESTINATION ${INCLUDE_INSTALL_DIR}/kleo/ui COMPONENT Devel) -diff -uarN kdepim-15.08.0.orig/libkpgp/CMakeLists.txt kdepim-15.08.0/libkpgp/CMakeLists.txt ---- kdepim-15.08.0.orig/libkpgp/CMakeLists.txt 2015-08-10 21:56:00.000000000 +0200 -+++ kdepim-15.08.0/libkpgp/CMakeLists.txt 2015-08-24 23:04:02.505074051 +0200 -@@ -44,6 +44,15 @@ - set_target_properties(kpgp PROPERTIES VERSION ${KDEPIM_LIB_VERSION} SOVERSION ${KDEPIM_LIB_SOVERSION}) - install(TARGETS kpgp ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) - -+install(FILES -+ kpgp.h -+ kpgpbase.h -+ kpgpblock.h -+ kpgpkey.h -+ kpgpui.h -+ libkpgp_export.h -+ DESTINATION ${INCLUDE_INSTALL_DIR}/kpgp COMPONENT Devel ) -+ - if(BUILD_TESTING) - add_subdirectory( tests ) - endif() diff --git a/kde/patch/kdepimlibs.patch b/kde/patch/kdepimlibs.patch deleted file mode 100644 index 05e5dfe..0000000 --- a/kde/patch/kdepimlibs.patch +++ /dev/null @@ -1,3 +0,0 @@ -# Fix a crash in kmail (fixed in 15.12.1): -#cat $CWD/patch/kdepimlibs/kdepimlibs_kmail_crash.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; } - diff --git a/kde/patch/kdepimlibs/kdepimlibs_kmail_crash.patch b/kde/patch/kdepimlibs/kdepimlibs_kmail_crash.patch deleted file mode 100644 index 1614e07..0000000 --- a/kde/patch/kdepimlibs/kdepimlibs_kmail_crash.patch +++ /dev/null @@ -1,59 +0,0 @@ -From: Weng Xuetian <wengxt@gmail.com> -Date: Thu, 17 Dec 2015 16:19:36 +0000 -Subject: Fix possible crash upon application exits (e.g. kmail) -X-Git-Url: http://quickgit.kde.org/?p=kdepimlibs.git&a=commitdiff&h=c6bf33a9018587e96a350bfd0b2bffde1859db27 ---- -Fix possible crash upon application exits (e.g. kmail) - -Qt lambda connection will not automatically disconnect if no context -qobject is provided. Since SessionPrivate is not a qobject, disconnect -the connection in the destructor to prevent accessing deleted object. - -REVIEW: 126395 ---- - - ---- a/akonadi/src/core/session.cpp -+++ b/akonadi/src/core/session.cpp -@@ -301,15 +301,16 @@ - // Shutdown the thread before QApplication event loop quits - the - // thread()->wait() mechanism in ConnectionThread dtor crashes sometimes - // when called from QApplication destructor -- QObject::connect(qApp, &QCoreApplication::aboutToQuit, -- [this]() { -- delete connThread; -- |