1// Copyright (C) 2017 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 "qquickmaterialstyle_p.h"
5
6#include <QtCore/qdebug.h>
7#if QT_CONFIG(settings)
8#include <QtCore/qsettings.h>
9#endif
10#include <QtQml/qqmlinfo.h>
11#include <QtQuickControls2/private/qquickstyle_p.h>
12
13QT_BEGIN_NAMESPACE
14
15static const QRgb colors[][14] = {
16 // Red
17 {
18 0xFFFFEBEE, // Shade50
19 0xFFFFCDD2, // Shade100
20 0xFFEF9A9A, // Shade200
21 0xFFE57373, // Shade300
22 0xFFEF5350, // Shade400
23 0xFFF44336, // Shade500
24 0xFFE53935, // Shade600
25 0xFFD32F2F, // Shade700
26 0xFFC62828, // Shade800
27 0xFFB71C1C, // Shade900
28 0xFFFF8A80, // ShadeA100
29 0xFFFF5252, // ShadeA200
30 0xFFFF1744, // ShadeA400
31 0xFFD50000 // ShadeA700
32 },
33 // Pink
34 {
35 0xFFFCE4EC, // Shade50
36 0xFFF8BBD0, // Shade100
37 0xFFF48FB1, // Shade200
38 0xFFF06292, // Shade300
39 0xFFEC407A, // Shade400
40 0xFFE91E63, // Shade500
41 0xFFD81B60, // Shade600
42 0xFFC2185B, // Shade700
43 0xFFAD1457, // Shade800
44 0xFF880E4F, // Shade900
45 0xFFFF80AB, // ShadeA100
46 0xFFFF4081, // ShadeA200
47 0xFFF50057, // ShadeA400
48 0xFFC51162 // ShadeA700
49 },
50 // Purple
51 {
52 0xFFF3E5F5, // Shade50
53 0xFFE1BEE7, // Shade100
54 0xFFCE93D8, // Shade200
55 0xFFBA68C8, // Shade300
56 0xFFAB47BC, // Shade400
57 0xFF9C27B0, // Shade500
58 0xFF8E24AA, // Shade600
59 0xFF7B1FA2, // Shade700
60 0xFF6A1B9A, // Shade800
61 0xFF4A148C, // Shade900
62 0xFFEA80FC, // ShadeA100
63 0xFFE040FB, // ShadeA200
64 0xFFD500F9, // ShadeA400
65 0xFFAA00FF // ShadeA700
66 },
67 // DeepPurple
68 {
69 0xFFEDE7F6, // Shade50
70 0xFFD1C4E9, // Shade100
71 0xFFB39DDB, // Shade200
72 0xFF9575CD, // Shade300
73 0xFF7E57C2, // Shade400
74 0xFF673AB7, // Shade500
75 0xFF5E35B1, // Shade600
76 0xFF512DA8, // Shade700
77 0xFF4527A0, // Shade800
78 0xFF311B92, // Shade900
79 0xFFB388FF, // ShadeA100
80 0xFF7C4DFF, // ShadeA200
81 0xFF651FFF, // ShadeA400
82 0xFF6200EA // ShadeA700
83 },
84 // Indigo
85 {
86 0xFFE8EAF6, // Shade50
87 0xFFC5CAE9, // Shade100
88 0xFF9FA8DA, // Shade200
89 0xFF7986CB, // Shade300
90 0xFF5C6BC0, // Shade400
91 0xFF3F51B5, // Shade500
92 0xFF3949AB, // Shade600
93 0xFF303F9F, // Shade700
94 0xFF283593, // Shade800
95 0xFF1A237E, // Shade900
96 0xFF8C9EFF, // ShadeA100
97 0xFF536DFE, // ShadeA200
98 0xFF3D5AFE, // ShadeA400
99 0xFF304FFE // ShadeA700
100 },
101 // Blue
102 {
103 0xFFE3F2FD, // Shade50
104 0xFFBBDEFB, // Shade100
105 0xFF90CAF9, // Shade200
106 0xFF64B5F6, // Shade300
107 0xFF42A5F5, // Shade400
108 0xFF2196F3, // Shade500
109 0xFF1E88E5, // Shade600
110 0xFF1976D2, // Shade700
111 0xFF1565C0, // Shade800
112 0xFF0D47A1, // Shade900
113 0xFF82B1FF, // ShadeA100
114 0xFF448AFF, // ShadeA200
115 0xFF2979FF, // ShadeA400
116 0xFF2962FF // ShadeA700
117 },
118 // LightBlue
119 {
120 0xFFE1F5FE, // Shade50
121 0xFFB3E5FC, // Shade100
122 0xFF81D4FA, // Shade200
123 0xFF4FC3F7, // Shade300
124 0xFF29B6F6, // Shade400
125 0xFF03A9F4, // Shade500
126 0xFF039BE5, // Shade600
127 0xFF0288D1, // Shade700
128 0xFF0277BD, // Shade800
129 0xFF01579B, // Shade900
130 0xFF80D8FF, // ShadeA100
131 0xFF40C4FF, // ShadeA200
132 0xFF00B0FF, // ShadeA400
133 0xFF0091EA // ShadeA700
134 },
135 // Cyan
136 {
137 0xFFE0F7FA, // Shade50
138 0xFFB2EBF2, // Shade100
139 0xFF80DEEA, // Shade200
140 0xFF4DD0E1, // Shade300
141 0xFF26C6DA, // Shade400
142 0xFF00BCD4, // Shade500
143 0xFF00ACC1, // Shade600
144 0xFF0097A7, // Shade700
145 0xFF00838F, // Shade800
146 0xFF006064, // Shade900
147 0xFF84FFFF, // ShadeA100
148 0xFF18FFFF, // ShadeA200
149 0xFF00E5FF, // ShadeA400
150 0xFF00B8D4 // ShadeA700
151 },
152 // Teal
153 {
154 0xFFE0F2F1, // Shade50
155 0xFFB2DFDB, // Shade100
156 0xFF80CBC4, // Shade200
157 0xFF4DB6AC, // Shade300
158 0xFF26A69A, // Shade400
159 0xFF009688, // Shade500
160 0xFF00897B, // Shade600
161 0xFF00796B, // Shade700
162 0xFF00695C, // Shade800
163 0xFF004D40, // Shade900
164 0xFFA7FFEB, // ShadeA100
165 0xFF64FFDA, // ShadeA200
166 0xFF1DE9B6, // ShadeA400
167 0xFF00BFA5 // ShadeA700
168 },
169 // Green
170 {
171 0xFFE8F5E9, // Shade50
172 0xFFC8E6C9, // Shade100
173 0xFFA5D6A7, // Shade200
174 0xFF81C784, // Shade300
175 0xFF66BB6A, // Shade400
176 0xFF4CAF50, // Shade500
177 0xFF43A047, // Shade600
178 0xFF388E3C, // Shade700
179 0xFF2E7D32, // Shade800
180 0xFF1B5E20, // Shade900
181 0xFFB9F6CA, // ShadeA100
182 0xFF69F0AE, // ShadeA200
183 0xFF00E676, // ShadeA400
184 0xFF00C853 // ShadeA700
185 },
186 // LightGreen
187 {
188 0xFFF1F8E9, // Shade50
189 0xFFDCEDC8, // Shade100
190 0xFFC5E1A5, // Shade200
191 0xFFAED581, // Shade300
192 0xFF9CCC65, // Shade400
193 0xFF8BC34A, // Shade500
194 0xFF7CB342, // Shade600
195 0xFF689F38, // Shade700
196 0xFF558B2F, // Shade800
197 0xFF33691E, // Shade900
198 0xFFCCFF90, // ShadeA100
199 0xFFB2FF59, // ShadeA200
200 0xFF76FF03, // ShadeA400
201 0xFF64DD17 // ShadeA700
202 },
203 // Lime
204 {
205 0xFFF9FBE7, // Shade50
206 0xFFF0F4C3, // Shade100
207 0xFFE6EE9C, // Shade200
208 0xFFDCE775, // Shade300
209 0xFFD4E157, // Shade400
210 0xFFCDDC39, // Shade500
211 0xFFC0CA33, // Shade600
212 0xFFAFB42B, // Shade700
213 0xFF9E9D24, // Shade800
214 0xFF827717, // Shade900
215 0xFFF4FF81, // ShadeA100
216 0xFFEEFF41, // ShadeA200
217 0xFFC6FF00, // ShadeA400
218 0xFFAEEA00 // ShadeA700
219 },
220 // Yellow
221 {
222 0xFFFFFDE7, // Shade50
223 0xFFFFF9C4, // Shade100
224 0xFFFFF59D, // Shade200
225 0xFFFFF176, // Shade300
226 0xFFFFEE58, // Shade400
227 0xFFFFEB3B, // Shade500
228 0xFFFDD835, // Shade600
229 0xFFFBC02D, // Shade700
230 0xFFF9A825, // Shade800
231 0xFFF57F17, // Shade900
232 0xFFFFFF8D, // ShadeA100
233 0xFFFFFF00, // ShadeA200
234 0xFFFFEA00, // ShadeA400
235 0xFFFFD600 // ShadeA700
236 },
237 // Amber
238 {
239 0xFFFFF8E1, // Shade50
240 0xFFFFECB3, // Shade100
241 0xFFFFE082, // Shade200
242 0xFFFFD54F, // Shade300
243 0xFFFFCA28, // Shade400
244 0xFFFFC107, // Shade500
245 0xFFFFB300, // Shade600
246 0xFFFFA000, // Shade700
247 0xFFFF8F00, // Shade800
248 0xFFFF6F00, // Shade900
249 0xFFFFE57F, // ShadeA100
250 0xFFFFD740, // ShadeA200
251 0xFFFFC400, // ShadeA400
252 0xFFFFAB00 // ShadeA700
253 },
254 // Orange
255 {
256 0xFFFFF3E0, // Shade50
257 0xFFFFE0B2, // Shade100
258 0xFFFFCC80, // Shade200
259 0xFFFFB74D, // Shade300
260 0xFFFFA726, // Shade400
261 0xFFFF9800, // Shade500
262 0xFFFB8C00, // Shade600
263 0xFFF57C00, // Shade700
264 0xFFEF6C00, // Shade800
265 0xFFE65100, // Shade900
266 0xFFFFD180, // ShadeA100
267 0xFFFFAB40, // ShadeA200
268 0xFFFF9100, // ShadeA400
269 0xFFFF6D00 // ShadeA700
270 },
271 // DeepOrange
272 {
273 0xFFFBE9E7, // Shade50
274 0xFFFFCCBC, // Shade100
275 0xFFFFAB91, // Shade200
276 0xFFFF8A65, // Shade300
277 0xFFFF7043, // Shade400
278 0xFFFF5722, // Shade500
279 0xFFF4511E, // Shade600
280 0xFFE64A19, // Shade700
281 0xFFD84315, // Shade800
282 0xFFBF360C, // Shade900
283 0xFFFF9E80, // ShadeA100
284 0xFFFF6E40, // ShadeA200
285 0xFFFF3D00, // ShadeA400
286 0xFFDD2C00 // ShadeA700
287 },
288 // Brown
289 {
290 0xFFEFEBE9, // Shade50
291 0xFFD7CCC8, // Shade100
292 0xFFBCAAA4, // Shade200
293 0xFFA1887F, // Shade300
294 0xFF8D6E63, // Shade400
295 0xFF795548, // Shade500
296 0xFF6D4C41, // Shade600
297 0xFF5D4037, // Shade700
298 0xFF4E342E, // Shade800
299 0xFF3E2723, // Shade900
300 0xFF000000, // ShadeA100
301 0xFF000000, // ShadeA200
302 0xFF000000, // ShadeA400
303 0xFF000000 // ShadeA700
304 },
305 // Grey
306 {
307 0xFFFAFAFA, // Shade50
308 0xFFF5F5F5, // Shade100
309 0xFFEEEEEE, // Shade200
310 0xFFE0E0E0, // Shade300
311 0xFFBDBDBD, // Shade400
312 0xFF9E9E9E, // Shade500
313 0xFF757575, // Shade600
314 0xFF616161, // Shade700
315 0xFF424242, // Shade800
316 0xFF212121, // Shade900
317 0xFF000000, // ShadeA100
318 0xFF000000, // ShadeA200
319 0xFF000000, // ShadeA400
320 0xFF000000 // ShadeA700
321 },
322 // BlueGrey
323 {
324 0xFFECEFF1, // Shade50
325 0xFFCFD8DC, // Shade100
326 0xFFB0BEC5, // Shade200
327 0xFF90A4AE, // Shade300
328 0xFF78909C, // Shade400
329 0xFF607D8B, // Shade500
330 0xFF546E7A, // Shade600
331 0xFF455A64, // Shade700
332 0xFF37474F, // Shade800
333 0xFF263238, // Shade900
334 0xFF000000, // ShadeA100
335 0xFF000000, // ShadeA200
336 0xFF000000, // ShadeA400
337 0xFF000000 // ShadeA700
338 }
339};
340
341// If no value was inherited from a parent or explicitly set, the "global" values are used.
342// The initial, default values of the globals are hard-coded here, but the environment
343// variables and .conf file override them if specified.
344static QQuickMaterialStyle::Theme globalTheme = QQuickMaterialStyle::Light;
345static uint globalPrimary = QQuickMaterialStyle::Indigo;
346static uint globalAccent = QQuickMaterialStyle::Pink;
347static uint globalForeground = 0xDD000000; // primaryTextColorLight
348static uint globalBackground = 0xFFFAFAFA; // backgroundColorLight
349// These represent whether a global foreground/background was set.
350// Each style's m_hasForeground/m_hasBackground are initialized to these values.
351static bool hasGlobalForeground = false;
352static bool hasGlobalBackground = false;
353// These represent whether or not the global color value was specified as one of the
354// values that QColor accepts, as opposed to one of the pre-defined colors like Red.
355static bool globalPrimaryCustom = false;
356static bool globalAccentCustom = false;
357static bool globalForegroundCustom = true;
358static bool globalBackgroundCustom = true;
359// This is global because:
360// 1) The theme needs access to it to determine font sizes.
361// 2) There can only be one variant used for the whole application.
362static QQuickMaterialStyle::Variant globalVariant = QQuickMaterialStyle::Normal;
363static const QRgb backgroundColorLight = 0xFFFFFBFE;
364static const QRgb backgroundColorDark = 0xFF1C1B1F;
365static const QRgb dialogColorLight = 0xFFFFFFFF;
366static const QRgb dialogColorDark = 0xFF424242;
367static const QRgb primaryTextColorLight = 0xDD000000;
368static const QRgb primaryTextColorDark = 0xFFFFFFFF;
369static const QRgb secondaryTextColorLight = 0x89000000;
370static const QRgb secondaryTextColorDark = 0xB2FFFFFF;
371static const QRgb hintTextColorLight = 0x60000000;
372static const QRgb hintTextColorDark = 0x4CFFFFFF;
373static const QRgb dividerColorLight = 0x1E000000;
374static const QRgb dividerColorDark = 0x1EFFFFFF;
375static const QRgb iconColorLight = 0x89000000;
376static const QRgb iconColorDark = 0xFFFFFFFF;
377static const QRgb iconDisabledColorLight = 0x42000000;
378static const QRgb iconDisabledColorDark = 0x4CFFFFFF;
379static const QRgb raisedButtonColorLight = 0xFFD6D7D7;
380static const QRgb raisedButtonColorDark = 0x3FCCCCCC;
381static const QRgb raisedButtonDisabledColorLight = dividerColorLight;
382static const QRgb raisedButtonDisabledColorDark = dividerColorDark;
383static const QRgb frameColorLight = hintTextColorLight;
384static const QRgb frameColorDark = hintTextColorDark;
385static const QRgb rippleColorLight = 0x10000000;
386static const QRgb rippleColorDark = 0x20FFFFFF;
387static const QRgb spinBoxDisabledIconColorLight = 0xFFCCCCCC;
388static const QRgb spinBoxDisabledIconColorDark = 0xFF666666;
389static const QRgb sliderDisabledColorLight = 0xFF9E9E9E;
390static const QRgb sliderDisabledColorDark = 0xFF616161;
391/*
392 https://m3.material.io/components/switch/specs#57a434cd-5fcc-4d79-9bff-12b2a9768789
393
394 light / dark
395 surface: #FFFBFE/#1C1B1F
396 on-surface: #1C1B1F/#E6E1E5
397 surface-variant: #E7E0EC/#49454F
398
399 12% = 1E
400 38% = 61
401
402 handle
403
404 unchecked checked
405 disabled #1C1B1F/#E6E1E5 @ 38% (#611C1B1F/#61E6E1E5) #FFFBFE/#1C1B1F @ 100%
406
407 track
408
409 unchecked checked
410 disabled #E7E0EC/#49454F @ 12% (#1EE7E0EC/#1E49454F) #1C1B1F/#E6E1E5 @ 12% (#1E1C1B1F/#1EE6E1E5)
411
412 track outline
413
414 unchecked checked
415 disabled #1C1B1F/#E6E1E5 @ 12% (#1E1C1B1F/#1EE6E1E5) same as track
416*/
417static const QRgb switchUncheckedTrackColorLight = 0xFFE7E0EC;
418static const QRgb switchUncheckedTrackColorDark = 0x49454F;
419static const QRgb switchDisabledUncheckedTrackColorLight = 0x1EE7E0EC;
420static const QRgb switchDisabledUncheckedTrackColorDark = 0x1E49454F;
421static const QRgb switchDisabledUncheckedTrackBorderColorLight = 0x1E1C1B1F;
422static const QRgb switchDisabledUncheckedTrackBorderColorDark = 0x1EE6E1E5;
423static const QRgb switchDisabledCheckedTrackColorLight = 0x1E1C1B1F;
424static const QRgb switchDisabledCheckedTrackColorDark = 0x1EE6E1E5;
425static const QRgb switchDisabledUncheckedIconColorLight = 0x611C1B1F;
426static const QRgb switchDisabledUncheckedIconColorDark = 0x61E6E1E5;
427static const QRgb textFieldFilledContainerColorLight = 0xFFE7E0EC;
428static const QRgb textFieldFilledContainerColorDark = 0xFF49454F;
429
430static QQuickMaterialStyle::Theme effectiveTheme(QQuickMaterialStyle::Theme theme)
431{
432 if (theme == QQuickMaterialStyle::System)
433 theme = QQuickStylePrivate::isDarkSystemTheme() ? QQuickMaterialStyle::Dark : QQuickMaterialStyle::Light;
434 return theme;
435}
436
437QQuickMaterialStyle::QQuickMaterialStyle(QObject *parent) : QQuickAttachedPropertyPropagator(parent),
438 m_customPrimary(globalPrimaryCustom),
439 m_customAccent(globalAccentCustom),
440 m_customForeground(globalForegroundCustom),
441 m_customBackground(globalBackgroundCustom),
442 m_hasForeground(hasGlobalForeground),
443 m_hasBackground(hasGlobalBackground),
444 m_theme(globalTheme),
445 m_primary(globalPrimary),
446 m_accent(globalAccent),
447 m_foreground(globalForeground),
448 m_background(globalBackground)
449{
450 QQuickAttachedPropertyPropagator::initialize();
451}
452
453QQuickMaterialStyle *QQuickMaterialStyle::qmlAttachedProperties(QObject *object)
454{
455 return new QQuickMaterialStyle(object);
456}
457
458QQuickMaterialStyle::Theme QQuickMaterialStyle::theme() const
459{
460 return m_theme;
461}
462
463void QQuickMaterialStyle::setTheme(Theme theme)
464{
465 if (theme == System)
466 theme = QQuickStylePrivate::isDarkSystemTheme() ? Dark : Light;
467
468 m_explicitTheme = true;
469 if (m_theme == theme)
470 return;
471
472 m_theme = theme;
473 propagateTheme();
474 themeChange();
475 if (!m_customAccent)
476 accentChange();
477 if (!m_hasBackground)
478 backgroundChange();
479 if (!m_hasForeground)
480 foregroundChange();
481}
482
483void QQuickMaterialStyle::inheritTheme(Theme theme)
484{
485 if (m_explicitTheme || m_theme == theme)
486 return;
487
488 m_theme = theme;
489 propagateTheme();
490 themeChange();
491 if (!m_customAccent)
492 accentChange();
493 if (!m_hasBackground)
494 backgroundChange();
495 if (!m_hasForeground)
496 foregroundChange();
497}
498
499void QQuickMaterialStyle::propagateTheme()
500{
501 const auto styles = attachedChildren();
502 for (QQuickAttachedPropertyPropagator *child : styles) {
503 QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(object: child);
504 if (material)
505 material->inheritTheme(theme: m_theme);
506 }
507}
508
509void QQuickMaterialStyle::resetTheme()
510{
511 if (!m_explicitTheme)
512 return;
513
514 m_explicitTheme = false;
515 QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(object: attachedParent());
516 inheritTheme(theme: material ? material->theme() : globalTheme);
517}
518
519void QQuickMaterialStyle::themeChange()
520{
521 emit themeChanged();
522 emit themeOrAccentChanged();
523 emit primaryHighlightedTextColor();
524 emit dialogColorChanged();
525 emit tooltipColorChanged();
526 emit toolBarColorChanged();
527 emit toolTextColorChanged();
528}
529
530QVariant QQuickMaterialStyle::primary() const
531{
532 return primaryColor();
533}
534
535void QQuickMaterialStyle::setPrimary(const QVariant &var)
536{
537 QRgb primary = 0;
538 bool custom = false;
539 if (!variantToRgba(var, name: "primary", rgba: &primary, custom: &custom))
540 return;
541
542 m_explicitPrimary = true;
543 if (m_primary == primary)
544 return;
545
546 m_customPrimary = custom;
547 m_primary = primary;
548 propagatePrimary();
549 primaryChange();
550}
551
552void QQuickMaterialStyle::inheritPrimary(uint primary, bool custom)
553{
554 if (m_explicitPrimary || m_primary == primary)
555 return;
556
557 m_customPrimary = custom;
558 m_primary = primary;
559 propagatePrimary();
560 primaryChange();
561}
562
563void QQuickMaterialStyle::propagatePrimary()
564{
565 const auto styles = attachedChildren();
566 for (QQuickAttachedPropertyPropagator *child : styles) {
567 QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(object: child);
568 if (material)
569 material->inheritPrimary(primary: m_primary, custom: m_customPrimary);
570 }
571}
572
573void QQuickMaterialStyle::resetPrimary()
574{
575 if (!m_explicitPrimary)
576 return;
577
578 m_customPrimary = false;
579 m_explicitPrimary = false;
580 QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(object: attachedParent());
581 if (material)
582 inheritPrimary(primary: material->m_primary, custom: material->m_customPrimary);
583 else
584 inheritPrimary(primary: globalPrimary, custom: false);
585}
586
587void QQuickMaterialStyle::primaryChange()
588{
589 emit primaryChanged();
590 emit toolBarColorChanged();
591 emit toolTextColorChanged();
592}
593
594QVariant QQuickMaterialStyle::accent() const
595{
596 return accentColor();
597}
598
599void QQuickMaterialStyle::setAccent(const QVariant &var)
600{
601 QRgb accent = 0;
602 bool custom = false;
603 if (!variantToRgba(var, name: "accent", rgba: &accent, custom: &custom))
604 return;
605
606 m_explicitAccent = true;
607 if (m_accent == accent)
608 return;
609
610 m_customAccent = custom;
611 m_accent = accent;
612 propagateAccent();
613 accentChange();
614}
615
616void QQuickMaterialStyle::inheritAccent(uint accent, bool custom)
617{
618 if (m_explicitAccent || m_accent == accent)
619 return;
620
621 m_customAccent = custom;
622 m_accent = accent;
623 propagateAccent();
624 accentChange();
625}
626
627void QQuickMaterialStyle::propagateAccent()
628{
629 const auto styles = attachedChildren();
630 for (QQuickAttachedPropertyPropagator *child : styles) {
631 QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(object: child);
632 if (material)
633 material->inheritAccent(accent: m_accent, custom: m_customAccent);
634 }
635}
636
637void QQuickMaterialStyle::resetAccent()
638{
639 if (!m_explicitAccent)
640 return;
641
642 m_customAccent = false;
643 m_explicitAccent = false;
644 QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(object: attachedParent());
645 if (material)
646 inheritAccent(accent: material->m_accent, custom: material->m_customAccent);
647 else
648 inheritAccent(accent: globalAccent, custom: false);
649}
650
651void QQuickMaterialStyle::accentChange()
652{
653 emit accentChanged();
654 emit themeOrAccentChanged();
655}
656
657QVariant QQuickMaterialStyle::foreground() const
658{
659 if (!m_hasForeground)
660 return QColor::fromRgba(rgba: m_theme == Light ? primaryTextColorLight : primaryTextColorDark);
661 if (m_customForeground)
662 return QColor::fromRgba(rgba: m_foreground);
663 if (m_foreground > BlueGrey)
664 return QColor();
665 return QColor::fromRgba(rgba: colors[m_foreground][Shade500]);
666}
667
668void QQuickMaterialStyle::setForeground(const QVariant &var)
669{
670 QRgb foreground = 0;
671 bool custom = false;
672 if (!variantToRgba(var, name: "foreground", rgba: &foreground, custom: &custom))
673 return;
674
675 m_hasForeground = true;
676 m_explicitForeground = true;
677 if (m_foreground == foreground)
678 return;
679
680 m_customForeground = custom;
681 m_foreground = foreground;
682 propagateForeground();
683 foregroundChange();
684}
685
686void QQuickMaterialStyle::inheritForeground(uint foreground, bool custom, bool has)
687{
688 if (m_explicitForeground || m_foreground == foreground)
689 return;
690
691 m_hasForeground = has;
692 m_customForeground = custom;
693 m_foreground = foreground;
694 propagateForeground();
695 foregroundChange();
696}
697
698void QQuickMaterialStyle::propagateForeground()
699{
700 const auto styles = attachedChildren();
701 for (QQuickAttachedPropertyPropagator *child : styles) {
702 QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(object: child);
703 if (material)
704 material->inheritForeground(foreground: m_foreground, custom: m_customForeground, has: m_hasForeground);
705 }
706}
707
708void QQuickMaterialStyle::resetForeground()
709{
710 if (!m_explicitForeground)
711 return;
712
713 m_hasForeground = false;
714 m_customForeground = false;
715 m_explicitForeground = false;
716 QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(object: attachedParent());
717 inheritForeground(foreground: material ? material->m_foreground : globalForeground, custom: true, has: material ? material->m_hasForeground : false);
718}
719
720void QQuickMaterialStyle::foregroundChange()
721{
722 emit foregroundChanged();
723 emit primaryHighlightedTextColorChanged();
724 // TODO: This causes a binding loop: see QTBUG-85699 and the comments on its fix
725// emit toolTextColorChanged();
726}
727
728QVariant QQuickMaterialStyle::background() const
729{
730 return backgroundColor();
731}
732
733void QQuickMaterialStyle::setBackground(const QVariant &var)
734{
735 QRgb background = 0;
736 bool custom = false;
737 if (!variantToRgba(var, name: "background", rgba: &background, custom: &custom))
738 return;
739
740 m_hasBackground = true;
741 m_explicitBackground = true;
742 if (m_background == background)
743 return;
744
745 m_customBackground = custom;
746 m_background = background;
747 propagateBackground();
748 backgroundChange();
749}
750
751void QQuickMaterialStyle::inheritBackground(uint background, bool custom, bool has)
752{
753 if (m_explicitBackground || m_background == background)
754 return;
755
756 m_hasBackground = has;
757 m_customBackground = custom;
758 m_background = background;
759 propagateBackground();
760 backgroundChange();
761}
762
763void QQuickMaterialStyle::propagateBackground()
764{
765 const auto styles = attachedChildren();
766 for (QQuickAttachedPropertyPropagator *child : styles) {
767 QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(object: child);
768 if (material)
769 material->inheritBackground(background: m_background, custom: m_customBackground, has: m_hasBackground);
770 }
771}
772
773void QQuickMaterialStyle::resetBackground()
774{
775 if (!m_explicitBackground)
776 return;
777
778 m_hasBackground = false;
779 m_customBackground = false;
780 m_explicitBackground = false;
781 QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(object: attachedParent());
782 inheritBackground(background: material ? material->m_background : globalBackground, custom: true, has: material ? material->m_hasBackground : false);
783}
784
785void QQuickMaterialStyle::backgroundChange()
786{
787 emit backgroundChanged();
788 emit dialogColorChanged();
789 emit tooltipColorChanged();
790 emit toolBarColorChanged();
791}
792
793int QQuickMaterialStyle::elevation() const
794{
795 return m_elevation;
796}
797
798void QQuickMaterialStyle::setElevation(int elevation)
799{
800 if (m_elevation == elevation)
801 return;
802
803 m_elevation = elevation;
804 elevationChange();
805}
806
807void QQuickMaterialStyle::resetElevation()
808{
809 setElevation(0);
810}
811
812void QQuickMaterialStyle::elevationChange()
813{
814 emit elevationChanged();
815}
816
817QQuickMaterialStyle::RoundedScale QQuickMaterialStyle::roundedScale() const
818{
819 return m_roundedScale;
820}
821
822void QQuickMaterialStyle::setRoundedScale(RoundedScale roundedScale)
823{
824 if (m_roundedScale == roundedScale)
825 return;
826
827 m_roundedScale = roundedScale;
828 emit roundedScaleChanged();
829}
830
831void QQuickMaterialStyle::resetRoundedScale()
832{
833 setRoundedScale(RoundedScale::NotRounded);
834}
835
836QQuickMaterialStyle::ContainerStyle QQuickMaterialStyle::containerStyle() const
837{
838 return m_containerStyle;
839}
840
841void QQuickMaterialStyle::setContainerStyle(ContainerStyle containerStyle)
842{
843 if (m_containerStyle == containerStyle)
844 return;
845
846 m_containerStyle = containerStyle;
847 emit containerStyleChanged();
848}
849
850void QQuickMaterialStyle::resetContainerStyle()
851{
852 setContainerStyle(ContainerStyle::Filled);
853}
854
855QColor QQuickMaterialStyle::primaryColor() const
856{
857 if (m_customPrimary)
858 return QColor::fromRgba(rgba: m_primary);
859 if (m_primary > BlueGrey)
860 return QColor();
861 return colors[m_primary][Shade500];
862}
863
864QColor QQuickMaterialStyle::accentColor(Shade shade) const
865{
866 if (m_customAccent)
867 return shade == themeShade() ? QColor::fromRgba(rgba: m_accent)
868 : this->shade(color: QColor::fromRgba(rgba: m_accent), shade);
869 if (m_accent > BlueGrey)
870 return QColor();
871 return colors[m_accent][shade];
872}
873
874QColor QQuickMaterialStyle::accentColor() const
875{
876 return accentColor(shade: themeShade());
877}
878
879QColor QQuickMaterialStyle::backgroundColor(Shade shade) const
880{
881 if (!m_hasBackground)
882 return QColor::fromRgba(rgba: m_theme == Light ? backgroundColorLight : backgroundColorDark);
883 if (m_customBackground)
884 return shade == themeShade() ? QColor::fromRgba(rgba: m_background)
885 : this->shade(color: QColor::fromRgba(rgba: m_background), shade);
886 if (m_background > BlueGrey)
887 return QColor();
888 return colors[m_background][shade];
889}
890
891QColor QQuickMaterialStyle::backgroundColor() const
892{
893 return backgroundColor(shade: themeShade());
894}
895
896QColor QQuickMaterialStyle::primaryTextColor() const
897{
898 return QColor::fromRgba(rgba: m_theme == Light ? primaryTextColorLight : primaryTextColorDark);
899}
900
901QColor QQuickMaterialStyle::primaryHighlightedTextColor() const
902{
903 if (m_explicitForeground)
904 return primaryTextColor();
905 return QColor::fromRgba(rgba: primaryTextColorDark);
906}
907
908QColor QQuickMaterialStyle::secondaryTextColor() const
909{
910 return QColor::fromRgba(rgba: m_theme == Light ? secondaryTextColorLight : secondaryTextColorDark);
911}
912
913QColor QQuickMaterialStyle::hintTextColor() const
914{
915 return QColor::fromRgba(rgba: m_theme == Light ? hintTextColorLight : hintTextColorDark);
916}
917
918QColor QQuickMaterialStyle::textSelectionColor() const
919{
920 QColor color = accentColor();
921 color.setAlphaF(0.4f);
922 return color;
923}
924
925QColor QQuickMaterialStyle::dropShadowColor() const
926{
927 return QColor::fromRgba(rgba: 0x40000000);
928}
929
930QColor QQuickMaterialStyle::dividerColor() const
931{
932 return QColor::fromRgba(rgba: m_theme == Light ? dividerColorLight : dividerColorDark);
933}
934
935QColor QQuickMaterialStyle::iconColor() const
936{
937 return QColor::fromRgba(rgba: m_theme == Light ? iconColorLight : iconColorDark);
938}
939
940QColor QQuickMaterialStyle::iconDisabledColor() const
941{
942 return QColor::fromRgba(rgba: m_theme == Light ? iconDisabledColorLight : iconDisabledColorDark);
943}
944
945QColor QQuickMaterialStyle::buttonColor(Theme theme, const QVariant &background, const QVariant &accent,
946 bool enabled, bool flat, bool highlighted, bool checked) const
947{
948 if (!enabled && !flat) {
949 return QColor::fromRgba(rgba: m_theme == Light
950 ? raisedButtonDisabledColorLight : raisedButtonDisabledColorDark);
951 }
952
953 // We don't use theme (and other arguments) here even though we pass it in, as it's
954 // simpler to just re-use themeShade. We still need the arguments because they allow
955 // us to be re-called whenever they change.
956 Shade shade = themeShade();
957 Q_UNUSED(theme);
958 Q_UNUSED(background);
959 Q_UNUSED(accent);
960
961 QColor color = Qt::transparent;
962
963 if (m_explicitBackground) {
964 color = backgroundColor(shade);
965 } else if (highlighted) {
966 if (m_theme == Light) {
967 color = accentColor(shade);
968 if (checked)
969 color = color.lighter();
970 } else {
971 // A highlighted + checked button should become darker.
972 color = accentColor(shade: checked ? Shade100 : shade);
973 }
974 // Flat, highlighted buttons need to have a semi-transparent background,
975 // otherwise the text won't be visible.
976 if (flat)
977 color.setAlphaF(0.25);
978 } else if (!flat) {
979 // Even if the elevation is zero, it should still have a background if it's not flat.
980 color = QColor::fromRgba(rgba: m_theme == Light ? raisedButtonColorLight
981 : raisedButtonColorDark);
982 }
983
984 return color;
985}
986
987QColor QQuickMaterialStyle::frameColor() const
988{
989 return QColor::fromRgba(rgba: m_theme == Light ? frameColorLight : frameColorDark);
990}
991
992QColor QQuickMaterialStyle::rippleColor() const
993{
994 return QColor::fromRgba(rgba: m_theme == Light ? rippleColorLight : rippleColorDark);
995}
996
997QColor QQuickMaterialStyle::highlightedRippleColor() const
998{
999 QColor pressColor = accentColor();
1000 pressColor.setAlpha(m_theme == Light ? 30 : 50);
1001 return pressColor;
1002}
1003
1004QColor QQuickMaterialStyle::switchUncheckedTrackColor() const
1005{
1006 return QColor::fromRgba(rgba: m_theme == Light ? switchUncheckedTrackColorLight : switchUncheckedTrackColorDark);
1007}
1008
1009QColor QQuickMaterialStyle::switchCheckedTrackColor() const
1010{
1011 return accentColor(shade: m_theme == Light ? themeShade() : Shade100);
1012}
1013
1014QColor QQuickMaterialStyle::switchDisabledUncheckedTrackColor() const
1015{
1016 return QColor::fromRgba(rgba: m_theme == Light
1017 ? switchDisabledUncheckedTrackColorLight : switchDisabledUncheckedTrackColorDark);
1018}
1019
1020QColor QQuickMaterialStyle::switchDisabledCheckedTrackColor() const
1021{
1022 return QColor::fromRgba(rgba: m_theme == Light
1023 ? switchDisabledCheckedTrackColorLight : switchDisabledCheckedTrackColorDark);
1024}
1025
1026QColor QQuickMaterialStyle::switchDisabledUncheckedTrackBorderColor() const
1027{
1028 return QColor::fromRgba(rgba: m_theme == Light
1029 ? switchDisabledUncheckedTrackBorderColorLight : switchDisabledUncheckedTrackBorderColorDark);
1030}
1031
1032QColor QQuickMaterialStyle::switchUncheckedHandleColor() const
1033{
1034 return m_theme == Light ? color(color: Grey, shade: Shade600) : color(color: Grey, shade: Shade400);
1035}
1036
1037QColor QQuickMaterialStyle::switchUncheckedHoveredHandleColor() const
1038{
1039 const QColor color = switchUncheckedHandleColor();
1040 return m_theme == Light ? color.darker(f: 140) : color.lighter(f: 120);
1041}
1042
1043QColor QQuickMaterialStyle::switchCheckedHandleColor() const
1044{
1045 return m_theme == Light ? QColor::fromRgb(rgb: 0xFFFFFF) : accentColor(shade: Shade800);
1046}
1047
1048QColor QQuickMaterialStyle::switchDisabledUncheckedHandleColor() const
1049{
1050 if (m_theme == Light)
1051 return QColor::fromRgba(rgba: 0x611C1B1F);
1052
1053 QColor darkHandleColor = color(color: Grey, shade: Shade800);
1054 darkHandleColor.setAlphaF(0.38f);
1055 return darkHandleColor;
1056}
1057
1058QColor QQuickMaterialStyle::switchDisabledCheckedHandleColor() const
1059{
1060 return QColor::fromRgb(rgb: m_theme == Light ? 0xFFFBFE : 0x1C1B1F);
1061}
1062
1063QColor QQuickMaterialStyle::switchDisabledCheckedIconColor() const
1064{
1065 return QColor::fromRgba(rgba: m_theme == Light ? 0x611C1B1F : 0x61E6E1E5);
1066}
1067
1068QColor QQuickMaterialStyle::switchDisabledUncheckedIconColor() const
1069{
1070 return QColor::fromRgba(rgba: m_theme == Light
1071 ? switchDisabledUncheckedIconColorLight : switchDisabledUncheckedIconColorDark);
1072}
1073
1074QColor QQuickMaterialStyle::scrollBarColor() const
1075{
1076 return QColor::fromRgba(rgba: m_theme == Light ? 0x40000000 : 0x40FFFFFF);
1077}
1078
1079QColor QQuickMaterialStyle::scrollBarHoveredColor() const
1080{
1081 return QColor::fromRgba(rgba: m_theme == Light ? 0x60000000 : 0x60FFFFFF);
1082}
1083
1084QColor QQuickMaterialStyle::scrollBarPressedColor() const
1085{
1086 return QColor::fromRgba(rgba: m_theme == Light ? 0x80000000 : 0x80FFFFFF);
1087}
1088
1089QColor QQuickMaterialStyle::dialogColor() const
1090{
1091 if (m_hasBackground)
1092 return backgroundColor();
1093 return QColor::fromRgba(rgba: m_theme == Light ? dialogColorLight : dialogColorDark);
1094}
1095
1096QColor QQuickMaterialStyle::backgroundDimColor() const
1097{
1098 return QColor::fromRgba(rgba: m_theme == Light ? 0x99303030 : 0x99fafafa);
1099}
1100
1101QColor QQuickMaterialStyle::listHighlightColor() const
1102{
1103 return QColor::fromRgba(rgba: m_theme == Light ? 0x1e000000 : 0x1effffff);
1104}
1105
1106QColor QQuickMaterialStyle::tooltipColor() const
1107{
1108 if (m_explicitBackground)
1109 return backgroundColor();
1110 return color(color: Grey, shade: Shade700);
1111}
1112
1113QColor QQuickMaterialStyle::toolBarColor() const
1114{
1115 if (m_explicitBackground)
1116 return backgroundColor();
1117 return primaryColor();
1118}
1119
1120QColor QQuickMaterialStyle::toolTextColor() const
1121{
1122 if (m_hasForeground || m_customPrimary)
1123 return primaryTextColor();
1124
1125 switch (m_primary) {
1126 case Red:
1127 case Pink:
1128 case Purple:
1129 case DeepPurple:
1130 case Indigo:
1131 case Blue:
1132 case Teal:
1133 case DeepOrange:
1134 case Brown:
1135 case BlueGrey:
1136 return QColor::fromRgba(rgba: primaryTextColorDark);
1137
1138 case LightBlue:
1139 case Cyan:
1140 case Green:
1141 case LightGreen:
1142 case Lime:
1143 case Yellow:
1144 case Amber:
1145 case Orange:
1146 case Grey:
1147 return QColor::fromRgba(rgba: primaryTextColorLight);
1148
1149 default:
1150 break;
1151 }
1152
1153 return primaryTextColor();
1154}
1155
1156QColor QQuickMaterialStyle::spinBoxDisabledIconColor() const
1157{
1158 return QColor::fromRgba(rgba: m_theme == Light ? spinBoxDisabledIconColorLight : spinBoxDisabledIconColorDark);
1159}
1160
1161QColor QQuickMaterialStyle::sliderDisabledColor() const
1162{
1163 return QColor::fromRgba(rgba: m_theme == Light ? sliderDisabledColorLight : sliderDisabledColorDark);
1164}
1165
1166QColor QQuickMaterialStyle::textFieldFilledContainerColor() const
1167{
1168 return QColor::fromRgba(rgba: m_theme == Light ? textFieldFilledContainerColorLight : textFieldFilledContainerColorDark);
1169}
1170
1171QColor QQuickMaterialStyle::color(QQuickMaterialStyle::Color color, QQuickMaterialStyle::Shade shade) const
1172{
1173 int count = sizeof(colors) / sizeof(colors[0]);
1174 if (color < 0 || color >= count)
1175 return QColor();
1176
1177 count = sizeof(colors[0]) / sizeof(colors[0][0]);
1178 if (shade < 0 || shade >= count)
1179 return QColor();
1180
1181 return colors[color][shade];
1182}
1183
1184static QColor lighterShade(const QColor &color, qreal amount)
1185{
1186 QColor hsl = color.toHsl();
1187 hsl.setHslF(h: hsl.hueF(), s: hsl.saturationF(), l: qBound<qreal>(min: 0.0, val: hsl.lightnessF() + amount, max: 1.0), a: color.alphaF());
1188 return hsl.convertTo(colorSpec: color.spec());
1189}
1190
1191static QColor darkerShade(const QColor &color, qreal amount)
1192{
1193 QColor hsl = color.toHsl();
1194 hsl.setHslF(h: hsl.hueF(), s: hsl.saturationF(), l: qBound<qreal>(min: 0.0, val: hsl.lightnessF() - amount, max: 1.0), a: color.alphaF());
1195 return hsl.convertTo(colorSpec: color.spec());
1196}
1197
1198QQuickMaterialStyle::Shade QQuickMaterialStyle::themeShade() const
1199{
1200 return m_theme == Light ? Shade500 : Shade200;
1201}
1202
1203/*
1204 * The following lightness values originate from the Material Design Color Generator project.
1205 *
1206 * The MIT License (MIT)
1207 *
1208 * Copyright (c) 2015 mbitson
1209 *
1210 * Permission is hereby granted, free of charge, to any person obtaining a copy
1211 * of this software and associated documentation files (the "Software"), to deal
1212 * in the Software without restriction, including without limitation the rights
1213 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1214 * copies of the Software, and to permit persons to whom the Software is
1215 * furnished to do so, subject to the following conditions:
1216 *
1217 * The above copyright notice and this permission notice shall be included in all
1218 * copies or substantial portions of the Software.
1219 *
1220 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1221 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1222 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1223 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1224 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1225 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1226 * SOFTWARE.
1227 */
1228
1229// Returns the same color, if shade == themeShade()
1230QColor QQuickMaterialStyle::shade(const QColor &color, Shade shade) const
1231{
1232 switch (shade) {
1233 case Shade50:
1234 return lighterShade(color, amount: m_theme == Light ? 0.52 : 0.26);
1235 case Shade100:
1236 return lighterShade(color, amount: m_theme == Light ? 0.37 : 0.11);
1237 case Shade200:
1238 return m_theme == Light ? lighterShade(color, amount: 0.26) : color;
1239 case Shade300:
1240 return m_theme == Light ? lighterShade(color, amount: 0.12) : darkerShade(color, amount: 0.14);
1241 case Shade400:
1242 return m_theme == Light ? lighterShade(color, amount: 0.06) : darkerShade(color, amount: 0.20);
1243 case Shade500:
1244 return m_theme == Light ? color : darkerShade(color, amount: 0.26);
1245 case Shade600:
1246 return darkerShade(color, amount: m_theme == Light ? 0.06 : 0.32);
1247 case Shade700:
1248 return darkerShade(color, amount: m_theme == Light ? 0.12 : 0.38);
1249 case Shade800:
1250 return darkerShade(color, amount: m_theme == Light ? 0.18 : 0.44);
1251 case Shade900:
1252 return darkerShade(color, amount: m_theme == Light ? 0.24 : 0.50);
1253 case ShadeA100:
1254 return lighterShade(color, amount: m_theme == Light ? 0.54 : 0.28);
1255 case ShadeA200:
1256 return lighterShade(color, amount: m_theme == Light ? 0.37 : 0.11);
1257 case ShadeA400:
1258 return m_theme == Light ? lighterShade(color, amount: 0.06) : darkerShade(color, amount: 0.20);
1259 case ShadeA700:
1260 return darkerShade(color, amount: m_theme == Light ? 0.12 : 0.38);
1261 default:
1262 Q_UNREACHABLE_RETURN(QColor());
1263 }
1264}
1265
1266int QQuickMaterialStyle::touchTarget() const
1267{
1268 // https://material.io/guidelines/components/buttons.html#buttons-style
1269 return globalVariant == Dense ? 44 : 48;
1270}
1271
1272int QQuickMaterialStyle::buttonHeight() const
1273{
1274 // https://m3.material.io/components/buttons/specs#256326ad-f934-40e7-b05f-0bcb41aa4382
1275 return globalVariant == Dense ? 32 : 40;
1276}
1277
1278int QQuickMaterialStyle::delegateHeight() const
1279{
1280 // https://material.io/guidelines/components/lists.html#lists-specs
1281 return globalVariant == Dense ? 40 : 48;
1282}
1283
1284int QQuickMaterialStyle::dialogButtonBoxHeight() const
1285{
1286 return globalVariant == Dense ? 48 : 52;
1287}
1288
1289int QQuickMaterialStyle::frameVerticalPadding() const
1290{
1291 return globalVariant == Dense ? 8 : 12;
1292}
1293
1294int QQuickMaterialStyle::menuItemHeight() const
1295{
1296 // https://material.io/guidelines/components/menus.html#menus-simple-menus
1297 return globalVariant == Dense ? 32 : 48;
1298}
1299
1300int QQuickMaterialStyle::menuItemVerticalPadding() const
1301{
1302 return globalVariant == Dense ? 8 : 12;
1303}
1304
1305int QQuickMaterialStyle::switchIndicatorWidth() const
1306{
1307 return globalVariant == Dense ? 40 : 52;
1308}
1309
1310int QQuickMaterialStyle::switchIndicatorHeight() const
1311{
1312 return globalVariant == Dense ? 22 : 32;
1313}
1314
1315int QQuickMaterialStyle::switchNormalHandleHeight() const
1316{
1317 return globalVariant == Dense ? 10 : 16;
1318}
1319
1320int QQuickMaterialStyle::switchCheckedHandleHeight() const
1321{
1322 return globalVariant == Dense ? 16 : 24;
1323}
1324
1325int QQuickMaterialStyle::switchLargestHandleHeight() const
1326{
1327 return globalVariant == Dense ? 18 : 28;
1328}
1329
1330int QQuickMaterialStyle::switchDelegateVerticalPadding() const
1331{
1332 // SwitchDelegate's indicator is much larger than the others due to the shadow,
1333 // so we must reduce its padding to ensure its implicitHeight is 40 when dense.
1334 return globalVariant == Dense ? 4 : 8;
1335}
1336
1337int QQuickMaterialStyle::textFieldHeight() const
1338{
1339 // filled: https://m3.material.io/components/text-fields/specs#8c032848-e442-46df-b25d-28f1315f234b
1340 // outlined: https://m3.material.io/components/text-fields/specs#605e24f1-1c1f-4c00-b385-4bf50733a5ef
1341 return globalVariant == Dense ? 44 : 56;
1342}
1343int QQuickMaterialStyle::textFieldHorizontalPadding() const
1344{
1345 return globalVariant == Dense ? 12 : 16;
1346}
1347int QQuickMaterialStyle::textFieldVerticalPadding() const
1348{
1349 return globalVariant == Dense ? 4 : 8;
1350}
1351
1352int QQuickMaterialStyle::tooltipHeight() const
1353{
1354 // https://material.io/guidelines/components/tooltips.html
1355 return globalVariant == Dense ? 22 : 32;
1356}
1357
1358QQuickMaterialStyle::Variant QQuickMaterialStyle::variant()
1359{
1360 return globalVariant;
1361}
1362
1363template <typename Enum>
1364static Enum toEnumValue(const QByteArray &value, bool *ok)
1365{
1366 QMetaEnum enumeration = QMetaEnum::fromType<Enum>();
1367 return static_cast<Enum>(enumeration.keyToValue(key: value, ok));
1368}
1369
1370static QByteArray resolveSetting(const QByteArray &env, const QSharedPointer<QSettings> &settings, const QString &name)
1371{
1372 QByteArray value = qgetenv(varName: env);
1373#if QT_CONFIG(settings)
1374 if (value.isNull() && !settings.isNull())
1375 value = settings->value(key: name).toByteArray();
1376#endif
1377 return value;
1378}
1379
1380void QQuickMaterialStyle::initGlobals()
1381{
1382 QSharedPointer<QSettings> settings = QQuickStylePrivate::settings(QStringLiteral("Material"));
1383
1384 bool ok = false;
1385 QByteArray themeValue = resolveSetting(env: "QT_QUICK_CONTROLS_MATERIAL_THEME", settings, QStringLiteral("Theme"));
1386 Theme themeEnum = toEnumValue<Theme>(value: themeValue, ok: &ok);
1387 if (ok)
1388 globalTheme = effectiveTheme(theme: themeEnum);
1389 else if (!themeValue.isEmpty())
1390 qWarning().nospace().noquote() << "Material: unknown theme value: " << themeValue;
1391
1392 QByteArray variantValue = resolveSetting(env: "QT_QUICK_CONTROLS_MATERIAL_VARIANT", settings, QStringLiteral("Variant"));
1393 Variant variantEnum = toEnumValue<Variant>(value: variantValue, ok: &ok);
1394 if (ok)
1395 globalVariant = variantEnum;
1396 else if (!variantValue.isEmpty())
1397 qWarning().nospace().noquote() << "Material: unknown variant value: " << variantValue;
1398
1399 QByteArray primaryValue = resolveSetting(env: "QT_QUICK_CONTROLS_MATERIAL_PRIMARY", settings, QStringLiteral("Primary"));
1400 Color primaryEnum = toEnumValue<Color>(value: primaryValue, ok: &ok);
1401 if (ok) {
1402 globalPrimaryCustom = false;
1403 globalPrimary = primaryEnum;
1404 } else {
1405 QColor color = QColor::fromString(name: primaryValue);
1406 if (color.isValid()) {
1407 globalPrimaryCustom = true;
1408 globalPrimary = color.rgba();
1409 } else if (!primaryValue.isEmpty()) {
1410 qWarning().nospace().noquote() << "Material: unknown primary value: " << primaryValue;
1411 }
1412 }
1413
1414 QByteArray accentValue = resolveSetting(env: "QT_QUICK_CONTROLS_MATERIAL_ACCENT", settings, QStringLiteral("Accent"));
1415 Color accentEnum = toEnumValue<Color>(value: accentValue, ok: &ok);
1416 if (ok) {
1417 globalAccentCustom = false;
1418 globalAccent = accentEnum;
1419 } else if (!accentValue.isEmpty()) {
1420 QColor color = QColor::fromString(name: accentValue);
1421 if (color.isValid()) {
1422 globalAccentCustom = true;
1423 globalAccent = color.rgba();
1424 } else {
1425 qWarning().nospace().noquote() << "Material: unknown accent value: " << accentValue;
1426 }
1427 }
1428
1429 QByteArray foregroundValue = resolveSetting(env: "QT_QUICK_CONTROLS_MATERIAL_FOREGROUND", settings, QStringLiteral("Foreground"));
1430 Color foregroundEnum = toEnumValue<Color>(value: foregroundValue, ok: &ok);
1431 if (ok) {
1432 globalForegroundCustom = false;
1433 globalForeground = foregroundEnum;
1434 hasGlobalForeground = true;
1435 } else if (!foregroundValue.isEmpty()) {
1436 QColor color = QColor::fromString(name: foregroundValue);
1437 if (color.isValid()) {
1438 globalForegroundCustom = true;
1439 globalForeground = color.rgba();
1440 hasGlobalForeground = true;
1441 } else {
1442 qWarning().nospace().noquote() << "Material: unknown foreground value: " << foregroundValue;
1443 }
1444 }
1445
1446 QByteArray backgroundValue = resolveSetting(env: "QT_QUICK_CONTROLS_MATERIAL_BACKGROUND", settings, QStringLiteral("Background"));
1447 Color backgroundEnum = toEnumValue<Color>(value: backgroundValue, ok: &ok);
1448 if (ok) {
1449 globalBackgroundCustom = false;
1450 globalBackground = backgroundEnum;
1451 hasGlobalBackground = true;
1452 } else if (!backgroundValue.isEmpty()) {
1453 QColor color = QColor::fromString(name: backgroundValue);
1454 if (color.isValid()) {
1455 globalBackgroundCustom = true;
1456 globalBackground = color.rgba();
1457 hasGlobalBackground = true;
1458 } else {
1459 qWarning().nospace().noquote() << "Material: unknown background value: " << backgroundValue;
1460 }
1461 }
1462}
1463
1464void QQuickMaterialStyle::attachedParentChange(QQuickAttachedPropertyPropagator *newParent, QQuickAttachedPropertyPropagator *oldParent)
1465{
1466 Q_UNUSED(oldParent);
1467 QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(object: newParent);
1468 if (material) {
1469 inheritPrimary(primary: material->m_primary, custom: material->m_customPrimary);
1470 inheritAccent(accent: material->m_accent, custom: material->m_customAccent);
1471 inheritForeground(foreground: material->m_foreground, custom: material->m_customForeground, has: material->m_hasForeground);
1472 inheritBackground(background: material->m_background, custom: material->m_customBackground, has: material->m_hasBackground);
1473 inheritTheme(theme: material->theme());
1474 }
1475}
1476
1477bool QQuickMaterialStyle::variantToRgba(const QVariant &var, const char *name, QRgb *rgba, bool *custom) const
1478{
1479 *custom = false;
1480 if (var.metaType().id() == QMetaType::Int) {
1481 int val = var.toInt();
1482 if (val > BlueGrey) {
1483 qmlWarning(me: parent()) << "unknown Material." << name << " value: " << val;
1484 return false;
1485 }
1486 *rgba = val;
1487 } else {
1488 int val = QMetaEnum::fromType<Color>().keyToValue(key: var.toByteArray());
1489 if (val != -1) {
1490 *rgba = val;
1491 } else {
1492 QColor color = QColor::fromString(name: var.toString());
1493 if (!color.isValid()) {
1494 qmlWarning(me: parent()) << "unknown Material." << name << " value: " << var.toString();
1495 return false;
1496 }
1497 *custom = true;
1498 *rgba = color.rgba();
1499 }
1500 }
1501 return true;
1502}
1503
1504QT_END_NAMESPACE
1505
1506#include "moc_qquickmaterialstyle_p.cpp"
1507

source code of qtdeclarative/src/quickcontrols/material/qquickmaterialstyle.cpp