File indexing completed on 2024-12-22 04:15:06

0001 /*
0002  *  SPDX-FileCopyrightText: 2007, 2010 Cyrille Berger <cberger@cberger.net>
0003  *  SPDX-FileCopyrightText: 2021 L. E. Segovia <amy@amyspark.me>
0004  *
0005  *  SPDX-License-Identifier: LGPL-2.1-or-later
0006  */
0007 
0008 #include "kis_meta_data_editor.h"
0009 
0010 #include <QDomDocument>
0011 #include <QFile>
0012 #include <QHeaderView>
0013 #include <QTableView>
0014 
0015 #include <KoResourcePaths.h>
0016 #include <kis_debug.h>
0017 #include <kis_icon.h>
0018 #include <kis_meta_data_entry.h>
0019 #include <kis_meta_data_schema.h>
0020 #include <kis_meta_data_schema_registry.h>
0021 #include <kis_meta_data_store.h>
0022 #include <kis_meta_data_value.h>
0023 #include <klocalizedstring.h>
0024 
0025 #include "kis_entry_editor.h"
0026 #include "kis_meta_data_model.h"
0027 
0028 
0029 struct KisMetaDataEditor::Private {
0030     KisMetaData::Store *store;
0031     KisMetaData::Store *temporaryStorage;
0032     QList<KisEntryEditor *> entryHandlers;
0033 };
0034 
0035 #define GET_VALUE(entryName, wdg, wdgPropertyName, editorSignal) \
0036     QString key = schema->generateQualifiedName(#entryName); \
0037     KisEntryEditor *ee = new KisEntryEditor(wdg, d->temporaryStorage, key, #wdgPropertyName, QString(), 0); \
0038     connect(wdg, editorSignal, ee, &KisEntryEditor::valueEdited); \
0039     d->entryHandlers.push_back(ee);
0040 
0041 #define GET_ARRAY_VALUE(entryName, arrayIndex, wdg, wdgPropertyName, editorSignal) \
0042     QString key = schema->generateQualifiedName(#entryName); \
0043     KisEntryEditor *ee = new KisEntryEditor(wdg, d->temporaryStorage, key, #wdgPropertyName, QString(), arrayIndex); \
0044     connect(wdg, editorSignal, ee, &KisEntryEditor::valueEdited); \
0045     d->entryHandlers.push_back(ee);
0046 
0047 #define GET_STRUCTURE_VALUE(entryName, structureField, wdg, wdgPropertyName, editorSignal) \
0048     QString key = schema->generateQualifiedName(#entryName); \
0049     KisEntryEditor *ee = new KisEntryEditor(wdg, d->temporaryStorage, key, #wdgPropertyName, #structureField, 0); \
0050     connect(wdg, editorSignal, ee, &KisEntryEditor::valueEdited); \
0051     d->entryHandlers.push_back(ee);
0052 
0053 #define GET_DC_VALUE(entryName, wdgPropertyName, editorSignal) { \
0054     GET_VALUE(entryName, wdg->entryName, wdgPropertyName, editorSignal) \
0055 }
0056 
0057 #define GET_EXIF_VALUE(entryName, wdgPropertyName, editorSignal) { \
0058     GET_VALUE(entryName, wdg->edit##entryName, wdgPropertyName, editorSignal) \
0059 }
0060 
0061 #define GET_EXIF_ARRAY_VALUE(entryName, arrayIndex, wdgPropertyName, editorSignal) { \
0062     GET_ARRAY_VALUE(entryName, arrayIndex, wdg->edit##entryName, wdgPropertyName, editorSignal) \
0063 }
0064 
0065 #define GET_EXIF_STRUCTURE_VALUE(entryName, structureField, wdgPropertyName, editorSignal) { \
0066     GET_STRUCTURE_VALUE(entryName, structureField, wdg->edit##entryName##structureField, wdgPropertyName, editorSignal) \
0067 }
0068 
0069 KisMetaDataEditor::KisMetaDataEditor(QWidget *parent, KisMetaData::Store *store)
0070     : KPageDialog(parent)
0071     , d(new Private)
0072 {
0073     d->temporaryStorage = new KisMetaData::Store(*store);
0074     d->store = store;
0075 
0076     // Add the Dublin Core widget
0077     {
0078         WdgDublinCore *wdg = new WdgDublinCore(this);
0079 
0080         {
0081             // copy from dublin core
0082             const KisMetaData::Schema *schema =
0083                 KisMetaData::SchemaRegistry::instance()->schemaFromUri(KisMetaData::Schema::DublinCoreSchemaUri);
0084 
0085             Q_ASSERT(schema);
0086 
0087             GET_DC_VALUE(creator, text, &QLineEdit::textEdited);
0088             GET_DC_VALUE(publisher, text, &QLineEdit::textEdited);
0089             GET_DC_VALUE(rights, text, &QLineEdit::textEdited);
0090             GET_DC_VALUE(date, date, &QDateTimeEdit::editingFinished);
0091             GET_DC_VALUE(title, text, &QLineEdit::textEdited);
0092             GET_DC_VALUE(description, plainText, &QTextEdit::textChanged);
0093         }
0094 
0095         wdg->date->setDisplayFormat(QLocale().dateFormat());
0096 
0097         KPageWidgetItem *page = new KPageWidgetItem(wdg, i18n("Dublin Core"));
0098         page->setIcon(KisIconUtils::loadIcon("user-identity"));
0099         addPage(page);
0100     }
0101 
0102     // Add the Exif widget
0103     {
0104         WdgExif *wdg = new WdgExif(this);
0105 
0106         {
0107             // copy from exif
0108             const KisMetaData::Schema *schema =
0109                 KisMetaData::SchemaRegistry::instance()->schemaFromUri(KisMetaData::Schema::EXIFSchemaUri);
0110 
0111             Q_ASSERT(schema);
0112 
0113             /* exposure tab */
0114             GET_EXIF_VALUE(BrightnessValue, text, &QLineEdit::textEdited);
0115             GET_EXIF_VALUE(ExposureTime, text, &QLineEdit::textEdited);
0116             GET_EXIF_ARRAY_VALUE(ISOSpeedRatings, 0, value, QOverload<int>::of(&KisIntParseSpinBox::valueChanged));
0117             GET_EXIF_VALUE(ExposureMode, currentIndex, QOverload<int>::of(&QComboBox::activated));
0118             GET_EXIF_VALUE(ExposureProgram, currentIndex, QOverload<int>::of(&QComboBox::activated));
0119             GET_EXIF_VALUE(ExposureIndex, text, &QLineEdit::textEdited);
0120             GET_EXIF_VALUE(ExposureBiasValue, text, &QLineEdit::textEdited);
0121             GET_EXIF_VALUE(ApertureValue, text, &QLineEdit::textEdited);
0122             GET_EXIF_VALUE(ShutterSpeedValue, text, &QLineEdit::textEdited);
0123             GET_EXIF_VALUE(FNumber, text, &QLineEdit::textEdited);
0124             /*  lens tab  */
0125             GET_EXIF_VALUE(FocalLengthIn35mmFilm, value, QOverload<int>::of(&QSpinBox::valueChanged));
0126             GET_EXIF_VALUE(FocalLength, value, QOverload<int>::of(&QSpinBox::valueChanged));
0127             GET_EXIF_VALUE(MaxApertureValue, text, &QLineEdit::textEdited);
0128             /*  autofocus tab  */
0129             GET_EXIF_VALUE(MeteringMode, currentIndex, QOverload<int>::of(&QComboBox::activated));
0130             GET_EXIF_VALUE(SubjectDistance, text, &QLineEdit::textEdited);
0131             GET_EXIF_VALUE(SubjectDistanceRange, currentIndex, QOverload<int>::of(&QComboBox::activated));
0132             /*  flash  */
0133             GET_EXIF_STRUCTURE_VALUE(Flash, Fired, isChecked, QOverload<bool>::of(&QCheckBox::toggled));
0134             GET_EXIF_STRUCTURE_VALUE(Flash, StrobeReturn, currentIndex, QOverload<int>::of(&QComboBox::activated));
0135             GET_EXIF_STRUCTURE_VALUE(Flash, Mode, currentIndex, QOverload<int>::of(&QComboBox::activated));
0136             GET_EXIF_STRUCTURE_VALUE(Flash, Function, isChecked, QOverload<bool>::of(&QCheckBox::toggled));
0137             GET_EXIF_STRUCTURE_VALUE(Flash, RedEyeMode, isChecked, QOverload<bool>::of(&QCheckBox::toggled));
0138             GET_EXIF_VALUE(FlashEnergy, text, &QLineEdit::textEdited);
0139             /*  postprocessing tab */
0140             GET_EXIF_VALUE(GainControl, currentIndex, QOverload<int>::of(&QComboBox::activated));
0141             GET_EXIF_VALUE(LightSource, currentIndex, QOverload<int>::of(&QComboBox::activated));
0142             GET_EXIF_VALUE(Sharpness, currentIndex, QOverload<int>::of(&QComboBox::activated));
0143             GET_EXIF_VALUE(Contrast, currentIndex, QOverload<int>::of(&QComboBox::activated));
0144             GET_EXIF_VALUE(WhiteBalance, currentIndex, QOverload<int>::of(&QComboBox::activated));
0145             /*  misc tab */
0146             GET_EXIF_VALUE(SceneCaptureType, currentIndex, QOverload<int>::of(&QComboBox::activated));
0147             GET_EXIF_VALUE(SensingMethod, currentIndex, QOverload<int>::of(&QComboBox::activated));
0148         }
0149 
0150         {
0151             // copy from exif (tiff schema)
0152             const KisMetaData::Schema *schema =
0153                 KisMetaData::SchemaRegistry::instance()->schemaFromUri(KisMetaData::Schema::TIFFSchemaUri);
0154 
0155             Q_ASSERT(schema);
0156 
0157             /*  misc  */
0158             GET_EXIF_VALUE(Make, text, &QLineEdit::textEdited);
0159             GET_EXIF_VALUE(Model, text, &QLineEdit::textEdited);
0160         }
0161 
0162         KPageWidgetItem *page = new KPageWidgetItem(wdg, i18n("Exif"));
0163         page->setIcon(KisIconUtils::loadIcon("camera-photo"));
0164         addPage(page);
0165     }
0166 
0167     {
0168         // Add the list page
0169         QTableView *tableView = new QTableView;
0170         KisMetaDataModel *model = new KisMetaDataModel(d->store);
0171         tableView->setModel(model);
0172         tableView->verticalHeader()->setVisible(false);
0173         tableView->resizeColumnsToContents();
0174         KPageWidgetItem *page = new KPageWidgetItem(tableView, i18n("List"));
0175         page->setIcon(KisIconUtils::loadIcon("format-list-unordered"));
0176         addPage(page);
0177     }
0178 }
0179 
0180 KisMetaDataEditor::~KisMetaDataEditor()
0181 {
0182     Q_FOREACH (KisEntryEditor *e, d->entryHandlers) {
0183         delete e;
0184     }
0185     delete d->temporaryStorage;
0186     delete d;
0187 }
0188 
0189 void KisMetaDataEditor::accept()
0190 {
0191     KPageDialog::accept();
0192 
0193     d->store->copyFrom(d->temporaryStorage);
0194 }