File indexing completed on 2025-01-05 03:53:54
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2007-03-21 0007 * Description : Collection scanning to database. 0008 * 0009 * SPDX-FileCopyrightText: 2005 by Renchi Raju <renchi dot raju at gmail dot com> 0010 * SPDX-FileCopyrightText: 2005-2006 by Tom Albers <tomalbers at kde dot nl> 0011 * SPDX-FileCopyrightText: 2007-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0012 * SPDX-FileCopyrightText: 2009-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0013 * 0014 * SPDX-License-Identifier: GPL-2.0-or-later 0015 * 0016 * ============================================================ */ 0017 0018 #ifndef DIGIKAM_COLLECTION_SCANNER_H 0019 #define DIGIKAM_COLLECTION_SCANNER_H 0020 0021 // Qt includes 0022 0023 #include <QString> 0024 #include <QObject> 0025 #include <QList> 0026 0027 // Local includes 0028 0029 #include "iteminfo.h" 0030 #include "digikam_export.h" 0031 #include "coredbaccess.h" 0032 #include "coredbalbuminfo.h" 0033 #include "collectionscannerhints.h" 0034 0035 class QFileInfo; 0036 0037 namespace Digikam 0038 { 0039 0040 class DIGIKAM_DATABASE_EXPORT CollectionScanner : public QObject 0041 { 0042 Q_OBJECT 0043 0044 public: 0045 0046 enum FileScanMode 0047 { 0048 /** 0049 * The file will be scanned like it is done for any usual scan. 0050 * If it was not modified, no further action is taken. 0051 * If the file is not known yet, it will be fully scanned, or, 0052 * if an identical file is found, this data will be copied. 0053 */ 0054 NormalScan, 0055 0056 /** 0057 * The file will scanned like a modified file. Only a selected portion 0058 * of the metadata will be updated into the database. 0059 * If the file is not known yet, it will be fully scanned, or, 0060 * if an identical file is found, this data will be copied. 0061 */ 0062 ModifiedScan, 0063 0064 /** 0065 * The file will be scanned like a completely new file. 0066 * The complete metadata is re-read into the database. 0067 * No search for identical files will be done. 0068 */ 0069 Rescan, 0070 0071 /** 0072 * This is the same as Rescan but the database metadata 0073 * will be cleaned up if the corresponding metadata 0074 * write option is enabled. 0075 */ 0076 CleanScan 0077 }; 0078 0079 public: 0080 0081 explicit CollectionScanner(); 0082 ~CollectionScanner() override; 0083 0084 //@{ 0085 /** 0086 * Hints give the scanner additional info about things that happened in the past 0087 * carried out by higher level which the collection scanner cannot know. 0088 * They allow to carry out optimizations. 0089 * Record hints in a container, and provide the container to the collection scanner. 0090 * The Container set in setHintContainer must be one created by createContainer. 0091 */ 0092 static CollectionScannerHintContainer* createHintContainer(); 0093 void setHintContainer(CollectionScannerHintContainer* const container); 0094 void setUpdateHashHint(bool hint = true); 0095 //@} 0096 0097 /** 0098 * Call this to enable the progress info signals. 0099 * Default is off. 0100 */ 0101 void setSignalsEnabled(bool on); 0102 0103 /** 0104 * Call this to enable emitting the total files to scan 0105 * (for progress info) before a complete collection scan. 0106 * Default is off. If on, setSignalEnabled() must be on to take effect. 0107 */ 0108 void setNeedFileCount(bool on); 0109 0110 /** 0111 * Call this to disable fast scan with album date check. 0112 * Default is on. 0113 */ 0114 void setPerformFastScan(bool on); 0115 0116 /** 0117 * Set an observer to be able to cancel a running scan 0118 */ 0119 void setObserver(CollectionScannerObserver* const observer); 0120 0121 void setDeferredFileScanning(bool defer); 0122 QStringList deferredAlbumPaths() const; 0123 0124 /** 0125 * Returns item ids from new detected items 0126 */ 0127 QList<qlonglong> getNewIdsList() const; 0128 0129 // ----------------------------------------------------------------------------- 0130 0131 /** @name Scan operations 0132 */ 0133 0134 //@{ 0135 0136 public: 0137 0138 /** 0139 * Carries out a full scan on all available parts of the collection. 0140 * Only a full scan can finally remove deleted files from the database, 0141 * only a full scan will mark the database as scanned. 0142 * The database will be locked while running (Note: this is not done for partialScans). 0143 */ 0144 void completeScan(); 0145 0146 /** 0147 * If you enable deferred file scanning for a completeScan(), new files 0148 * will not be scanned. The relevant albums are available from 0149 * deferredAlbumPaths() when completeScan() has finished. 0150 * You need to call finishCompleteScan() afterwards with the list 0151 * to get the same complete scan than undeferred completeScan(). 0152 */ 0153 void finishCompleteScan(const QStringList& albumPaths); 0154 0155 /** 0156 * Returns if the initial scan of the database has been done. 0157 * This is the first complete scan after creation of a new database file 0158 * (or update requiring a rescan) 0159 */ 0160 static bool databaseInitialScanDone(); 0161 0162 /** 0163 * Carries out a partial scan on the specified path of the collection. 0164 * The includes scanning for new files + albums and updating modified file data. 0165 * Files no longer found in the specified path however are not completely 0166 * removed, but only marked as removed. They will be removed only after a complete scan. 0167 */ 0168 void partialScan(const QString& filePath); 0169 0170 /** 0171 * Same procedure as above, but albumRoot and album is provided. 0172 */ 0173 void partialScan(const QString& albumRoot, const QString& album); 0174 0175 /** 0176 * The given file will be scanned according to the given mode. 0177 * Returns the image id of the file. 0178 */ 0179 qlonglong scanFile(const QString& filePath, FileScanMode mode = ModifiedScan); 0180 0181 /** 0182 * Same procedure as above, but albumRoot and album is provided. 0183 * If you already have this info it need not be retrieved. 0184 * Returns the image id of the file, or -1 on failure. 0185 */ 0186 qlonglong scanFile(const QString& albumRoot, 0187 const QString& album, 0188 const QString& fileName, 0189 FileScanMode mode = ModifiedScan); 0190 0191 /** 0192 * The given file represented by the ItemInfo will be scanned according to mode 0193 */ 0194 void scanFile(const ItemInfo& info, FileScanMode mode = ModifiedScan); 0195 0196 protected: 0197 0198 void scanForStaleAlbums(const QList<CollectionLocation>& locations); 0199 void scanForStaleAlbums(const QList<int>& locationIdsToScan); 0200 void scanAlbumRoot(const CollectionLocation& location); 0201 void scanAlbum(const CollectionLocation& location, const QString& album, bool checkDate = false); 0202 void scanExistingFile(const QFileInfo& fi, qlonglong id); 0203 void scanFileNormal(const QFileInfo& info, const ItemScanInfo& scanInfo, 0204 bool checkSidecar = true, const QFileInfo* const sidecarInfo = nullptr); 0205 void scanModifiedFile(const QFileInfo& info, const ItemScanInfo& scanInfo); 0206 void scanFileUpdateHashReuseThumbnail(const QFileInfo& fi, const ItemScanInfo& scanInfo, bool fileWasEdited); 0207 void cleanScanFile(const QFileInfo& info, const ItemScanInfo& scanInfo); 0208 void rescanFile(const QFileInfo& info, const ItemScanInfo& scanInfo); 0209 void completeScanCleanupPart(); 0210 void completeHistoryScanning(); 0211 void finishHistoryScanning(); 0212 void historyScanningStage2(const QList<qlonglong>& ids); 0213 void historyScanningStage3(const QList<qlonglong>& ids); 0214 0215 qlonglong scanFile(const QFileInfo& fi, int albumId, qlonglong id, FileScanMode mode); 0216 qlonglong scanNewFile(const QFileInfo& info, int albumId); 0217 qlonglong scanNewFileFullScan(const QFileInfo& info, int albumId); 0218 0219 //@} 0220 0221 // ----------------------------------------------------------------------------- 0222 0223 /** @name Scan utilities 0224 */ 0225 0226 //@{ 0227 0228 public: 0229 0230 /** 0231 * Prepare the given albums to be removed, 0232 * typically by setting the albums as orphan 0233 * and removing all entries from the albums 0234 */ 0235 void safelyRemoveAlbums(const QList<int>& albumIds); 0236 0237 /** 0238 * When a file is derived from another file, typically through editing, 0239 * copy all relevant attributes from source file to the new file. 0240 */ 0241 static void copyFileProperties(const ItemInfo& source, const ItemInfo& dest); 0242 0243 protected: 0244 0245 void markDatabaseAsScanned(); 0246 void mainEntryPoint(bool complete); 0247 int checkAlbum(const CollectionLocation& location, const QString& album); 0248 void itemsWereRemoved(const QList<qlonglong>& removedIds); 0249 void updateRemovedItemsTime(); 0250 void incrementDeleteRemovedCompleteScanCount(); 0251 void resetDeleteRemovedSettings(); 0252 bool checkDeleteRemoved(); 0253 void loadNameFilters(); 0254 int countItemsInFolder(const QString& path); 0255 DatabaseItem::Category category(const QFileInfo& info); 0256 0257 //@} 0258 0259 Q_SIGNALS: 0260 0261 /** 0262 * Emitted once in scanAlbums(), the scan() methods, and updateItemsWithoutDate(). 0263 * Gives the number of the files that need to be scanned. 0264 */ 0265 void totalFilesToScan(int count); 0266 0267 //@{ 0268 /** 0269 * Notifies the begin of the scanning of the specified album root, 0270 * album, of stale files, or of the whole collection (after stale files) 0271 */ 0272 void startScanningAlbumRoot(const QString& albumRoot); 0273 void startScanningAlbum(const QString& albumRoot, const QString& album); 0274 void startScanningForStaleAlbums(); 0275 void startScanningAlbumRoots(); 0276 void startCompleteScan(); 0277 void signalScannedNewImage(const QFileInfo& info); 0278 //@} 0279 0280 //@{ 0281 /** 0282 * Emitted when the scanning has finished. 0283 * Note that start/finishScanningAlbum may be emitted recursively. 0284 */ 0285 void finishedScanningAlbumRoot(const QString& albumRoot); 0286 void finishedScanningAlbum(const QString& albumRoot, const QString& album, int filesScanned); 0287 void finishedScanningForStaleAlbums(); 0288 void finishedCompleteScan(); 0289 //@} 0290 0291 /** 0292 * Emitted between startScanningAlbum and finishedScanningAlbum. 0293 * In between these two signals, the sum of filesScanned of all sent signals 0294 * equals the one reported by finishedScanningAlbum() 0295 */ 0296 void scannedFiles(int filesScanned); 0297 0298 /** 0299 * Emitted when the observer told to cancel the scan 0300 */ 0301 void cancelled(); 0302 0303 private: 0304 0305 // Disable 0306 CollectionScanner(QObject*) = delete; 0307 0308 class Private; 0309 Private* const d; 0310 }; 0311 0312 } // namespace Digikam 0313 0314 #endif // DIGIKAM_COLLECTION_SCANNER_H