File indexing completed on 2025-01-19 03:55:48

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2012-01-18
0007  * Description : database worker interface
0008  *
0009  * SPDX-FileCopyrightText: 2012 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0010  *
0011  * SPDX-License-Identifier: GPL-2.0-or-later
0012  *
0013  * ============================================================ */
0014 
0015 #include "databaseworkeriface.h"
0016 
0017 // KDE includes
0018 
0019 #include <klocalizedstring.h>
0020 
0021 // Local includes
0022 
0023 #include "digikam_debug.h"
0024 #include "collectionscanner.h"
0025 #include "coredboperationgroup.h"
0026 #include "iteminfotasksplitter.h"
0027 #include "fileactionmngr_p.h"
0028 #include "scancontroller.h"
0029 #include "disjointmetadata.h"
0030 #include "faceutils.h"
0031 
0032 namespace Digikam
0033 {
0034 
0035 void FileActionMngrDatabaseWorker::assignTags(const FileActionItemInfoList& infos, const QList<int>& tagIDs)
0036 {
0037     changeTags(infos, tagIDs, true);
0038 }
0039 
0040 void FileActionMngrDatabaseWorker::removeTags(const FileActionItemInfoList& infos, const QList<int>& tagIDs)
0041 {
0042     changeTags(infos, tagIDs, false);
0043 }
0044 
0045 void FileActionMngrDatabaseWorker::changeTags(const FileActionItemInfoList& infos,
0046                                               const QList<int>& tagIDs, bool addOrRemove)
0047 {
0048     DisjointMetadata hub;
0049     QList<ItemInfo> forWriting;
0050 
0051     {
0052         CoreDbOperationGroup group;
0053         group.setMaximumTime(200);
0054 
0055         Q_FOREACH (const ItemInfo& info, infos)
0056         {
0057             if (state() == WorkerObject::Deactivating)
0058             {
0059                 break;
0060             }
0061 
0062             hub.load(info);
0063 
0064             for (QList<int>::const_iterator tagIt = tagIDs.constBegin() ; tagIt != tagIDs.constEnd() ; ++tagIt)
0065             {
0066                 if (addOrRemove)
0067                 {
0068                     hub.setTag(*tagIt, DisjointMetadataDataFields::MetadataAvailable);
0069                 }
0070                 else
0071                 {
0072                     hub.setTag(*tagIt, DisjointMetadataDataFields::MetadataInvalid);
0073                 }
0074             }
0075 
0076             hub.write(info, DisjointMetadata::PartialWrite);
0077 
0078             if (hub.willWriteMetadata(DisjointMetadata::FullWriteIfChanged) &&
0079                 d->shallSendForWriting(info.id()))
0080             {
0081                 forWriting << info;
0082             }
0083 
0084             infos.dbProcessedOne();
0085             group.allowLift();
0086         }
0087     }
0088 
0089     // send for writing file metadata
0090 
0091     if (!forWriting.isEmpty())
0092     {
0093         FileActionItemInfoList forWritingTaskList = FileActionItemInfoList::continueTask(forWriting, infos.progress());
0094         forWritingTaskList.schedulingForWrite(i18n("Writing metadata to files"), d->fileProgressCreator());
0095 
0096         qCDebug(DIGIKAM_GENERAL_LOG) << "Scheduled to write";
0097 
0098         for (ItemInfoTaskSplitter splitter(forWritingTaskList) ; splitter.hasNext() ; )
0099         {
0100             Q_EMIT writeMetadata(FileActionItemInfoList(splitter.next()), MetadataHub::WRITE_TAGS);
0101         }
0102     }
0103 
0104     infos.dbFinished();
0105 }
0106 
0107 void FileActionMngrDatabaseWorker::assignPickLabel(const FileActionItemInfoList& infos, int pickId)
0108 {
0109     DisjointMetadata hub;
0110     QList<ItemInfo> forWriting;
0111 
0112     {
0113         CoreDbOperationGroup group;
0114         group.setMaximumTime(200);
0115 
0116         Q_FOREACH (const ItemInfo& info, infos)
0117         {
0118             if (state() == WorkerObject::Deactivating)
0119             {
0120                 break;
0121             }
0122 
0123             hub.load(info);
0124             hub.setPickLabel(pickId);
0125             hub.write(info, DisjointMetadata::PartialWrite);
0126 
0127             if (hub.willWriteMetadata(DisjointMetadata::FullWriteIfChanged) &&
0128                 d->shallSendForWriting(info.id()))
0129             {
0130                 forWriting << info;
0131             }
0132 
0133             infos.dbProcessedOne();
0134             group.allowLift();
0135         }
0136     }
0137 
0138     // send for writing file metadata
0139 
0140     if (!forWriting.isEmpty())
0141     {
0142         FileActionItemInfoList forWritingTaskList = FileActionItemInfoList::continueTask(forWriting, infos.progress());
0143         forWritingTaskList.schedulingForWrite(i18n("Writing metadata to files"), d->fileProgressCreator());
0144 
0145         for (ItemInfoTaskSplitter splitter(forWritingTaskList) ; splitter.hasNext() ; )
0146         {
0147             Q_EMIT writeMetadata(FileActionItemInfoList(splitter.next()), MetadataHub::WRITE_PICKLABEL);
0148         }
0149     }
0150 
0151     infos.dbFinished();
0152 }
0153 
0154 void FileActionMngrDatabaseWorker::assignColorLabel(const FileActionItemInfoList& infos, int colorId)
0155 {
0156     DisjointMetadata hub;
0157     QList<ItemInfo> forWriting;
0158 
0159     {
0160         CoreDbOperationGroup group;
0161         group.setMaximumTime(200);
0162 
0163         Q_FOREACH (const ItemInfo& info, infos)
0164         {
0165             if (state() == WorkerObject::Deactivating)
0166             {
0167                 break;
0168             }
0169 
0170             hub.load(info);
0171             hub.setColorLabel(colorId);
0172             hub.write(info, DisjointMetadata::PartialWrite);
0173 
0174             if (hub.willWriteMetadata(DisjointMetadata::FullWriteIfChanged) &&
0175                 d->shallSendForWriting(info.id()))
0176             {
0177                 forWriting << info;
0178             }
0179 
0180             infos.dbProcessedOne();
0181             group.allowLift();
0182         }
0183     }
0184 
0185     // send for writing file metadata
0186 
0187     if (!forWriting.isEmpty())
0188     {
0189         FileActionItemInfoList forWritingTaskList = FileActionItemInfoList::continueTask(forWriting, infos.progress());
0190         forWritingTaskList.schedulingForWrite(i18n("Writing metadata to files"), d->fileProgressCreator());
0191 
0192         for (ItemInfoTaskSplitter splitter(forWritingTaskList) ; splitter.hasNext() ; )
0193         {
0194             Q_EMIT writeMetadata(FileActionItemInfoList(splitter.next()), MetadataHub::WRITE_COLORLABEL);
0195         }
0196     }
0197 
0198     infos.dbFinished();
0199 }
0200 
0201 void FileActionMngrDatabaseWorker::assignRating(const FileActionItemInfoList& infos, int rating)
0202 {
0203     DisjointMetadata hub;
0204     QList<ItemInfo> forWriting;
0205     rating = qMin(RatingMax, qMax(RatingMin, rating));
0206 
0207     {
0208         CoreDbOperationGroup group;
0209         group.setMaximumTime(200);
0210 
0211         Q_FOREACH (const ItemInfo& info, infos)
0212         {
0213             if (state() == WorkerObject::Deactivating)
0214             {
0215                 break;
0216             }
0217 
0218             hub.load(info);
0219             hub.setRating(rating);
0220             hub.write(info, DisjointMetadata::PartialWrite);
0221 
0222             if (hub.willWriteMetadata(DisjointMetadata::FullWriteIfChanged) &&
0223                 d->shallSendForWriting(info.id()))
0224             {
0225                 forWriting << info;
0226             }
0227 
0228             infos.dbProcessedOne();
0229             group.allowLift();
0230         }
0231     }
0232 
0233     // send for writing file metadata
0234 
0235     if (!forWriting.isEmpty())
0236     {
0237         FileActionItemInfoList forWritingTaskList = FileActionItemInfoList::continueTask(forWriting, infos.progress());
0238         forWritingTaskList.schedulingForWrite(i18n("Writing metadata to files"), d->fileProgressCreator());
0239 
0240         for (ItemInfoTaskSplitter splitter(forWritingTaskList) ; splitter.hasNext() ; )
0241         {
0242             Q_EMIT writeMetadata(FileActionItemInfoList(splitter.next()), MetadataHub::WRITE_RATING);
0243         }
0244     }
0245 
0246     infos.dbFinished();
0247 }
0248 
0249 void FileActionMngrDatabaseWorker::editGroup(int groupAction, const ItemInfo& pick, const FileActionItemInfoList& infos)
0250 {
0251     {
0252         CoreDbOperationGroup group;
0253         group.setMaximumTime(200);
0254 
0255         Q_FOREACH (const ItemInfo& constInfo, infos)
0256         {
0257             if (state() == WorkerObject::Deactivating)
0258             {
0259                 break;
0260             }
0261 
0262             ItemInfo info(constInfo);
0263 
0264             switch (groupAction)
0265             {
0266                 case AddToGroup:
0267                 {
0268                     info.addToGroup(pick);
0269                     break;
0270                 }
0271 
0272                 case RemoveFromGroup:
0273                 {
0274                     info.removeFromGroup();
0275                     break;
0276                 }
0277 
0278                 case Ungroup:
0279                 {
0280                     info.clearGroup();
0281                     break;
0282                 }
0283             }
0284 
0285             infos.dbProcessedOne();
0286             group.allowLift();
0287         }
0288     }
0289 
0290     infos.dbFinished();
0291 }
0292 
0293 void FileActionMngrDatabaseWorker::setExifOrientation(const FileActionItemInfoList& infos, int orientation)
0294 {
0295     {
0296         CoreDbOperationGroup group;
0297         group.setMaximumTime(200);
0298 
0299         Q_FOREACH (ItemInfo info, infos)
0300         {
0301             if (state() == WorkerObject::Deactivating)
0302             {
0303                 break;
0304             }
0305 
0306             // Adjust Faces
0307 
0308             FaceUtils().rotateFaces(info.id(), info.dimensions(),
0309                                     info.orientation(), orientation);
0310 
0311             info.setOrientation(orientation);
0312         }
0313     }
0314 
0315     infos.dbProcessed(infos.count());
0316     infos.schedulingForWrite(infos.count(), i18n("Revising Exif Orientation tags"), d->fileProgressCreator());
0317 
0318     for (ItemInfoTaskSplitter splitter(infos) ; splitter.hasNext() ; )
0319     {
0320         Q_EMIT writeOrientationToFiles(FileActionItemInfoList(splitter.next()), orientation);
0321     }
0322 
0323     infos.dbFinished();
0324 }
0325 
0326 void FileActionMngrDatabaseWorker::applyMetadata(const FileActionItemInfoList& infos,
0327                                                  DisjointMetadata* hub)
0328 {
0329     {
0330         CoreDbOperationGroup group;
0331         group.setMaximumTime(200);
0332 
0333         Q_FOREACH (const ItemInfo& info, infos)
0334         {
0335             if (state() == WorkerObject::Deactivating)
0336             {
0337                 break;
0338             }
0339 
0340             // apply to database
0341 
0342             hub->write(info);
0343             infos.dbProcessedOne();
0344             group.allowLift();
0345         }
0346     }
0347 
0348     if (hub->willWriteMetadata(DisjointMetadata::FullWriteIfChanged))
0349     {
0350         int flags = hub->changedFlags();
0351 
0352         // don't filter by shallSendForWriting here; we write from the hub, not from freshly loaded data
0353 
0354         infos.schedulingForWrite(infos.size(), i18n("Writing metadata to files"), d->fileProgressCreator());
0355 
0356         for (ItemInfoTaskSplitter splitter(infos) ; splitter.hasNext() ; )
0357         {
0358             Q_EMIT writeMetadata(FileActionItemInfoList(splitter.next()), flags);
0359         }
0360     }
0361 
0362     delete hub;
0363     infos.dbFinished();
0364 }
0365 
0366 void FileActionMngrDatabaseWorker::copyAttributes(const FileActionItemInfoList& infos, const QStringList& derivedPaths)
0367 {
0368     if (infos.size() == 1)
0369     {
0370         Q_FOREACH (const QString& path, derivedPaths)
0371         {
0372             if (state() == WorkerObject::Deactivating)
0373             {
0374                 break;
0375             }
0376 
0377             ItemInfo dest = ScanController::instance()->scannedInfo(path);
0378             CollectionScanner::copyFileProperties(infos.first(), dest);
0379         }
0380 
0381         infos.dbProcessedOne();
0382     }
0383 
0384     infos.dbFinished();
0385 }
0386 
0387 } // namespace Digikam
0388 
0389 #include "moc_databaseworkeriface.cpp"