File indexing completed on 2024-06-02 04:19:23

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2023-21-06
0007  * Description : Batch remover of metadata.
0008  *
0009  * SPDX-FileCopyrightText: 2013-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  * SPDX-FileCopyrightText: 2023      by Maik Qualmann <metzpinguin at gmail dot com>
0011  *
0012  * SPDX-License-Identifier: GPL-2.0-or-later
0013  *
0014  * ============================================================ */
0015 
0016 #include "metadataremover.h"
0017 
0018 // Qt includes
0019 
0020 #include <QApplication>
0021 #include <QMessageBox>
0022 #include <QString>
0023 #include <QTimer>
0024 #include <QIcon>
0025 
0026 // KDE includes
0027 
0028 #include <klocalizedstring.h>
0029 
0030 // Local includes
0031 
0032 #include "albummanager.h"
0033 #include "albummanager.h"
0034 #include "iteminfojob.h"
0035 #include "maintenancethread.h"
0036 
0037 namespace Digikam
0038 {
0039 
0040 class Q_DECL_HIDDEN MetadataRemover::Private
0041 {
0042 public:
0043 
0044     explicit Private()
0045       : imageInfoJob (nullptr),
0046         thread       (nullptr),
0047         removeAction (MetadataRemover::None)
0048     {
0049     }
0050 
0051     AlbumList                     palbumList;
0052     AlbumList::Iterator           albumsIt;
0053 
0054     ItemInfoJob*                  imageInfoJob;
0055 
0056     ItemInfoList                  imageInfoList;
0057 
0058     MaintenanceThread*            thread;
0059 
0060     MetadataRemover::RemoveAction removeAction;
0061 };
0062 
0063 MetadataRemover::MetadataRemover(const AlbumList& list, RemoveAction action, ProgressItem* const parent)
0064     : MaintenanceTool(QLatin1String("MetadataRemover"), parent),
0065       d(new Private)
0066 {
0067     if (list.isEmpty())
0068     {
0069         d->palbumList = AlbumManager::instance()->allPAlbums();
0070     }
0071     else
0072     {
0073         d->palbumList = list;
0074     }
0075 
0076     init(action);
0077 }
0078 
0079 MetadataRemover::MetadataRemover(const ItemInfoList& list, RemoveAction action, ProgressItem* const parent)
0080     : MaintenanceTool(QLatin1String("MetadataRemover"), parent),
0081       d(new Private)
0082 {
0083     d->imageInfoList = list;
0084 
0085     init(action);
0086 }
0087 
0088 // Common methods ----------------------------------------------------------------------------
0089 
0090 void MetadataRemover::init(RemoveAction action)
0091 {
0092     d->removeAction = action;
0093     d->thread       = new MaintenanceThread(this);
0094 
0095     connect(d->thread, SIGNAL(signalCompleted()),
0096             this, SLOT(slotDone()));
0097 
0098     connect(d->thread, SIGNAL(signalAdvance(QImage)),
0099             this, SLOT(slotAdvance()));
0100 }
0101 
0102 void MetadataRemover::setUseMultiCoreCPU(bool b)
0103 {
0104     d->thread->setUseMultiCore(b);
0105 }
0106 
0107 void MetadataRemover::slotStart()
0108 {
0109     MaintenanceTool::slotStart();
0110 
0111     ProgressManager::addProgressItem(this);
0112 
0113     d->imageInfoJob = new ItemInfoJob;
0114 
0115     connect(d->imageInfoJob, SIGNAL(signalItemsInfo(ItemInfoList)),
0116             this, SLOT(slotAlbumParsed(ItemInfoList)));
0117 
0118     connect(d->imageInfoJob, SIGNAL(signalCompleted()),
0119             this, SLOT(slotOneAlbumIsComplete()));
0120 
0121     connect(this, SIGNAL(progressItemCanceled(ProgressItem*)),
0122             this, SLOT(slotCancel()));
0123 
0124     QTimer::singleShot(500, this, SLOT(slotParseAlbums()));
0125 }
0126 
0127 MetadataRemover::~MetadataRemover()
0128 {
0129     delete d->imageInfoJob;
0130     delete d;
0131 }
0132 
0133 void MetadataRemover::slotCancel()
0134 {
0135     d->imageInfoJob->stop();
0136     d->thread->cancel();
0137     MaintenanceTool::slotCancel();
0138 }
0139 
0140 // Parse Albums methods ------------------------------------------------------------------
0141 
0142 void MetadataRemover::slotParseAlbums()
0143 {
0144     setUsesBusyIndicator(true);
0145     d->albumsIt = d->palbumList.begin();
0146     processOneAlbum();
0147 }
0148 
0149 void MetadataRemover::processOneAlbum()
0150 {
0151     if (canceled())
0152     {
0153         return;
0154     }
0155 
0156     if (d->albumsIt == d->palbumList.end())     // All albums are parsed.
0157     {
0158         parseList();
0159         return;
0160     }
0161 
0162     d->imageInfoJob->allItemsFromAlbum(*d->albumsIt);
0163 }
0164 
0165 void MetadataRemover::slotAlbumParsed(const ItemInfoList& list)
0166 {
0167     d->imageInfoList << list;
0168 }
0169 
0170 void MetadataRemover::slotOneAlbumIsComplete()
0171 {
0172     d->albumsIt++;
0173     processOneAlbum();
0174 }
0175 
0176 // Parse info list methods -----------------------------------------------------------------------
0177 
0178 void MetadataRemover::parseList()
0179 {
0180     setUsesBusyIndicator(false);
0181 
0182     if      (d->removeAction == None)
0183     {
0184         slotDone();
0185         return;
0186     }
0187     else if (d->removeAction == Faces)
0188     {
0189         setLabel(i18n("Remove all faces from image"));
0190         setThumbnail(QIcon::fromTheme(QLatin1String("list-remove-user")).pixmap(22));
0191     }
0192     else if (d->removeAction == Tags)
0193     {
0194         setLabel(i18n("Remove all tags from image"));
0195         setThumbnail(QIcon::fromTheme(QLatin1String("tag-delete")).pixmap(22));
0196     }
0197 
0198     if (d->imageInfoList.isEmpty())
0199     {
0200         slotDone();
0201         return;
0202     }
0203 
0204     if (d->imageInfoList.size() > 1)
0205     {
0206         QString message;
0207 
0208         if      (d->removeAction == MetadataRemover::Faces)
0209         {
0210             message = i18n("All faces are removed from %1 selected images.\n"
0211                            "Do you want to continue?", d->imageInfoList.size());
0212         }
0213         else if (d->removeAction == MetadataRemover::Tags)
0214         {
0215             message = i18n("All tags are removed from %1 selected images.\n"
0216                            "Do you want to continue?", d->imageInfoList.size());
0217         }
0218 
0219         int ret = QMessageBox::question(qApp->activeWindow(), qApp->applicationName(),
0220                                         message, QMessageBox::Yes | QMessageBox::No);
0221 
0222         if (ret == QMessageBox::No)
0223         {
0224             slotDone();
0225             return;
0226         }
0227     }
0228 
0229     setTotalItems(d->imageInfoList.count());
0230 
0231     d->thread->removeMetadata(d->imageInfoList, d->removeAction);
0232     d->thread->start();
0233 }
0234 
0235 void MetadataRemover::slotAdvance()
0236 {
0237     advance(1);
0238 }
0239 
0240 } // namespace Digikam
0241 
0242 #include "moc_metadataremover.cpp"