File indexing completed on 2025-01-19 03:50:57
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2024-02-11 0007 * Description : apply metadata batch tool with ExifTool. 0008 * 0009 * SPDX-FileCopyrightText: 2024 by Maik Qualmann <metzpinguin at gmail dot com> 0010 * 0011 * SPDX-License-Identifier: GPL-2.0-or-later 0012 * 0013 * ============================================================ */ 0014 0015 #include "applymetadata.h" 0016 0017 // Qt includes 0018 0019 #include <QDir> 0020 #include <QFile> 0021 #include <QLabel> 0022 #include <QWidget> 0023 #include <QFileInfo> 0024 #include <QGridLayout> 0025 #include <QTemporaryDir> 0026 #include <QScopedPointer> 0027 0028 // KDE includes 0029 0030 #include <klocalizedstring.h> 0031 0032 // Local includes 0033 0034 #include "dimg.h" 0035 #include "dmetadata.h" 0036 #include "dfileselector.h" 0037 #include "exiftoolparser.h" 0038 #include "dfileoperations.h" 0039 0040 namespace DigikamBqmApplyMetadataPlugin 0041 { 0042 0043 class Q_DECL_HIDDEN ApplyMetadata::Private 0044 { 0045 public: 0046 0047 Private() = default; 0048 0049 public: 0050 0051 DFileSelector* fileSelector = nullptr; 0052 QLabel* descFileLabel = nullptr; 0053 0054 bool changeSettings = false; 0055 }; 0056 0057 ApplyMetadata::ApplyMetadata(QObject* const parent) 0058 : BatchTool(QLatin1String("ApplyMetadata"), MetadataTool, parent), 0059 d (new Private) 0060 { 0061 } 0062 0063 ApplyMetadata::~ApplyMetadata() 0064 { 0065 delete d; 0066 } 0067 0068 BatchTool* ApplyMetadata::clone(QObject* const parent) const 0069 { 0070 return new ApplyMetadata(parent); 0071 } 0072 0073 void ApplyMetadata::registerSettingsWidget() 0074 { 0075 QWidget* const panel = new QWidget; 0076 QGridLayout* const grid = new QGridLayout(panel); 0077 0078 d->descFileLabel = new QLabel(i18n("Select an image or JSON file supported by ExifTool " 0079 "to apply the file metadata to the images."), panel); 0080 d->descFileLabel->setWordWrap(true); 0081 d->fileSelector = new DFileSelector(panel); 0082 d->fileSelector->setFileDlgMode(QFileDialog::ExistingFile); 0083 0084 grid->addWidget(d->descFileLabel, 0, 0, 1, 1); 0085 grid->addWidget(d->fileSelector, 1, 0, 1, 1); 0086 grid->setRowStretch(2, 10); 0087 0088 m_settingsWidget = panel; 0089 0090 connect(d->fileSelector, SIGNAL(signalUrlSelected(QUrl)), 0091 this, SLOT(slotSettingsChanged())); 0092 0093 BatchTool::registerSettingsWidget(); 0094 } 0095 0096 BatchToolSettings ApplyMetadata::defaultSettings() 0097 { 0098 BatchToolSettings settings; 0099 0100 settings.insert(QLatin1String("MetadataFile"), QString()); 0101 0102 return settings; 0103 } 0104 0105 void ApplyMetadata::slotAssignSettings2Widget() 0106 { 0107 d->changeSettings = false; 0108 0109 d->fileSelector->setFileDlgPath(settings()[QLatin1String("MetadataFile")].toString()); 0110 0111 d->changeSettings = true; 0112 } 0113 0114 void ApplyMetadata::slotSettingsChanged() 0115 { 0116 if (d->changeSettings) 0117 { 0118 BatchToolSettings settings; 0119 0120 settings.insert(QLatin1String("MetadataFile"), d->fileSelector->fileDlgPath()); 0121 0122 BatchTool::slotSettingsChanged(settings); 0123 } 0124 } 0125 0126 bool ApplyMetadata::toolOperations() 0127 { 0128 bool ret = true; 0129 0130 if (image().isNull()) 0131 { 0132 QFile::remove(outputUrl().toLocalFile()); 0133 ret = DFileOperations::copyFile(inputUrl().toLocalFile(), outputUrl().toLocalFile()); 0134 } 0135 else 0136 { 0137 ret = savefromDImg(); 0138 } 0139 0140 QFileInfo metaInfo(settings()[QLatin1String("MetadataFile")].toString()); 0141 0142 if (!ret || !metaInfo.exists()) 0143 { 0144 setErrorDescription(i18nc("@info", "Apply Metadata: No image or JSON file selected.")); 0145 return false; 0146 } 0147 0148 QScopedPointer<ExifToolParser> const parser(new ExifToolParser(this)); 0149 0150 if (!parser->exifToolAvailable()) 0151 { 0152 setErrorDescription(i18nc("@info", "Apply Metadata: ExifTool is not available.")); 0153 return false; 0154 } 0155 0156 if (metaInfo.suffix().toUpper() == QLatin1String("JSON")) 0157 { 0158 QString dirTemplate = QDir::tempPath() + QLatin1String("/bqm-apply-metadata-XXXXXX"); 0159 QTemporaryDir tempDir(dirTemplate); 0160 0161 if (!tempDir.isValid()) 0162 { 0163 return false; 0164 } 0165 0166 QFile jsonFileRead(metaInfo.filePath()); 0167 0168 if (!jsonFileRead.open(QIODevice::ReadOnly)) 0169 { 0170 return false; 0171 } 0172 0173 QString metaFile = tempDir.path() + QLatin1Char('/') + metaInfo.fileName(); 0174 QString jsonSource = QString::fromUtf8("\"SourceFile\": \"%1\","); 0175 QString jsonString = QString::fromUtf8(jsonFileRead.readAll()); 0176 jsonFileRead.close(); 0177 0178 if (!jsonString.contains(jsonSource.arg(imageInfo().name(), Qt::CaseInsensitive))) 0179 { 0180 setErrorDescription(i18nc("@info", "Apply Metadata: File name not exist in JSON file.")); 0181 return false; 0182 } 0183 0184 jsonString.replace(jsonSource.arg(imageInfo().name()), 0185 jsonSource.arg(outputUrl().toLocalFile(), Qt::CaseInsensitive)); 0186 0187 QFile jsonFileWrite(metaFile); 0188 0189 if (!jsonFileWrite.open(QIODevice::WriteOnly)) 0190 { 0191 return false; 0192 } 0193 0194 jsonFileWrite.write(jsonString.toUtf8()); 0195 jsonFileWrite.close(); 0196 0197 ret = parser->applyMetadataFile(outputUrl().toLocalFile(), metaFile); 0198 } 0199 else 0200 { 0201 ret = parser->applyMetadataFile(outputUrl().toLocalFile(), metaInfo.filePath()); 0202 } 0203 0204 if (!ret) 0205 { 0206 setErrorDescription(i18nc("@info", "Apply Metadata: ExifTool reported an error.")); 0207 return false; 0208 } 0209 0210 return true; 0211 } 0212 0213 } // namespace DigikamBqmApplyMetadataPlugin 0214 0215 #include "moc_applymetadata.cpp"