8#include <QtCore/qdir.h>
9#include <QtCore/qfile.h>
10#include <QtCore/qdebug.h>
11#if QT_CONFIG(settings)
12#include <QtCore/qsettings.h>
14#include <QtCore/qfileselector.h>
15#include <QtCore/qlibraryinfo.h>
16#include <QtCore/qloggingcategory.h>
17#include <QtCore/qmetaobject.h>
18#include <QtGui/qcolor.h>
19#include <QtGui/qfont.h>
20#include <QtGui/qpalette.h>
21#include <QtGui/private/qguiapplication_p.h>
22#include <QtGui/qpa/qplatformtheme.h>
23#include <QtQml/private/qqmlmetatype_p.h>
24#include <QtQml/qqmlengine.h>
25#include <QtQml/qqmlfile.h>
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
89 return style.mid(style.lastIndexOf(QLatin1Char(
'/')) + 1);
97 if (QQmlFile::isLocalFile(s))
98 s = QQmlFile::urlToLocalFileOrQrc(s);
99 return s.left(s.lastIndexOf(QLatin1Char(
'/')) + 1);
104 qCDebug(lcQtQuickControlsStyle) <<
"style" << s <<
"set on QQuickStyleSpec";
105 if (s.contains(QLatin1Char(
'/'))) {
106 qWarning() <<
"Style names must not contain paths; see the \"Definition of a Style\" documentation for more information";
110 qCDebug(lcQtQuickControlsStyle) <<
"clearing resolved flag and resolving";
118 if (!fallback.isEmpty())
119 qCDebug(lcQtQuickControlsStyle) <<
"fallback style" << fallback <<
"set on QQuickStyleSpec via" << method;
121 fallbackStyle = fallback;
122 fallbackMethod = method;
127 qCDebug(lcQtQuickControlsStyle) <<
"resolving style";
130 style = QGuiApplicationPrivate::styleOverride;
132 style = QString::fromLocal8Bit(qgetenv(
"QT_QUICK_CONTROLS_STYLE"));
133 if (fallbackStyle.isEmpty())
134 setFallbackStyle(QString::fromLocal8Bit(qgetenv(
"QT_QUICK_CONTROLS_FALLBACK_STYLE")),
"QT_QUICK_CONTROLS_FALLBACK_STYLE");
135#if QT_CONFIG(settings)
136 if (style.isEmpty() || fallbackStyle.isEmpty()) {
137 QSharedPointer<QSettings> settings = QQuickStylePrivate::settings(QStringLiteral(
"Controls"));
140 style = settings->value(QStringLiteral(
"Style")).toString();
141 if (fallbackStyle.isEmpty())
142 setFallbackStyle(settings->value(QStringLiteral(
"FallbackStyle")).toString(),
":/qtquickcontrols2.conf");
147 auto builtInStyleList = QQuickStylePrivate::builtInStyles();
148 if (!fallbackStyle.isEmpty() && !builtInStyleList.contains(fallbackStyle)) {
149 qWarning().nospace().noquote() << fallbackMethod <<
": the specified fallback style \"" <<
150 fallbackStyle <<
"\" is not one of the built-in Qt Quick Controls 2 styles";
151 fallbackStyle.clear();
155 resolveConfigFilePath();
159 if (style.isEmpty() || style.toLower() == QStringLiteral(
"default")) {
163 qCDebug(lcQtQuickControlsStyle) <<
"no style (or Default) was specified;"
164 <<
"checking if we have an appropriate style for this platform";
168#if defined(Q_OS_MACOS)
169 style = QLatin1String(
"macOS");
170#elif defined(Q_OS_WINDOWS)
171 style = QLatin1String(
"Windows");
172#elif defined(Q_OS_ANDROID)
173 style = QLatin1String(
"Material");
174#elif defined(Q_OS_LINUX)
175 style = QLatin1String(
"Fusion");
176#elif defined(Q_OS_IOS)
177 style = QLatin1String(
"iOS");
179 if (!style.isEmpty())
180 qCDebug(lcQtQuickControlsStyle) <<
"using" << style <<
"as a default";
182 qCDebug(lcQtQuickControlsStyle) <<
"no appropriate style found; using Basic as a default";
188 custom = !builtInStyleList.contains(QQuickStylePrivate::effectiveStyleName(style));
192 qCDebug(lcQtQuickControlsStyle).nospace() <<
"done resolving:"
193 <<
"\n style=" << style
194 <<
"\n custom=" << custom
195 <<
"\n resolved=" << resolved
196 <<
"\n fallbackStyle=" << fallbackStyle
197 <<
"\n fallbackMethod=" << fallbackMethod
198 <<
"\n configFilePath=" << configFilePath;
203 qCDebug(lcQtQuickControlsStyle) <<
"resetting values to their defaults";
209 fallbackStyle.clear();
210 fallbackMethod.clear();
211 configFilePath.clear();
216 if (configFilePath.isEmpty()) {
217 configFilePath = QFile::decodeName(qgetenv(
"QT_QUICK_CONTROLS_CONF"));
218 if (configFilePath.isEmpty() || !QFile::exists(configFilePath)) {
219 if (!configFilePath.isEmpty())
220 qWarning(
"QT_QUICK_CONTROLS_CONF=%s: No such file", qPrintable(configFilePath));
222 configFilePath = QStringLiteral(
":/qtquickcontrols2.conf");
225 return configFilePath;
244Q_GLOBAL_STATIC(QQuickStyleSpec, styleSpec)
247
248
249
250
251QString QQuickStylePrivate::style()
253 return styleSpec()->style;
256QString QQuickStylePrivate::effectiveStyleName(
const QString &styleName)
258 return !styleName.isEmpty() ? styleName : QLatin1String(
"Basic");
261QString QQuickStylePrivate::fallbackStyle()
263 return styleSpec()->fallbackStyle;
266bool QQuickStylePrivate::isCustomStyle()
268 return styleSpec()->custom;
271bool QQuickStylePrivate::isResolved()
273 return styleSpec()->resolved;
276bool QQuickStylePrivate::isUsingDefaultStyle()
278 return styleSpec()->usingDefaultStyle;
281void QQuickStylePrivate::init()
283 QQuickStyleSpec *spec = styleSpec();
287void QQuickStylePrivate::reset()
290 styleSpec()->reset();
293QString QQuickStylePrivate::configFilePath()
295 return styleSpec()->resolveConfigFilePath();
298QSharedPointer<QSettings> QQuickStylePrivate::settings(
const QString &group)
300#ifndef QT_NO_SETTINGS
301 const QString filePath = QQuickStylePrivate::configFilePath();
302 if (QFile::exists(filePath)) {
303 QFileSelector selector;
304 QSettings *settings =
new QSettings(selector.select(filePath), QSettings::IniFormat);
305 if (!group.isEmpty())
306 settings->beginGroup(group);
307 return QSharedPointer<QSettings>(settings);
311 return QSharedPointer<QSettings>();
314#if QT_CONFIG(settings)
315static void readValue(
const QSharedPointer<QSettings> &settings,
const QString &name, std::function<
void(
const QVariant &)> setValue)
317 const QVariant var = settings->value(name);
322template <
typename Enum>
323static Enum toEnumValue(
const QVariant &var)
333 return static_cast<Enum>(var.toInt());
336const QFont *QQuickStylePrivate::readFont(
const QSharedPointer<QSettings> &settings)
338 const QVariant var = settings->value(QStringLiteral(
"Font"));
340 return new QFont(var.value<QFont>());
343 settings->beginGroup(QStringLiteral(
"Font"));
344 readValue(settings, QStringLiteral(
"Family"), [&f](
const QVariant &var) { f.setFamilies(QStringList{var.toString()}); });
345 readValue(settings, QStringLiteral(
"PointSize"), [&f](
const QVariant &var) { f.setPointSizeF(var.toReal()); });
346 readValue(settings, QStringLiteral(
"PixelSize"), [&f](
const QVariant &var) { f.setPixelSize(var.toInt()); });
347 readValue(settings, QStringLiteral(
"StyleHint"), [&f](
const QVariant &var) { f.setStyleHint(toEnumValue<QFont::StyleHint>(var.toInt())); });
348 readValue(settings, QStringLiteral(
"Weight"), [&f](
const QVariant &var) { f.setWeight(toEnumValue<QFont::Weight>(var)); });
349 readValue(settings, QStringLiteral(
"Style"), [&f](
const QVariant &var) { f.setStyle(toEnumValue<QFont::Style>(var.toInt())); });
350 settings->endGroup();
354static void readColorGroup(
const QSharedPointer<QSettings> &settings, QPalette::ColorGroup group, QPalette *palette)
356 const QStringList keys = settings->childKeys();
360 static const int index = QPalette::staticMetaObject.indexOfEnumerator(
"ColorRole");
361 Q_ASSERT(index != -1);
362 QMetaEnum metaEnum = QPalette::staticMetaObject.enumerator(index);
364 for (
const QString &key : keys) {
366 int role = metaEnum.keyToValue(key.toUtf8(), &ok);
368 palette->setColor(group,
static_cast<QPalette::ColorRole>(role), settings->value(key).value<QColor>());
372const QPalette *QQuickStylePrivate::readPalette(
const QSharedPointer<QSettings> &settings)
375 settings->beginGroup(QStringLiteral(
"Palette"));
376 readColorGroup(settings, QPalette::All, &p);
378 settings->beginGroup(QStringLiteral(
"Normal"));
379 readColorGroup(settings, QPalette::Normal, &p);
380 settings->endGroup();
382 settings->beginGroup(QStringLiteral(
"Disabled"));
383 readColorGroup(settings, QPalette::Disabled, &p);
384 settings->endGroup();
385 return new QPalette(p);
389bool QQuickStylePrivate::isDarkSystemTheme()
391 const bool dark = [](){
392 if (
const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
393 if (theme->colorScheme() == Qt::ColorScheme::Unknown)
394 return theme->palette()->windowText().color().lightnessF() > theme->palette()->window().color().lightnessF();
395 return theme->colorScheme() == Qt::ColorScheme::Dark;
402QStringList QQuickStylePrivate::builtInStyles()
405 QLatin1String(
"Basic"),
406 QLatin1String(
"Fusion"),
407 QLatin1String(
"FluentWinUI3"),
408 QLatin1String(
"Imagine"),
410 QLatin1String(
"macOS"),
411 QLatin1String(
"iOS"),
414 QLatin1String(
"iOS"),
416 QLatin1String(
"Material"),
417 QLatin1String(
"Universal"),
419 QLatin1String(
"Windows")
425
426
427
428
429
430
431QString QQuickStyle::name()
433 return styleSpec()->name();
437
438
439
440
441
442
443
444void QQuickStyle::setStyle(
const QString &style)
446 qCDebug(lcQtQuickControlsStyle) <<
"setStyle called with" << style;
448 if (QQmlMetaType::matchingModuleVersion(
449 QStringLiteral(
"QtQuick.Controls"), QTypeRevision::fromVersion(2, 0)).isValid()) {
450 qWarning() <<
"ERROR: QQuickStyle::setStyle() must be called before loading QML that imports Qt Quick Controls 2.";
454 styleSpec()->setStyle(style);
458
459
460
461
462
463
464
465
466
467
468
469
470
471void QQuickStyle::setFallbackStyle(
const QString &style)
473 if (QQmlMetaType::matchingModuleVersion(
474 QStringLiteral(
"QtQuick.Controls"), QTypeRevision::fromVersion(2, 0)).isValid()) {
475 qWarning() <<
"ERROR: QQuickStyle::setFallbackStyle() must be called before loading QML that imports Qt Quick Controls 2.";
479 styleSpec()->setFallbackStyle(style,
"QQuickStyle::setFallbackStyle()");
Q_STATIC_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core")
QByteArray fallbackMethod
void setFallbackStyle(const QString &fallback, const QByteArray &method)
QString resolveConfigFilePath()
void setStyle(const QString &s)