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        : 2021-04-29
0007  * Description : ExifTool configuration panel.
0008  *
0009  * SPDX-FileCopyrightText: 2021-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 "exiftoolconfpanel.h"
0016 
0017 // Qt includes
0018 
0019 #include <QGridLayout>
0020 #include <QVBoxLayout>
0021 #include <QTreeWidget>
0022 #include <QTreeWidgetItem>
0023 #include <QLabel>
0024 #include <QStringList>
0025 #include <QGroupBox>
0026 #include <QApplication>
0027 #include <QStyle>
0028 #include <QHeaderView>
0029 
0030 // KDE includes
0031 
0032 #include <klocalizedstring.h>
0033 
0034 // Local includes
0035 
0036 #include "exiftoolbinary.h"
0037 #include "exiftoolparser.h"
0038 #include "dbinarysearch.h"
0039 #include "metaenginesettings.h"
0040 
0041 namespace Digikam
0042 {
0043 
0044 class Q_DECL_HIDDEN ExifToolConfPanel::Private
0045 {
0046 public:
0047 
0048     explicit Private()
0049       : exifToolBinWidget(nullptr),
0050         searchBar        (nullptr),
0051         exifToolFormats  (nullptr)
0052     {
0053     }
0054 
0055 public:
0056 
0057     DBinarySearch* exifToolBinWidget;
0058     ExifToolBinary exifToolBin;
0059     SearchTextBar* searchBar;
0060 
0061     QTreeWidget*   exifToolFormats;
0062 };
0063 
0064 // --------------------------------------------------------
0065 
0066 ExifToolConfPanel::ExifToolConfPanel(QWidget* const parent)
0067     : QWidget(parent),
0068       d      (new Private)
0069 {
0070     QGridLayout* const grid        = new QGridLayout;
0071     QLabel* const exifToolBinLabel = new QLabel(i18nc("@info",
0072                                                 "%1 is an open-source software program for reading, writing, "
0073                                                 "and manipulating multimedia files. It is platform independent "
0074                                                 "available as a command-line application. ExifTool is commonly "
0075                                                 "incorporated into different types of digital workflows and supports "
0076                                                 "many types of metadata including Exif, IPTC, XMP, JFIF, GeoTIFF, ICC Profile, "
0077                                                 "Photoshop IRB, as well as the manufacturer-specific metadata formats of "
0078                                                 "many digital cameras.\n\n"
0079                                                 "Here you can configure location where ExifTool binary is located. "
0080                                                 "Application will try to find this binary automatically if they are "
0081                                                 "already installed on your computer.",
0082                                                 QString::fromUtf8("<a href='https://www.exiftool.org'>ExifTool</a>")),
0083                                                 this);
0084     exifToolBinLabel->setWordWrap(true);
0085     exifToolBinLabel->setOpenExternalLinks(true);
0086 
0087     d->exifToolBinWidget         = new DBinarySearch(this);
0088     d->exifToolBinWidget->addBinary(d->exifToolBin);
0089 
0090     QGroupBox* const exifToolBox = new QGroupBox(i18nc("@title: group", "Supported File Formats"), this);
0091     d->exifToolFormats           = new QTreeWidget(exifToolBox);
0092     d->exifToolFormats->setRootIsDecorated(false);
0093     d->exifToolFormats->setSortingEnabled(true);
0094     d->exifToolFormats->sortByColumn(0, Qt::AscendingOrder);
0095     d->exifToolFormats->setSelectionMode(QAbstractItemView::SingleSelection);
0096     d->exifToolFormats->setAllColumnsShowFocus(true);
0097     d->exifToolFormats->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
0098     d->exifToolFormats->setColumnCount(4);
0099     d->exifToolFormats->setHeaderHidden(false);
0100     d->exifToolFormats->setHeaderLabels(QStringList() << i18nc("@title: column", "Extension")
0101                                                       << i18nc("@title: column", "Read")
0102                                                       << i18nc("@title: column", "Write")
0103                                                       << i18nc("@title: column", "Description"));
0104 
0105     d->searchBar                 = new SearchTextBar(this, QLatin1String("ExifToolFormatsSearchBar"));
0106 
0107     QVBoxLayout* const vlay      = new QVBoxLayout(exifToolBox);
0108     vlay->addWidget(d->exifToolFormats);
0109     vlay->addWidget(d->searchBar);
0110 
0111     grid->addWidget(exifToolBinLabel,     0, 0, 1, 2);
0112     grid->addWidget(d->exifToolBinWidget, 1, 0, 1, 2);
0113     grid->addWidget(exifToolBox,          2, 0, 1, 2);
0114     grid->setRowStretch(2, 10);
0115     setLayout(grid);
0116 
0117     // ---
0118 
0119     connect(d->searchBar, SIGNAL(signalSearchTextSettings(SearchTextSettings)),
0120             this, SLOT(slotSearchTextChanged(SearchTextSettings)));
0121 
0122     connect(d->exifToolBinWidget, SIGNAL(signalBinariesFound(bool)),
0123             this, SLOT(slotExifToolBinaryFound(bool)));
0124 
0125     Q_FOREACH (const QString& path, MetaEngineSettings::instance()->settings().defaultExifToolSearchPaths())
0126     {
0127         d->exifToolBinWidget->addDirectory(path);
0128     }
0129 }
0130 
0131 ExifToolConfPanel::~ExifToolConfPanel()
0132 {
0133     delete d;
0134 }
0135 
0136 void ExifToolConfPanel::slotStartFoundExifTool()
0137 {
0138     d->exifToolBinWidget->allBinariesFound();
0139 }
0140 
0141 QString ExifToolConfPanel::exifToolDirectory() const
0142 {
0143     return d->exifToolBin.directory();
0144 }
0145 
0146 void ExifToolConfPanel::setExifToolDirectory(const QString& dir)
0147 {
0148     d->exifToolBin.setup(dir);
0149 }
0150 
0151 void ExifToolConfPanel::slotExifToolBinaryFound(bool found)
0152 {
0153     d->exifToolFormats->clear();
0154     bool exifToolAvailable = false;
0155 
0156     if (found)
0157     {
0158         QScopedPointer<ExifToolParser> const parser(new ExifToolParser(this));
0159         parser->setExifToolProgram(exifToolDirectory());
0160         exifToolAvailable = parser->exifToolAvailable();
0161 
0162         if (exifToolAvailable)
0163         {
0164             ExifToolParser::ExifToolData parsed;
0165             QStringList read;
0166             QStringList write;
0167 
0168             if (parser->readableFormats() && !parser->currentData().isEmpty())
0169             {
0170                 parsed = parser->currentData();
0171                 read   = parsed.find(QLatin1String("READ_FORMATS")).value()[0].toStringList();
0172             }
0173 
0174             if (parser->writableFormats() && !parser->currentData().isEmpty())
0175             {
0176                 parsed = parser->currentData();
0177                 write  = parsed.find(QLatin1String("WRITE_FORMATS")).value()[0].toStringList();
0178             }
0179 
0180             QString ext;
0181             QString desc;
0182 
0183             for (int i = 0 ; i < read.size()  ; i += 2)
0184             {
0185                 ext  = read[i];
0186                 desc = read[i + 1];
0187                 new QTreeWidgetItem(d->exifToolFormats, QStringList() << ext
0188                                                                       << i18nc("@info: status", "yes")
0189                                                                       << (write.contains(ext) ? i18nc("@info: status", "yes")
0190                                                                                               : i18nc("@info: status", "no"))
0191                                                                       << desc);
0192             }
0193         }
0194     }
0195 
0196     Q_EMIT signalExifToolSettingsChanged(exifToolAvailable);
0197 }
0198 
0199 void ExifToolConfPanel::slotSearchTextChanged(const SearchTextSettings& settings)
0200 {
0201     bool query     = false;
0202     int  results   = 0;
0203     QString search = settings.text.toLower();
0204 
0205     QTreeWidgetItemIterator it(d->exifToolFormats);
0206 
0207     while (*it)
0208     {
0209         QTreeWidgetItem* const item  = *it;
0210 
0211         if (item->text(0).toLower().contains(search, settings.caseSensitive) ||
0212             item->text(3).toLower().contains(search, settings.caseSensitive))
0213         {
0214             ++results;
0215             query = true;
0216             item->setHidden(false);
0217         }
0218         else
0219         {
0220             item->setHidden(true);
0221         }
0222 
0223         ++it;
0224     }
0225 
0226     d->searchBar->slotSearchResult(query);
0227 }
0228 
0229 } // namespace Digikam
0230 
0231 #include "moc_exiftoolconfpanel.cpp"