1 /* ============================================================
2  *
3  * This file is a part of digiKam project
4  * https://www.digikam.org
5  *
6  * Date        : 2008-08-21
7  * Description : Editor tool settings template box
8  *
9  * Copyright (C) 2008-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
10  * Copyright (C) 2008-2011 by Andi Clemens <andi dot clemens 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) 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 "editortoolsettings.h"
25 
26 // Qt includes
27 
28 #include <QButtonGroup>
29 #include <QLabel>
30 #include <QPixmap>
31 #include <QLayout>
32 #include <QMap>
33 #include <QPair>
34 #include <QString>
35 #include <QToolButton>
36 #include <QVariant>
37 #include <QScrollBar>
38 #include <QPushButton>
39 #include <QApplication>
40 #include <QScreen>
41 #include <QWindow>
42 #include <QStyle>
43 
44 // KDE includes
45 
46 #include <klocalizedstring.h>
47 
48 // Local includes
49 
50 #include "dlayoutbox.h"
51 #include "dnuminput.h"
52 #include "colorgradientwidget.h"
53 #include "histogramwidget.h"
54 #include "histogrambox.h"
55 #include "digikam_globals.h"
56 #include "dcolorselector.h"
57 #include "dpluginaboutdlg.h"
58 #include "dplugineditor.h"
59 #include "editortool.h"
60 
61 namespace Digikam
62 {
63 
64 class Q_DECL_HIDDEN EditorToolSettings::Private
65 {
66 
67 public:
68 
Private()69     explicit Private()
70       : scaleBG         (nullptr),
71         linHistoButton  (nullptr),
72         logHistoButton  (nullptr),
73         settingsArea    (nullptr),
74         plainPage       (nullptr),
75         toolName        (nullptr),
76         toolIcon        (nullptr),
77         toolAbout       (nullptr),
78         guideBox        (nullptr),
79         okBtn           (nullptr),
80         cancelBtn       (nullptr),
81         tryBtn          (nullptr),
82         defaultBtn      (nullptr),
83         saveAsBtn       (nullptr),
84         loadBtn         (nullptr),
85         guideColorBt    (nullptr),
86         hGradient       (nullptr),
87         histogramBox    (nullptr),
88         guideSize       (nullptr),
89         tool            (nullptr)
90     {
91     }
92 
93     QButtonGroup*        scaleBG;
94 
95     QToolButton*         linHistoButton;
96     QToolButton*         logHistoButton;
97 
98     QWidget*             settingsArea;
99     QWidget*             plainPage;
100 
101     QLabel*              toolName;
102     QLabel*              toolIcon;
103     QPushButton*         toolAbout;
104 
105     DHBox*               guideBox;
106 
107     QPushButton*         okBtn;
108     QPushButton*         cancelBtn;
109     QPushButton*         tryBtn;
110     QPushButton*         defaultBtn;
111     QPushButton*         saveAsBtn;
112     QPushButton*         loadBtn;
113 
114     DColorSelector*      guideColorBt;
115 
116     ColorGradientWidget* hGradient;
117 
118     HistogramBox*        histogramBox;
119 
120     DIntNumInput*        guideSize;
121 
122     EditorTool*          tool;
123 };
124 
EditorToolSettings(QWidget * const parent)125 EditorToolSettings::EditorToolSettings(QWidget* const parent)
126     : QScrollArea(parent),
127       d          (new Private)
128 {
129     setFrameStyle(QFrame::NoFrame);
130     setWidgetResizable(true);
131 
132     d->settingsArea                 = new QWidget;
133 
134     // ---------------------------------------------------------------
135 
136     QGridLayout* const gridSettings = new QGridLayout(d->settingsArea);
137     d->plainPage                    = new QWidget;
138     d->guideBox                     = new DHBox;
139     d->histogramBox                 = new HistogramBox;
140 
141     // ---------------------------------------------------------------
142 
143     QFrame* const toolDescriptor    = new QFrame;
144     d->toolName                     = new QLabel();
145     d->toolIcon                     = new QLabel();
146     QFont font                      = d->toolName->font();
147     font.setBold(true);
148     d->toolName->setFont(font);
149 
150     d->toolAbout                    = new QPushButton();
151     d->toolAbout->setIcon(QIcon::fromTheme(QLatin1String("help-about")));
152     d->toolAbout->setToolTip(i18n("About this tool..."));
153 
154     QString frameStyle = QString::fromLatin1("QFrame {"
155                                              "color: %1;"
156                                              "border: 1px solid %2;"
157                                              "border-radius: 5px;"
158                                              "background-color: %3;"
159                                              "}")
160                          .arg(QApplication::palette().color(QPalette::HighlightedText).name())
161                          .arg(QApplication::palette().color(QPalette::HighlightedText).name())
162                          .arg(QApplication::palette().color(QPalette::Highlight).name());
163 
164     QString noFrameStyle(QLatin1String("QFrame {"
165                                        "border: none;"
166                                        "}"));
167 
168     toolDescriptor->setStyleSheet(frameStyle);
169     d->toolName->setStyleSheet(noFrameStyle);
170     d->toolIcon->setStyleSheet(noFrameStyle);
171     d->toolAbout->setStyleSheet(noFrameStyle);
172 
173     QGridLayout* const descrLayout = new QGridLayout();
174     descrLayout->addWidget(d->toolIcon,  0, 0, 1, 1);
175     descrLayout->addWidget(d->toolName,  0, 1, 1, 1);
176     descrLayout->addWidget(d->toolAbout, 0, 2, 1, 1);
177     descrLayout->setColumnStretch(1, 10);
178     toolDescriptor->setLayout(descrLayout);
179 
180     // ---------------------------------------------------------------
181 
182     new QLabel(i18n("Guide:"), d->guideBox);
183     QLabel* const space4 = new QLabel(d->guideBox);
184     d->guideColorBt      = new DColorSelector(d->guideBox);
185     d->guideColorBt->setColor(QColor(Qt::red));
186     d->guideColorBt->setWhatsThis(i18n("Set here the color used to draw dashed guide lines."));
187     d->guideSize         = new DIntNumInput(d->guideBox);
188     d->guideSize->setSuffix(QLatin1String("px"));
189     d->guideSize->setRange(1, 5, 1);
190     d->guideSize->setDefaultValue(1);
191     d->guideSize->setWhatsThis(i18n("Set here the width in pixels used to draw dashed guide lines."));
192 
193     d->guideBox->setStretchFactor(space4, 10);
194     d->guideBox->setContentsMargins(QMargins());
195     d->guideBox->setSpacing(spacingHint());
196 
197     // ---------------------------------------------------------------
198 
199     d->defaultBtn = new QPushButton(i18n("Defaults"));
200     d->defaultBtn->setIcon(QIcon::fromTheme(QLatin1String("document-revert")));
201     d->defaultBtn->setToolTip(i18n("Reset all settings to their default values."));
202 
203     d->okBtn = new QPushButton(i18n("OK"));
204     d->okBtn->setIcon(QIcon::fromTheme(QLatin1String("dialog-ok-apply")));
205     d->okBtn->setDefault(true);
206 
207     d->cancelBtn = new QPushButton(i18n("Cancel"));
208     d->cancelBtn->setIcon(QIcon::fromTheme(QLatin1String("dialog-cancel")));
209 
210     QHBoxLayout* const hbox1 = new QHBoxLayout;
211     hbox1->addWidget(d->defaultBtn);
212     hbox1->addStretch(1);
213     hbox1->addWidget(d->okBtn);
214     hbox1->addWidget(d->cancelBtn);
215 
216     // ---------------------------------------------------------------
217 
218     d->loadBtn = new QPushButton(i18nc("@action: load previously saved filter settings", "Load..."));
219     d->loadBtn->setIcon(QIcon::fromTheme(QLatin1String("document-open")));
220     d->loadBtn->setToolTip(i18n("Load all parameters from settings text file."));
221 
222     d->saveAsBtn = new QPushButton(i18nc("@action: save current filter settings", "Save As..."));
223     d->saveAsBtn->setIcon(QIcon::fromTheme(QLatin1String("document-save-as")));
224     d->saveAsBtn->setToolTip(i18n("Save all parameters to settings text file."));
225 
226     d->tryBtn = new QPushButton(i18nc("@action: try current filter settings", "Try"));
227     d->tryBtn->setIcon(QIcon::fromTheme(QLatin1String("dialog-ok-apply")));
228     d->tryBtn->setToolTip(i18n("Try all settings."));
229 
230     QHBoxLayout* const hbox2 = new QHBoxLayout;
231     hbox2->addWidget(d->loadBtn);
232     hbox2->addWidget(d->saveAsBtn);
233     hbox2->addStretch(1);
234     hbox2->addWidget(d->tryBtn);
235 
236     // ---------------------------------------------------------------
237 
238     const int spacing = spacingHint();
239 
240     gridSettings->addWidget(toolDescriptor,  0, 0, 1, -1);
241     gridSettings->addWidget(d->histogramBox, 1, 0, 2, 2);
242     gridSettings->addWidget(d->plainPage,    4, 0, 1, 2);
243     gridSettings->addWidget(d->guideBox,     5, 0, 1, 2);
244     gridSettings->addLayout(hbox2,           6, 0, 1, 2);
245     gridSettings->addLayout(hbox1,           7, 0, 1, 2);
246     gridSettings->setContentsMargins(spacing, spacing, spacing, spacing);
247     gridSettings->setSpacing(spacing);
248 
249     // ---------------------------------------------------------------
250 
251     setWidget(d->settingsArea);
252 
253     // ---------------------------------------------------------------
254 
255     connect(d->okBtn, SIGNAL(clicked()),
256             this, SIGNAL(signalOkClicked()));
257 
258     connect(d->cancelBtn, SIGNAL(clicked()),
259             this, SIGNAL(signalCancelClicked()));
260 
261     connect(d->tryBtn, SIGNAL(clicked()),
262             this, SIGNAL(signalTryClicked()));
263 
264     connect(d->defaultBtn, SIGNAL(clicked()),
265             this, SIGNAL(signalDefaultClicked()));
266 
267     connect(d->saveAsBtn, SIGNAL(clicked()),
268             this, SIGNAL(signalSaveAsClicked()));
269 
270     connect(d->loadBtn, SIGNAL(clicked()),
271             this, SIGNAL(signalLoadClicked()));
272 
273     connect(d->guideColorBt, SIGNAL(signalColorSelected(QColor)),
274             this, SIGNAL(signalColorGuideChanged()));
275 
276     connect(d->guideSize, SIGNAL(valueChanged(int)),
277             this, SIGNAL(signalColorGuideChanged()));
278 
279     connect(d->histogramBox, SIGNAL(signalChannelChanged(ChannelType)),
280             this, SIGNAL(signalChannelChanged()));
281 
282     connect(d->histogramBox, SIGNAL(signalScaleChanged(HistogramScale)),
283             this, SIGNAL(signalScaleChanged()));
284 
285     connect(d->toolAbout, SIGNAL(clicked()),
286             this, SLOT(slotAboutPlugin()));
287 
288     // --------------------------------------------------------
289 
290     setTabOrder(d->tryBtn,     d->okBtn);
291     setTabOrder(d->okBtn,      d->cancelBtn);
292     setTabOrder(d->cancelBtn,  d->defaultBtn);
293     setTabOrder(d->defaultBtn, d->loadBtn);
294     setTabOrder(d->loadBtn,    d->saveAsBtn);
295 
296     // ---------------------------------------------------------------
297 
298     setButtons(Default | Ok | Cancel);
299     setTools(NoTool);
300 }
301 
~EditorToolSettings()302 EditorToolSettings::~EditorToolSettings()
303 {
304     delete d;
305 }
306 
minimumSizeHint() const307 QSize EditorToolSettings::minimumSizeHint() const
308 {
309     // Editor Tools usually require a larger horizontal space than other widgets in right side bar
310     // Set scroll area to a horizontal minimum size sufficient for the settings.
311     // Do not touch vertical size hint.
312     // Limit to 40% of the desktop width.
313 
314     QScreen* screen = qApp->primaryScreen();
315 
316     if (QWidget* const widget = d->settingsArea->nativeParentWidget())
317     {
318         if (QWindow* const window = widget->windowHandle())
319         {
320             screen = window->screen();
321         }
322     }
323 
324     QRect desktopRect = screen->geometry();
325     QSize hint        = QScrollArea::minimumSizeHint();
326     int wSB           = verticalScrollBar()->sizeHint().width();
327     hint.setWidth(qMin(d->settingsArea->sizeHint().width() + wSB, desktopRect.width() * 2 / 5));
328 
329     return hint;
330 }
331 
marginHint()332 int EditorToolSettings::marginHint()
333 {
334     return QApplication::style()->pixelMetric(QStyle::PM_DefaultChildMargin);
335 }
336 
spacingHint()337 int EditorToolSettings::spacingHint()
338 {
339     return QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing);
340 }
341 
plainPage() const342 QWidget* EditorToolSettings::plainPage() const
343 {
344     return d->plainPage;
345 }
346 
histogramBox() const347 HistogramBox* EditorToolSettings::histogramBox() const
348 {
349     return d->histogramBox;
350 }
351 
button(int buttonCode) const352 QPushButton* EditorToolSettings::button(int buttonCode) const
353 {
354     if (buttonCode & Default)
355     {
356         return d->defaultBtn;
357     }
358 
359     if (buttonCode & Try)
360     {
361         return d->tryBtn;
362     }
363 
364     if (buttonCode & Ok)
365     {
366         return d->okBtn;
367     }
368 
369     if (buttonCode & Cancel)
370     {
371         return d->cancelBtn;
372     }
373 
374     if (buttonCode & Load)
375     {
376         return d->loadBtn;
377     }
378 
379     if (buttonCode & SaveAs)
380     {
381         return d->saveAsBtn;
382     }
383 
384     return nullptr;
385 }
386 
enableButton(int buttonCode,bool state)387 void EditorToolSettings::enableButton(int buttonCode, bool state)
388 {
389     QPushButton* const btn = button(buttonCode);
390 
391     if (btn)
392     {
393         btn->setEnabled(state);
394     }
395 }
396 
guideColor() const397 QColor EditorToolSettings::guideColor() const
398 {
399     return d->guideColorBt->color();
400 }
401 
setGuideColor(const QColor & color)402 void EditorToolSettings::setGuideColor(const QColor& color)
403 {
404     d->guideColorBt->setColor(color);
405 }
406 
guideSize() const407 int EditorToolSettings::guideSize() const
408 {
409     return d->guideSize->value();
410 }
411 
setGuideSize(int size)412 void EditorToolSettings::setGuideSize(int size)
413 {
414     d->guideSize->setValue(size);
415 }
416 
setButtons(Buttons buttonMask)417 void EditorToolSettings::setButtons(Buttons buttonMask)
418 {
419     d->okBtn->setVisible(buttonMask & Ok);
420     d->cancelBtn->setVisible(buttonMask & Cancel);
421     d->defaultBtn->setVisible(buttonMask & Default);
422 
423     d->loadBtn->setVisible(buttonMask & Load);
424     d->saveAsBtn->setVisible(buttonMask & SaveAs);
425     d->tryBtn->setVisible(buttonMask & Try);
426 }
427 
setTools(Tools toolMask)428 void EditorToolSettings::setTools(Tools toolMask)
429 {
430     d->histogramBox->setVisible(toolMask & Histogram);
431     d->guideBox->setVisible(toolMask & ColorGuide);
432 }
433 
setHistogramType(HistogramBoxType type)434 void EditorToolSettings::setHistogramType(HistogramBoxType type)
435 {
436     d->histogramBox->setHistogramType(type);
437 }
438 
setTool(EditorTool * const tool)439 void EditorToolSettings::setTool(EditorTool* const tool)
440 {
441     d->tool = tool;
442     d->toolName->setText(d->tool->toolName());
443     d->toolIcon->setPixmap(d->tool->toolIcon().pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize)));
444 }
445 
slotAboutPlugin()446 void EditorToolSettings::slotAboutPlugin()
447 {
448     if (d->tool)
449     {
450         if (d->tool->plugin())
451         {
452             DPlugin* const p = dynamic_cast<DPlugin*>(d->tool->plugin());
453 
454             if (p)
455             {
456                 QPointer<DPluginAboutDlg> dlg = new DPluginAboutDlg(p);
457                 dlg->exec();
458                 delete dlg;
459             }
460         }
461     }
462 }
463 
464 } // namespace Digikam
465