File indexing completed on 2025-01-19 03:53:17

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