File indexing completed on 2025-01-19 03:50:58

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2010-09-14
0007  * Description : remove metadata batch tool.
0008  *
0009  * SPDX-FileCopyrightText: 2010-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  *
0011  * SPDX-License-Identifier: GPL-2.0-or-later
0012  *
0013  * ============================================================ */
0014 
0015 #include "removemetadata.h"
0016 
0017 // Qt includes
0018 
0019 #include <QGridLayout>
0020 #include <QCheckBox>
0021 #include <QComboBox>
0022 #include <QWidget>
0023 #include <QLabel>
0024 #include <QFile>
0025 #include <QScopedPointer>
0026 
0027 // KDE includes
0028 
0029 #include <klocalizedstring.h>
0030 
0031 // Local includes
0032 
0033 #include "dimg.h"
0034 #include "dmetadata.h"
0035 #include "dfileoperations.h"
0036 
0037 namespace DigikamBqmRemoveMetadataPlugin
0038 {
0039 
0040 class Q_DECL_HIDDEN RemoveMetadata::Private
0041 {
0042 public:
0043 
0044     enum RemoveAction
0045     {
0046         ALL = 0,
0047         GPS,
0048         DATE,
0049         EXIF,
0050         VIDEO,
0051         DUBLIN,
0052         COMMENT,
0053         DIGIKAM,
0054         HISTORY,
0055         PREVIEW,
0056         XPKEYWORDS
0057 
0058     };
0059 
0060 public:
0061 
0062     explicit Private()
0063       : removeExif      (nullptr),
0064         removeIptc      (nullptr),
0065         removeXmp       (nullptr),
0066         exifComboBox    (nullptr),
0067         iptcComboBox    (nullptr),
0068         xmpComboBox     (nullptr),
0069         changeSettings  (true)
0070     {
0071     }
0072 
0073     QCheckBox* removeExif;
0074     QCheckBox* removeIptc;
0075     QCheckBox* removeXmp;
0076 
0077     QComboBox* exifComboBox;
0078     QComboBox* iptcComboBox;
0079     QComboBox* xmpComboBox;
0080 
0081     bool       changeSettings;
0082 };
0083 
0084 RemoveMetadata::RemoveMetadata(QObject* const parent)
0085     : BatchTool(QLatin1String("RemoveMetadata"), MetadataTool, parent),
0086       d        (new Private)
0087 {
0088 }
0089 
0090 RemoveMetadata::~RemoveMetadata()
0091 {
0092     delete d;
0093 }
0094 
0095 BatchTool* RemoveMetadata::clone(QObject* const parent) const
0096 {
0097     return new RemoveMetadata(parent);
0098 }
0099 
0100 void RemoveMetadata::registerSettingsWidget()
0101 {
0102     QWidget* const panel     = new QWidget;
0103     QGridLayout* const grid  = new QGridLayout(panel);
0104 
0105     d->removeExif            = new QCheckBox(i18nc("@title", "Exif:"), panel);
0106     d->exifComboBox          = new QComboBox(panel);
0107     d->exifComboBox->addItem(i18nc("@item: exif namespace", "Completely"),              Private::ALL);
0108     d->exifComboBox->addItem(i18nc("@item: exif namespace", "Date"),                    Private::DATE);
0109     d->exifComboBox->addItem(i18nc("@item: exif namespace", "GPS"),                     Private::GPS);
0110     d->exifComboBox->addItem(i18nc("@item: exif namespace", "XPKeywords"),              Private::XPKEYWORDS);
0111     d->exifComboBox->addItem(i18nc("@item: exif namespace", "Comment and description"), Private::COMMENT);
0112 
0113     d->removeIptc            = new QCheckBox(i18nc("@title", "Iptc:"), panel);
0114     d->iptcComboBox          = new QComboBox(panel);
0115     d->iptcComboBox->addItem(i18nc("@item: iptc namespace", "Completely"),    Private::ALL);
0116     d->iptcComboBox->addItem(i18nc("@item: iptc namespace", "Date"),          Private::DATE);
0117     d->iptcComboBox->addItem(i18nc("@item: iptc namespace", "Caption"),       Private::COMMENT);
0118     d->iptcComboBox->addItem(i18nc("@item: iptc namespace", "Preview image"), Private::PREVIEW);
0119 
0120     d->removeXmp             = new QCheckBox(i18nc("@title", "Xmp:"), panel);
0121     d->xmpComboBox           = new QComboBox(panel);
0122     d->xmpComboBox->addItem(i18nc("@item: xmp namespace", "Completely"),                       Private::ALL);
0123     d->xmpComboBox->addItem(i18nc("@item: xmp namespace", "Date"),                             Private::DATE);
0124     d->xmpComboBox->addItem(i18nc("@item: xmp namespace", "DigiKam"),                          Private::DIGIKAM);
0125     d->xmpComboBox->addItem(i18nc("@item: xmp namespace", "DigiKam image history"),            Private::HISTORY);
0126     d->xmpComboBox->addItem(i18nc("@item: xmp namespace", "Dublin Core"),                      Private::DUBLIN);
0127     d->xmpComboBox->addItem(i18nc("@item: xmp namespace", "Exif"),                             Private::EXIF);
0128     d->xmpComboBox->addItem(i18nc("@item: xmp namespace", "Video"),                            Private::VIDEO);
0129     d->xmpComboBox->addItem(i18nc("@item: xmp namespace", "Caption, Comment and Description"), Private::COMMENT);
0130 
0131     grid->addWidget(d->removeExif,   0, 0, 1, 1);
0132     grid->addWidget(d->exifComboBox, 0, 1, 1, 2);
0133     grid->addWidget(d->removeIptc,   1, 0, 1, 1);
0134     grid->addWidget(d->iptcComboBox, 1, 1, 1, 2);
0135     grid->addWidget(d->removeXmp,    2, 0, 1, 1);
0136     grid->addWidget(d->xmpComboBox,  2, 1, 1, 2);
0137     grid->setColumnStretch(2, 10);
0138     grid->setRowStretch(3, 10);
0139 
0140     m_settingsWidget = panel;
0141 
0142     connect(d->removeExif, SIGNAL(toggled(bool)),
0143             this, SLOT(slotSettingsChanged()));
0144 
0145     connect(d->removeIptc, SIGNAL(toggled(bool)),
0146             this, SLOT(slotSettingsChanged()));
0147 
0148     connect(d->removeXmp, SIGNAL(toggled(bool)),
0149             this, SLOT(slotSettingsChanged()));
0150 
0151     connect(d->exifComboBox, SIGNAL(currentIndexChanged(int)),
0152             this, SLOT(slotSettingsChanged()));
0153 
0154     connect(d->iptcComboBox, SIGNAL(currentIndexChanged(int)),
0155             this, SLOT(slotSettingsChanged()));
0156 
0157     connect(d->xmpComboBox, SIGNAL(currentIndexChanged(int)),
0158             this, SLOT(slotSettingsChanged()));
0159 
0160     BatchTool::registerSettingsWidget();
0161 }
0162 
0163 BatchToolSettings RemoveMetadata::defaultSettings()
0164 {
0165     BatchToolSettings settings;
0166 
0167     settings.insert(QLatin1String("RemoveExif"), false);
0168     settings.insert(QLatin1String("RemoveIptc"), false);
0169     settings.insert(QLatin1String("RemoveXmp"),  false);
0170     settings.insert(QLatin1String("ExifData"),   Private::ALL);
0171     settings.insert(QLatin1String("IptcData"),   Private::ALL);
0172     settings.insert(QLatin1String("XmpData"),    Private::ALL);
0173 
0174     return settings;
0175 }
0176 
0177 void RemoveMetadata::slotAssignSettings2Widget()
0178 {
0179     d->changeSettings = false;
0180 
0181     d->removeExif->setChecked(settings()[QLatin1String("RemoveExif")].toBool());
0182     d->removeIptc->setChecked(settings()[QLatin1String("RemoveIptc")].toBool());
0183     d->removeXmp->setChecked(settings()[QLatin1String("RemoveXmp")].toBool());
0184 
0185     int exifData = settings()[QLatin1String("ExifData")].toInt();
0186     d->exifComboBox->setCurrentIndex(d->exifComboBox->findData(exifData));
0187 
0188     int iptcData = settings()[QLatin1String("IptcData")].toInt();
0189     d->iptcComboBox->setCurrentIndex(d->iptcComboBox->findData(iptcData));
0190 
0191     int xmpData  = settings()[QLatin1String("XmpData")].toInt();
0192     d->xmpComboBox->setCurrentIndex(d->xmpComboBox->findData(xmpData));
0193 
0194     d->exifComboBox->setEnabled(d->removeExif->isChecked());
0195     d->iptcComboBox->setEnabled(d->removeIptc->isChecked());
0196     d->xmpComboBox->setEnabled(d->removeXmp->isChecked());
0197 
0198     d->changeSettings = true;
0199 }
0200 
0201 void RemoveMetadata::slotSettingsChanged()
0202 {
0203     if (d->changeSettings)
0204     {
0205         BatchToolSettings settings;
0206 
0207         settings.insert(QLatin1String("RemoveExif"), d->removeExif->isChecked());
0208         settings.insert(QLatin1String("RemoveIptc"), d->removeIptc->isChecked());
0209         settings.insert(QLatin1String("RemoveXmp"),  d->removeXmp->isChecked());
0210         settings.insert(QLatin1String("ExifData"),   d->exifComboBox->currentData().toInt());
0211         settings.insert(QLatin1String("IptcData"),   d->iptcComboBox->currentData().toInt());
0212         settings.insert(QLatin1String("XmpData" ),   d->xmpComboBox->currentData().toInt());
0213 
0214         BatchTool::slotSettingsChanged(settings);
0215     }
0216 }
0217 
0218 bool RemoveMetadata::toolOperations()
0219 {
0220     if (!isLastChainedTool())
0221     {
0222         setErrorDescription(i18nc("@info", "Remove Metadata: Not the last tool in the list."));
0223         return false;
0224     }
0225 
0226     bool ret = true;
0227     QScopedPointer<DMetadata> meta(new DMetadata);
0228 
0229     if (image().isNull())
0230     {
0231         QFile::remove(outputUrl().toLocalFile());
0232         ret = DFileOperations::copyFile(inputUrl().toLocalFile(), outputUrl().toLocalFile());
0233 
0234         if (!ret || !meta->load(outputUrl().toLocalFile()))
0235         {
0236             return ret;
0237         }
0238     }
0239     else
0240     {
0241         ret = savefromDImg();
0242         meta->setData(image().getMetadata());
0243     }
0244 
0245     bool removeExif = settings()[QLatin1String("RemoveExif")].toBool();
0246     bool removeIptc = settings()[QLatin1String("RemoveIptc")].toBool();
0247     bool removeXmp  = settings()[QLatin1String("RemoveXmp")].toBool();
0248 
0249     int exifData    = settings()[QLatin1String("ExifData")].toInt();
0250     int iptcData    = settings()[QLatin1String("IptcData")].toInt();
0251     int xmpData     = settings()[QLatin1String("XmpData")].toInt();
0252 
0253     if (removeExif)
0254     {
0255         if      (exifData == Private::ALL)
0256         {
0257             meta->clearExif();
0258             meta->clearComments();
0259         }
0260         else if (exifData == Private::DATE)
0261         {
0262             meta->removeExifTag("Exif.Image.DateTime");
0263             meta->removeExifTag("Exif.Image.PreviewDateTime");
0264             meta->removeExifTag("Exif.Photo.DateTimeOriginal");
0265             meta->removeExifTag("Exif.Photo.DateTimeDigitized");
0266         }
0267         else if (exifData == Private::GPS)
0268         {
0269             meta->removeExifTags(QStringList() << QLatin1String("GPSInfo"));
0270         }
0271         else if (exifData == Private::XPKEYWORDS)
0272         {
0273             meta->removeExifTag("Exif.Image.XPKeywords");
0274         }
0275         else if (exifData == Private::COMMENT)
0276         {
0277             meta->removeExifTag("Exif.Image.ImageDescription");
0278             meta->removeExifTag("Exif.Photo.UserComment");
0279             meta->clearComments();
0280         }
0281     }
0282 
0283     if (removeIptc)
0284     {
0285         if      (iptcData == Private::ALL)
0286         {
0287             meta->clearIptc();
0288         }
0289         else if (iptcData == Private::DATE)
0290         {
0291             meta->removeIptcTag("Iptc.Application2.DateCreated");
0292             meta->removeIptcTag("Iptc.Application2.TimeCreated");
0293         }
0294         else if (iptcData == Private::COMMENT)
0295         {
0296             meta->removeIptcTag("Iptc.Application2.Caption");
0297             meta->clearComments();
0298         }
0299         else if (iptcData == Private::PREVIEW)
0300         {
0301             meta->removeIptcTag("Iptc.Application2.Preview");
0302             meta->removeIptcTag("Iptc.Application2.PreviewFormat");
0303             meta->removeIptcTag("Iptc.Application2.PreviewVersion");
0304         }
0305     }
0306 
0307     if (removeXmp)
0308     {
0309         if      (xmpData == Private::ALL)
0310         {
0311             meta->clearXmp();
0312         }
0313         else if (xmpData == Private::DATE)
0314         {
0315             meta->removeXmpTag("Xmp.photoshop.DateCreated");
0316             meta->removeXmpTag("Xmp.exif.DateTimeOriginal");
0317             meta->removeXmpTag("Xmp.xmp.MetadataDate");
0318             meta->removeXmpTag("Xmp.xmp.CreateDate");
0319             meta->removeXmpTag("Xmp.xmp.ModifyDate");
0320             meta->removeXmpTag("Xmp.tiff.DateTime");
0321             meta->removeXmpTag("Xmp.video.DateTimeDigitized");
0322             meta->removeXmpTag("Xmp.video.DateTimeOriginal");
0323             meta->removeXmpTag("Xmp.video.ModificationDate");
0324             meta->removeXmpTag("Xmp.video.DateUTC");
0325         }
0326         else if (xmpData == Private::HISTORY)
0327         {
0328             meta->removeXmpTag("Xmp.digiKam.ImageHistory");
0329         }
0330         else if (xmpData == Private::DIGIKAM)
0331         {
0332             meta->removeXmpTags(QStringList() << QLatin1String("digiKam"));
0333         }
0334         else if (xmpData == Private::DUBLIN)
0335         {
0336             meta->removeXmpTags(QStringList() << QLatin1String("dc"));
0337         }
0338         else if (xmpData == Private::EXIF)
0339         {
0340             meta->removeXmpTags(QStringList() << QLatin1String("exif"));
0341         }
0342         else if (xmpData == Private::VIDEO)
0343         {
0344             meta->removeXmpTags(QStringList() << QLatin1String("video"));
0345         }
0346         else if (xmpData == Private::COMMENT)
0347         {
0348             meta->removeXmpTag("Xmp.acdsee.Caption");
0349             meta->removeXmpTag("Xmp.dc.Description");
0350             meta->removeXmpTag("Xmp.crs.Description");
0351             meta->removeXmpTag("Xmp.exif.UserComment");
0352             meta->removeXmpTag("Xmp.tiff.ImageDescription");
0353             meta->removeXmpTag("Xmp.xmp.Description");
0354             meta->removeXmpTag("Xmp.xmpDM.DMComment");
0355             meta->clearComments();
0356         }
0357     }
0358 
0359     if (ret && (removeExif || removeIptc || removeXmp))
0360     {
0361         ret = meta->save(outputUrl().toLocalFile());
0362     }
0363 
0364     return ret;
0365 }
0366 
0367 } // namespace DigikamBqmRemoveMetadataPlugin
0368 
0369 #include "moc_removemetadata.cpp"