File indexing completed on 2025-04-27 03:58:33

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2009-07-17
0007  * Description : Metadata tags selector config panel.
0008  *
0009  * SPDX-FileCopyrightText: 2009-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 "metadatapanel.h"
0016 
0017 // Qt includes
0018 
0019 #include <QFrame>
0020 #include <QVBoxLayout>
0021 #include <QList>
0022 #include <QApplication>
0023 #include <QScopedPointer>
0024 
0025 // KDE includes
0026 
0027 #include <klocalizedstring.h>
0028 #include <ksharedconfig.h>
0029 #include <kconfiggroup.h>
0030 
0031 // Local includes
0032 
0033 #include "metaengine.h"
0034 #include "metadataselector.h"
0035 #include "dmetadata.h"
0036 
0037 namespace Digikam
0038 {
0039 
0040 static const char* ExifHumanList[] =
0041 {
0042     "Make",
0043     "Model",
0044     "DateTime",
0045     "ImageDescription",
0046     "Copyright",
0047     "ShutterSpeedValue",
0048     "ApertureValue",
0049     "ExposureProgram",
0050     "ExposureMode",
0051     "ExposureBiasValue",
0052     "ExposureTime",
0053     "WhiteBalance",
0054     "ISOSpeedRatings",
0055     "FocalLength",
0056     "SubjectDistance",
0057     "MeteringMode",
0058     "Contrast",
0059     "Saturation",
0060     "Sharpness",
0061     "LightSource",
0062     "Flash",
0063     "FNumber",
0064     "GPSLatitude",
0065     "GPSLongitude",
0066     "GPSAltitude",
0067     "-1"
0068 };
0069 
0070 // This list mix different tags name used by camera makers.
0071 static const char* MakerNoteHumanList[] =
0072 {
0073     "AFFocusPos",
0074     "AFMode",
0075     "AFPoint",
0076     "AutofocusMode",
0077     "ColorMode",
0078     "ColorTemperature",
0079     "Contrast",
0080     "DigitalZoom",
0081     "ExposureMode",
0082     "ExposureProgram",
0083     "ExposureCompensation",
0084     "ExposureManualBias",
0085     "Flash",
0086     "FlashBias",
0087     "FlashMode",
0088     "FlashType",
0089     "FlashDevice",
0090     "FNumber",
0091     "Focus",
0092     "FocusDistance",
0093     "FocusMode",
0094     "FocusSetting",
0095     "FocusType",
0096     "Hue",
0097     "HueAdjustment",
0098     "ImageStabilizer",
0099     "ImageStabilization",
0100     "InternalFlash",
0101     "ISOSelection",
0102     "ISOSpeed",
0103     "Lens",
0104     "LensType",
0105     "LensRange",
0106     "Macro",
0107     "MacroFocus",
0108     "MeteringMode",
0109     "NoiseReduction",
0110     "OwnerName",
0111     "Quality",
0112     "Tone",
0113     "ToneComp",
0114     "Saturation",
0115     "Sharpness",
0116     "ShootingMode",
0117     "ShutterSpeedValue",
0118     "SpotMode",
0119     "SubjectDistance",
0120     "WhiteBalance",
0121     "WhiteBalanceBias",
0122     "-1"
0123 };
0124 
0125 static const char* IptcHumanList[] =
0126 {
0127     "Caption",
0128     "City",
0129     "Contact",
0130     "Copyright",
0131     "Credit",
0132     "DateCreated",
0133     "Headline",
0134     "Keywords",
0135     "ProvinceState",
0136     "Source",
0137     "Urgency",
0138     "Writer",
0139     "-1"
0140 };
0141 
0142 static const char* XmpHumanList[] =
0143 {
0144     "Description",
0145     "City",
0146     "Relation",
0147     "Rights",
0148     "Publisher",
0149     "CreateDate",
0150     "Title",
0151     "Identifier",
0152     "State",
0153     "Source",
0154     "Rating",
0155     "Advisory",
0156     "-1"
0157 };
0158 
0159 class Q_DECL_HIDDEN MetadataPanel::Private
0160 {
0161 public:
0162 
0163     explicit Private()
0164       : tab                 (nullptr),
0165         parser              (nullptr),
0166         parserRunning       (false),
0167         exifViewerConfig    (nullptr),
0168         mknoteViewerConfig  (nullptr),
0169         iptcViewerConfig    (nullptr),
0170         xmpViewerConfig     (nullptr),
0171         exifToolViewerConfig(nullptr)
0172     {
0173         setDefaultFilter(ExifHumanList,      defaultExifFilter);
0174         setDefaultFilter(MakerNoteHumanList, defaultMknoteFilter);
0175         setDefaultFilter(IptcHumanList,      defaultIptcFilter);
0176         setDefaultFilter(XmpHumanList,       defaultXmpFilter);
0177 
0178         defaultExifToolFilter = defaultExifFilter   +
0179                                 defaultMknoteFilter +
0180                                 defaultIptcFilter   +
0181                                 defaultXmpFilter;
0182     };
0183 
0184     void setDefaultFilter(const char** const list, QStringList& filter)
0185     {
0186         for (int i = 0 ; QLatin1String(list[i]) != QLatin1String("-1") ; ++i)
0187         {
0188             filter << QLatin1String(list[i]);
0189         }
0190     };
0191 
0192 public:
0193 
0194     QTabWidget*                  tab;
0195 
0196     QStringList                  defaultExifFilter;
0197     QStringList                  defaultMknoteFilter;
0198     QStringList                  defaultIptcFilter;
0199     QStringList                  defaultXmpFilter;
0200     QStringList                  defaultExifToolFilter;
0201 
0202     ExifToolParser::ExifToolData parsedData;
0203     ExifToolParser*              parser;
0204     bool                         parserRunning;
0205 
0206     MetadataSelectorView*        exifViewerConfig;
0207     MetadataSelectorView*        mknoteViewerConfig;
0208     MetadataSelectorView*        iptcViewerConfig;
0209     MetadataSelectorView*        xmpViewerConfig;
0210     MetadataSelectorView*        exifToolViewerConfig;
0211 };
0212 
0213 MetadataPanel::MetadataPanel(QTabWidget* const tab)
0214     : QObject(tab),
0215       d      (new Private)
0216 {
0217     d->tab    = tab;
0218     d->parser = new ExifToolParser(this, true);
0219 
0220     // --------------------------------------------------------
0221 
0222     d->exifViewerConfig     = new MetadataSelectorView(d->tab, MetadataSelectorView::Exiv2Backend);
0223     d->exifViewerConfig->setDefaultFilter(d->defaultExifFilter);
0224     d->tab->addTab(d->exifViewerConfig, i18n("EXIF viewer"));
0225 
0226     d->mknoteViewerConfig   = new MetadataSelectorView(d->tab, MetadataSelectorView::Exiv2Backend);
0227     d->mknoteViewerConfig->setDefaultFilter(d->defaultMknoteFilter);
0228     d->tab->addTab(d->mknoteViewerConfig, i18n("Makernotes viewer"));
0229 
0230     d->iptcViewerConfig     = new MetadataSelectorView(d->tab, MetadataSelectorView::Exiv2Backend);
0231     d->iptcViewerConfig->setDefaultFilter(d->defaultIptcFilter);
0232     d->tab->addTab(d->iptcViewerConfig, i18n("IPTC viewer"));
0233 
0234     d->xmpViewerConfig      = new MetadataSelectorView(d->tab, MetadataSelectorView::Exiv2Backend);
0235     d->xmpViewerConfig->setDefaultFilter(d->defaultXmpFilter);
0236     d->tab->addTab(d->xmpViewerConfig, i18n("XMP viewer"));
0237 
0238     d->exifToolViewerConfig = new MetadataSelectorView(d->tab, MetadataSelectorView::ExifToolBackend);
0239     d->exifToolViewerConfig->setDefaultFilter(d->defaultExifToolFilter);
0240     d->tab->addTab(d->exifToolViewerConfig, i18n("ExifTool viewer"));
0241 
0242     slotTabChanged(d->tab->currentIndex());
0243 
0244     // --------------------------------------------------------
0245 
0246     connect(d->parser, SIGNAL(signalExifToolAsyncData(ExifToolParser::ExifToolData)),
0247             this, SLOT(slotExifToolAsyncData(ExifToolParser::ExifToolData)));
0248 
0249     connect(d->tab, SIGNAL(currentChanged(int)),
0250             this, SLOT(slotTabChanged(int)));
0251 }
0252 
0253 MetadataPanel::~MetadataPanel()
0254 {
0255     qApp->restoreOverrideCursor();
0256 
0257     delete d;
0258 }
0259 
0260 QStringList MetadataPanel::defaultExifFilter()
0261 {
0262     Private d;
0263     return d.defaultExifFilter;
0264 }
0265 
0266 QStringList MetadataPanel::defaultMknoteFilter()
0267 {
0268     Private d;
0269     return d.defaultMknoteFilter;
0270 }
0271 
0272 QStringList MetadataPanel::defaultIptcFilter()
0273 {
0274     Private d;
0275     return d.defaultIptcFilter;
0276 }
0277 
0278 QStringList MetadataPanel::defaultXmpFilter()
0279 {
0280     Private d;
0281     return d.defaultXmpFilter;
0282 }
0283 
0284 QStringList MetadataPanel::defaultExifToolFilter()
0285 {
0286     Private d;
0287     return d.defaultExifToolFilter;
0288 }
0289 
0290 void MetadataPanel::applySettings()
0291 {
0292     KSharedConfig::Ptr config = KSharedConfig::openConfig();
0293     KConfigGroup group        = config->group(QLatin1String("Image Properties SideBar"));
0294 
0295     if (d->exifViewerConfig->itemsCount())
0296     {
0297         group.writeEntry("EXIF Tags Filter", d->exifViewerConfig->checkedTagsList());
0298     }
0299 
0300     if (d->mknoteViewerConfig->itemsCount())
0301     {
0302         group.writeEntry("MAKERNOTE Tags Filter", d->mknoteViewerConfig->checkedTagsList());
0303     }
0304 
0305     if (d->iptcViewerConfig->itemsCount())
0306     {
0307         group.writeEntry("IPTC Tags Filter", d->iptcViewerConfig->checkedTagsList());
0308     }
0309 
0310     if (d->xmpViewerConfig->itemsCount())
0311     {
0312         group.writeEntry("XMP Tags Filter", d->xmpViewerConfig->checkedTagsList());
0313     }
0314 
0315     if (d->exifToolViewerConfig->itemsCount())
0316     {
0317         group.writeEntry("EXIFTOOL Tags Filter", d->exifToolViewerConfig->checkedTagsList());
0318     }
0319 
0320     config->sync();
0321 }
0322 
0323 void MetadataPanel::slotTabChanged(int)
0324 {
0325     QScopedPointer<DMetadata> meta(new DMetadata);
0326     qApp->setOverrideCursor(Qt::WaitCursor);
0327     qApp->processEvents();
0328     KSharedConfig::Ptr config = KSharedConfig::openConfig();
0329     KConfigGroup group        = config->group(QLatin1String("Image Properties SideBar"));
0330     QWidget* const tab        = d->tab->currentWidget();
0331 
0332     if      (tab == d->exifViewerConfig)
0333     {
0334         if (!d->exifViewerConfig->itemsCount())
0335         {
0336             d->exifViewerConfig->setTagsMap(meta->getStdExifTagsList());
0337             d->exifViewerConfig->setcheckedTagsList(group.readEntry("EXIF Tags Filter",
0338                                                                     d->exifViewerConfig->defaultFilter()));
0339         }
0340     }
0341     else if (tab == d->mknoteViewerConfig)
0342     {
0343         if (!d->mknoteViewerConfig->itemsCount())
0344         {
0345             d->mknoteViewerConfig->setTagsMap(meta->getMakernoteTagsList());
0346             d->mknoteViewerConfig->setcheckedTagsList(group.readEntry("MAKERNOTE Tags Filter",
0347                                                                       d->mknoteViewerConfig->defaultFilter()));
0348         }
0349     }
0350     else if (tab == d->iptcViewerConfig)
0351     {
0352         if (!d->iptcViewerConfig->itemsCount())
0353         {
0354             d->iptcViewerConfig->setTagsMap(meta->getIptcTagsList());
0355             d->iptcViewerConfig->setcheckedTagsList(group.readEntry("IPTC Tags Filter",
0356                                                                     d->iptcViewerConfig->defaultFilter()));
0357         }
0358     }
0359     else if (tab == d->xmpViewerConfig)
0360     {
0361         if (!d->xmpViewerConfig->itemsCount())
0362         {
0363             d->xmpViewerConfig->setTagsMap(meta->getXmpTagsList());
0364             d->xmpViewerConfig->setcheckedTagsList(group.readEntry("XMP Tags Filter",
0365                                                                    d->xmpViewerConfig->defaultFilter()));
0366         }
0367     }
0368     else if (tab == d->exifToolViewerConfig)
0369     {
0370         if (!d->exifToolViewerConfig->itemsCount() && d->parser->exifToolAvailable())
0371         {
0372             if (!d->parserRunning)
0373             {
0374                 d->parserRunning = d->parser->tagsDatabase();
0375 
0376                 // Let the waiting cursor continue to run.
0377 
0378                 return;
0379             }
0380             else if (!d->parsedData.isEmpty())
0381             {
0382                 d->exifToolViewerConfig->setTagsMap(d->parser->tagsDbToOrderedMap(d->parsedData));
0383                 d->exifToolViewerConfig->setcheckedTagsList(group.readEntry("EXIFTOOL Tags Filter",
0384                                                                             d->exifToolViewerConfig->defaultFilter()));
0385                 d->parserRunning = false;
0386             }
0387         }
0388     }
0389 
0390     qApp->restoreOverrideCursor();
0391 }
0392 
0393 void MetadataPanel::slotExifToolAsyncData(const ExifToolParser::ExifToolData& data)
0394 {
0395     d->parsedData = data;
0396     qApp->restoreOverrideCursor();
0397     slotTabChanged(d->tab->currentIndex());
0398 }
0399 
0400 QStringList MetadataPanel::getAllCheckedTags() const
0401 {
0402     QStringList checkedTags;
0403     checkedTags
0404             << d->exifViewerConfig->checkedTagsList()
0405             << d->iptcViewerConfig->checkedTagsList()
0406             << d->mknoteViewerConfig->checkedTagsList()
0407             << d->xmpViewerConfig->checkedTagsList()
0408             << d->exifToolViewerConfig->checkedTagsList()
0409             ;
0410 
0411     return checkedTags;
0412 }
0413 
0414 QList<MetadataSelectorView*> MetadataPanel::viewers() const
0415 {
0416     QList<MetadataSelectorView*> viewers;
0417     viewers
0418             << d->exifViewerConfig
0419             << d->iptcViewerConfig
0420             << d->mknoteViewerConfig
0421             << d->xmpViewerConfig
0422             << d->exifToolViewerConfig
0423             ;
0424 
0425     return viewers;
0426 }
0427 
0428 } // namespace Digikam
0429 
0430 #include "moc_metadatapanel.cpp"