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