File indexing completed on 2025-01-05 03:53:46

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2019-09-18
0007  * Description : ART raw import plugin.
0008  *
0009  * SPDX-FileCopyrightText: 2019-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 "rawimportartplugin.h"
0016 
0017 // Qt includes
0018 
0019 #include <QMessageBox>
0020 #include <QApplication>
0021 #include <QPointer>
0022 #include <QByteArray>
0023 #include <QFileInfo>
0024 #include <QSettings>
0025 #include <QTemporaryFile>
0026 
0027 // KDE includes
0028 
0029 #include <klocalizedstring.h>
0030 
0031 // Local includes
0032 
0033 #include "digikam_debug.h"
0034 #include "digikam_globals_p.h"      // For KF6::Ki18n deprecated
0035 #include "dimg.h"
0036 #include "filteraction.h"
0037 #include "dfileoperations.h"
0038 #include "loadingdescription.h"
0039 
0040 namespace DigikamRawImportARTPlugin
0041 {
0042 
0043 class Q_DECL_HIDDEN ARTRawImportPlugin::Private
0044 {
0045 public:
0046 
0047     explicit Private()
0048       : art(nullptr)
0049     {
0050     }
0051 
0052     QProcess*          art;
0053     DImg               decoded;
0054     LoadingDescription props;
0055     QString            tempName;
0056 };
0057 
0058 ARTRawImportPlugin::ARTRawImportPlugin(QObject* const parent)
0059     : DPluginRawImport(parent),
0060       d               (new Private)
0061 {
0062 }
0063 
0064 ARTRawImportPlugin::~ARTRawImportPlugin()
0065 {
0066     delete d;
0067 }
0068 
0069 QString ARTRawImportPlugin::name() const
0070 {
0071     return QString::fromUtf8("Raw Import using ART");
0072 }
0073 
0074 QString ARTRawImportPlugin::iid() const
0075 {
0076     return QLatin1String(DPLUGIN_IID);
0077 }
0078 
0079 QIcon ARTRawImportPlugin::icon() const
0080 {
0081     return QIcon::fromTheme(QLatin1String("image-x-adobe-dng"));
0082 }
0083 
0084 QString ARTRawImportPlugin::description() const
0085 {
0086     return QString::fromUtf8("A RAW import plugin based on ART");
0087 }
0088 
0089 QString ARTRawImportPlugin::details() const
0090 {
0091     return QString::fromUtf8("<p>This RAW Import plugin use ART tool to pre-process file in Image Editor.</p>"
0092                              "<p>It requires at least ART version 1.8.2 to work.</p>"
0093                              "<p>See ART web site for details: <a href='https://bitbucket.org/agriggio/art/wiki/Home'>"
0094                              "https://bitbucket.org/agriggio/art/wiki/Home</a></p>");
0095 }
0096 
0097 QString ARTRawImportPlugin::handbookSection() const
0098 {
0099     return QLatin1String("setup_application");
0100 }
0101 
0102 QString ARTRawImportPlugin::handbookChapter() const
0103 {
0104     return QLatin1String("editor_settings");
0105 }
0106 
0107 QString ARTRawImportPlugin::handbookReference() const
0108 {
0109     return QLatin1String("setup-raw");
0110 }
0111 
0112 QList<DPluginAuthor> ARTRawImportPlugin::authors() const
0113 {
0114     return QList<DPluginAuthor>()
0115             << DPluginAuthor(QString::fromUtf8("Gilles Caulier"),
0116                              QString::fromUtf8("caulier dot gilles at gmail dot com"),
0117                              QString::fromUtf8("(C) 2019-2022"))
0118             ;
0119 }
0120 
0121 void ARTRawImportPlugin::setup(QObject* const /*parent*/)
0122 {
0123     // Nothing to do
0124 }
0125 
0126 QString ARTRawImportPlugin::getRawProgram() const
0127 {
0128     return DFileOperations::findExecutable(QLatin1String("ART"));
0129 }
0130 
0131 bool ARTRawImportPlugin::run(const QString& filePath, const DRawDecoding& /*def*/)
0132 {
0133     QFileInfo fileInfo(filePath);
0134     d->props       = LoadingDescription(fileInfo.filePath(), LoadingDescription::ConvertForEditor);
0135     d->decoded     = DImg();
0136 
0137     QTemporaryFile tempFile;
0138     tempFile.open();
0139     d->tempName    = tempFile.fileName();
0140 
0141     d->art = new QProcess(this);
0142     d->art->setProcessChannelMode(QProcess::MergedChannels);
0143     d->art->setWorkingDirectory(fileInfo.path());
0144     d->art->setProcessEnvironment(adjustedEnvironmentForAppImage());
0145 
0146     connect(d->art, SIGNAL(errorOccurred(QProcess::ProcessError)),
0147             this, SLOT(slotErrorOccurred(QProcess::ProcessError)));
0148 
0149     connect(d->art, SIGNAL(finished(int,QProcess::ExitStatus)),
0150             this, SLOT(slotProcessFinished(int,QProcess::ExitStatus)));
0151 
0152     connect(d->art, SIGNAL(readyRead()),
0153             this, SLOT(slotProcessReadyRead()));
0154 
0155     // --------
0156 
0157     d->art->setProgram(getRawProgram());
0158     d->art->setArguments(QStringList() << QLatin1String("-gimp") // Special mode used initially as Gimp plugin
0159                                        << filePath               // Input file
0160                                        << d->tempName);          // Output file
0161 
0162     qCDebug(DIGIKAM_GENERAL_LOG) << "ART arguments:" << d->art->arguments();
0163 
0164     d->art->start();
0165 
0166     return d->art->waitForStarted(10000);
0167 }
0168 
0169 void ARTRawImportPlugin::slotErrorOccurred(QProcess::ProcessError error)
0170 {
0171     switch (error)
0172     {
0173         case QProcess::FailedToStart:
0174         {
0175             qCDebug(DIGIKAM_GENERAL_LOG) << "ART :: Process has failed to start";
0176             break;
0177         }
0178 
0179         case QProcess::Crashed:
0180         {
0181             qCDebug(DIGIKAM_GENERAL_LOG) << "ART :: Process has crashed";
0182             break;
0183         }
0184 
0185         case QProcess::Timedout:
0186         {
0187             qCDebug(DIGIKAM_GENERAL_LOG) << "ART :: Process time-out";
0188             break;
0189         }
0190 
0191         case QProcess::WriteError:
0192         {
0193             qCDebug(DIGIKAM_GENERAL_LOG) << "ART :: Process write error";
0194             break;
0195         }
0196 
0197         case QProcess::ReadError:
0198         {
0199             qCDebug(DIGIKAM_GENERAL_LOG) << "ART :: Process read error";
0200             break;
0201         }
0202 
0203         default:
0204         {
0205             qCDebug(DIGIKAM_GENERAL_LOG) << "ART :: Process error unknown";
0206             break;
0207         }
0208     }
0209 }
0210 
0211 void ARTRawImportPlugin::slotProcessFinished(int code, QProcess::ExitStatus status)
0212 {
0213     qCDebug(DIGIKAM_GENERAL_LOG) << "ART :: return code:" << code << ":: Exit status:" << status;
0214 
0215     d->decoded = DImg(d->tempName);
0216     d->decoded.setAttribute(QLatin1String("isReadOnly"), true);
0217 
0218     if (d->decoded.isNull())
0219     {
0220         QString message = i18n("Error to import RAW image with ART\nClose this dialog to load RAW image with native import tool");
0221         QMessageBox::information(nullptr, qApp->applicationName(), message);
0222 
0223         qCDebug(DIGIKAM_GENERAL_LOG) << "Decoded image is null! Load with Native tool...";
0224         qCDebug(DIGIKAM_GENERAL_LOG) << d->props.filePath;
0225 
0226         Q_EMIT signalLoadRaw(d->props);
0227     }
0228     else
0229     {
0230         qCDebug(DIGIKAM_GENERAL_LOG) << "Decoded image is not null...";
0231         qCDebug(DIGIKAM_GENERAL_LOG) << d->props.filePath;
0232         d->props = LoadingDescription(d->tempName, LoadingDescription::ConvertForEditor);
0233 
0234         FilterAction action(QLatin1String("art:RawConverter"), 1, FilterAction::DocumentedHistory);
0235         action.setDisplayableName(QString::fromUtf8(I18N_NOOP("ART Raw Conversion")));
0236         d->decoded.addFilterAction(action);
0237 
0238         Q_EMIT signalDecodedImage(d->props, d->decoded);
0239     }
0240 
0241     delete d->art;
0242     d->art = nullptr;
0243 
0244     QFile::remove(d->tempName);
0245 }
0246 
0247 void ARTRawImportPlugin::slotProcessReadyRead()
0248 {
0249     QByteArray data   = d->art->readAllStandardError();
0250     QStringList lines = QString::fromUtf8(data).split(QLatin1Char('\n'), QT_SKIP_EMPTY_PARTS);
0251 
0252     Q_FOREACH (const QString& one, lines)
0253     {
0254         qCDebug(DIGIKAM_GENERAL_LOG) << "ART ::" << one;
0255     }
0256 }
0257 
0258 } // namespace DigikamRawImportARTPlugin
0259 
0260 #include "moc_rawimportartplugin.cpp"