1 /* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2010-11-10
7 * Description : meta-filter to apply FilterAction
8 *
9 * Copyright (C) 2010-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
10 * Copyright (C) 2010 by Martin Klapetek <martin dot klapetek at gmail dot com>
11 *
12 * This program is free software; you can redistribute it
13 * and/or modify it under the terms of the GNU General
14 * Public License as published by the Free Software Foundation;
15 * either version 2, or (at your option)
16 * any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * ============================================================ */
24
25 #include "filteractionfilter.h"
26
27 // Qt includes
28
29 #include <QScopedPointer>
30
31 // KDE includes
32
33 #include <klocalizedstring.h>
34
35 // Local includes
36
37 #include "digikam_debug.h"
38 #include "digikam_export.h"
39 #include "dimgbuiltinfilter.h"
40 #include "dimgfiltermanager.h"
41 #include "filteraction.h"
42
43 namespace Digikam
44 {
45
46 class Q_DECL_HIDDEN FilterActionFilter::Private
47 {
48 public:
49
Private()50 explicit Private()
51 : continueOnError(false)
52 {
53 }
54
55 bool continueOnError;
56
57 QList<FilterAction> actions;
58 QList<FilterAction> appliedActions;
59
60 QString errorMessage;
61 };
62
FilterActionFilter(QObject * const parent)63 FilterActionFilter::FilterActionFilter(QObject* const parent)
64 : DImgThreadedFilter(parent),
65 d(new Private)
66 {
67 initFilter();
68 }
69
~FilterActionFilter()70 FilterActionFilter::~FilterActionFilter()
71 {
72 delete d;
73 }
74
setContinueOnError(bool cont)75 void FilterActionFilter::setContinueOnError(bool cont)
76 {
77 d->continueOnError = cont;
78 }
79
setFilterActions(const QList<FilterAction> & actions)80 void FilterActionFilter::setFilterActions(const QList<FilterAction>& actions)
81 {
82 d->actions = actions;
83 }
84
addFilterActions(const QList<FilterAction> & actions)85 void FilterActionFilter::addFilterActions(const QList<FilterAction>& actions)
86 {
87 d->actions += actions;
88 }
89
setFilterAction(const FilterAction & action)90 void FilterActionFilter::setFilterAction(const FilterAction& action)
91 {
92 d->actions.clear();
93 d->actions << action;
94 }
95
addFilterAction(const FilterAction & action)96 void FilterActionFilter::addFilterAction(const FilterAction& action)
97 {
98 d->actions << action;
99 }
100
filterActions() const101 QList<FilterAction> FilterActionFilter::filterActions() const
102 {
103 return d->actions;
104 }
105
isReproducible() const106 bool FilterActionFilter::isReproducible() const
107 {
108 foreach (const FilterAction& action, d->actions)
109 {
110 if (!action.isNull() &&
111 (action.category() != FilterAction::ReproducibleFilter))
112 {
113 return false;
114 }
115 }
116
117 return true;
118 }
119
isComplexAction() const120 bool FilterActionFilter::isComplexAction() const
121 {
122 foreach (const FilterAction& action, d->actions)
123 {
124 if (!action.isNull() &&
125 (action.category() != FilterAction::ReproducibleFilter) &&
126 (action.category() != FilterAction::ComplexFilter))
127 {
128 return false;
129 }
130 }
131
132 return true;
133 }
134
isSupported() const135 bool FilterActionFilter::isSupported() const
136 {
137 foreach (const FilterAction& action, d->actions)
138 {
139 if (!action.isNull() && !DImgFilterManager::instance()->isSupported(action.identifier(), action.version()))
140 {
141 return false;
142 }
143 }
144
145 return true;
146 }
147
completelyApplied() const148 bool FilterActionFilter::completelyApplied() const
149 {
150 return (d->appliedActions.size() == d->actions.size());
151 }
152
appliedFilterActions() const153 QList<FilterAction> FilterActionFilter::appliedFilterActions() const
154 {
155 return d->appliedActions;
156 }
157
failedAction() const158 FilterAction FilterActionFilter::failedAction() const
159 {
160 if (d->appliedActions.size() >= d->actions.size())
161 {
162 return FilterAction();
163 }
164
165 return d->actions.at(d->appliedActions.size());
166 }
167
failedActionIndex() const168 int FilterActionFilter::failedActionIndex() const
169 {
170 return d->appliedActions.size();
171 }
172
failedActionMessage() const173 QString FilterActionFilter::failedActionMessage() const
174 {
175 return d->errorMessage;
176 }
177
filterImage()178 void FilterActionFilter::filterImage()
179 {
180 d->appliedActions.clear();
181 d->errorMessage.clear();
182 const float progressIncrement = 1.0 / qMax(1, d->actions.size());
183 float progress = 0;
184
185 postProgress(0);
186
187 DImg img = m_orgImage;
188
189 foreach (const FilterAction& action, d->actions)
190 {
191 qCDebug(DIGIKAM_DIMG_LOG) << "Replaying action" << action.identifier();
192
193 if (action.isNull())
194 {
195 continue;
196 }
197
198 if (DImgBuiltinFilter::isSupported(action.identifier()))
199 {
200 DImgBuiltinFilter filter(action);
201
202 if (!filter.isValid())
203 {
204 d->errorMessage = i18n("Built-in transformation not supported");
205
206 if (d->continueOnError)
207 {
208 continue;
209 }
210 else
211 {
212 break;
213 }
214 }
215
216 filter.apply(img);
217 d->appliedActions << filter.filterAction();
218 }
219 else
220 {
221 QScopedPointer<DImgThreadedFilter> filter
222 (DImgFilterManager::instance()->createFilter(action.identifier(), action.version()));
223
224 if (!filter)
225 {
226 d->errorMessage = i18n("Filter identifier or version is not supported");
227
228 if (d->continueOnError)
229 {
230 continue;
231 }
232 else
233 {
234 break;
235 }
236 }
237
238 filter->readParameters(action);
239
240 if (!filter->parametersSuccessfullyRead())
241 {
242 d->errorMessage = filter->readParametersError(action);
243
244 if (d->continueOnError)
245 {
246 continue;
247 }
248 else
249 {
250 break;
251 }
252 }
253
254 // compute
255 filter->setupAndStartDirectly(img, this, (int)progress, (int)(progress + progressIncrement));
256 img = filter->getTargetImage();
257 d->appliedActions << filter->filterAction();
258 }
259
260 progress += progressIncrement;
261 postProgress((int)progress);
262 }
263
264 m_destImage = img;
265 }
266
267 } // namespace Digikam
268