1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qquickcolorinputs_p.h"
5
6#include <QtCore/QRegularExpression>
7
8QT_BEGIN_NAMESPACE
9
10QQuickColorInputs::QQuickColorInputs() = default;
11
12QColor QQuickColorInputs::color() const
13{
14 return QColor::fromHsvF(h: m_hsva.h, s: m_hsva.s, v: m_hsva.v, a: m_hsva.a);
15}
16
17void QQuickColorInputs::setColor(const QColor &c)
18{
19 if (color().rgba() == c.rgba())
20 return;
21
22 // If we get a QColor from an Hsv or Hsl color system,
23 // we want to get the raw values without the risk of QColor converting them,
24 // and possible deleting relevant information for achromatic cases.
25 if (c.spec() == QColor::Spec::Hsl) {
26 const auto sv = getSaturationAndValue(saturation: c.hslSaturationF(), lightness: c.lightnessF());
27 m_hsva.h = qBound(min: .0, val: c.hslHueF(), max: 1.0);
28 m_hsva.s = qBound(min: .0, val: sv.first, max: 1.0);
29 m_hsva.v = qBound(min: .0, val: sv.second, max: 1.0);
30 } else {
31 m_hsva.h = qBound(min: .0, val: c.hsvHueF(), max: 1.0);
32 m_hsva.s = qBound(min: .0, val: c.hsvSaturationF(), max: 1.0);
33 m_hsva.v = qBound(min: .0, val: c.valueF(), max: 1.0);
34 }
35
36 m_hsva.a = c.alphaF();
37
38 emit colorChanged(c: color());
39}
40
41int QQuickColorInputs::red() const
42{
43 return color().red();
44}
45
46int QQuickColorInputs::green() const
47{
48 return color().green();
49}
50
51int QQuickColorInputs::blue() const
52{
53 return color().blue();
54}
55
56qreal QQuickColorInputs::alpha() const
57{
58 return m_hsva.a;
59}
60
61qreal QQuickColorInputs::hue() const
62{
63 return m_hsva.h;
64}
65
66qreal QQuickColorInputs::hslSaturation() const
67{
68 return getSaturationAndLightness(saturation: m_hsva.s, value: m_hsva.v).first;
69}
70
71qreal QQuickColorInputs::hsvSaturation() const
72{
73 return m_hsva.s;
74}
75
76qreal QQuickColorInputs::value() const
77{
78 return m_hsva.v;
79}
80
81qreal QQuickColorInputs::lightness() const
82{
83 return getSaturationAndLightness(saturation: m_hsva.s, value: m_hsva.v).second;
84}
85
86bool QQuickColorInputs::showAlpha() const
87{
88 return m_showAlpha;
89}
90
91void QQuickColorInputs::setShowAlpha(bool showAlpha)
92{
93 if (m_showAlpha == showAlpha)
94 return;
95
96 m_showAlpha = showAlpha;
97 emit showAlphaChanged(m_showAlpha);
98}
99
100QQuickTextInput *QQuickColorInputs::hexInput() const
101{
102 return m_hexInput;
103}
104
105void QQuickColorInputs::setHexInput(QQuickTextInput *hexInput)
106{
107 if (m_hexInput == hexInput)
108 return;
109
110 if (m_hexInput)
111 disconnect(sender: m_hexInput, signal: &QQuickTextInput::editingFinished, receiver: this, slot: &QQuickColorInputs::handleHexChanged);
112
113 m_hexInput = hexInput;
114
115 if (m_hexInput)
116 connect(sender: m_hexInput, signal: &QQuickTextInput::editingFinished, context: this, slot: &QQuickColorInputs::handleHexChanged);
117
118 emit hexInputChanged();
119}
120
121QQuickTextInput *QQuickColorInputs::redInput() const
122{
123 return m_redInput;
124}
125
126void QQuickColorInputs::setRedInput(QQuickTextInput *redInput)
127{
128 if (m_redInput == redInput)
129 return;
130
131 if (m_redInput)
132 disconnect(sender: m_redInput, signal: &QQuickTextInput::editingFinished, receiver: this, slot: &QQuickColorInputs::handleRedChanged);
133
134 m_redInput = redInput;
135
136 if (m_redInput)
137 connect(sender: m_redInput, signal: &QQuickTextInput::editingFinished, context: this, slot: &QQuickColorInputs::handleRedChanged);
138
139 emit redInputChanged();
140}
141
142QQuickTextInput *QQuickColorInputs::greenInput() const
143{
144 return m_greenInput;
145}
146
147void QQuickColorInputs::setGreenInput(QQuickTextInput *greenInput)
148{
149 if (m_greenInput == greenInput)
150 return;
151
152 if (m_greenInput)
153 disconnect(sender: m_greenInput, signal: &QQuickTextInput::editingFinished, receiver: this, slot: &QQuickColorInputs::handleGreenChanged);
154
155 m_greenInput = greenInput;
156
157 if (m_greenInput)
158 connect(sender: m_greenInput, signal: &QQuickTextInput::editingFinished, context: this, slot: &QQuickColorInputs::handleGreenChanged);
159
160 emit greenInputChanged();
161}
162
163QQuickTextInput *QQuickColorInputs::blueInput() const
164{
165 return m_blueInput;
166}
167
168void QQuickColorInputs::setBlueInput(QQuickTextInput *blueInput)
169{
170 if (m_blueInput == blueInput)
171 return;
172
173 if (m_blueInput)
174 disconnect(sender: m_blueInput, signal: &QQuickTextInput::editingFinished, receiver: this, slot: &QQuickColorInputs::handleBlueChanged);
175
176 m_blueInput = blueInput;
177
178 if (m_blueInput)
179 connect(sender: m_blueInput, signal: &QQuickTextInput::editingFinished, context: this, slot: &QQuickColorInputs::handleBlueChanged);
180
181 emit blueInputChanged();
182}
183
184QQuickTextInput *QQuickColorInputs::hsvHueInput() const
185{
186 return m_hsvHueInput;
187}
188
189void QQuickColorInputs::setHsvHueInput(QQuickTextInput *hsvHueInput)
190{
191 if (m_hsvHueInput == hsvHueInput)
192 return;
193
194 if (m_hsvHueInput)
195 disconnect(sender: m_hsvHueInput, signal: &QQuickTextInput::editingFinished, receiver: this, slot: &QQuickColorInputs::handleHsvHueChanged);
196
197 m_hsvHueInput = hsvHueInput;
198
199 if (m_hsvHueInput)
200 connect(sender: m_hsvHueInput, signal: &QQuickTextInput::editingFinished, context: this, slot: &QQuickColorInputs::handleHsvHueChanged);
201
202 emit hsvHueInputChanged();
203}
204
205QQuickTextInput *QQuickColorInputs::hslHueInput() const
206{
207 return m_hslHueInput;
208}
209
210void QQuickColorInputs::setHslHueInput(QQuickTextInput *hslHueInput)
211{
212 if (m_hslHueInput == hslHueInput)
213 return;
214
215 if (m_hslHueInput)
216 disconnect(sender: m_hslHueInput, signal: &QQuickTextInput::editingFinished, receiver: this, slot: &QQuickColorInputs::handleHslHueChanged);
217
218 m_hslHueInput = hslHueInput;
219
220 if (m_hslHueInput)
221 connect(sender: m_hslHueInput, signal: &QQuickTextInput::editingFinished, context: this, slot: &QQuickColorInputs::handleHslHueChanged);
222
223 emit hslHueInputChanged();
224}
225
226QQuickTextInput *QQuickColorInputs::hsvSaturationInput() const
227{
228 return m_hsvSaturationInput;
229}
230
231void QQuickColorInputs::setHsvSaturationInput(QQuickTextInput *hsvSaturationInput)
232{
233 if (m_hsvSaturationInput == hsvSaturationInput)
234 return;
235
236 if (m_hsvSaturationInput)
237 disconnect(sender: m_hsvSaturationInput, signal: &QQuickTextInput::editingFinished, receiver: this, slot: &QQuickColorInputs::handleHsvSaturationChanged);
238
239 m_hsvSaturationInput = hsvSaturationInput;
240
241 if (m_hsvSaturationInput)
242 connect(sender: m_hsvSaturationInput, signal: &QQuickTextInput::editingFinished, context: this, slot: &QQuickColorInputs::handleHsvSaturationChanged);
243
244 emit hsvSaturationInputChanged();
245}
246
247QQuickTextInput *QQuickColorInputs::hslSaturationInput() const
248{
249 return m_hslSaturationInput;
250}
251
252void QQuickColorInputs::setHslSaturationInput(QQuickTextInput *hslSaturationInput)
253{
254 if (m_hslSaturationInput == hslSaturationInput)
255 return;
256
257 if (m_hslSaturationInput)
258 disconnect(sender: m_hslSaturationInput, signal: &QQuickTextInput::editingFinished, receiver: this, slot: &QQuickColorInputs::handleHslSaturationChanged);
259
260 m_hslSaturationInput = hslSaturationInput;
261
262 if (m_hslSaturationInput)
263 connect(sender: m_hslSaturationInput, signal: &QQuickTextInput::editingFinished, context: this, slot: &QQuickColorInputs::handleHslSaturationChanged);
264
265 emit hslSaturationInputChanged();
266}
267
268QQuickTextInput *QQuickColorInputs::valueInput() const
269{
270 return m_valueInput;
271}
272
273void QQuickColorInputs::setValueInput(QQuickTextInput *valueInput)
274{
275 if (m_valueInput == valueInput)
276 return;
277
278 if (m_valueInput)
279 disconnect(sender: m_valueInput, signal: &QQuickTextInput::editingFinished, receiver: this, slot: &QQuickColorInputs::handleValueChanged);
280
281 m_valueInput = valueInput;
282
283 if (m_valueInput)
284 connect(sender: m_valueInput, signal: &QQuickTextInput::editingFinished, context: this, slot: &QQuickColorInputs::handleValueChanged);
285
286 emit valueInputChanged();
287}
288
289QQuickTextInput *QQuickColorInputs::lightnessInput() const
290{
291 return m_lightnessInput;
292}
293
294void QQuickColorInputs::setLightnessInput(QQuickTextInput *lightnessInput)
295{
296 if (m_lightnessInput == lightnessInput)
297 return;
298
299 if (m_lightnessInput)
300 disconnect(sender: m_lightnessInput, signal: &QQuickTextInput::editingFinished, receiver: this, slot: &QQuickColorInputs::handleLightnessChanged);
301
302 m_lightnessInput = lightnessInput;
303
304 if (m_lightnessInput)
305 connect(sender: m_lightnessInput, signal: &QQuickTextInput::editingFinished, context: this, slot: &QQuickColorInputs::handleLightnessChanged);
306
307 emit lightnessInputChanged();
308}
309
310QQuickTextInput *QQuickColorInputs::rgbAlphaInput() const
311{
312 return m_rgbAlphaInput;
313}
314
315void QQuickColorInputs::setRgbAlphaInput(QQuickTextInput *alphaInput)
316{
317 if (alphaInput == m_rgbAlphaInput)
318 return;
319
320 if (m_rgbAlphaInput) {
321 disconnect(sender: m_rgbAlphaInput, signal: &QQuickTextInput::editingFinished, receiver: this, slot: &QQuickColorInputs::handleRgbAlphaChanged);
322 disconnect(sender: this, signal: &QQuickColorInputs::showAlphaChanged, receiver: m_rgbAlphaInput, slot: &QQuickTextInput::setVisible);
323 }
324
325 m_rgbAlphaInput = alphaInput;
326
327 if (m_rgbAlphaInput) {
328 connect(sender: m_rgbAlphaInput, signal: &QQuickTextInput::editingFinished, context: this, slot: &QQuickColorInputs::handleRgbAlphaChanged);
329 connect(sender: this, signal: &QQuickColorInputs::showAlphaChanged, context: m_rgbAlphaInput, slot: &QQuickTextInput::setVisible);
330 m_rgbAlphaInput->setVisible(showAlpha());
331 }
332
333 emit rgbAlphaInputChanged();
334}
335
336QQuickTextInput *QQuickColorInputs::hsvAlphaInput() const
337{
338 return m_hsvAlphaInput;
339}
340
341void QQuickColorInputs::setHsvAlphaInput(QQuickTextInput *alphaInput)
342{
343 if (alphaInput == m_hsvAlphaInput)
344 return;
345
346 if (m_hsvAlphaInput) {
347 disconnect(sender: m_hsvAlphaInput, signal: &QQuickTextInput::editingFinished, receiver: this, slot: &QQuickColorInputs::handleHsvAlphaChanged);
348 disconnect(sender: this, signal: &QQuickColorInputs::showAlphaChanged, receiver: m_hsvAlphaInput, slot: &QQuickTextInput::setVisible);
349 }
350
351 m_hsvAlphaInput = alphaInput;
352
353 if (m_hsvAlphaInput) {
354 connect(sender: m_hsvAlphaInput, signal: &QQuickTextInput::editingFinished, context: this, slot: &QQuickColorInputs::handleHsvAlphaChanged);
355 connect(sender: this, signal: &QQuickColorInputs::showAlphaChanged, context: m_hsvAlphaInput, slot: &QQuickTextInput::setVisible);
356 m_hsvAlphaInput->setVisible(showAlpha());
357 }
358
359 emit hsvAlphaInputChanged();
360}
361
362QQuickTextInput *QQuickColorInputs::hslAlphaInput() const
363{
364 return m_hslAlphaInput;
365}
366
367void QQuickColorInputs::setHslAlphaInput(QQuickTextInput *alphaInput)
368{
369 if (alphaInput == m_hslAlphaInput)
370 return;
371
372 if (m_hslAlphaInput) {
373 disconnect(sender: m_hslAlphaInput, signal: &QQuickTextInput::editingFinished, receiver: this, slot: &QQuickColorInputs::handleHslAlphaChanged);
374 disconnect(sender: this, signal: &QQuickColorInputs::showAlphaChanged, receiver: m_hslAlphaInput, slot: &QQuickTextInput::setVisible);
375 }
376
377 m_hslAlphaInput = alphaInput;
378
379 if (m_hslAlphaInput) {
380 connect(sender: m_hslAlphaInput, signal: &QQuickTextInput::editingFinished, context: this, slot: &QQuickColorInputs::handleHslAlphaChanged);
381 connect(sender: this, signal: &QQuickColorInputs::showAlphaChanged, context: m_hslAlphaInput, slot: &QQuickTextInput::setVisible);
382 m_hslAlphaInput->setVisible(showAlpha());
383 }
384
385 emit hslAlphaInputChanged();
386}
387
388void QQuickColorInputs::handleHexChanged()
389{
390 emit colorModified(c: QColor::fromString(name: m_hexInput->text()));
391}
392
393void QQuickColorInputs::handleRedChanged()
394{
395 QColor c = color();
396 c.setRed(qBound(min: 0, val: m_redInput->text().toInt(), max: 255));
397 emit colorModified(c);
398}
399
400void QQuickColorInputs::handleGreenChanged()
401{
402 QColor c = color();
403 c.setGreen(qBound(min: 0, val: m_greenInput->text().toInt(), max: 255));
404 emit colorModified(c);
405}
406
407void QQuickColorInputs::handleBlueChanged()
408{
409 QColor c = color();
410 c.setBlue(qBound(min: 0, val: m_blueInput->text().toInt(), max: 255));
411 emit colorModified(c);
412}
413
414static QString s_percentage_pattern = QString::fromUtf8(utf8: "^(\\d+)%?$");
415static QString s_degree_pattern = QString::fromUtf8(utf8: "(\\d+)°?$");
416
417void QQuickColorInputs::handleHsvHueChanged()
418{
419 const QRegularExpression pattern(s_degree_pattern);
420 const auto match = pattern.match(subject: m_hsvHueInput->text());
421 if (match.hasMatch()) {
422 const auto substr = match.captured(nth: 1);
423 const qreal input = static_cast<qreal>(qBound(min: 0, val: substr.toInt(), max: 360)) / static_cast<qreal>(360);
424 emit colorModified(c: QColor::fromHsvF(h: input, s: hsvSaturation(), v: value(), a: alpha()));
425 }
426}
427
428void QQuickColorInputs::handleHslHueChanged()
429{
430 const QRegularExpression pattern(s_degree_pattern);
431 const auto match = pattern.match(subject: m_hslHueInput->text());
432 if (match.hasMatch()) {
433 const auto substr = match.captured(nth: 1);
434 const qreal input = static_cast<qreal>(qBound(min: 0, val: substr.toInt(), max: 360)) / static_cast<qreal>(360);
435 emit colorModified(c: QColor::fromHslF(h: input, s: hslSaturation(), l: lightness(), a: alpha()));
436 }
437}
438
439void QQuickColorInputs::handleHsvSaturationChanged()
440{
441 const QRegularExpression pattern(s_percentage_pattern);
442 const auto match = pattern.match(subject: m_hsvSaturationInput->text());
443 if (match.hasMatch()) {
444 const auto substr = match.captured(nth: 1);
445 const qreal input = static_cast<qreal>(qBound(min: 0, val: substr.toInt(), max: 100)) / static_cast<qreal>(100);
446 emit colorModified(c: QColor::fromHsvF(h: hue(), s: input, v: value(), a: alpha()));
447 }
448}
449
450void QQuickColorInputs::handleHslSaturationChanged()
451{
452 const QRegularExpression pattern(s_percentage_pattern);
453 const auto match = pattern.match(subject: m_hslSaturationInput->text());
454 if (match.hasMatch()) {
455 const auto substr = match.captured(nth: 1);
456 const qreal input = static_cast<qreal>(qBound(min: 0, val: substr.toInt(), max: 100)) / static_cast<qreal>(100);
457 emit colorModified(c: QColor::fromHslF(h: hue(), s: input, l: lightness(), a: alpha()));
458 }
459}
460
461void QQuickColorInputs::handleValueChanged()
462{
463 const QRegularExpression pattern(s_percentage_pattern);
464 const auto match = pattern.match(subject: m_valueInput->text());
465 if (match.hasMatch()) {
466 const auto substr = match.captured(nth: 1);
467 const qreal input = static_cast<qreal>(qBound(min: 0, val: substr.toInt(), max: 100)) / static_cast<qreal>(100);
468 emit colorModified(c: QColor::fromHsvF(h: hue(), s: hsvSaturation(), v: input, a: alpha()));
469 }
470}
471
472void QQuickColorInputs::handleLightnessChanged()
473{
474 const QRegularExpression pattern(s_percentage_pattern);
475 const auto match = pattern.match(subject: m_lightnessInput->text());
476 if (match.hasMatch()) {
477 const auto substr = match.captured(nth: 1);
478 const qreal input = static_cast<qreal>(qBound(min: 0, val: substr.toInt(), max: 100)) / static_cast<qreal>(100);
479 emit colorModified(c: QColor::fromHslF(h: hue(), s: hslSaturation(), l: input, a: alpha()));
480 }
481}
482
483void QQuickColorInputs::handleRgbAlphaChanged()
484{
485 handleAlphaChanged(input: m_rgbAlphaInput->text());
486}
487
488void QQuickColorInputs::handleHsvAlphaChanged()
489{
490 handleAlphaChanged(input: m_hsvAlphaInput->text());
491}
492
493void QQuickColorInputs::handleHslAlphaChanged()
494{
495 handleAlphaChanged(input: m_hslAlphaInput->text());
496}
497
498void QQuickColorInputs::handleAlphaChanged(const QString &input)
499{
500 const QRegularExpression pattern(s_percentage_pattern);
501 const auto match = pattern.match(subject: input);
502 if (match.hasMatch()) {
503 QColor c = color();
504 const auto substr = match.captured(nth: 1);
505 const qreal input = static_cast<qreal>(qBound(min: 0, val: substr.toInt(), max: 100)) / static_cast<qreal>(100);
506 c.setAlphaF(input);
507 emit colorModified(c);
508 }
509}
510
511QT_END_NAMESPACE
512

source code of qtdeclarative/src/quickdialogs/quickdialogsquickimpl/qquickcolorinputs.cpp