File indexing completed on 2025-01-05 03:54:17
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2005-10-28 0007 * Description : scan item controller - start operations. 0008 * 0009 * SPDX-FileCopyrightText: 2005-2006 by Tom Albers <tomalbers at kde dot nl> 0010 * SPDX-FileCopyrightText: 2006-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0011 * SPDX-FileCopyrightText: 2007-2013 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0012 * 0013 * SPDX-License-Identifier: GPL-2.0-or-later 0014 * 0015 * ============================================================ */ 0016 0017 #include "scancontroller_p.h" 0018 0019 namespace Digikam 0020 { 0021 0022 void ScanController::restart() 0023 { 0024 if (isRunning()) 0025 { 0026 return; 0027 } 0028 0029 d->running = true; 0030 d->scanSuspended = 0; 0031 start(); 0032 } 0033 0034 ScanController::Advice ScanController::databaseInitialization() 0035 { 0036 d->advice = Success; 0037 createProgressDialog(); 0038 setInitializationMessage(); 0039 0040 { 0041 QMutexLocker lock(&d->mutex); 0042 d->needsInitialization = true; 0043 d->condVar.wakeAll(); 0044 } 0045 0046 // NOTE: loop is quit by signal 0047 0048 d->eventLoop->exec(); 0049 0050 // setup file watch service for LoadingCache - now that we are sure we have a CoreDbWatch 0051 0052 if (!d->fileWatchInstalled) 0053 { 0054 d->fileWatchInstalled = true; // once per application lifetime only 0055 LoadingCache* const cache = LoadingCache::cache(); 0056 LoadingCache::CacheLock lock(cache); 0057 cache->setFileWatch(new ScanControllerLoadingCacheFileWatch); 0058 } 0059 0060 delete d->progressDialog; 0061 d->progressDialog = nullptr; 0062 0063 return d->advice; 0064 } 0065 0066 void ScanController::completeCollectionScanDeferFiles() 0067 { 0068 completeCollectionScan(true); 0069 } 0070 0071 void ScanController::completeCollectionScan(bool defer) 0072 { 0073 createProgressDialog(); 0074 0075 // we only need to count the files in advance 0076 // if we show a progress percentage in progress dialog 0077 0078 completeCollectionScanCore(!CollectionScanner::databaseInitialScanDone(), defer, false); 0079 0080 delete d->progressDialog; 0081 d->progressDialog = nullptr; 0082 } 0083 0084 void ScanController::completeCollectionScanInBackground(bool defer, bool fastScan) 0085 { 0086 completeCollectionScanCore(true, defer, fastScan); 0087 } 0088 0089 void ScanController::completeCollectionScanCore(bool needTotalFiles, bool defer, bool fastScan) 0090 { 0091 d->performFastScan = fastScan; 0092 d->needTotalFiles = needTotalFiles; 0093 0094 { 0095 QMutexLocker lock(&d->mutex); 0096 d->needsCompleteScan = true; 0097 d->deferFileScanning = defer; 0098 d->condVar.wakeAll(); 0099 } 0100 0101 // NOTE: loop is quit by signal 0102 0103 d->eventLoop->exec(); 0104 0105 d->needTotalFiles = false; 0106 d->performFastScan = true; 0107 } 0108 0109 void ScanController::scheduleCollectionScan(const QString& path) 0110 { 0111 QMutexLocker lock(&d->mutex); 0112 0113 if (!d->scanTasks.contains(path)) 0114 { 0115 d->scanTasks << path; 0116 } 0117 0118 d->condVar.wakeAll(); 0119 } 0120 0121 void ScanController::scheduleCollectionScanRelaxed(const QString& path) 0122 { 0123 if (!d->relaxedTimer->isActive()) 0124 { 0125 d->relaxedTimer->start(); 0126 } 0127 0128 QMutexLocker lock(&d->mutex); 0129 0130 if (!d->scanTasks.contains(path)) 0131 { 0132 d->scanTasks << path; 0133 } 0134 } 0135 0136 void ScanController::scheduleCollectionScanExternal(const QString& path) 0137 { 0138 d->externalTimer->start(); 0139 0140 QMutexLocker lock(&d->mutex); 0141 0142 if (!d->scanTasks.contains(path)) 0143 { 0144 d->scanTasks << path; 0145 } 0146 } 0147 0148 void ScanController::scanFileDirectly(const QString& filePath) 0149 { 0150 suspendCollectionScan(); 0151 0152 CollectionScanner scanner; 0153 scanner.setHintContainer(d->hints); 0154 scanner.scanFile(filePath); 0155 0156 resumeCollectionScan(); 0157 } 0158 0159 void ScanController::scanFileDirectlyNormal(const ItemInfo& info) 0160 { 0161 CollectionScanner scanner; 0162 scanner.setHintContainer(d->hints); 0163 scanner.scanFile(info, CollectionScanner::NormalScan); 0164 } 0165 0166 /* 0167 /// This variant shall be used when a new file is created which is a version 0168 /// of another image, and all relevant attributes shall be copied. 0169 void scanFileDirectlyCopyAttributes(const QString& filePath, qlonglong parentVersion); 0170 0171 void ScanController::scanFileDirectlyCopyAttributes(const QString& filePath, qlonglong parentVersion) 0172 { 0173 suspendCollectionScan(); 0174 0175 CollectionScanner scanner; 0176 scanner.recordHints(d->itemHints); 0177 scanner.recordHints(d->itemChangeHints); 0178 qlonglong id = scanner.scanFile(filePath); 0179 ItemInfo dest(id), source(parentVersion); 0180 scanner.copyFileProperties(source, dest); 0181 0182 resumeCollectionScan(); 0183 } 0184 */ 0185 0186 void ScanController::resumeCollectionScan() 0187 { 0188 QMutexLocker lock(&d->mutex); 0189 0190 if (d->scanSuspended) 0191 { 0192 d->scanSuspended--; 0193 } 0194 0195 if (!d->scanSuspended) 0196 { 0197 d->condVar.wakeAll(); 0198 } 0199 } 0200 0201 void ScanController::restartCollectionScan() 0202 { 0203 QMutexLocker lock(&d->mutex); 0204 0205 if (d->scanSuspended) 0206 { 0207 d->scanSuspended = 0; 0208 d->condVar.wakeAll(); 0209 } 0210 } 0211 0212 void ScanController::slotStartCompleteScan() 0213 { 0214 d->totalFilesToScan = 0; 0215 slotTriggerShowProgressDialog(); 0216 0217 QString message = i18n("Preparing collection scan..."); 0218 0219 if (d->progressDialog) 0220 { 0221 d->progressDialog->addedAction(d->restartPixmap(), message); 0222 } 0223 } 0224 0225 void ScanController::slotStartScanningAlbum(const QString& albumRoot, const QString& album) 0226 { 0227 Q_UNUSED(albumRoot); 0228 0229 if (d->progressDialog) 0230 { 0231 d->progressDialog->addedAction(d->albumPixmap(), QLatin1Char(' ') + album); 0232 } 0233 } 0234 0235 void ScanController::slotStartScanningAlbumRoot(const QString& albumRoot) 0236 { 0237 if (d->progressDialog) 0238 { 0239 d->progressDialog->addedAction(d->rootPixmap(), albumRoot); 0240 } 0241 } 0242 0243 void ScanController::slotStartScanningForStaleAlbums() 0244 { 0245 QString message = i18n("Scanning for removed albums..."); 0246 0247 if (d->progressDialog) 0248 { 0249 d->progressDialog->addedAction(d->actionPixmap(), message); 0250 } 0251 } 0252 0253 void ScanController::slotStartScanningAlbumRoots() 0254 { 0255 QString message = i18n("Scanning images in individual albums..."); 0256 0257 if (d->progressDialog) 0258 { 0259 d->progressDialog->addedAction(d->actionPixmap(), message); 0260 } 0261 } 0262 0263 void ScanController::beginFileMetadataWrite(const ItemInfo& info) 0264 { 0265 { 0266 // throw in a lock to synchronize with all parallel writing 0267 FileReadLocker locker(info.filePath()); 0268 } 0269 0270 QFileInfo fi(info.filePath()); 0271 d->hints->recordHint(ItemMetadataAdjustmentHint(info.id(), 0272 ItemMetadataAdjustmentHint::AboutToEditMetadata, 0273 fi.lastModified(), 0274 fi.size())); 0275 } 0276 0277 } // namespace Digikam