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 : 2009-05-05 0007 * Description : file action manager 0008 * 0009 * SPDX-FileCopyrightText: 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0010 * SPDX-FileCopyrightText: 2011-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0011 * 0012 * SPDX-License-Identifier: GPL-2.0-or-later 0013 * 0014 * ============================================================ */ 0015 0016 #include "fileactionmngr_p.h" 0017 0018 // Qt includes 0019 0020 #include <QPointer> 0021 #include <QProgressDialog> 0022 0023 // KDE includes 0024 0025 #include <klocalizedstring.h> 0026 0027 // Local includes 0028 0029 #include "digikam_debug.h" 0030 #include "applicationsettings.h" 0031 #include "iteminfotasksplitter.h" 0032 #include "loadingcacheinterface.h" 0033 #include "metadatahub.h" 0034 #include "metaenginesettings.h" 0035 #include "thumbnailloadthread.h" 0036 #include "disjointmetadata.h" 0037 0038 namespace Digikam 0039 { 0040 0041 class Q_DECL_HIDDEN FileActionMngrCreator 0042 { 0043 public: 0044 0045 FileActionMngr object; 0046 }; 0047 0048 Q_GLOBAL_STATIC(FileActionMngrCreator, metadataManagercreator) 0049 0050 FileActionMngr* FileActionMngr::instance() 0051 { 0052 return &metadataManagercreator->object; 0053 } 0054 0055 FileActionMngr::FileActionMngr() 0056 : d(new Private(this)) 0057 { 0058 0059 connect(d->fileWorker, SIGNAL(imageChangeFailed(QString,QStringList)), 0060 this, SIGNAL(signalImageChangeFailed(QString,QStringList))); 0061 } 0062 0063 FileActionMngr::~FileActionMngr() 0064 { 0065 shutDown(); 0066 delete d; 0067 } 0068 0069 bool FileActionMngr::requestShutDown() 0070 { 0071 if (!isActive()) 0072 { 0073 shutDown(); 0074 return true; 0075 } 0076 0077 QPointer<QProgressDialog> dialog = new QProgressDialog; 0078 dialog->setMinimum(0); 0079 dialog->setMaximum(0); 0080 dialog->setMinimumDuration(100); 0081 dialog->setLabelText(i18nc("@label", "Finishing tasks")); 0082 0083 connect(d, SIGNAL(signalTasksFinished()), 0084 dialog, SLOT(accept())); 0085 0086 dialog->exec(); 0087 0088 // Either, we finished and all is fine, or the user cancelled and we kill 0089 shutDown(); 0090 0091 return true; 0092 } 0093 0094 void FileActionMngr::shutDown() 0095 { 0096 d->dbWorker->deactivate(); 0097 d->fileWorker->deactivate(); 0098 d->dbWorker->wait(); 0099 d->fileWorker->wait(); 0100 } 0101 0102 bool FileActionMngr::isActive() 0103 { 0104 return d->isActive(); 0105 } 0106 0107 void FileActionMngr::assignTags(const QList<qlonglong>& ids, const QList<int>& tagIDs) 0108 { 0109 assignTags(ItemInfoList(ids), tagIDs); 0110 } 0111 0112 void FileActionMngr::assignTag(const ItemInfo& info, int tagID) 0113 { 0114 assignTags(QList<ItemInfo>() << info, QList<int>() << tagID); 0115 } 0116 0117 void FileActionMngr::assignTag(const QList<ItemInfo>& infos, int tagID) 0118 { 0119 assignTags(infos, QList<int>() << tagID); 0120 } 0121 0122 void FileActionMngr::assignTags(const ItemInfo& info, const QList<int>& tagIDs) 0123 { 0124 assignTags(QList<ItemInfo>() << info, tagIDs); 0125 } 0126 0127 void FileActionMngr::assignTags(const QList<ItemInfo>& infos, const QList<int>& tagIDs) 0128 { 0129 FileActionItemInfoList taskList = FileActionItemInfoList::create(infos); 0130 taskList.schedulingForDB(i18n("Assigning image tags"), d->dbProgressCreator()); 0131 d->assignTags(taskList, tagIDs); 0132 } 0133 0134 void FileActionMngr::removeTag(const ItemInfo& info, int tagID) 0135 { 0136 removeTags(QList<ItemInfo>() << info, QList<int>() << tagID); 0137 } 0138 0139 void FileActionMngr::removeTag(const QList<ItemInfo>& infos, int tagID) 0140 { 0141 removeTags(infos, QList<int>() << tagID); 0142 } 0143 0144 void FileActionMngr::removeTags(const ItemInfo& info, const QList<int>& tagIDs) 0145 { 0146 removeTags(QList<ItemInfo>() << info, tagIDs); 0147 } 0148 0149 void FileActionMngr::removeTags(const QList<ItemInfo>& infos, const QList<int>& tagIDs) 0150 { 0151 FileActionItemInfoList taskList = FileActionItemInfoList::create(infos); 0152 taskList.schedulingForDB(i18n("Removing image tags"), d->dbProgressCreator()); 0153 d->removeTags(taskList, tagIDs); 0154 } 0155 0156 void FileActionMngr::assignPickLabel(const ItemInfo& info, int pickId) 0157 { 0158 assignPickLabel(QList<ItemInfo>() << info, pickId); 0159 } 0160 0161 void FileActionMngr::assignColorLabel(const ItemInfo& info, int colorId) 0162 { 0163 assignColorLabel(QList<ItemInfo>() << info, colorId); 0164 } 0165 0166 void FileActionMngr::assignPickLabel(const QList<ItemInfo>& infos, int pickId) 0167 { 0168 FileActionItemInfoList taskList = FileActionItemInfoList::create(infos); 0169 taskList.schedulingForDB(i18n("Assigning image pick label"), d->dbProgressCreator()); 0170 d->assignPickLabel(taskList, pickId); 0171 } 0172 0173 void FileActionMngr::assignColorLabel(const QList<ItemInfo>& infos, int colorId) 0174 { 0175 FileActionItemInfoList taskList = FileActionItemInfoList::create(infos); 0176 taskList.schedulingForDB(i18n("Assigning image color label"), d->dbProgressCreator()); 0177 d->assignColorLabel(taskList, colorId); 0178 } 0179 0180 void FileActionMngr::assignRating(const ItemInfo& info, int rating) 0181 { 0182 assignRating(QList<ItemInfo>() << info, rating); 0183 } 0184 0185 void FileActionMngr::assignRating(const QList<ItemInfo>& infos, int rating) 0186 { 0187 FileActionItemInfoList taskList = FileActionItemInfoList::create(infos); 0188 taskList.schedulingForDB(i18n("Assigning image ratings"), d->dbProgressCreator()); 0189 d->assignRating(taskList, rating); 0190 } 0191 0192 void FileActionMngr::addToGroup(const ItemInfo& pick, const QList<ItemInfo>& infos) 0193 { 0194 FileActionItemInfoList taskList = FileActionItemInfoList::create(infos); 0195 taskList.schedulingForDB(i18n("Editing group"), d->dbProgressCreator()); 0196 d->editGroup(AddToGroup, pick, taskList); 0197 } 0198 0199 void FileActionMngr::removeFromGroup(const ItemInfo& info) 0200 { 0201 removeFromGroup(QList<ItemInfo>() << info); 0202 } 0203 0204 void FileActionMngr::removeFromGroup(const QList<ItemInfo>& infos) 0205 { 0206 FileActionItemInfoList taskList = FileActionItemInfoList::create(infos); 0207 taskList.schedulingForDB(i18n("Editing group"), d->dbProgressCreator()); 0208 d->editGroup(RemoveFromGroup, ItemInfo(), taskList); 0209 } 0210 0211 void FileActionMngr::ungroup(const ItemInfo& info) 0212 { 0213 ungroup(QList<ItemInfo>() << info); 0214 } 0215 0216 void FileActionMngr::ungroup(const QList<ItemInfo>& infos) 0217 { 0218 FileActionItemInfoList taskList = FileActionItemInfoList::create(infos); 0219 taskList.schedulingForDB(i18n("Editing group"), d->dbProgressCreator()); 0220 d->editGroup(Ungroup, ItemInfo(), taskList); 0221 } 0222 0223 void FileActionMngr::setExifOrientation(const QList<ItemInfo>& infos, int orientation) 0224 { 0225 FileActionItemInfoList taskList = FileActionItemInfoList::create(infos); 0226 taskList.schedulingForDB(i18n("Updating orientation in database"), d->dbProgressCreator()); 0227 d->setExifOrientation(taskList, orientation); 0228 } 0229 0230 /* 0231 void FileActionMngr::applyMetadata(const QList<ItemInfo>& infos, const MetadataHub& hub) 0232 { 0233 FileActionItemInfoList taskList = FileActionItemInfoList::create(infos); 0234 taskList.schedulingForDB(i18n("Applying metadata"), d->dbProgressCreator()); 0235 // create hub parent-less, we will need to clone() it in a thread, 0236 // and that does not work with parent in a different thread 0237 // d->applyMetadata(taskList, new MetadataHubOnTheRoad(hub)); 0238 } 0239 */ 0240 0241 void FileActionMngr::applyMetadata(const QList<ItemInfo>& infos, const DisjointMetadata& hub) 0242 { 0243 FileActionItemInfoList taskList = FileActionItemInfoList::create(infos); 0244 taskList.schedulingForDB(i18n("Applying metadata"), d->dbProgressCreator()); 0245 0246 DisjointMetadata* const hub2 = new DisjointMetadata(); 0247 hub2->setDataFields(hub.dataFields()); 0248 d->applyMetadata(taskList, hub2); 0249 } 0250 0251 void FileActionMngr::applyMetadata(const QList<ItemInfo>& infos, DisjointMetadata* hub) 0252 { 0253 /* 0254 if (hub->parent()) 0255 { 0256 qCDebug(DIGIKAM_GENERAL_LOG) << "MetadataHubOnTheRoad object must not have a QObject parent"; 0257 delete hub; 0258 return; 0259 } 0260 */ 0261 FileActionItemInfoList taskList = FileActionItemInfoList::create(infos); 0262 taskList.schedulingForDB(i18n("Applying metadata"), d->dbProgressCreator()); 0263 d->applyMetadata(taskList, hub); 0264 } 0265 0266 void FileActionMngr::transform(const QList<ItemInfo>& infos, MetaEngineRotation::TransformationAction action) 0267 { 0268 FileActionItemInfoList taskList = FileActionItemInfoList::create(infos); 0269 taskList.schedulingForWrite(i18n("Rotating images"), d->fileProgressCreator()); 0270 0271 for (ItemInfoTaskSplitter splitter(taskList); splitter.hasNext();) 0272 { 0273 d->transform(splitter.next(), action); 0274 } 0275 } 0276 0277 void FileActionMngr::copyAttributes(const ItemInfo& source, const QString& derivedPath) 0278 { 0279 copyAttributes(source, QStringList() << derivedPath); 0280 } 0281 0282 void FileActionMngr::copyAttributes(const ItemInfo& source, const QStringList& derivedPaths) 0283 { 0284 FileActionItemInfoList taskList = FileActionItemInfoList::create(QList<ItemInfo>() << source); 0285 taskList.schedulingForDB(i18n("Copying attributes"), d->dbProgressCreator()); 0286 d->copyAttributes(taskList, derivedPaths); 0287 } 0288 0289 } // namespace Digikam 0290 0291 #include "moc_fileactionmngr.cpp"