summaryrefslogtreecommitdiffstats
path: root/kde
diff options
context:
space:
mode:
Diffstat (limited to 'kde')
-rw-r--r--kde/build/digikam1
-rw-r--r--kde/build/krita1
-rw-r--r--kde/build/sddm-qt52
-rw-r--r--kde/cmake/sddm-qt51
-rw-r--r--kde/cmake/xdg-desktop-portal-kde2
-rw-r--r--kde/modules/frameworks1
-rw-r--r--kde/modules/kdepim1
-rw-r--r--kde/patch/akonadi.patch12
-rw-r--r--kde/patch/akonadi/akonadi_mariadb_qtsql.patch91
-rw-r--r--kde/patch/akonadi/akonadi_rename-header.patch77
-rw-r--r--kde/patch/akonadi/akonadi_revert-abs-path.patch70
-rw-r--r--kde/patch/akonadi4.patch1
-rw-r--r--kde/patch/amarok.patch1
-rw-r--r--kde/patch/ark.patch8
-rw-r--r--kde/patch/ark/ark_cve-2020-16116.patch47
-rw-r--r--kde/patch/ark/ark_kdebug357057.patch37
-rw-r--r--kde/patch/baloo5.patch5
-rw-r--r--kde/patch/baloo5/baloo-4.96.0_kaboutdata.diff69
-rw-r--r--kde/patch/baloo5/baloo_def_indexing_disabled.patch12
-rw-r--r--kde/patch/calligra.patch15
-rw-r--r--kde/patch/calligra/calligra3_poppler-0.71.patch131
-rw-r--r--kde/patch/calligra/calligra3_poppler-0.72.patch29
-rw-r--r--kde/patch/calligra/calligra3_poppler-0.73.patch32
-rw-r--r--kde/patch/calligra/calligra3_qt511.patch135
-rw-r--r--kde/patch/calligra/calligra3_qt513.patch22
-rw-r--r--kde/patch/calligraplan.patch13
-rw-r--r--kde/patch/calligraplan/calligraplan.kcalcore.1.patch47
-rw-r--r--kde/patch/calligraplan/calligraplan.kcalcore.2.patch85
-rw-r--r--kde/patch/calligraplan/calligraplan.kcalendarcore.patch34
-rw-r--r--kde/patch/calligraplan/calligraplan.missingheader.patch25
-rw-r--r--kde/patch/calligraplan/calligraplan.qt-5.15.patch10
-rw-r--r--kde/patch/calligraplan/calligraplan.qt-511.patch125
-rw-r--r--kde/patch/cantor.patch4
-rw-r--r--kde/patch/cantor/cantor_julia.patch193
-rw-r--r--kde/patch/cantor/cantor_python.patch31
-rw-r--r--kde/patch/digikam.patch12
-rw-r--r--kde/patch/digikam/digikam_clang_fix.patch38
-rw-r--r--kde/patch/digikam/digikam_databasemodel.patch13337
-rw-r--r--kde/patch/digikam/digikam_imagemagick7.patch40
-rw-r--r--kde/patch/dolphin.patch1
-rw-r--r--kde/patch/falkon.patch2
-rw-r--r--kde/patch/falkon/falkon.qt-5.15.diff20
-rw-r--r--kde/patch/gwenview.patch4
-rw-r--r--kde/patch/gwenview/gwenview-17.04.1_dataloss.patch131
-rw-r--r--kde/patch/kaccounts-integration.patch4
-rw-r--r--kde/patch/kaccounts-integration/kaccounts-integration-15.08.3_service.patch28
-rw-r--r--kde/patch/kalgebra.patch1
-rw-r--r--kde/patch/kalzium.patch3
-rw-r--r--kde/patch/kalzium/kalzium_kf_5.31.patch156
-rw-r--r--kde/patch/kate.patch5
-rw-r--r--kde/patch/kate/kate-15.12.0.patch31
-rw-r--r--kde/patch/kcalc.patch5
-rw-r--r--kde/patch/kcalc/kcalc-kdebug_360105.patch15
-rw-r--r--kde/patch/kcalcore.patch4
-rw-r--r--kde/patch/kcalcore/kcalcore_libical3.patch109
-rw-r--r--kde/patch/kcoreaddons.patch5
-rw-r--r--kde/patch/kcoreaddons/kcoreaddons.kdebug_362161.patch27
-rw-r--r--kde/patch/kde-baseapps.patch5
-rw-r--r--kde/patch/kde-baseapps/dolphin_kdebug_327224.patch57
-rw-r--r--kde/patch/kde-cli-tools.patch6
-rw-r--r--kde/patch/kde-cli-tools/kde-cli-tools_ecm.patch11
-rw-r--r--kde/patch/kde-cli-tools/kde-cli-tools_kaboutdata.diff59
-rw-r--r--kde/patch/kde-dev-utils.patch3
-rw-r--r--kde/patch/kde-dev-utils/build_with_kf548.patch156
-rw-r--r--kde/patch/kde-gtk-config.patch4
-rw-r--r--kde/patch/kde-gtk-config/kde-gtk-config_loadcurrentsettings.patch622
-rw-r--r--kde/patch/kde-runtime.patch8
-rw-r--r--kde/patch/kde-runtime/kde-runtime.kdebug324470.diff49
-rw-r--r--kde/patch/kde-runtime/kde-runtime_gpgme.patch133
-rw-r--r--kde/patch/kde-workspace.patch4
-rw-r--r--kde/patch/kde-workspace/kde-workspace.desktopnames.diff34
-rw-r--r--kde/patch/kdeconnect-kde.patch1
-rw-r--r--kde/patch/kdelibs.patch3
-rw-r--r--kde/patch/kdelibs/fixbic-4.14.6.patch47
-rw-r--r--kde/patch/kdelibs/kdelibs.grantlee-qt4.include.path.patch11
-rw-r--r--kde/patch/kdelibs4support.patch4
-rw-r--r--kde/patch/kdelibs4support/update-FindGettext.patch36
-rw-r--r--kde/patch/kdenlive.patch4
-rw-r--r--kde/patch/kdenlive/kdenlive_gcc7.patch32
-rw-r--r--kde/patch/kdepim.patch4
-rw-r--r--kde/patch/kdepim/kdepim-install_kleopatra_headers.patch129
-rw-r--r--kde/patch/kdepimlibs.patch3
-rw-r--r--kde/patch/kdepimlibs/kdepimlibs_kmail_crash.patch59
-rw-r--r--kde/patch/kdepimlibs4.patch3
-rw-r--r--kde/patch/kdepimlibs4/kdepimlibs.libical3.diff184
-rw-r--r--kde/patch/kdeplasma-addons.patch4
-rw-r--r--kde/patch/kdeplasma-addons/random_generator_cve-2013-2120.patch76
-rw-r--r--kde/patch/kdesdk-kioslaves.patch3
-rw-r--r--kde/patch/kdesdk-kioslaves/svn19.patch87
-rw-r--r--kde/patch/kdev-python.patch4
-rw-r--r--kde/patch/kdev-python/kdev-python-5.4.4_python38.patch560
-rw-r--r--kde/patch/kdewebdev.patch6
-rw-r--r--kde/patch/kdewebdev/include-tidy.patch13
-rw-r--r--kde/patch/kholidays.patch8
-rw-r--r--kde/patch/kholidays/kholidays_depfreeze_revert.patch61
-rw-r--r--kde/patch/kholidays/kholidays_isnan.patch30
-rw-r--r--kde/patch/kinfocenter.patch1
-rw-r--r--kde/patch/kio.patch18
-rw-r--r--kde/patch/kio/kio_KDEBUG_399709.patch44
-rw-r--r--kde/patch/kio/kio_dolphin_servicemenus.patch126
-rw-r--r--kde/patch/kio/kio_fix_url_setpath.patch65
-rw-r--r--kde/patch/kio/kio_kdelibs4_docpatch.patch22
-rw-r--r--kde/patch/kirigami2.patch8
-rw-r--r--kde/patch/kirigami2/kirigami_iconview_crash.patch143
-rw-r--r--kde/patch/kirigami2/kirigami_scrollbar.patch25
-rw-r--r--kde/patch/kmail.patch4
-rw-r--r--kde/patch/kmail/kmail_kontact_kdebug_404881.patch75
-rw-r--r--kde/patch/kmplot.patch3
-rw-r--r--kde/patch/kmplot/kmplot_isnan.patch42
-rw-r--r--kde/patch/konsole.patch16
-rw-r--r--kde/patch/konsole/konsole.cursor.antialias.patch83
-rw-r--r--kde/patch/konsole/konsole.konsolepart.segfault.closing.after.contextmenu.patch43
-rw-r--r--kde/patch/konsole/konsole.konsolepart.segfault.closing.session.via.menu.patch58
-rw-r--r--kde/patch/konsole/konsole.term.is.konsole.patch24
-rw-r--r--kde/patch/kopete.patch9
-rw-r--r--kde/patch/kopete/kopete_kdebug376348.patch127
-rw-r--r--kde/patch/kopete/kopete_kdebug393372.patch30
-rw-r--r--kde/patch/korundum.patch5
-rw-r--r--kde/patch/korundum/korundum_ruby19.patch31
-rw-r--r--kde/patch/kpat.patch6
-rw-r--r--kde/patch/kpat/kpat_no_freecell_solver_dep.patch1475
-rw-r--r--kde/patch/krita.patch7
-rw-r--r--kde/patch/krita/krita_qt512.patch117
-rw-r--r--kde/patch/krita/krita_qt59.patch26
-rw-r--r--kde/patch/krita/krita_qtabletevents.patch67
-rw-r--r--kde/patch/krunner.patch4
-rw-r--r--kde/patch/krunner/krunner_KDEBUG_423003.patch54
-rw-r--r--kde/patch/kscreenlocker.patch13
-rw-r--r--kde/patch/kscreenlocker/kscreenlocker_CVE-2016-2312.patch36
-rw-r--r--kde/patch/kscreenlocker/kscreenlocker_crash_force_softrender.patch112
-rw-r--r--kde/patch/kscreenlocker/kscreenlocker_rendersettings.patch49
-rw-r--r--kde/patch/kstars.patch3
-rw-r--r--kde/patch/kstars/kstars_isnan.patch46
-rw-r--r--kde/patch/ksudoku.patch4
-rw-r--r--kde/patch/ksudoku/ksudoku_qwindowtitle.patch15
-rw-r--r--kde/patch/ktexteditor.patch3
-rw-r--r--kde/patch/ktexteditor/ktexteditor_fix_indentation.patch32
-rw-r--r--kde/patch/ktorrent.patch7
-rw-r--r--kde/patch/ktorrent/ktorrent_systray.patch24
-rw-r--r--kde/patch/ktorrent/ktorrent_taglib_linking.patch248
-rw-r--r--kde/patch/ktp-accounts-kcm.patch4
-rw-r--r--kde/patch/ktp-accounts-kcm/ktp-accounts-kcm_kdebug_351785.patch32
-rw-r--r--kde/patch/kwin.patch11
-rw-r--r--kde/patch/kwin/kwin_cmake310.patch52
-rw-r--r--kde/patch/kwin/kwin_qt59_rootwindow_events.patch63
-rw-r--r--kde/patch/kwin/kwin_replace_logind_with_ck2.patch85
-rw-r--r--kde/patch/libkdcraw.patch3
-rw-r--r--kde/patch/libkdcraw/libkdcraw_cmake_minver.patch7
-rw-r--r--kde/patch/libkexiv2.patch3
-rw-r--r--kde/patch/libkexiv2/libkexiv2_cmake_minver.patch7
-rw-r--r--kde/patch/libkface.patch1
-rw-r--r--kde/patch/libkleo.patch4
-rw-r--r--kde/patch/libkleo/libkleo_gcc7.patch27
-rw-r--r--kde/patch/libksysguard.patch4
-rw-r--r--kde/patch/libksysguard/libksysguard_isnan.patch176
-rw-r--r--kde/patch/marble.patch4
-rw-r--r--kde/patch/marble/marble_qt4.patch47
-rw-r--r--kde/patch/messagelib.patch4
-rw-r--r--kde/patch/messagelib/messagelib_CVE-2018-19516.patch20
-rw-r--r--kde/patch/okular.patch3
-rw-r--r--kde/patch/okular/cve-2020-9359.patch32
-rw-r--r--kde/patch/oxygen-gtk2.patch1
-rw-r--r--kde/patch/oxygen-gtk3.patch3
-rw-r--r--kde/patch/oxygen-gtk3/oxygen-gtk3-1.3.1_gtk3.8.patch29
-rw-r--r--kde/patch/perlqt.patch1
-rw-r--r--kde/patch/plasma-browser-integration.patch1
-rw-r--r--kde/patch/plasma-desktop.patch20
-rwxr-xr-xkde/patch/plasma-desktop/plasma-desktop-4.99.0_kfontinst_po.diff60
-rw-r--r--kde/patch/plasma-desktop/plasma-desktop_kdebug_401508.patch39
-rw-r--r--kde/patch/plasma-desktop/plasma-desktop_kdebug_416358.patch16
-rw-r--r--kde/patch/plasma-desktop/plasma-desktop_kdebug_417424.patch25
-rw-r--r--kde/patch/plasma-desktop/plasma-desktop_kdelibs4support.diff88
-rw-r--r--kde/patch/plasma-desktop/plasma-desktop_kickoff_kdebug_356398.patch24
-rw-r--r--kde/patch/plasma-framework.patch11
-rw-r--r--kde/patch/plasma-framework/plasma-framework_KDEBUG_357895.patch24
-rw-r--r--kde/patch/plasma-framework/plasma-framework_KDEBUG_359388.patch31
-rw-r--r--kde/patch/plasma-pa.patch5
-rw-r--r--kde/patch/plasma-pa/plasma-pa_enable_gsettings.patch583
-rw-r--r--kde/patch/plasma-wayland-protocols.patch2
-rw-r--r--kde/patch/plasma-wayland-protocols/plasma-wayland-protocols_add.missing.since.13.patch60
-rw-r--r--kde/patch/plasma-workspace.patch17
-rw-r--r--kde/patch/plasma-workspace/plasma-workspace.systray_cpubug.patch152
-rw-r--r--kde/patch/plasma-workspace/plasma-workspace_apply_767aa57.patch23
-rw-r--r--kde/patch/plasma-workspace/plasma-workspace_consolekit2.patch189
-rw-r--r--kde/patch/plasma-workspace/plasma-workspace_kdebug389815.patch32
-rw-r--r--kde/patch/plasma5-nm.patch14
-rw-r--r--kde/patch/plasma5-nm/plasma-nm-fixes.patch322
-rw-r--r--kde/patch/plasma5-nm/plasma-nm_modemmanager-qt_api.patch73
-rw-r--r--kde/patch/plasma5-nm/plasma-nm_networkmanager.patch17
-rw-r--r--kde/patch/plasma5-nm/plasma5-nm_KDEBUG_423093.patch31
-rw-r--r--kde/patch/powerdevil.patch4
-rw-r--r--kde/patch/powerdevil/powerdevil-5.12.4_firstrun.patch42
-rw-r--r--kde/patch/pykde4.patch1
-rw-r--r--kde/patch/qqc2-desktop-style.patch5
-rw-r--r--kde/patch/qqc2-desktop-style/qqc2-desktop-style_scrollbar.patch51
-rw-r--r--kde/patch/sddm-theme-breeze.patch2
-rw-r--r--kde/patch/sddm-theme-breeze/sddm-theme-breeze_path.diff10
-rw-r--r--kde/patch/spectacle.patch7
-rw-r--r--kde/patch/spectacle/spectacle_hidpi.patch28
-rw-r--r--kde/patch/spectacle/spectacle_rect_capture.patch52
-rw-r--r--kde/patch/strigi-multimedia.patch1
-rw-r--r--kde/patch/umbrello.patch10
-rw-r--r--kde/patch/umbrello/umbrello-4.11.4_listitem.patch13
-rw-r--r--kde/patch/umbrello/umbrello_qt510_kaboutdata_h.patch33
-rw-r--r--kde/slack-desc/akonadi2
-rw-r--r--kde/slack-desc/akonadi-calendar2
-rw-r--r--kde/slack-desc/akonadi-calendar-tools2
-rw-r--r--kde/slack-desc/akonadi-contacts6
-rw-r--r--kde/slack-desc/akonadi-import-wizard4
-rw-r--r--kde/slack-desc/akonadi-mime6
-rw-r--r--kde/slack-desc/akonadi-notes6
-rw-r--r--kde/slack-desc/akonadi-search6
-rw-r--r--kde/slack-desc/akonadiconsole2
-rw-r--r--kde/slack-desc/akregator2
-rw-r--r--kde/slack-desc/alkimia4
-rw-r--r--kde/slack-desc/analitza2
-rw-r--r--kde/slack-desc/ark2
-rw-r--r--kde/slack-desc/artikulate8
-rw-r--r--kde/slack-desc/attica-framework2
-rw-r--r--kde/slack-desc/audiocd-kio2
-rw-r--r--kde/slack-desc/baloo512
-rw-r--r--kde/slack-desc/baloo5-widgets4
-rw-r--r--kde/slack-desc/blinken2
-rw-r--r--kde/slack-desc/bluez-qt10
-rw-r--r--kde/slack-desc/bomber10
-rw-r--r--kde/slack-desc/bovo6
-rw-r--r--kde/slack-desc/breeze6
-rw-r--r--kde/slack-desc/breeze-grub2
-rw-r--r--kde/slack-desc/breeze-gtk4
-rw-r--r--kde/slack-desc/breeze-icons4
-rw-r--r--kde/slack-desc/calendarsupport2
-rw-r--r--kde/slack-desc/calligra10
-rw-r--r--kde/slack-desc/calligraplan8
-rw-r--r--kde/slack-desc/cantor10
-rw-r--r--kde/slack-desc/cervisia2
-rw-r--r--kde/slack-desc/digikam14
-rw-r--r--kde/slack-desc/discover4
-rw-r--r--kde/slack-desc/dolphin8
-rw-r--r--kde/slack-desc/dolphin-plugins2
-rw-r--r--kde/slack-desc/dragon4
-rw-r--r--kde/slack-desc/drkonqi2
-rw-r--r--kde/slack-desc/elisa6
-rw-r--r--kde/slack-desc/eventviews2
-rw-r--r--kde/slack-desc/extra-cmake-modules6
-rw-r--r--kde/slack-desc/falkon4
-rw-r--r--kde/slack-desc/ffmpegthumbs8
-rw-r--r--kde/slack-desc/filelight2
-rw-r--r--kde/slack-desc/frameworkintegration4
-rw-r--r--kde/slack-desc/granatier6
-rw-r--r--kde/slack-desc/grantlee-editor2
-rw-r--r--kde/slack-desc/grantleetheme4
-rw-r--r--kde/slack-desc/gwenview4
-rw-r--r--kde/slack-desc/incidenceeditor2
-rw-r--r--kde/slack-desc/juk8
-rw-r--r--kde/slack-desc/k3b2
-rw-r--r--kde/slack-desc/kaccounts-integration8
-rw-r--r--kde/slack-desc/kaccounts-providers8
-rw-r--r--kde/slack-desc/kactivities6
-rw-r--r--kde/slack-desc/kactivities-framework6
-rw-r--r--kde/slack-desc/kactivities-stats8
-rw-r--r--kde/slack-desc/kactivitymanagerd10
-rw-r--r--kde/slack-desc/kaddressbook2
-rw-r--r--kde/slack-desc/kajongg12
-rw-r--r--kde/slack-desc/kalarm2
-rw-r--r--kde/slack-desc/kalarmcal2
-rw-r--r--kde/slack-desc/kalgebra6
-rw-r--r--kde/slack-desc/kalzium2
-rw-r--r--kde/slack-desc/kamera4
-rw-r--r--kde/slack-desc/kamoso4
-rw-r--r--kde/slack-desc/kanagram12
-rw-r--r--kde/slack-desc/kapidox6
-rw-r--r--kde/slack-desc/kapman14
-rw-r--r--kde/slack-desc/kapptemplate6
-rw-r--r--kde/slack-desc/karchive10
-rw-r--r--kde/slack-desc/kate14
-rw-r--r--kde/slack-desc/katomic8
-rw-r--r--kde/slack-desc/kaudiocreator6
-rw-r--r--kde/slack-desc/kauth8
-rw-r--r--kde/slack-desc/kbackup8
-rw-r--r--kde/slack-desc/kblackbox6
-rw-r--r--kde/slack-desc/kblocks2
-rw-r--r--kde/slack-desc/kblog10
-rw-r--r--kde/slack-desc/kbookmarks14
-rw-r--r--kde/slack-desc/kbounce6
-rw-r--r--kde/slack-desc/kbreakout2
-rw-r--r--kde/slack-desc/kbruch2
-rw-r--r--kde/slack-desc/kcachegrind6
-rw-r--r--kde/slack-desc/kcalc2
-rw-r--r--kde/slack-desc/kcalcore8
-rw-r--r--kde/slack-desc/kcalendarcore8
-rw-r--r--kde/slack-desc/kcalutils4
-rw-r--r--kde/slack-desc/kcharselect6
-rw-r--r--kde/slack-desc/kcmutils6
-rw-r--r--kde/slack-desc/kcodecs12
-rw-r--r--kde/slack-desc/kcolorchooser2
-rw-r--r--kde/slack-desc/kcompletion16
-rw-r--r--kde/slack-desc/kconfig14
-rw-r--r--kde/slack-desc/kconfigwidgets8
-rw-r--r--kde/slack-desc/kcontacts4
-rw-r--r--kde/slack-desc/kcoreaddons12
-rw-r--r--kde/slack-desc/kcrash6
-rw-r--r--kde/slack-desc/kcron2
-rw-r--r--kde/slack-desc/kdav10
-rw-r--r--kde/slack-desc/kdbusaddons6
-rw-r--r--kde/slack-desc/kde-cli-tools8
-rw-r--r--kde/slack-desc/kde-dev-scripts2
-rw-r--r--kde/slack-desc/kde-dev-utils2
-rw-r--r--kde/slack-desc/kde-gtk-config6
-rw-r--r--kde/slack-desc/kde-wallpapers2
-rw-r--r--kde/slack-desc/kdeaccessibility1
-rw-r--r--kde/slack-desc/kdeadmin2
-rw-r--r--kde/slack-desc/kdebugsettings2
-rw-r--r--kde/slack-desc/kdeclarative12
-rw-r--r--kde/slack-desc/kdeconnect-kde4
-rw-r--r--kde/slack-desc/kdecoration8
-rw-r--r--kde/slack-desc/kded10
-rw-r--r--kde/slack-desc/kdeedu-data2
-rw-r--r--kde/slack-desc/kdegraphics-mobipocket2
-rw-r--r--kde/slack-desc/kdegraphics-thumbnailers8
-rw-r--r--kde/slack-desc/kdelibs4support10
-rw-r--r--kde/slack-desc/kdenetwork-filesharing6
-rw-r--r--kde/slack-desc/kdenlive2
-rw-r--r--kde/slack-desc/kdepim2
-rw-r--r--kde/slack-desc/kdepim-addons2
-rw-r--r--kde/slack-desc/kdepim-apps-libs6
-rw-r--r--kde/slack-desc/kdepim-runtime2
-rw-r--r--kde/slack-desc/kdesdk6
-rw-r--r--kde/slack-desc/kdesdk-kioslaves2
-rw-r--r--kde/slack-desc/kdesdk-thumbnailers6
-rw-r--r--kde/slack-desc/kdesignerplugin8
-rw-r--r--kde/slack-desc/kdesu8
-rw-r--r--kde/slack-desc/kdeutils2
-rw-r--r--kde/slack-desc/kdewebdev6
-rw-r--r--kde/slack-desc/kdewebkit14
-rw-r--r--kde/slack-desc/kdf2
-rw-r--r--kde/slack-desc/kdiagram2
-rw-r--r--kde/slack-desc/kdialog4
-rw-r--r--kde/slack-desc/kdiamond6
-rw-r--r--kde/slack-desc/kdnssd2
-rw-r--r--kde/slack-desc/kdoctools6
-rw-r--r--kde/slack-desc/keditbookmarks2
-rw-r--r--kde/slack-desc/kemoticons8
-rw-r--r--kde/slack-desc/kfilemetadata58
-rw-r--r--kde/slack-desc/kfind10
-rw-r--r--kde/slack-desc/kfloppy2
-rw-r--r--kde/slack-desc/kfourinline8
-rw-r--r--kde/slack-desc/kgamma52
-rw-r--r--kde/slack-desc/kgeography14
-rw-r--r--kde/slack-desc/kget2
-rw-r--r--kde/slack-desc/kglobalaccel8
-rw-r--r--kde/slack-desc/kgoldrunner8
-rw-r--r--kde/slack-desc/kgpg2
-rw-r--r--kde/slack-desc/kguiaddons6
-rw-r--r--kde/slack-desc/khangman6
-rw-r--r--kde/slack-desc/khelpcenter10
-rw-r--r--kde/slack-desc/kholidays8
-rw-r--r--kde/slack-desc/khotkeys12
-rw-r--r--kde/slack-desc/khtml6
-rw-r--r--kde/slack-desc/ki18n14
-rw-r--r--kde/slack-desc/kiconthemes6
-rw-r--r--kde/slack-desc/kid310
-rw-r--r--kde/slack-desc/kidentitymanagement4
-rw-r--r--kde/slack-desc/kidletime10
-rw-r--r--kde/slack-desc/kig2
-rw-r--r--kde/slack-desc/kigo14
-rw-r--r--kde/slack-desc/kile6
-rw-r--r--kde/slack-desc/killbots2
-rw-r--r--kde/slack-desc/kimageformats10
-rw-r--r--kde/slack-desc/kimagemapeditor4
-rw-r--r--kde/slack-desc/kimap2
-rw-r--r--kde/slack-desc/kinfocenter8
-rw-r--r--kde/slack-desc/kinit12
-rw-r--r--kde/slack-desc/kio16
-rw-r--r--kde/slack-desc/kio-extras4
-rw-r--r--kde/slack-desc/kipi-plugins6
-rw-r--r--kde/slack-desc/kirigami-gallery6
-rw-r--r--kde/slack-desc/kirigami28
-rw-r--r--kde/slack-desc/kiriki4
-rw-r--r--kde/slack-desc/kitemmodels6
-rw-r--r--kde/slack-desc/kitemviews8
-rw-r--r--kde/slack-desc/kiten12
-rw-r--r--kde/slack-desc/kitinerary4
-rw-r--r--kde/slack-desc/kjobwidgets6
-rw-r--r--kde/slack-desc/kjots8
-rw-r--r--kde/slack-desc/kjs8
-rw-r--r--kde/slack-desc/kjsembed6
-rw-r--r--kde/slack-desc/kjumpingcube10
-rw-r--r--kde/slack-desc/kldap2
-rw-r--r--kde/slack-desc/kleopatra2
-rw-r--r--kde/slack-desc/klettres8
-rw-r--r--kde/slack-desc/klickety8
-rw-r--r--kde/slack-desc/klines6
-rw-r--r--kde/slack-desc/kmag8
-rw-r--r--kde/slack-desc/kmahjongg6
-rw-r--r--kde/slack-desc/kmail14
-rw-r--r--kde/slack-desc/kmail-account-wizard4
-rw-r--r--kde/slack-desc/kmailtransport4
-rw-r--r--kde/slack-desc/kmbox2
-rw-r--r--kde/slack-desc/kmediaplayer6
-rw-r--r--kde/slack-desc/kmenuedit6
-rw-r--r--kde/slack-desc/kmime2
-rw-r--r--kde/slack-desc/kmines4
-rw-r--r--kde/slack-desc/kmix8
-rw-r--r--kde/slack-desc/kmousetool2
-rw-r--r--kde/slack-desc/kmouth4
-rw-r--r--kde/slack-desc/kmplot10
-rw-r--r--kde/slack-desc/kmymoney4
-rw-r--r--kde/slack-desc/knavalbattle10
-rw-r--r--kde/slack-desc/knetwalk2
-rw-r--r--kde/slack-desc/knewstuff8
-rw-r--r--kde/slack-desc/knights8
-rw-r--r--kde/slack-desc/knotes2
-rw-r--r--kde/slack-desc/knotifications6
-rw-r--r--kde/slack-desc/knotifyconfig6
-rw-r--r--kde/slack-desc/kolf4
-rw-r--r--kde/slack-desc/kollision2
-rw-r--r--kde/slack-desc/kolourpaint2
-rw-r--r--kde/slack-desc/kompare2
-rw-r--r--kde/slack-desc/konqueror10
-rw-r--r--kde/slack-desc/konquest8
-rw-r--r--kde/slack-desc/konsole6
-rw-r--r--kde/slack-desc/kontact2
-rw-r--r--kde/slack-desc/kontactinterface6
-rw-r--r--kde/slack-desc/kopete2
-rw-r--r--kde/slack-desc/korganizer2
-rw-r--r--kde/slack-desc/kpackage6
-rw-r--r--kde/slack-desc/kparts8
-rw-r--r--kde/slack-desc/kpat4
-rw-r--r--kde/slack-desc/kpeople8
-rw-r--r--kde/slack-desc/kpeoplevcard2
-rw-r--r--kde/slack-desc/kpimtextedit8
-rw-r--r--kde/slack-desc/kpkpass2
-rw-r--r--kde/slack-desc/kplotting18
-rw-r--r--kde/slack-desc/kpmcore12
-rw-r--r--kde/slack-desc/kpty8
-rw-r--r--kde/slack-desc/kqtquickcharts6
-rw-r--r--kde/slack-desc/kquickcharts12
-rw-r--r--kde/slack-desc/krdc2
-rw-r--r--kde/slack-desc/krename14
-rw-r--r--kde/slack-desc/kreversi10
-rw-r--r--kde/slack-desc/krfb2
-rw-r--r--kde/slack-desc/krita8
-rw-r--r--kde/slack-desc/kross10
-rw-r--r--kde/slack-desc/kross-interpreters2
-rw-r--r--kde/slack-desc/kruler2
-rw-r--r--kde/slack-desc/krunner10
-rw-r--r--kde/slack-desc/krusader12
-rw-r--r--kde/slack-desc/kscreen210
-rw-r--r--kde/slack-desc/kscreenlocker2
-rw-r--r--kde/slack-desc/kservice8
-rw-r--r--kde/slack-desc/kshisen4
-rw-r--r--kde/slack-desc/ksirk8
-rw-r--r--kde/slack-desc/ksmtp6
-rw-r--r--kde/slack-desc/ksnakeduel12
-rw-r--r--kde/slack-desc/kspaceduel6
-rw-r--r--kde/slack-desc/ksquares8
-rw-r--r--kde/slack-desc/ksshaskpass2
-rw-r--r--kde/slack-desc/kstars16
-rw-r--r--kde/slack-desc/ksudoku10
-rw-r--r--kde/slack-desc/ksysguard10
-rw-r--r--kde/slack-desc/ksystemlog14
-rw-r--r--kde/slack-desc/kteatime8
-rw-r--r--kde/slack-desc/ktexteditor14
-rw-r--r--kde/slack-desc/ktextwidgets6
-rw-r--r--kde/slack-desc/ktimer2
-rw-r--r--kde/slack-desc/ktimetracker6
-rw-r--r--kde/slack-desc/ktnef10
-rw-r--r--kde/slack-desc/ktorrent10
-rw-r--r--kde/slack-desc/ktouch8
-rw-r--r--kde/slack-desc/ktp-accounts-kcm4
-rw-r--r--kde/slack-desc/ktp-approver4
-rw-r--r--kde/slack-desc/ktp-auth-handler4
-rw-r--r--kde/slack-desc/ktp-call-ui4
-rw-r--r--kde/slack-desc/ktp-common-internals4
-rw-r--r--kde/slack-desc/ktp-contact-list4
-rw-r--r--kde/slack-desc/ktp-contact-runner4
-rw-r--r--kde/slack-desc/ktp-desktop-applets8
-rw-r--r--kde/slack-desc/ktp-filetransfer-handler8
-rw-r--r--kde/slack-desc/ktp-kded-module8
-rw-r--r--kde/slack-desc/ktp-send-file4
-rw-r--r--kde/slack-desc/ktp-text-ui4
-rw-r--r--kde/slack-desc/ktuberling8
-rw-r--r--kde/slack-desc/kturtle18
-rw-r--r--kde/slack-desc/kubrick12
-rw-r--r--kde/slack-desc/kunitconversion10
-rw-r--r--kde/slack-desc/kuser2
-rw-r--r--kde/slack-desc/kwallet4
-rw-r--r--kde/slack-desc/kwallet-pam2
-rw-r--r--kde/slack-desc/kwalletmanager4
-rw-r--r--kde/slack-desc/kwave12
-rw-r--r--kde/slack-desc/kwayland2
-rw-r--r--kde/slack-desc/kwayland-integration6
-rw-r--r--kde/slack-desc/kwayland-server2
-rw-r--r--kde/slack-desc/kwebkitpart4
-rw-r--r--kde/slack-desc/kwidgetsaddons14
-rw-r--r--kde/slack-desc/kwin10
-rw-r--r--kde/slack-desc/kwindowsystem12
-rw-r--r--kde/slack-desc/kwordquiz8
-rw-r--r--kde/slack-desc/kwrited6
-rw-r--r--kde/slack-desc/kxmlgui10
-rw-r--r--kde/slack-desc/kxmlrpcclient2
-rw-r--r--kde/slack-desc/labplot12
-rw-r--r--kde/slack-desc/latte-dock12
-rw-r--r--kde/slack-desc/libgravatar4
-rw-r--r--kde/slack-desc/libkcddb2
-rw-r--r--kde/slack-desc/libkcompactdisc6
-rw-r--r--kde/slack-desc/libkdcraw6
-rw-r--r--kde/slack-desc/libkdegames4
-rw-r--r--kde/slack-desc/libkdepim4
-rw-r--r--kde/slack-desc/libkeduvocdocument10
-rw-r--r--kde/slack-desc/libkexiv26
-rw-r--r--kde/slack-desc/libkgapi8
-rw-r--r--kde/slack-desc/libkgeomap10
-rw-r--r--kde/slack-desc/libkipi8
-rw-r--r--kde/slack-desc/libkleo6
-rw-r--r--kde/slack-desc/libkmahjongg8
-rw-r--r--kde/slack-desc/libkomparediff210
-rw-r--r--kde/slack-desc/libksane4
-rw-r--r--kde/slack-desc/libkscreen212
-rw-r--r--kde/slack-desc/libksieve4
-rw-r--r--kde/slack-desc/libksysguard6
-rw-r--r--kde/slack-desc/libktorrent10
-rw-r--r--kde/slack-desc/lokalize2
-rw-r--r--kde/slack-desc/lskat4
-rw-r--r--kde/slack-desc/mailcommon4
-rw-r--r--kde/slack-desc/mailimporter2
-rw-r--r--kde/slack-desc/marble15
-rw-r--r--kde/slack-desc/mbox-importer2
-rw-r--r--kde/slack-desc/messagelib2
-rw-r--r--kde/slack-desc/milou6
-rw-r--r--kde/slack-desc/minuet8
-rw-r--r--kde/slack-desc/modemmanager-qt6
-rw-r--r--kde/slack-desc/networkmanager-qt4
-rw-r--r--kde/slack-desc/okteta2
-rw-r--r--kde/slack-desc/okular10
-rw-r--r--kde/slack-desc/oxygen4
-rw-r--r--kde/slack-desc/oxygen-fonts6
-rw-r--r--kde/slack-desc/oxygen-gtk214
-rw-r--r--kde/slack-desc/oxygen-icons54
-rw-r--r--kde/slack-desc/palapeli12
-rw-r--r--kde/slack-desc/parley2
-rw-r--r--kde/slack-desc/partitionmanager10
-rw-r--r--kde/slack-desc/picmi8
-rw-r--r--kde/slack-desc/pim-data-exporter4
-rw-r--r--kde/slack-desc/pim-sieve-editor6
-rw-r--r--kde/slack-desc/pimcommon2
-rw-r--r--kde/slack-desc/plasma-browser-integration8
-rw-r--r--kde/slack-desc/plasma-desktop16
-rw-r--r--kde/slack-desc/plasma-framework8
-rw-r--r--kde/slack-desc/plasma-integration6
-rw-r--r--kde/slack-desc/plasma-pa4
-rw-r--r--kde/slack-desc/plasma-sdk2
-rw-r--r--kde/slack-desc/plasma-vault12
-rw-r--r--kde/slack-desc/plasma-wayland-protocols6
-rw-r--r--kde/slack-desc/plasma-workspace6
-rw-r--r--kde/slack-desc/plasma-workspace-wallpapers6
-rw-r--r--kde/slack-desc/plasma5-nm6
-rw-r--r--kde/slack-desc/polkit-kde-framework6
-rw-r--r--kde/slack-desc/polkit-kde-kcmodules-framework3
-rw-r--r--kde/slack-desc/powerdevil8
-rw-r--r--kde/slack-desc/poxml10
-rw-r--r--kde/slack-desc/print-manager10
-rw-r--r--kde/slack-desc/prison8
-rw-r--r--kde/slack-desc/pulseaudio-qt8
-rw-r--r--kde/slack-desc/purpose18
-rw-r--r--kde/slack-desc/qqc2-desktop-style14
-rw-r--r--kde/slack-desc/rocs12
-rw-r--r--kde/slack-desc/sddm-kcm8
-rw-r--r--kde/slack-desc/sddm-qt512
-rw-r--r--kde/slack-desc/signon-kwallet-extension6
-rw-r--r--kde/slack-desc/skanlite4
-rw-r--r--kde/slack-desc/solid12
-rw-r--r--kde/slack-desc/sonnet10
-rw-r--r--kde/slack-desc/spectacle4
-rw-r--r--kde/slack-desc/step12
-rw-r--r--kde/slack-desc/svgpart2
-rw-r--r--kde/slack-desc/sweeper2
-rw-r--r--kde/slack-desc/syndication8
-rw-r--r--kde/slack-desc/syntax-highlighting2
-rw-r--r--kde/slack-desc/systemsettings2
-rw-r--r--kde/slack-desc/threadweaver12
-rw-r--r--kde/slack-desc/umbrello2
-rw-r--r--kde/slack-desc/user-manager6
-rw-r--r--kde/slack-desc/wacomtablet8
-rw-r--r--kde/slack-desc/xdg-desktop-portal-kde2
-rw-r--r--kde/slack-desc/yakuake12
-rw-r--r--kde/slack-desc/zeroconf-ioslave2
-rwxr-xr-xkde/src/applications-extra/fetch-krita.sh52
-rwxr-xr-xkde/src/plasma-extra/fetch-wacomtablet.sh52
589 files changed, 1845 insertions, 24672 deletions
diff --git a/kde/build/digikam b/kde/build/digikam
deleted file mode 100644
index 0cfbf08..0000000
--- a/kde/build/digikam
+++ /dev/null
@@ -1 +0,0 @@
-2
diff --git a/kde/build/krita b/kde/build/krita
deleted file mode 100644
index 0cfbf08..0000000
--- a/kde/build/krita
+++ /dev/null
@@ -1 +0,0 @@
-2
diff --git a/kde/build/sddm-qt5 b/kde/build/sddm-qt5
index 7ed6ff8..1e8b314 100644
--- a/kde/build/sddm-qt5
+++ b/kde/build/sddm-qt5
@@ -1 +1 @@
-5
+6
diff --git a/kde/cmake/sddm-qt5 b/kde/cmake/sddm-qt5
index 6f187cb..cd8ebfb 100644
--- a/kde/cmake/sddm-qt5
+++ b/kde/cmake/sddm-qt5
@@ -24,6 +24,7 @@ cd build
-DCMAKE_CXX_FLAGS:STRING="$SLKCFLAGS" \
-DCMAKE_CXX_FLAGS_RELEASE:STRING="$SLKCFLAGS" \
-DCMAKE_INSTALL_PREFIX=/usr \
+ -DCMAKE_INSTALL_MANDIR=/usr/man \
-DLIB_SUFFIX=${LIBDIRSUFFIX} \
-DBUILD_MAN_PAGES:BOOL=TRUE \
-DDBUS_CONFIG_FILENAME="org.freedesktop.sddm.conf" \
diff --git a/kde/cmake/xdg-desktop-portal-kde b/kde/cmake/xdg-desktop-portal-kde
index 74dc9f6..26bc0a8 100644
--- a/kde/cmake/xdg-desktop-portal-kde
+++ b/kde/cmake/xdg-desktop-portal-kde
@@ -18,7 +18,7 @@ cd build
-DKDE_INSTALL_SYSCONFDIR=/etc/kde \
-DKDE_INSTALL_USE_QT_SYS_PATHS=ON \
-DBUILD_TESTING=OFF \
- -DENABLE_PIPEWIRE=OFF \
+ -DENABLE_PIPEWIRE=ON \
-DQca-qt5_DIR=/usr/lib${LIBDIRSUFFIX}/cmake/Qca \
..
diff --git a/kde/modules/frameworks b/kde/modules/frameworks
index 7c2ed82..002e935 100644
--- a/kde/modules/frameworks
+++ b/kde/modules/frameworks
@@ -51,6 +51,7 @@ syndication
kquickcharts
# Tier 3, depends on Tier 1 and 2, Qt5, system libraries:
kconfigwidgets
+kdav
kservice
kglobalaccel
kiconthemes
diff --git a/kde/modules/kdepim b/kde/modules/kdepim
index 8f5b281..eb58f35 100644
--- a/kde/modules/kdepim
+++ b/kde/modules/kdepim
@@ -37,7 +37,6 @@ incidenceeditor
messagelib
mailcommon
kleopatra
-kdav
kpkpass
kitinerary
kdepim-addons
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.patch b/kde/patch/ark.patch
index 35ac2d3..3710075 100644
--- a/kde/patch/ark.patch
+++ b/kde/patch/ark.patch
@@ -1,7 +1,5 @@
-# Ark won't open RAR archives unless rar is installed (even for read access).
-# KDEBUG #357057 is fixed in 15.12.1; still needs unrar.
-#cat $CWD/patch/ark/ark_kdebug357057.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; }
-
# Fix a compilation issue in 18.04.0:
-cat $CWD/patch/ark/ark_include_memory.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; }
+#cat $CWD/patch/ark/ark_include_memory.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; }
+# Fix for CVE-2020-16116:
+cat $CWD/patch/ark/ark_cve-2020-16116.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; }
diff --git a/kde/patch/ark/ark_cve-2020-16116.patch b/kde/patch/ark/ark_cve-2020-16116.patch
new file mode 100644
index 0000000..b3feb1b
--- /dev/null
+++ b/kde/patch/ark/ark_cve-2020-16116.patch
@@ -0,0 +1,47 @@
+From 0df592524fed305d6fbe74ddf8a196bc9ffdb92f Mon Sep 17 00:00:00 2001
+From: Elvis Angelaccio <elvis.angelaccio@kde.org>
+Date: Wed, 29 Jul 2020 23:45:30 +0200
+Subject: [PATCH] Fix vulnerability to path traversal attacks
+
+Ark was vulnerable to directory traversal attacks because of
+missing validation of file paths in the archive.
+
+More details about this attack are available at:
+https://github.com/snyk/zip-slip-vulnerability
+
+Job::onEntry() is the only place where we can safely check the path of
+every entry in the archive. There shouldn't be a valid reason
+to have a "../" in an archive path, so we can just play safe and abort
+the LoadJob if we detect such an entry. This makes impossibile to
+extract this kind of malicious archives and perform the attack.
+
+Thanks to Albert Astals Cid for suggesting to use QDir::cleanPath()
+so that we can still allow loading of legitimate archives that
+contain "../" in their paths but still resolve inside the extraction folder.
+---
+ kerfuffle/jobs.cpp | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/kerfuffle/jobs.cpp b/kerfuffle/jobs.cpp
+index fdaa48695..f73b56f86 100644
+--- a/kerfuffle/jobs.cpp
++++ b/kerfuffle/jobs.cpp
+@@ -180,6 +180,14 @@ void Job::onError(const QString & message, const QString & details)
+
+ void Job::onEntry(Archive::Entry *entry)
+ {
++ const QString entryFullPath = entry->fullPath();
++ if (QDir::cleanPath(entryFullPath).contains(QLatin1String("../"))) {
++ qCWarning(ARK) << "Possibly malicious archive. Detected entry that could lead to a directory traversal attack:" << entryFullPath;
++ onError(i18n("Could not load the archive because it contains ill-formed entries and might be a malicious archive."), QString());
++ onFinished(false);
++ return;
++ }
++
+ emit newEntry(entry);
+ }
+
+--
+GitLab
+
+
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.patch b/kde/patch/baloo5.patch
index 794bcd9..75aa4d1 100644
--- a/kde/patch/baloo5.patch
+++ b/kde/patch/baloo5.patch
@@ -1,3 +1,2 @@
-# Adapt to changes in KAboutData (will be fixed in next release):
-#cat $CWD/patch/baloo5/baloo-4.96.0_kaboutdata.diff | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; }
-
+# Disable file indexing by default in Baloo:
+cat $CWD/patch/baloo5/baloo_def_indexing_disabled.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; }
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/baloo5/baloo_def_indexing_disabled.patch b/kde/patch/baloo5/baloo_def_indexing_disabled.patch
new file mode 100644
index 0000000..8a12e45
--- /dev/null
+++ b/kde/patch/baloo5/baloo_def_indexing_disabled.patch
@@ -0,0 +1,12 @@
+diff -uar baloo-5.72.0.orig/src/lib/baloosettings.kcfg baloo-5.72.0/src/lib/baloosettings.kcfg
+--- baloo-5.72.0.orig/src/lib/baloosettings.kcfg 2020-07-04 15:03:02.000000000 +0200
++++ baloo-5.72.0/src/lib/baloosettings.kcfg 2020-07-29 19:51:58.891567902 +0200
+@@ -9,7 +9,7 @@
+ <group name="Basic Settings">
+ <entry name="indexingEnabled" key="Indexing-Enabled" type="Bool">
+ <label>Indexing-Enabled</label>
+- <default>true</default>
++ <default>false</default>
+ </entry>
+ </group>
+ <group name="General">
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.patch b/kde/patch/calligraplan.patch
index 4cc1f85..5895d0c 100644
--- a/kde/patch/calligraplan.patch
+++ b/kde/patch/calligraplan.patch
@@ -1,11 +1,2 @@
-# Fix build against Qt 5.11 (fixed in 3.2.0):
-#cat $CWD/patch/calligraplan/calligraplan.qt-511.patch | patch -p2 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; }
-
-# Fix build against kcalendarcore (fixed in 3.2.0):
-#cat $CWD/patch/calligraplan/calligraplan.kcalcore.1.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; }
-#cat $CWD/patch/calligraplan/calligraplan.kcalcore.2.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; }
-#cat $CWD/patch/calligraplan/calligraplan.kcalendarcore.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; }
-
-# Fix missing include (fixed in 3.2.0):
-#cat $CWD/patch/calligraplan/calligraplan.missingheader.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; }
-
+# Fix build against Qt 5.15:
+cat $CWD/patch/calligraplan/calligraplan.qt-5.15.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; }
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-5.15.patch b/kde/patch/calligraplan/calligraplan.qt-5.15.patch
new file mode 100644
index 0000000..c8962a1
--- /dev/null
+++ b/kde/patch/calligraplan/calligraplan.qt-5.15.patch
@@ -0,0 +1,10 @@
+--- ./src/libs/ui/kptganttitemdelegate.cpp.orig 2019-12-12 05:48:13.000000000 -0600
++++ ./src/libs/ui/kptganttitemdelegate.cpp 2020-07-18 14:48:48.058351438 -0500
+@@ -28,6 +28,7 @@
+ #include <QModelIndex>
+ #include <QApplication>
+ #include <QPainter>
++#include <QPainterPath>
+ #include <QLocale>
+
+ #include <KLocalizedString>
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 &regexp = 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 &regexp = 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