1 /** ===========================================================
2  * @file
3  *
4  * This file is a part of digiKam project
5  * <a href="https://www.digikam.org">https://www.digikam.org</a>
6  *
7  * @date  : 2014-10-17
8  * @brief : a class to manage Raw to Png conversion using threads
9  *
10  * @author Copyright (C) 2011-2015 by Gilles Caulier
11  *         <a href="mailto:caulier dot gilles at gmail dot com">caulier dot gilles at gmail dot com</a>
12  * @author Copyright (C) 2014 by Veaceslav Munteanu
13  *         <a href="mailto:veaceslav dot munteanu90 at gmail dot com">veaceslav dot munteanu90 at gmail dot com</a>
14  *
15  * This program is free software; you can redistribute it
16  * and/or modify it under the terms of the GNU General
17  * Public License as published by the Free Software Foundation;
18  * either version 2, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * ============================================================ */
26 
27 #include "actionthread.h"
28 
29 // Qt includes
30 
31 #include <QFileInfo>
32 #include <QImage>
33 #include <QDebug>
34 
35 // Local includes
36 
37 #include "kdcraw.h"
38 #include "ractionjob.h"
39 
40 class Task : public RActionJob
41 {
42 public:
43 
Task()44     Task()
45         : RActionJob()
46     {
47     }
48 
49     RawDecodingSettings settings;
50     QString             errString;
51     QUrl                fileUrl;
52 
53 protected:
54 
run()55     void run()
56     {
57         emit signalStarted();
58 
59         QImage image;
60 
61         if (m_cancel) return;
62 
63         emit signalProgress(20);
64 
65         KDcraw rawProcessor;
66 
67         if (m_cancel) return;
68 
69         emit signalProgress(30);
70 
71         QFileInfo input(fileUrl.toLocalFile());
72         QString   fullFilePath(input.baseName() + QString::fromLatin1(".full.png"));
73         QFileInfo fullOutput(fullFilePath);
74 
75         if (m_cancel) return;
76 
77         emit signalProgress(40);
78 
79         if (!rawProcessor.loadFullImage(image, fileUrl.toLocalFile(), settings))
80         {
81             errString = QString::fromLatin1("raw2png: Loading full RAW image failed. Aborted...");
82             return;
83         }
84 
85         if (m_cancel) return;
86 
87         emit signalProgress(60);
88 
89         qDebug() << "raw2png: Saving full RAW image to "
90                  << fullOutput.fileName() << " size ("
91                  << image.width() << "x" << image.height()
92                  << ")";
93 
94         if (m_cancel) return;
95 
96         emit signalProgress(80);
97 
98         image.save(fullFilePath, "PNG");
99 
100         emit signalDone();
101     }
102 };
103 
104 // ----------------------------------------------------------------------------------------------------
105 
ActionThread(QObject * const parent)106 ActionThread::ActionThread(QObject* const parent)
107     : RActionThreadBase(parent)
108 {
109 }
110 
~ActionThread()111 ActionThread::~ActionThread()
112 {
113 }
114 
convertRAWtoPNG(const QList<QUrl> & list,const RawDecodingSettings & settings,int priority)115 void ActionThread::convertRAWtoPNG(const QList<QUrl>& list, const RawDecodingSettings& settings, int priority)
116 {
117     RJobCollection collection;
118 
119     Q_FOREACH (const QUrl& url, list)
120     {
121         Task* const job = new Task();
122         job->fileUrl    = url;
123         job->settings   = settings;
124 
125         connect(job, SIGNAL(signalStarted()),
126                 this, SLOT(slotJobStarted()));
127 
128         connect(job, SIGNAL(signalProgress(int)),
129                 this, SLOT(slotJobProgress(int)));
130 
131         connect(job, SIGNAL(signalDone()),
132                 this, SLOT(slotJobDone()));
133 
134         collection.insert(job, priority);
135 
136         qDebug() << "Appending file to process " << url;
137     }
138 
139     appendJobs(collection);
140 }
141 
slotJobDone()142 void ActionThread::slotJobDone()
143 {
144     Task* const task = dynamic_cast<Task*>(sender());
145     if (!task) return;
146 
147     if (task->errString.isEmpty())
148     {
149         emit finished(task->fileUrl);
150     }
151     else
152     {
153         emit failed(task->fileUrl, task->errString);
154     }
155 }
156 
slotJobProgress(int p)157 void ActionThread::slotJobProgress(int p)
158 {
159     Task* const task = dynamic_cast<Task*>(sender());
160     if (!task) return;
161 
162     emit progress(task->fileUrl, p);
163 }
164 
slotJobStarted()165 void ActionThread::slotJobStarted()
166 {
167     Task* const task = dynamic_cast<Task*>(sender());
168     if (!task) return;
169 
170     emit starting(task->fileUrl);
171 }
172