1 /** -*- mode: c++ ; c-basic-offset: 2 -*-
2 *
3 * @file IntParameter.cpp
4 *
5 * Copyright 2017 Sebastien Fourey
6 *
7 * This file is part of G'MIC-Qt, a generic plug-in for raster graphics
8 * editors, offering hundreds of filters thanks to the underlying G'MIC
9 * image processing framework.
10 *
11 * gmic_qt is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * gmic_qt is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with gmic_qt. If not, see <http://www.gnu.org/licenses/>.
23 *
24 */
25 #include "FilterParameters/IntParameter.h"
26 #include <QGridLayout>
27 #include <QLabel>
28 #include <QPalette>
29 #include <QSlider>
30 #include <QTimerEvent>
31 #include <QWidget>
32 #include "DialogSettings.h"
33 #include "FilterParameters/CustomSpinBox.h"
34 #include "FilterTextTranslator.h"
35 #include "Globals.h"
36 #include "HtmlTranslator.h"
37 #include "Logger.h"
38
39 namespace GmicQt
40 {
41
IntParameter(QObject * parent)42 IntParameter::IntParameter(QObject * parent) : AbstractParameter(parent), _min(0), _max(0), _default(0), _value(0), _label(nullptr), _slider(nullptr), _spinBox(nullptr)
43 {
44 _timerId = 0;
45 _connected = false;
46 }
47
~IntParameter()48 IntParameter::~IntParameter()
49 {
50 delete _spinBox;
51 delete _slider;
52 delete _label;
53 }
54
size() const55 int IntParameter::size() const
56 {
57 return 1;
58 }
59
addTo(QWidget * widget,int row)60 bool IntParameter::addTo(QWidget * widget, int row)
61 {
62 _grid = dynamic_cast<QGridLayout *>(widget->layout());
63 Q_ASSERT_X(_grid, __PRETTY_FUNCTION__, "No grid layout in widget");
64 _row = row;
65 delete _spinBox;
66 delete _slider;
67 delete _label;
68 _slider = new QSlider(Qt::Horizontal, widget);
69 _slider->setMinimumWidth(SLIDER_MIN_WIDTH);
70 _slider->setRange(_min, _max);
71 _slider->setValue(_value);
72
73 const int delta = 1 + _max - _min;
74 if (delta < 20) {
75 _slider->setPageStep(1);
76 } else {
77 const int fact = delta < 100 ? 10 : delta < 1000 ? 100 : delta < 10000 ? 1000 : 10000;
78 _slider->setPageStep(fact * (delta / fact) / 10);
79 }
80
81 _spinBox = new CustomSpinBox(widget, _min, _max);
82 _spinBox->setValue(_value);
83 if (DialogSettings::darkThemeEnabled()) {
84 QPalette p = _slider->palette();
85 p.setColor(QPalette::Button, QColor(100, 100, 100));
86 p.setColor(QPalette::Highlight, QColor(130, 130, 130));
87 _slider->setPalette(p);
88 }
89 _grid->addWidget(_label = new QLabel(_name, widget), row, 0, 1, 1);
90 _grid->addWidget(_slider, row, 1, 1, 1);
91 _grid->addWidget(_spinBox, row, 2, 1, 1);
92 connectSliderSpinBox();
93
94 connect(_spinBox, &CustomSpinBox::editingFinished, [this]() { notifyIfRelevant(); });
95
96 return true;
97 }
98
value() const99 QString IntParameter::value() const
100 {
101 return _spinBox->text();
102 }
103
defaultValue() const104 QString IntParameter::defaultValue() const
105 {
106 return QString::number(_default);
107 }
108
setValue(const QString & value)109 void IntParameter::setValue(const QString & value)
110 {
111 bool ok = true;
112 const int k = value.toInt(&ok);
113 if (!ok) {
114 Logger::warning(QString("IntParameter::setValue(\"%1\"): bad value").arg(value));
115 return;
116 }
117 _value = k;
118 if (_spinBox) {
119 disconnectSliderSpinBox();
120 _spinBox->setValue(_value);
121 _slider->setValue(_value);
122 connectSliderSpinBox();
123 }
124 }
125
reset()126 void IntParameter::reset()
127 {
128 disconnectSliderSpinBox();
129 _slider->setValue(_default);
130 _spinBox->setValue(_default);
131 _value = _default;
132 connectSliderSpinBox();
133 }
134
initFromText(const char * text,int & textLength)135 bool IntParameter::initFromText(const char * text, int & textLength)
136 {
137 QList<QString> list = parseText("int", text, textLength);
138 if (list.isEmpty()) {
139 return false;
140 }
141 _name = HtmlTranslator::html2txt(FilterTextTranslator::translate(list[0]));
142
143 QList<QString> values = list[1].split(QChar(','));
144 if (values.size() != 3) {
145 return false;
146 }
147 bool ok1, ok2, ok3;
148 _default = values[0].toInt(&ok1);
149 _min = values[1].toInt(&ok2);
150 _max = values[2].toInt(&ok3);
151 _value = _default;
152 return ok1 && ok2 && ok3;
153 }
154
timerEvent(QTimerEvent * e)155 void IntParameter::timerEvent(QTimerEvent * e)
156 {
157 killTimer(e->timerId());
158 _timerId = 0;
159 if (not _spinBox->unfinishedKeyboardEditing()) {
160 notifyIfRelevant();
161 }
162 }
163
onSliderMoved(int value)164 void IntParameter::onSliderMoved(int value)
165 {
166 if (value != _value) {
167 _spinBox->setValue(_value = value);
168 }
169 }
170
onSliderValueChanged(int value)171 void IntParameter::onSliderValueChanged(int value)
172 {
173 if (value != _value) {
174 _spinBox->setValue(_value = value);
175 }
176 }
177
onSpinBoxChanged(int i)178 void IntParameter::onSpinBoxChanged(int i)
179 {
180 _value = i;
181 _slider->setValue(i);
182 if (_timerId) {
183 killTimer(_timerId);
184 }
185 if (_spinBox->unfinishedKeyboardEditing()) {
186 _timerId = 0;
187 } else {
188 _timerId = startTimer(UPDATE_DELAY);
189 }
190 }
191
connectSliderSpinBox()192 void IntParameter::connectSliderSpinBox()
193 {
194 if (_connected) {
195 return;
196 }
197 connect(_slider, SIGNAL(sliderMoved(int)), this, SLOT(onSliderMoved(int)));
198 connect(_slider, SIGNAL(valueChanged(int)), this, SLOT(onSliderValueChanged(int)));
199 connect(_spinBox, SIGNAL(valueChanged(int)), this, SLOT(onSpinBoxChanged(int)));
200 _connected = true;
201 }
202
disconnectSliderSpinBox()203 void IntParameter::disconnectSliderSpinBox()
204 {
205 if (!_connected) {
206 return;
207 }
208 _slider->disconnect(this);
209 _spinBox->disconnect(this);
210 _connected = false;
211 }
212
213 } // namespace GmicQt
214