1 /* ============================================================
2  *
3  * This file is a part of digiKam project
4  * https://www.digikam.org
5  *
6  * Date        : 2010-03-09
7  * Description : Local Contrast settings view.
8  *               LDR ToneMapper <zynaddsubfx.sourceforge.net/other/tonemapping>
9  *
10  * Copyright (C) 2010-2021 by Gilles Caulier <caulier dot gilles 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 "localcontrastsettings.h"
26 
27 // Qt includes
28 
29 #include <QString>
30 #include <QButtonGroup>
31 #include <QFile>
32 #include <QFrame>
33 #include <QGridLayout>
34 #include <QCheckBox>
35 #include <QHBoxLayout>
36 #include <QLabel>
37 #include <QRegExp>
38 #include <QTextStream>
39 #include <QToolButton>
40 #include <QVBoxLayout>
41 #include <QStandardPaths>
42 #include <QApplication>
43 #include <QStyle>
44 #include <QUrl>
45 #include <QIcon>
46 #include <QMessageBox>
47 
48 // KDE includes
49 
50 #include <kconfiggroup.h>
51 #include <klocalizedstring.h>
52 
53 // Local includes
54 
55 #include "dexpanderbox.h"
56 #include "dfiledialog.h"
57 #include "dnuminput.h"
58 #include "digikam_debug.h"
59 #include "dcombobox.h"
60 
61 namespace Digikam
62 {
63 
64 class Q_DECL_HIDDEN LocalContrastSettings::Private
65 {
66 
67 public:
68 
Private()69     explicit Private()
70       : stretchContrastCheck(nullptr),
71         label4              (nullptr),
72         label5              (nullptr),
73         label6              (nullptr),
74         label7              (nullptr),
75         label8              (nullptr),
76         label9              (nullptr),
77         label10             (nullptr),
78         label11             (nullptr),
79         lowSaturationInput  (nullptr),
80         highSaturationInput (nullptr),
81         functionInput       (nullptr),
82         powerInput1         (nullptr),
83         blurInput1          (nullptr),
84         powerInput2         (nullptr),
85         blurInput2          (nullptr),
86         powerInput3         (nullptr),
87         blurInput3          (nullptr),
88         powerInput4         (nullptr),
89         blurInput4          (nullptr),
90         expanderBox         (nullptr)
91     {
92     }
93 
94     static const QString  configLowSaturationEntry;
95     static const QString  configHighSaturationEntry;
96     static const QString  configPower1Entry;
97     static const QString  configBlur1Entry;
98     static const QString  configPower2Entry;
99     static const QString  configBlur2Entry;
100     static const QString  configPower3Entry;
101     static const QString  configBlur3Entry;
102     static const QString  configPower4Entry;
103     static const QString  configBlur4Entry;
104     static const QString  configStretchContrastEntry;
105     static const QString  configFastModeEntry;
106     static const QString  configStageOneEntry;
107     static const QString  configStageTwoEntry;
108     static const QString  configStageThreeEntry;
109     static const QString  configStageFourEntry;
110     static const QString  configFunctionInputEntry;
111 
112     QCheckBox*            stretchContrastCheck;
113 
114     QLabel*               label4;
115     QLabel*               label5;
116     QLabel*               label6;
117     QLabel*               label7;
118     QLabel*               label8;
119     QLabel*               label9;
120     QLabel*               label10;
121     QLabel*               label11;
122 
123     DIntNumInput*         lowSaturationInput;
124     DIntNumInput*         highSaturationInput;
125 
126     DComboBox*            functionInput;
127 
128     DDoubleNumInput*      powerInput1;
129     DDoubleNumInput*      blurInput1;
130     DDoubleNumInput*      powerInput2;
131     DDoubleNumInput*      blurInput2;
132     DDoubleNumInput*      powerInput3;
133     DDoubleNumInput*      blurInput3;
134     DDoubleNumInput*      powerInput4;
135     DDoubleNumInput*      blurInput4;
136 
137     DExpanderBox*         expanderBox;
138 };
139 
140 const QString LocalContrastSettings::Private::configLowSaturationEntry(QLatin1String("LowSaturation"));
141 const QString LocalContrastSettings::Private::configHighSaturationEntry(QLatin1String("HighSaturation"));
142 const QString LocalContrastSettings::Private::configPower1Entry(QLatin1String("Power1"));
143 const QString LocalContrastSettings::Private::configBlur1Entry(QLatin1String("Blur1"));
144 const QString LocalContrastSettings::Private::configPower2Entry(QLatin1String("Power2"));
145 const QString LocalContrastSettings::Private::configBlur2Entry(QLatin1String("Blur2"));
146 const QString LocalContrastSettings::Private::configPower3Entry(QLatin1String("Power3"));
147 const QString LocalContrastSettings::Private::configBlur3Entry(QLatin1String("Blur3"));
148 const QString LocalContrastSettings::Private::configPower4Entry(QLatin1String("Power4"));
149 const QString LocalContrastSettings::Private::configBlur4Entry(QLatin1String("Blur4"));
150 const QString LocalContrastSettings::Private::configStretchContrastEntry(QLatin1String("StretchContrast"));
151 const QString LocalContrastSettings::Private::configStageOneEntry(QLatin1String("StageOne"));
152 const QString LocalContrastSettings::Private::configStageTwoEntry(QLatin1String("StageTwo"));
153 const QString LocalContrastSettings::Private::configStageThreeEntry(QLatin1String("StageThree"));
154 const QString LocalContrastSettings::Private::configStageFourEntry(QLatin1String("StageFour"));
155 const QString LocalContrastSettings::Private::configFunctionInputEntry(QLatin1String("FunctionInput"));
156 
157 // --------------------------------------------------------
158 
LocalContrastSettings(QWidget * const parent)159 LocalContrastSettings::LocalContrastSettings(QWidget* const parent)
160     : QWidget(parent),
161       d      (new Private)
162 {
163     const int spacing        = QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing);
164 
165     QGridLayout* const grid  = new QGridLayout(parent);
166 
167     QWidget* const firstPage = new QWidget();
168     QGridLayout* const grid1 = new QGridLayout(firstPage);
169 
170     QLabel* const label1     = new QLabel(i18n("Function:"), firstPage);
171     d->functionInput         = new DComboBox(firstPage);
172     d->functionInput->addItem(i18nc("@item: function type", "Power"));
173     d->functionInput->addItem(i18nc("@item: function type", "Linear"));
174     d->functionInput->setDefaultIndex(0);
175     d->functionInput->setWhatsThis(i18n("<b>Function</b>: This function combines the original RGB "
176                                         "channels with the desaturated blurred image. This function is used in each of "
177                                         "the tonemapping stages. It can be linear or power. Basically, this function "
178                                         "increases the values where both the original and blurred image's value are low "
179                                         "and do the opposite on high values."));
180 
181     // -------------------------------------------------------------
182 
183     d->stretchContrastCheck = new QCheckBox(i18n("Stretch contrast"), firstPage);
184     d->stretchContrastCheck->setWhatsThis(i18n("<b>Stretch contrast</b>: This stretches the contrast of the original image. "
185                                                "It is applied before the tonemapping process."));
186     d->stretchContrastCheck->setChecked(true);
187 
188     // -------------------------------------------------------------
189 
190     QLabel* const label2   = new QLabel(i18n("Highlights saturation:"), firstPage);
191     d->highSaturationInput = new DIntNumInput(firstPage);
192     d->highSaturationInput->setRange(0, 100, 1);
193     d->highSaturationInput->setDefaultValue(100);
194     d->highSaturationInput->setObjectName(QLatin1String("highSaturationInput"));
195     d->highSaturationInput->setWhatsThis(i18n("<b>Highlights saturation</b>: Usually the (perceived) saturation is "
196                                               "increased. The user can choose to lower the saturation on original highlight "
197                                               "and shadows from the image with these parameters."));
198 
199     // -------------------------------------------------------------
200 
201     QLabel* const label3  = new QLabel(i18n("Shadow saturation:"), firstPage);
202     d->lowSaturationInput = new DIntNumInput(firstPage);
203     d->lowSaturationInput->setRange(0, 100, 1);
204     d->lowSaturationInput->setDefaultValue(100);
205     d->lowSaturationInput->setObjectName(QLatin1String("lowSaturationInput"));
206     d->lowSaturationInput->setWhatsThis(i18n("<b>Shadow saturation</b>: Usually the (perceived) saturation is "
207                                              "increased. The user can choose to lower the saturation on original highlight "
208                                              "and shadows from the image with these parameters."));
209 
210     // -------------------------------------------------------------
211 
212     grid1->addWidget(label1,                  0, 0, 1, 2);
213     grid1->addWidget(d->functionInput,        0, 1, 1, 1);
214     grid1->addWidget(d->stretchContrastCheck, 1, 0, 1, 1);
215     grid1->addWidget(label2,                  2, 0, 1, 2);
216     grid1->addWidget(d->highSaturationInput,  3, 0, 1, 2);
217     grid1->addWidget(label3,                  4, 0, 1, 2);
218     grid1->addWidget(d->lowSaturationInput,   5, 0, 1, 2);
219     grid1->setContentsMargins(spacing, spacing, spacing, spacing);
220     grid1->setSpacing(spacing);
221 
222     // -------------------------------------------------------------
223 
224     QWidget* const secondPage = new QWidget();
225     QGridLayout* const grid2  = new QGridLayout(secondPage);
226 
227     // -------------------------------------------------------------
228 
229     d->label4      = new QLabel(i18n("Power:"), secondPage);
230     d->powerInput1 = new DDoubleNumInput(firstPage);
231     d->powerInput1->setRange(0.0, 100.0, 1.0);
232     d->powerInput1->setDefaultValue(30.0);
233     d->powerInput1->setObjectName(QLatin1String("powerInput1"));
234     d->powerInput1->setWhatsThis(i18n("<b>Power</b>: How strong the effect is applied."));
235 
236     // -------------------------------------------------------------
237 
238     d->label5      = new QLabel(i18n("Blur:"), secondPage);
239     d->blurInput1  = new DDoubleNumInput(firstPage);
240     d->blurInput1->setRange(0.0, 1000.0, 1.0);
241     d->blurInput1->setDefaultValue(80.0);
242     d->blurInput1->setObjectName(QLatin1String("blurInput1"));
243     d->blurInput1->setWhatsThis(i18n("<b>Blur</b>: How strong the image is blurred before combining with the original "
244                                      "image and with the tonemapping function."));
245 
246     grid2->addWidget(d->label4,      0, 0, 1, 1);
247     grid2->addWidget(d->powerInput1, 0, 1, 1, 1);
248     grid2->addWidget(d->label5,      1, 0, 1, 1);
249     grid2->addWidget(d->blurInput1,  1, 1, 1, 1);
250     grid2->setContentsMargins(spacing, spacing, spacing, spacing);
251     grid2->setSpacing(spacing);
252 
253     // -------------------------------------------------------------
254 
255     QWidget* const thirdPage = new QWidget();
256     QGridLayout* const grid3 = new QGridLayout(thirdPage);
257 
258     // -------------------------------------------------------------
259 
260     d->label6      = new QLabel(i18n("Power:"), thirdPage);
261     d->powerInput2 = new DDoubleNumInput(thirdPage);
262     d->powerInput2->setRange(0.0, 100.0, 1.0);
263     d->powerInput2->setDefaultValue(30.0);
264     d->powerInput2->setObjectName(QLatin1String("powerInput2"));
265     d->powerInput2->setWhatsThis(i18n("<b>Power</b>: How strong the effect is applied."));
266 
267     // -------------------------------------------------------------
268 
269     d->label7     = new QLabel(i18n("Blur:"), thirdPage);
270     d->blurInput2 = new DDoubleNumInput(thirdPage);
271     d->blurInput2->setRange(0.0, 1000.0, 1.0);
272     d->blurInput2->setDefaultValue(80.0);
273     d->blurInput2->setObjectName(QLatin1String("blurInput2"));
274     d->blurInput2->setWhatsThis(i18n("<b>Blur</b>: How strong the image is blurred before combining with the original "
275                                      "image and with the tonemapping function."));
276 
277     grid3->addWidget(d->label6,      0, 0, 1, 1);
278     grid3->addWidget(d->powerInput2, 0, 1, 1, 1);
279     grid3->addWidget(d->label7,      1, 0, 1, 1);
280     grid3->addWidget(d->blurInput2,  1, 1, 1, 1);
281     grid3->setContentsMargins(spacing, spacing, spacing, spacing);
282     grid3->setSpacing(spacing);
283 
284     // -------------------------------------------------------------
285 
286     QWidget* const fourthPage = new QWidget();
287     QGridLayout* const grid4  = new QGridLayout(fourthPage);
288 
289     // -------------------------------------------------------------
290 
291     d->label8      = new QLabel(i18n("Power:"), fourthPage);
292     d->powerInput3 = new DDoubleNumInput(fourthPage);
293     d->powerInput3->setRange(0.0, 100.0, 1.0);
294     d->powerInput3->setDefaultValue(30.0);
295     d->powerInput3->setObjectName(QLatin1String("powerInput3"));
296     d->powerInput3->setWhatsThis(i18n("<b>Power</b>: How strong the effect is applied."));
297 
298     // -------------------------------------------------------------
299 
300     d->label9     = new QLabel(i18n("Blur:"), fourthPage);
301     d->blurInput3 = new DDoubleNumInput(fourthPage);
302     d->blurInput3->setRange(0.0, 1000.0, 1.0);
303     d->blurInput3->setDefaultValue(80.0);
304     d->blurInput3->setObjectName(QLatin1String("blurInput3"));
305     d->blurInput3->setWhatsThis(i18n("<b>Blur</b>: How strong the image is blurred before combining with the original "
306                                      "image and with the tonemapping function."));
307 
308     grid4->addWidget(d->label8,      0, 0, 1, 1);
309     grid4->addWidget(d->powerInput3, 0, 1, 1, 1);
310     grid4->addWidget(d->label9,      1, 0, 1, 1);
311     grid4->addWidget(d->blurInput3,  1, 1, 1, 1);
312     grid4->setContentsMargins(spacing, spacing, spacing, spacing);
313     grid4->setSpacing(spacing);
314 
315     // -------------------------------------------------------------
316 
317     QWidget* const fifthPage = new QWidget();
318     QGridLayout* const grid5 = new QGridLayout(fifthPage);
319 
320     // -------------------------------------------------------------
321 
322     d->label10     = new QLabel(i18n("Power:"), fifthPage);
323     d->powerInput4 = new DDoubleNumInput(fifthPage);
324     d->powerInput4->setRange(0.0, 100.0, 1.0);
325     d->powerInput4->setDefaultValue(30.0);
326     d->powerInput4->setObjectName(QLatin1String("powerInput4"));
327     d->powerInput4->setWhatsThis(i18n("<b>Power</b>: How strong the effect is applied."));
328 
329     // -------------------------------------------------------------
330 
331     d->label11    = new QLabel(i18n("Blur:"), fifthPage);
332     d->blurInput4 = new DDoubleNumInput(fifthPage);
333     d->blurInput4->setRange(0.0, 1000.0, 1.0);
334     d->blurInput4->setDefaultValue(80.0);
335     d->blurInput4->setObjectName(QLatin1String("blurInput4"));
336     d->blurInput4->setWhatsThis(i18n("<b>Blur</b>: How strong the image is blurred before combining with the original "
337                                      "image and with the tonemapping function."));
338 
339     grid5->addWidget(d->label10,     0, 0, 1, 1);
340     grid5->addWidget(d->powerInput4, 0, 1, 1, 1);
341     grid5->addWidget(d->label11,     1, 0, 1, 1);
342     grid5->addWidget(d->blurInput4,  1, 1, 1, 1);
343     grid5->setContentsMargins(spacing, spacing, spacing, spacing);
344     grid5->setSpacing(spacing);
345 
346     // -------------------------------------------------------------
347 
348     d->expanderBox = new DExpanderBox;
349     d->expanderBox->setObjectName(QLatin1String("LocalContrastTool Expander"));
350     d->expanderBox->addItem(firstPage, QIcon::fromTheme(QLatin1String("contrast")), i18n("General settings"),
351                             QLatin1String("GeneralSettingsContainer"), true);
352     d->expanderBox->addItem(secondPage, QIcon::fromTheme(QLatin1String("contrast")), i18n("Stage 1"),
353                             QLatin1String("Stage1SettingsContainer"), true);
354     d->expanderBox->addItem(thirdPage, QIcon::fromTheme(QLatin1String("contrast")), i18n("Stage 2"),
355                             QLatin1String("Stage2SettingsContainer"), true);
356     d->expanderBox->addItem(fourthPage, QIcon::fromTheme(QLatin1String("contrast")), i18n("Stage 3"),
357                             QLatin1String("Stage3SettingsContainer"), true);
358     d->expanderBox->addItem(fifthPage, QIcon::fromTheme(QLatin1String("contrast")), i18n("Stage 4"),
359                             QLatin1String("Stage4SettingsContainer"), true);
360     d->expanderBox->addStretch();
361     d->expanderBox->setCheckBoxVisible(1, true);
362     d->expanderBox->setCheckBoxVisible(2, true);
363     d->expanderBox->setCheckBoxVisible(3, true);
364     d->expanderBox->setCheckBoxVisible(4, true);
365 
366     grid->addWidget(d->expanderBox, 0, 0, 1, 1);
367     grid->setRowStretch(0, 10);
368     grid->setContentsMargins(spacing, spacing, spacing, spacing);
369     grid->setSpacing(spacing);
370 
371     // -------------------------------------------------------------
372 
373     connect(d->expanderBox, SIGNAL(signalItemToggled(int,bool)),
374             this, SLOT(slotStageEnabled(int,bool)));
375 
376     connect(d->lowSaturationInput, SIGNAL(valueChanged(int)),
377             this, SIGNAL(signalSettingsChanged()));
378 
379     connect(d->highSaturationInput, SIGNAL(valueChanged(int)),
380             this, SIGNAL(signalSettingsChanged()));
381 
382     connect(d->powerInput1, SIGNAL(valueChanged(double)),
383             this, SIGNAL(signalSettingsChanged()));
384 
385     connect(d->blurInput1, SIGNAL(valueChanged(double)),
386             this, SIGNAL(signalSettingsChanged()));
387 
388     connect(d->powerInput2, SIGNAL(valueChanged(double)),
389             this, SIGNAL(signalSettingsChanged()));
390 
391     connect(d->blurInput2, SIGNAL(valueChanged(double)),
392             this, SIGNAL(signalSettingsChanged()));
393 
394     connect(d->powerInput3, SIGNAL(valueChanged(double)),
395             this, SIGNAL(signalSettingsChanged()));
396 
397     connect(d->blurInput3, SIGNAL(valueChanged(double)),
398             this, SIGNAL(signalSettingsChanged()));
399 
400     connect(d->powerInput4, SIGNAL(valueChanged(double)),
401             this, SIGNAL(signalSettingsChanged()));
402 
403     connect(d->blurInput4, SIGNAL(valueChanged(double)),
404             this, SIGNAL(signalSettingsChanged()));
405 
406     connect(d->functionInput, SIGNAL(currentIndexChanged(int)),
407             this, SIGNAL(signalSettingsChanged()));
408 
409     connect(d->stretchContrastCheck, SIGNAL(toggled(bool)),
410             this, SIGNAL(signalSettingsChanged()));
411 }
412 
~LocalContrastSettings()413 LocalContrastSettings::~LocalContrastSettings()
414 {
415     delete d;
416 }
417 
slotStageEnabled(int index,bool b)418 void LocalContrastSettings::slotStageEnabled(int index, bool b)
419 {
420     switch (index)
421     {
422         case 1:
423         {
424             d->label4->setEnabled(b);
425             d->powerInput1->setEnabled(b);
426             d->label5->setEnabled(b);
427             d->blurInput1->setEnabled(b);
428             break;
429         }
430 
431         case 2:
432         {
433             d->label6->setEnabled(b);
434             d->powerInput2->setEnabled(b);
435             d->label7->setEnabled(b);
436             d->blurInput2->setEnabled(b);
437             break;
438         }
439 
440         case 3:
441         {
442             d->label8->setEnabled(b);
443             d->powerInput3->setEnabled(b);
444             d->label9->setEnabled(b);
445             d->blurInput3->setEnabled(b);
446             break;
447         }
448 
449         case 4:
450         {
451             d->label10->setEnabled(b);
452             d->powerInput4->setEnabled(b);
453             d->label11->setEnabled(b);
454             d->blurInput4->setEnabled(b);
455             break;
456         }
457     }
458 
459     emit signalSettingsChanged();
460 }
461 
settings() const462 LocalContrastContainer LocalContrastSettings::settings() const
463 {
464     LocalContrastContainer prm;
465 
466     prm.stretchContrast  = d->stretchContrastCheck->isChecked();
467     prm.lowSaturation    = d->lowSaturationInput->value();
468     prm.highSaturation   = d->highSaturationInput->value();
469     prm.functionId       = d->functionInput->currentIndex();
470 
471     prm.stage[0].enabled = d->expanderBox->isChecked(1);
472     prm.stage[0].power   = d->powerInput1->value();
473     prm.stage[0].blur    = d->blurInput1->value();
474 
475     prm.stage[1].enabled = d->expanderBox->isChecked(2);
476     prm.stage[1].power   = d->powerInput2->value();
477     prm.stage[1].blur    = d->blurInput2->value();
478 
479     prm.stage[2].enabled = d->expanderBox->isChecked(3);
480     prm.stage[2].power   = d->powerInput3->value();
481     prm.stage[2].blur    = d->blurInput3->value();
482 
483     prm.stage[3].enabled = d->expanderBox->isChecked(4);
484     prm.stage[3].power   = d->powerInput4->value();
485     prm.stage[3].blur    = d->blurInput4->value();
486 
487     return prm;
488 }
489 
setSettings(const LocalContrastContainer & settings)490 void LocalContrastSettings::setSettings(const LocalContrastContainer& settings)
491 {
492     blockSignals(true);
493     d->expanderBox->setEnabled(false);
494 
495     d->stretchContrastCheck->setChecked(settings.stretchContrast);
496     d->lowSaturationInput->setValue(settings.lowSaturation);
497     d->highSaturationInput->setValue(settings.highSaturation);
498     d->functionInput->setCurrentIndex(settings.functionId);
499 
500     d->expanderBox->setChecked(1, settings.stage[0].enabled);
501     d->powerInput1->setValue(settings.stage[0].power);
502     d->blurInput1->setValue(settings.stage[0].blur);
503 
504     d->expanderBox->setChecked(2, settings.stage[1].enabled);
505     d->powerInput2->setValue(settings.stage[1].power);
506     d->blurInput2->setValue(settings.stage[1].blur);
507 
508     d->expanderBox->setChecked(3, settings.stage[2].enabled);
509     d->powerInput3->setValue(settings.stage[2].power);
510     d->blurInput3->setValue(settings.stage[2].blur);
511 
512     d->expanderBox->setChecked(4, settings.stage[3].enabled);
513     d->powerInput4->setValue(settings.stage[3].power);
514     d->blurInput4->setValue(settings.stage[3].blur);
515 
516 /*
517     slotStage1Enabled(d->stageOne->isChecked());
518     slotStage2Enabled(d->stageTwo->isChecked());
519     slotStage3Enabled(d->stageThree->isChecked());
520     slotStage4Enabled(d->stageFour->isChecked());
521 */
522 
523     d->expanderBox->setEnabled(true);
524     blockSignals(false);
525 }
526 
resetToDefault()527 void LocalContrastSettings::resetToDefault()
528 {
529     blockSignals(true);
530 
531     d->stretchContrastCheck->setChecked(true);
532     d->lowSaturationInput->slotReset();
533     d->highSaturationInput->slotReset();
534     d->functionInput->slotReset();
535 
536     d->expanderBox->setChecked(1, true);
537     d->powerInput1->slotReset();
538     d->blurInput1->slotReset();
539 
540     d->expanderBox->setChecked(2, false);
541     d->powerInput2->slotReset();
542     d->blurInput2->slotReset();
543 
544     d->expanderBox->setChecked(3, false);
545     d->powerInput3->slotReset();
546     d->blurInput3->slotReset();
547 
548     d->expanderBox->setChecked(4, false);
549     d->powerInput4->slotReset();
550     d->blurInput4->slotReset();
551 
552     blockSignals(false);
553 }
554 
defaultSettings() const555 LocalContrastContainer LocalContrastSettings::defaultSettings() const
556 {
557     LocalContrastContainer prm;
558 
559     prm.stretchContrast  = true;
560     prm.lowSaturation    = d->lowSaturationInput->defaultValue();
561     prm.highSaturation   = d->highSaturationInput->defaultValue();
562     prm.functionId       = d->functionInput->defaultIndex();
563 
564     prm.stage[0].enabled = true;
565     prm.stage[0].power   = d->powerInput1->defaultValue();
566     prm.stage[0].blur    = d->blurInput1->defaultValue();
567 
568     prm.stage[1].enabled = false;
569     prm.stage[1].power   = d->powerInput2->defaultValue();
570     prm.stage[1].blur    = d->blurInput2->defaultValue();
571 
572     prm.stage[2].enabled = false;
573     prm.stage[2].power   = d->powerInput3->defaultValue();
574     prm.stage[2].blur    = d->blurInput3->defaultValue();
575 
576     prm.stage[3].enabled = false;
577     prm.stage[3].power   = d->powerInput4->defaultValue();
578     prm.stage[3].blur    = d->blurInput4->defaultValue();
579 
580     return prm;
581 }
582 
readSettings(KConfigGroup & group)583 void LocalContrastSettings::readSettings(KConfigGroup& group)
584 {
585     LocalContrastContainer prm;
586     LocalContrastContainer defaultPrm = defaultSettings();
587 
588     prm.stretchContrast  = group.readEntry(d->configStretchContrastEntry, defaultPrm.stretchContrast);
589     prm.lowSaturation    = group.readEntry(d->configLowSaturationEntry,   defaultPrm.lowSaturation);
590     prm.highSaturation   = group.readEntry(d->configHighSaturationEntry,  defaultPrm.highSaturation);
591     prm.functionId       = group.readEntry(d->configFunctionInputEntry,   defaultPrm.functionId);
592 
593     prm.stage[0].enabled = group.readEntry(d->configStageOneEntry,        defaultPrm.stage[0].enabled);
594     prm.stage[0].power   = group.readEntry(d->configPower1Entry,          defaultPrm.stage[0].power);
595     prm.stage[0].blur    = group.readEntry(d->configBlur1Entry,           defaultPrm.stage[0].blur);
596 
597     prm.stage[1].enabled = group.readEntry(d->configStageTwoEntry,        defaultPrm.stage[1].enabled);
598     prm.stage[1].power   = group.readEntry(d->configPower2Entry,          defaultPrm.stage[1].power);
599     prm.stage[1].blur    = group.readEntry(d->configBlur2Entry,           defaultPrm.stage[1].blur);
600 
601     prm.stage[2].enabled = group.readEntry(d->configStageThreeEntry,      defaultPrm.stage[2].enabled);
602     prm.stage[2].power   = group.readEntry(d->configPower3Entry,          defaultPrm.stage[2].power);
603     prm.stage[2].blur    = group.readEntry(d->configBlur3Entry,           defaultPrm.stage[2].blur);
604 
605     prm.stage[3].enabled = group.readEntry(d->configStageFourEntry,       defaultPrm.stage[3].enabled);
606     prm.stage[3].power   = group.readEntry(d->configPower4Entry,          defaultPrm.stage[3].power);
607     prm.stage[3].blur    = group.readEntry(d->configBlur4Entry,           defaultPrm.stage[3].blur);
608 
609     setSettings(prm);
610 
611     d->expanderBox->readSettings(group);
612 
613     d->expanderBox->setEnabled(true);
614 }
615 
writeSettings(KConfigGroup & group)616 void LocalContrastSettings::writeSettings(KConfigGroup& group)
617 {
618     LocalContrastContainer prm = settings();
619 
620     group.writeEntry(d->configStretchContrastEntry, prm.stretchContrast);
621     group.writeEntry(d->configLowSaturationEntry,   prm.lowSaturation);
622     group.writeEntry(d->configHighSaturationEntry,  prm.highSaturation);
623     group.writeEntry(d->configFunctionInputEntry,   prm.functionId);
624 
625     group.writeEntry(d->configStageOneEntry,        prm.stage[0].enabled);
626     group.writeEntry(d->configPower1Entry,          prm.stage[0].power);
627     group.writeEntry(d->configBlur1Entry,           prm.stage[0].blur);
628 
629     group.writeEntry(d->configStageTwoEntry,        prm.stage[1].enabled);
630     group.writeEntry(d->configPower2Entry,          prm.stage[1].power);
631     group.writeEntry(d->configBlur2Entry,           prm.stage[1].blur);
632 
633     group.writeEntry(d->configStageThreeEntry,      prm.stage[2].enabled);
634     group.writeEntry(d->configPower3Entry,          prm.stage[2].power);
635     group.writeEntry(d->configBlur3Entry,           prm.stage[2].blur);
636 
637     group.writeEntry(d->configStageFourEntry,       prm.stage[3].enabled);
638     group.writeEntry(d->configPower4Entry,          prm.stage[3].power);
639     group.writeEntry(d->configBlur4Entry,           prm.stage[3].blur);
640 
641     d->expanderBox->writeSettings(group);
642 }
643 
loadSettings()644 void LocalContrastSettings::loadSettings()
645 {
646     QUrl loadFile = DFileDialog::getOpenFileUrl(qApp->activeWindow(), i18n("Photograph Local Contrast Settings File to Load"),
647                                                 QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)),
648                                                 QLatin1String("*"));
649 
650     if (loadFile.isEmpty())
651     {
652         return;
653     }
654 
655     QFile file(loadFile.toLocalFile());
656 
657     if (file.open(QIODevice::ReadOnly))
658     {
659         QTextStream stream(&file);
660 
661         if (stream.readLine() != QLatin1String("# Photograph Local Contrast Configuration File"))
662         {
663             QMessageBox::critical(qApp->activeWindow(), qApp->applicationName(),
664                                   i18n("\"%1\" is not a Photograph Local Contrast settings text file.",
665                                        loadFile.fileName()));
666             file.close();
667             return;
668         }
669 
670         blockSignals(true);
671         d->stretchContrastCheck->setChecked(stream.readLine().toInt());
672         d->expanderBox->setChecked(1, stream.readLine().toInt());
673         d->expanderBox->setChecked(2, stream.readLine().toInt());
674         d->expanderBox->setChecked(3, stream.readLine().toInt());
675         d->expanderBox->setChecked(4, stream.readLine().toInt());
676         d->lowSaturationInput->setValue(stream.readLine().toInt());
677         d->highSaturationInput->setValue(stream.readLine().toInt());
678         d->functionInput->setCurrentIndex(stream.readLine().toInt());
679         d->powerInput1->setValue(stream.readLine().toDouble());
680         d->blurInput1->setValue(stream.readLine().toDouble());
681         d->powerInput2->setValue(stream.readLine().toDouble());
682         d->blurInput2->setValue(stream.readLine().toDouble());
683         d->powerInput3->setValue(stream.readLine().toDouble());
684         d->blurInput3->setValue(stream.readLine().toDouble());
685         d->powerInput4->setValue(stream.readLine().toDouble());
686         d->blurInput4->setValue(stream.readLine().toDouble());
687         blockSignals(false);
688     }
689     else
690     {
691         QMessageBox::critical(qApp->activeWindow(), qApp->applicationName(),
692                               i18n("Cannot load settings from the Photograph Local Contrast text file."));
693     }
694 
695     file.close();
696 }
697 
saveAsSettings()698 void LocalContrastSettings::saveAsSettings()
699 {
700     QUrl saveFile = DFileDialog::getSaveFileUrl(qApp->activeWindow(), i18n("Photograph Local Contrast Settings File to Save"),
701                                                 QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)),
702                                                 QLatin1String("*"));
703 
704     if (saveFile.isEmpty())
705     {
706         return;
707     }
708 
709     QFile file(saveFile.toLocalFile());
710 
711     if (file.open(QIODevice::WriteOnly))
712     {
713         QTextStream stream(&file);
714         stream << QLatin1String("# Photograph Local Contrast Configuration File\n");
715 
716         stream << d->stretchContrastCheck->isChecked() << QLatin1Char('\n');
717         stream << d->expanderBox->isChecked(1) << QLatin1Char('\n');
718         stream << d->expanderBox->isChecked(2) << QLatin1Char('\n');
719         stream << d->expanderBox->isChecked(3) << QLatin1Char('\n');
720         stream << d->expanderBox->isChecked(4) << QLatin1Char('\n');
721         stream << d->lowSaturationInput->value() << QLatin1Char('\n');
722         stream << d->highSaturationInput->value() << QLatin1Char('\n');
723         stream << d->functionInput->currentIndex() << QLatin1Char('\n');
724         stream << d->powerInput1->value() << QLatin1Char('\n');
725         stream << d->blurInput1->value() << QLatin1Char('\n');
726         stream << d->powerInput2->value() << QLatin1Char('\n');
727         stream << d->blurInput2->value() << QLatin1Char('\n');
728         stream << d->powerInput3->value() << QLatin1Char('\n');
729         stream << d->blurInput3->value() << QLatin1Char('\n');
730         stream << d->powerInput4->value() << QLatin1Char('\n');
731         stream << d->blurInput4->value() << QLatin1Char('\n');
732     }
733     else
734     {
735         QMessageBox::critical(qApp->activeWindow(), qApp->applicationName(),
736                               i18n("Cannot save settings to the Photograph Local Contrast text file."));
737     }
738 
739     file.close();
740 }
741 
742 } // namespace Digikam
743