1 // SPDX-FileCopyrightText: 2003-2020 The KPhotoAlbum Development Team 2 // SPDX-FileCopyrightText: 2021 Johannes Zarl-Zierl <johannes@zarl-zierl.at> 3 // 4 // SPDX-License-Identifier: GPL-2.0-or-later 5 6 #ifndef IMAGEDB_H 7 #define IMAGEDB_H 8 9 #include "Category.h" 10 #include "ImageDateCollection.h" 11 #include "ImageInfoList.h" 12 #include "ImageInfoPtr.h" 13 #include "ImageSearchInfo.h" 14 #include "MediaCount.h" 15 16 #include <kpabase/FileNameList.h> 17 18 #include <QObject> 19 #include <memory> 20 21 class QProgressBar; 22 23 namespace DB 24 { 25 26 class CategoryCollection; 27 class Category; 28 class MD5Map; 29 class MemberMap; 30 class FileName; 31 class UIDelegate; 32 33 /** 34 * @brief The ClassificationMode enum can be used to short-circuit classification in the classify() method. 35 * This allows you to only check whether a given category has more than one sub-category (including the "No other" category). 36 * In other words, you can use a partial count when all you want to know is whether further search refinement is possible 37 * in a category. 38 * @see ImageDB::classify() 39 * @see Browser::OverviewPage::updateImageCount() 40 */ 41 enum class ClassificationMode { 42 FullCount ///< @brief run a full classification. This is normally what you want. 43 , 44 PartialCount ///< @brief Count until at least 2 categories are found 45 }; 46 47 class ImageDB : public QObject 48 { 49 Q_OBJECT 50 51 public: 52 static ImageDB *instance(); 53 static void setupXMLDB(const QString &configFile, UIDelegate &delegate); 54 static void deleteInstance(); 55 static QString NONE(); 56 57 DB::FileNameSet imagesWithMD5Changed(); 58 UIDelegate &uiDelegate() const; 59 DB::FileNameList currentScope(bool requireOnDisk) const; 60 61 virtual DB::FileName findFirstItemInRange( 62 const FileNameList &files, 63 const ImageDate &range, 64 bool includeRanges) const; 65 66 bool untaggedCategoryFeatureConfigured() const; 67 68 virtual uint totalCount() const = 0; 69 virtual DB::ImageInfoList search(const ImageSearchInfo &, bool requireOnDisk = false) const = 0; 70 71 virtual void renameCategory(const QString &oldName, const QString newName) = 0; 72 73 /** 74 * @brief classify computes a histogram of tags within a category. 75 * I.e. for each sub-category within a given category it counts all images matching the current context, and 76 * computes the date range for those images. 77 * 78 * @param info ImageSearchInfo describing the current search context 79 * @param category the category for which images should be classified 80 * @param typemask images/videos/both 81 * @param mode whether accurate counts are required or not 82 * @return a mapping of sub-category (tags/tag-groups) to the number of images (and the associated date range) 83 */ 84 virtual QMap<QString, CountWithRange> classify(const ImageSearchInfo &info, const QString &category, MediaType typemask, ClassificationMode mode = ClassificationMode::FullCount) = 0; 85 virtual FileNameList files(MediaType type = anyMediaType) const = 0; 86 virtual ImageInfoList images() const = 0; 87 /** 88 * @brief addImages to the database. 89 * The parameter \p doUpdate decides whether all bookkeeping should be done right away 90 * (\c true; the "normal" use-case), or if it should be deferred until later(\c false). 91 * If doUpdate is deferred, either commitDelayedImages() or clearDelayedImages() needs to be called afterwards. 92 * @param files 93 * @param doUpdate 94 */ 95 virtual void addImages(const ImageInfoList &files, bool doUpdate = true) = 0; 96 virtual void commitDelayedImages() = 0; 97 virtual void clearDelayedImages() = 0; 98 /** @short Update file name stored in the DB */ 99 virtual void renameImage(const ImageInfoPtr info, const DB::FileName &newName) = 0; 100 101 virtual void addToBlockList(const DB::FileNameList &list) = 0; 102 virtual bool isBlocking(const DB::FileName &fileName) = 0; 103 virtual void deleteList(const DB::FileNameList &list) = 0; 104 virtual ImageInfoPtr info(const DB::FileName &fileName) const = 0; 105 virtual MemberMap &memberMap() = 0; 106 virtual void save(const QString &fileName, bool isAutoSave) = 0; 107 virtual MD5Map *md5Map() = 0; 108 virtual void sortAndMergeBackIn(const DB::FileNameList &list) = 0; 109 110 virtual CategoryCollection *categoryCollection() = 0; 111 virtual const CategoryCollection *categoryCollection() const = 0; 112 virtual QExplicitlySharedDataPointer<ImageDateCollection> rangeCollection() = 0; 113 114 /** 115 * Reorder the items in the database by placing all the items given in 116 * cutList directly before or after the given item. 117 * If the parameter "after" determines where to place it. 118 */ 119 virtual void reorder(const DB::FileName &item, const DB::FileNameList &cutList, bool after) = 0; 120 121 /** @short Create a stack of images/videos/whatever 122 * 123 * If the specified images already belong to different stacks, then no 124 * change happens and the function returns false. 125 * 126 * If some of them are in one stack and others aren't stacked at all, then 127 * the unstacked will be added to the existing stack and we return true. 128 * 129 * If none of them are stacked, then a new stack is created and we return 130 * true. 131 * 132 * All images which previously weren't in the stack are added in order they 133 * are present in the provided list and after all items that are already in 134 * the stack. The order of images which were already in the stack is not 135 * changed. 136 * */ 137 virtual bool stack(const DB::FileNameList &items) = 0; 138 139 /** @short Remove all images from whichever stacks they might be in 140 * 141 * We might destroy some stacks in the process if they become empty or just 142 * containing one image. 143 * 144 * This function doesn't touch the order of images at all. 145 * */ 146 virtual void unstack(const DB::FileNameList &files) = 0; 147 148 /** @short Return a list of images which are in the same stack as the one specified. 149 * 150 * Returns an empty list when the image is not stacked. 151 * 152 * They are returned sorted according to their stackOrder. 153 * */ 154 virtual DB::FileNameList getStackFor(const DB::FileName &referenceId) const = 0; 155 156 virtual void copyData(const DB::FileName &from, const DB::FileName &to) = 0; 157 158 Exif::Database *exifDB() const; 159 160 public slots: 161 void setDateRange(const ImageDate &, bool includeFuzzyCounts); 162 void clearDateRange(); 163 virtual void slotRescan(); 164 void slotRecalcCheckSums(const DB::FileNameList &selection); 165 virtual MediaCount count(const ImageSearchInfo &info); 166 virtual void slotReread(const DB::FileNameList &list, DB::ExifMode mode); 167 void setCurrentScope(const DB::ImageSearchInfo &info); 168 169 signals: 170 void totalChanged(uint); 171 void dirty(); 172 void imagesDeleted(const DB::FileNameList &); 173 174 protected: 175 ImageDB(UIDelegate &delegate); 176 ImageDate m_selectionRange; 177 bool m_includeFuzzyCounts; 178 ImageInfoList m_clipboard; 179 UIDelegate &m_UI; 180 std::unique_ptr<Exif::Database> m_exifDB; 181 182 protected slots: 183 virtual void lockDB(bool lock, bool exclude) = 0; 184 void markDirty(); 185 186 private: 187 static void connectSlots(); 188 static ImageDB *s_instance; 189 DB::ImageSearchInfo m_currentScope; 190 }; 191 } 192 #endif /* IMAGEDB_H */ 193 194 // vi:expandtab:tabstop=4 shiftwidth=4: 195