1 /* ============================================================
2  *
3  * This file is a part of digiKam project
4  * https://www.digikam.org
5  *
6  * Date        : 2010-03-17
7  * Description : Border settings view.
8  *
9  * Copyright (C) 2010-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
10  *
11  * This program is free software; you can redistribute it
12  * and/or modify it under the terms of the GNU General
13  * Public License as published by the Free Software Foundation;
14  * either version 2, or (at your option)
15  * any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * ============================================================ */
23 
24 #include "bordersettings.h"
25 
26 // Qt includes
27 
28 #include <QGridLayout>
29 #include <QLabel>
30 #include <QString>
31 #include <QFile>
32 #include <QTextStream>
33 #include <QCheckBox>
34 #include <QUrl>
35 #include <QApplication>
36 #include <QStyle>
37 
38 // KDE includes
39 
40 #include <kconfiggroup.h>
41 #include <klocalizedstring.h>
42 
43 // Local includes
44 
45 #include "dlayoutbox.h"
46 #include "dexpanderbox.h"
47 #include "dnuminput.h"
48 #include "dcombobox.h"
49 #include "dcolorselector.h"
50 #include "digikam_debug.h"
51 
52 namespace Digikam
53 {
54 
55 class Q_DECL_HIDDEN BorderSettings::Private
56 {
57 public:
58 
Private()59     explicit Private()
60       : preserveAspectRatio (nullptr),
61         labelBackground     (nullptr),
62         labelBorderPercent  (nullptr),
63         labelBorderWidth    (nullptr),
64         labelForeground     (nullptr),
65         firstColorButton    (nullptr),
66         secondColorButton   (nullptr),
67         borderType          (nullptr),
68         borderPercent       (nullptr),
69         borderWidth         (nullptr)
70     {
71     }
72 
73     static const QString configBorderTypeEntry;
74     static const QString configBorderPercentEntry;
75     static const QString configBorderWidthEntry;
76     static const QString configPreserveAspectRatioEntry;
77     static const QString configSolidColorEntry;
78     static const QString configNiepceBorderColorEntry;
79     static const QString configNiepceLineColorEntry;
80     static const QString configBevelUpperLeftColorEntry;
81     static const QString configBevelLowerRightColorEntry;
82     static const QString configDecorativeFirstColorEntry;
83     static const QString configDecorativeSecondColorEntry;
84 
85     QCheckBox*           preserveAspectRatio;
86 
87     QLabel*              labelBackground;
88     QLabel*              labelBorderPercent;
89     QLabel*              labelBorderWidth;
90     QLabel*              labelForeground;
91 
92     QColor               bevelLowerRightColor;
93     QColor               bevelUpperLeftColor;
94     QColor               decorativeFirstColor;
95     QColor               decorativeSecondColor;
96     QColor               niepceBorderColor;
97     QColor               niepceLineColor;
98     QColor               solidColor;
99 
100     DColorSelector*      firstColorButton;
101     DColorSelector*      secondColorButton;
102 
103     DComboBox*           borderType;
104     DIntNumInput*        borderPercent;
105     DIntNumInput*        borderWidth;
106 };
107 
108 const QString BorderSettings::Private::configBorderTypeEntry(QLatin1String("Border Type"));
109 const QString BorderSettings::Private::configBorderPercentEntry(QLatin1String("Border Percent"));
110 const QString BorderSettings::Private::configBorderWidthEntry(QLatin1String("Border Width"));
111 const QString BorderSettings::Private::configPreserveAspectRatioEntry(QLatin1String("Preserve Aspect Ratio"));
112 const QString BorderSettings::Private::configSolidColorEntry(QLatin1String("Solid Color"));
113 const QString BorderSettings::Private::configNiepceBorderColorEntry(QLatin1String("Niepce Border Color"));
114 const QString BorderSettings::Private::configNiepceLineColorEntry(QLatin1String("Niepce Line Color"));
115 const QString BorderSettings::Private::configBevelUpperLeftColorEntry(QLatin1String("Bevel Upper Left Color"));
116 const QString BorderSettings::Private::configBevelLowerRightColorEntry(QLatin1String("Bevel Lower Right Color"));
117 const QString BorderSettings::Private::configDecorativeFirstColorEntry(QLatin1String("Decorative First Color"));
118 const QString BorderSettings::Private::configDecorativeSecondColorEntry(QLatin1String("Decorative Second Color"));
119 
120 // --------------------------------------------------------
121 
BorderSettings(QWidget * const parent)122 BorderSettings::BorderSettings(QWidget* const parent)
123     : QWidget(parent),
124       d      (new Private)
125 {
126     const int spacing       = QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing);
127 
128     QGridLayout* const grid = new QGridLayout(parent);
129 
130     QLabel* const label1    = new QLabel(i18n("Type:"));
131     d->borderType           = new DComboBox();
132     d->borderType->addItem(i18nc("solid border type", "Solid"));
133 
134     // NOTE: Niepce is a real name. This is the first guy in the world to have built a camera.
135 
136     d->borderType->addItem(QLatin1String("Niepce"));
137 
138     d->borderType->addItem(i18nc("beveled border type", "Beveled"));
139     d->borderType->addItem(i18n("Decorative Pine"));
140     d->borderType->addItem(i18n("Decorative Wood"));
141     d->borderType->addItem(i18n("Decorative Paper"));
142     d->borderType->addItem(i18n("Decorative Parquet"));
143     d->borderType->addItem(i18n("Decorative Ice"));
144     d->borderType->addItem(i18n("Decorative Leaf"));
145     d->borderType->addItem(i18n("Decorative Marble"));
146     d->borderType->addItem(i18n("Decorative Rain"));
147     d->borderType->addItem(i18n("Decorative Craters"));
148     d->borderType->addItem(i18n("Decorative Dried"));
149     d->borderType->addItem(i18n("Decorative Pink"));
150     d->borderType->addItem(i18n("Decorative Stone"));
151     d->borderType->addItem(i18n("Decorative Chalk"));
152     d->borderType->addItem(i18n("Decorative Granite"));
153     d->borderType->addItem(i18n("Decorative Rock"));
154     d->borderType->addItem(i18n("Decorative Wall"));
155     d->borderType->setDefaultIndex(BorderContainer::SolidBorder);
156     d->borderType->setWhatsThis(i18n("Select the border type to add around the image here."));
157 
158     DLineWidget* const line1 = new DLineWidget(Qt::Horizontal);
159 
160     // -------------------------------------------------------------------
161 
162     d->preserveAspectRatio = new QCheckBox();
163     d->preserveAspectRatio->setText(i18n("Preserve Aspect Ratio"));
164     d->preserveAspectRatio->setWhatsThis(i18n("Enable this option if you want to preserve the aspect "
165                                               "ratio of image. If enabled, the border width will be "
166                                               "a percentage of the image size, else the border width will be "
167                                               "in pixels."));
168 
169     d->labelBorderPercent  = new QLabel(i18n("Width (%):"));
170     d->borderPercent       = new DIntNumInput();
171     d->borderPercent->setRange(1, 50, 1);
172     d->borderPercent->setDefaultValue(10);
173     d->borderPercent->setWhatsThis(i18n("Set here the border width as a percentage of the image size."));
174 
175     d->labelBorderWidth = new QLabel(i18n("Width (pixels):"));
176     d->borderWidth      = new DIntNumInput();
177     d->borderWidth->setRange(1, 1000, 1);
178     d->borderWidth->setDefaultValue(100);
179     d->borderWidth->setWhatsThis(i18n("Set here the border width in pixels to add around the image."));
180 
181     DLineWidget* const line2 = new DLineWidget(Qt::Horizontal);
182 
183     // -------------------------------------------------------------------
184 
185     d->labelForeground   = new QLabel();
186     d->firstColorButton  = new DColorSelector();
187     d->firstColorButton->setColor(QColor(192, 192, 192));
188     d->labelBackground   = new QLabel();
189     d->secondColorButton = new DColorSelector();
190     d->secondColorButton->setColor(QColor(128, 128, 128));
191 
192     // -------------------------------------------------------------------
193 
194     grid->addWidget(label1,                  0, 0, 1, 3);
195     grid->addWidget(d->borderType,           1, 0, 1, 3);
196     grid->addWidget(line1,                   2, 0, 1, 3);
197     grid->addWidget(d->preserveAspectRatio,  3, 0, 1, 3);
198     grid->addWidget(d->labelBorderPercent,   4, 0, 1, 3);
199     grid->addWidget(d->borderPercent,        5, 0, 1, 3);
200     grid->addWidget(d->labelBorderWidth,     6, 0, 1, 3);
201     grid->addWidget(d->borderWidth,          7, 0, 1, 3);
202     grid->addWidget(line2,                   8, 0, 1, 3);
203     grid->addWidget(d->labelForeground,      9, 0, 1, 1);
204     grid->addWidget(d->firstColorButton,     9, 1, 1, 2);
205     grid->addWidget(d->labelBackground,     10, 0, 1, 1);
206     grid->addWidget(d->secondColorButton,   10, 1, 1, 2);
207     grid->setRowStretch(11, 10);
208     grid->setContentsMargins(spacing, spacing, spacing, spacing);
209     grid->setSpacing(spacing);
210 
211     // -------------------------------------------------------------
212 
213     connect(d->preserveAspectRatio, SIGNAL(toggled(bool)),
214             this, SLOT(slotPreserveAspectRatioToggled(bool)));
215 
216     connect(d->borderType, SIGNAL(activated(int)),
217             this, SLOT(slotBorderTypeChanged(int)));
218 
219     connect(d->borderPercent, SIGNAL(valueChanged(int)),
220             this, SIGNAL(signalSettingsChanged()));
221 
222     connect(d->borderWidth, SIGNAL(valueChanged(int)),
223             this, SIGNAL(signalSettingsChanged()));
224 
225     connect(d->firstColorButton, SIGNAL(signalColorSelected(QColor)),
226             this, SLOT(slotColorForegroundChanged(QColor)));
227 
228     connect(d->secondColorButton, SIGNAL(signalColorSelected(QColor)),
229             this, SLOT(slotColorBackgroundChanged(QColor)));
230 }
231 
~BorderSettings()232 BorderSettings::~BorderSettings()
233 {
234     delete d;
235 }
236 
settings() const237 BorderContainer BorderSettings::settings() const
238 {
239     BorderContainer prm;
240 
241     prm.preserveAspectRatio   = d->preserveAspectRatio->isChecked();
242     prm.borderType            = d->borderType->currentIndex();
243     prm.borderWidth1          = d->borderWidth->value();
244     prm.borderWidth2          = 15;
245     prm.borderWidth3          = 15;
246     prm.borderWidth4          = 10;
247     prm.borderPercent         = d->borderPercent->value() / 100.0;
248     prm.borderPath            = BorderContainer::getBorderPath(d->borderType->currentIndex());
249     prm.solidColor            = d->solidColor;
250     prm.niepceBorderColor     = d->niepceBorderColor;
251     prm.niepceLineColor       = d->niepceLineColor;
252     prm.bevelUpperLeftColor   = d->bevelUpperLeftColor;
253     prm.bevelLowerRightColor  = d->bevelLowerRightColor;
254     prm.decorativeFirstColor  = d->decorativeFirstColor;
255     prm.decorativeSecondColor = d->decorativeSecondColor;
256 
257     return prm;
258 }
259 
setSettings(const BorderContainer & settings)260 void BorderSettings::setSettings(const BorderContainer& settings)
261 {
262     blockSignals(true);
263 
264     d->preserveAspectRatio->setChecked(settings.preserveAspectRatio);
265     d->borderType->setCurrentIndex(settings.borderType);
266     d->borderWidth->setValue(settings.borderWidth1);
267     d->borderPercent->setValue((int)(settings.borderPercent * 100.0));
268 
269     d->solidColor            = settings.solidColor;
270     d->niepceBorderColor     = settings.niepceBorderColor;
271     d->niepceLineColor       = settings.niepceLineColor;
272     d->bevelUpperLeftColor   = settings.bevelUpperLeftColor;
273     d->bevelLowerRightColor  = settings.bevelLowerRightColor;
274     d->decorativeFirstColor  = settings.decorativeFirstColor;
275     d->decorativeSecondColor = settings.decorativeSecondColor;
276 
277     slotBorderTypeChanged(settings.borderType);
278 
279     blockSignals(false);
280 }
281 
resetToDefault()282 void BorderSettings::resetToDefault()
283 {
284     setSettings(defaultSettings());
285 }
286 
defaultSettings() const287 BorderContainer BorderSettings::defaultSettings() const
288 {
289     BorderContainer prm;
290     return prm;
291 }
292 
readSettings(KConfigGroup & group)293 void BorderSettings::readSettings(KConfigGroup& group)
294 {
295     blockSignals(true);
296 
297     d->borderType->setCurrentIndex(group.readEntry(d->configBorderTypeEntry, d->borderType->defaultIndex()));
298     d->borderPercent->setValue(group.readEntry(d->configBorderPercentEntry,  d->borderPercent->defaultValue()));
299     d->borderWidth->setValue(group.readEntry(d->configBorderWidthEntry,      d->borderWidth->defaultValue()));
300     d->preserveAspectRatio->setChecked(group.readEntry(d->configPreserveAspectRatioEntry, true));
301 
302     d->solidColor            = group.readEntry(d->configSolidColorEntry,            QColor(0, 0, 0));
303     d->niepceBorderColor     = group.readEntry(d->configNiepceBorderColorEntry,     QColor(255, 255, 255));
304     d->niepceLineColor       = group.readEntry(d->configNiepceLineColorEntry,       QColor(0, 0, 0));
305     d->bevelUpperLeftColor   = group.readEntry(d->configBevelUpperLeftColorEntry,   QColor(192, 192, 192));
306     d->bevelLowerRightColor  = group.readEntry(d->configBevelLowerRightColorEntry,  QColor(128, 128, 128));
307     d->decorativeFirstColor  = group.readEntry(d->configDecorativeFirstColorEntry,  QColor(0, 0, 0));
308     d->decorativeSecondColor = group.readEntry(d->configDecorativeSecondColorEntry, QColor(0, 0, 0));
309 
310     blockSignals(false);
311     slotBorderTypeChanged(d->borderType->currentIndex());
312 }
313 
writeSettings(KConfigGroup & group)314 void BorderSettings::writeSettings(KConfigGroup& group)
315 {
316     group.writeEntry(d->configBorderTypeEntry,            d->borderType->currentIndex());
317     group.writeEntry(d->configBorderPercentEntry,         d->borderPercent->value());
318     group.writeEntry(d->configBorderWidthEntry,           d->borderWidth->value());
319     group.writeEntry(d->configPreserveAspectRatioEntry,   d->preserveAspectRatio->isChecked());
320     group.writeEntry(d->configSolidColorEntry,            d->solidColor);
321     group.writeEntry(d->configNiepceBorderColorEntry,     d->niepceBorderColor);
322     group.writeEntry(d->configNiepceLineColorEntry,       d->niepceLineColor);
323     group.writeEntry(d->configBevelUpperLeftColorEntry,   d->bevelUpperLeftColor);
324     group.writeEntry(d->configBevelLowerRightColorEntry,  d->bevelLowerRightColor);
325     group.writeEntry(d->configDecorativeFirstColorEntry,  d->decorativeFirstColor);
326     group.writeEntry(d->configDecorativeSecondColorEntry, d->decorativeSecondColor);
327 }
328 
slotColorForegroundChanged(const QColor & color)329 void BorderSettings::slotColorForegroundChanged(const QColor& color)
330 {
331     switch (d->borderType->currentIndex())
332     {
333         case BorderContainer::SolidBorder:
334             d->solidColor = color;
335             break;
336 
337         case BorderContainer::NiepceBorder:
338             d->niepceBorderColor = color;
339             break;
340 
341         case BorderContainer::BeveledBorder:
342             d->bevelUpperLeftColor = color;
343             break;
344 
345         case BorderContainer::PineBorder:
346         case BorderContainer::WoodBorder:
347         case BorderContainer::PaperBorder:
348         case BorderContainer::ParqueBorder:
349         case BorderContainer::IceBorder:
350         case BorderContainer::LeafBorder:
351         case BorderContainer::MarbleBorder:
352         case BorderContainer::RainBorder:
353         case BorderContainer::CratersBorder:
354         case BorderContainer::DriedBorder:
355         case BorderContainer::PinkBorder:
356         case BorderContainer::StoneBorder:
357         case BorderContainer::ChalkBorder:
358         case BorderContainer::GraniteBorder:
359         case BorderContainer::RockBorder:
360         case BorderContainer::WallBorder:
361             d->decorativeFirstColor = color;
362             break;
363     }
364 
365     emit signalSettingsChanged();
366 }
367 
slotColorBackgroundChanged(const QColor & color)368 void BorderSettings::slotColorBackgroundChanged(const QColor& color)
369 {
370     switch (d->borderType->currentIndex())
371     {
372         case BorderContainer::SolidBorder:
373             d->solidColor = color;
374             break;
375 
376         case BorderContainer::NiepceBorder:
377             d->niepceLineColor = color;
378             break;
379 
380         case BorderContainer::BeveledBorder:
381             d->bevelLowerRightColor = color;
382             break;
383 
384         case BorderContainer::PineBorder:
385         case BorderContainer::WoodBorder:
386         case BorderContainer::PaperBorder:
387         case BorderContainer::ParqueBorder:
388         case BorderContainer::IceBorder:
389         case BorderContainer::LeafBorder:
390         case BorderContainer::MarbleBorder:
391         case BorderContainer::RainBorder:
392         case BorderContainer::CratersBorder:
393         case BorderContainer::DriedBorder:
394         case BorderContainer::PinkBorder:
395         case BorderContainer::StoneBorder:
396         case BorderContainer::ChalkBorder:
397         case BorderContainer::GraniteBorder:
398         case BorderContainer::RockBorder:
399         case BorderContainer::WallBorder:
400             d->decorativeSecondColor = color;
401             break;
402     }
403 
404     emit signalSettingsChanged();
405 }
406 
slotBorderTypeChanged(int borderType)407 void BorderSettings::slotBorderTypeChanged(int borderType)
408 {
409     d->labelForeground->setText(i18nc("first color for border effect", "First:"));
410     d->labelBackground->setText(i18nc("second color for border effect", "Second:"));
411     d->firstColorButton->setWhatsThis(i18n("Set here the foreground color of the border."));
412     d->secondColorButton->setWhatsThis(i18n("Set here the Background color of the border."));
413     d->firstColorButton->setEnabled(true);
414     d->secondColorButton->setEnabled(true);
415     d->labelForeground->setEnabled(true);
416     d->labelBackground->setEnabled(true);
417     d->borderPercent->setEnabled(true);
418 
419     switch (borderType)
420     {
421         case BorderContainer::SolidBorder:
422             d->firstColorButton->setColor(d->solidColor);
423             d->secondColorButton->setEnabled(false);
424             d->labelBackground->setEnabled(false);
425             break;
426 
427         case BorderContainer::NiepceBorder:
428             d->firstColorButton->setWhatsThis(i18n("Set here the color of the main border."));
429             d->secondColorButton->setWhatsThis(i18n("Set here the color of the line."));
430             d->firstColorButton->setColor(d->niepceBorderColor);
431             d->secondColorButton->setColor(d->niepceLineColor);
432             break;
433 
434         case BorderContainer::BeveledBorder:
435             d->firstColorButton->setWhatsThis(i18n("Set here the color of the upper left area."));
436             d->secondColorButton->setWhatsThis(i18n("Set here the color of the lower right area."));
437             d->firstColorButton->setColor(d->bevelUpperLeftColor);
438             d->secondColorButton->setColor(d->bevelLowerRightColor);
439             break;
440 
441         case BorderContainer::PineBorder:
442         case BorderContainer::WoodBorder:
443         case BorderContainer::PaperBorder:
444         case BorderContainer::ParqueBorder:
445         case BorderContainer::IceBorder:
446         case BorderContainer::LeafBorder:
447         case BorderContainer::MarbleBorder:
448         case BorderContainer::RainBorder:
449         case BorderContainer::CratersBorder:
450         case BorderContainer::DriedBorder:
451         case BorderContainer::PinkBorder:
452         case BorderContainer::StoneBorder:
453         case BorderContainer::ChalkBorder:
454         case BorderContainer::GraniteBorder:
455         case BorderContainer::RockBorder:
456         case BorderContainer::WallBorder:
457             d->firstColorButton->setWhatsThis(i18n("Set here the color of the first line."));
458             d->secondColorButton->setWhatsThis(i18n("Set here the color of the second line."));
459             d->firstColorButton->setColor(d->decorativeFirstColor);
460             d->secondColorButton->setColor(d->decorativeSecondColor);
461             break;
462     }
463 
464     emit signalSettingsChanged();
465 }
466 
slotPreserveAspectRatioToggled(bool b)467 void BorderSettings::slotPreserveAspectRatioToggled(bool b)
468 {
469     toggleBorderSlider(b);
470     emit signalSettingsChanged();
471 }
472 
toggleBorderSlider(bool b)473 void BorderSettings::toggleBorderSlider(bool b)
474 {
475     d->borderPercent->setEnabled(b);
476     d->borderWidth->setEnabled(!b);
477     d->labelBorderPercent->setEnabled(b);
478     d->labelBorderWidth->setEnabled(!b);
479 }
480 
481 } // namespace Digikam
482