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>
27#include <QtCore/qtyperevision.h>
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
80
81
91 return style.mid(style.lastIndexOf(QLatin1Char(
'/')) + 1);
99 if (QQmlFile::isLocalFile(s))
100 s = QQmlFile::urlToLocalFileOrQrc(s);
101 return s.left(s.lastIndexOf(QLatin1Char(
'/')) + 1);
106 qCDebug(lcQtQuickControlsStyle) <<
"style" << s <<
"set on QQuickStyleSpec";
107 if (s.contains(QLatin1Char(
'/'))) {
108 qWarning() <<
"Style names must not contain paths; see the \"Definition of a Style\" documentation for more information";
112 qCDebug(lcQtQuickControlsStyle) <<
"clearing resolved flag and resolving";
120 if (!fallback.isEmpty())
121 qCDebug(lcQtQuickControlsStyle) <<
"fallback style" << fallback <<
"set on QQuickStyleSpec via" << method;
123 fallbackStyle = fallback;
124 fallbackMethod = method;
129 qCDebug(lcQtQuickControlsStyle) <<
"resolving style";
132 style = QGuiApplicationPrivate::styleOverride;
134 style = QString::fromLocal8Bit(qgetenv(
"QT_QUICK_CONTROLS_STYLE"));
135 if (fallbackStyle.isEmpty())
136 setFallbackStyle(QString::fromLocal8Bit(qgetenv(
"QT_QUICK_CONTROLS_FALLBACK_STYLE")),
"QT_QUICK_CONTROLS_FALLBACK_STYLE");
137#if QT_CONFIG(settings)
138 if (style.isEmpty() || fallbackStyle.isEmpty()) {
139 QSharedPointer<QSettings> settings = QQuickStylePrivate::settings(QStringLiteral(
"Controls"));
142 style = settings->value(QStringLiteral(
"Style")).toString();
143 if (fallbackStyle.isEmpty())
144 setFallbackStyle(settings->value(QStringLiteral(
"FallbackStyle")).toString(),
":/qtquickcontrols2.conf");
149 auto builtInStyleList = QQuickStylePrivate::builtInStyles();
150 if (!fallbackStyle.isEmpty() && !builtInStyleList.contains(fallbackStyle)) {
151 qWarning().nospace().noquote() << fallbackMethod <<
": the specified fallback style \"" <<
152 fallbackStyle <<
"\" is not one of the built-in Qt Quick Controls 2 styles";
153 fallbackStyle.clear();
157 resolveConfigFilePath();
161 if (style.isEmpty() || style.toLower() == QStringLiteral(
"default")) {
165 qCDebug(lcQtQuickControlsStyle) <<
"no style (or Default) was specified;"
166 <<
"checking if we have an appropriate style for this platform";
170#if defined(Q_OS_MACOS)
171 style = QLatin1String(
"macOS");
172#elif defined(Q_OS_WINDOWS)
173 style = QLatin1String(
"Windows");
174#elif defined(Q_OS_ANDROID)
175 style = QLatin1String(
"Material");
176#elif defined(Q_OS_LINUX)
177 style = QLatin1String(
"Fusion");
178#elif defined(Q_OS_IOS)
179 style = QLatin1String(
"iOS");
181 if (!style.isEmpty())
182 qCDebug(lcQtQuickControlsStyle) <<
"using" << style <<
"as a default";
184 qCDebug(lcQtQuickControlsStyle) <<
"no appropriate style found; using Basic as a default";
190 custom = !builtInStyleList.contains(QQuickStylePrivate::effectiveStyleName(style));
194 qCDebug(lcQtQuickControlsStyle).nospace() <<
"done resolving:"
195 <<
"\n style=" << style
196 <<
"\n custom=" << custom
197 <<
"\n resolved=" << resolved
198 <<
"\n fallbackStyle=" << fallbackStyle
199 <<
"\n fallbackMethod=" << fallbackMethod
200 <<
"\n configFilePath=" << configFilePath;
205 qCDebug(lcQtQuickControlsStyle) <<
"resetting values to their defaults";
211 fallbackStyle.clear();
212 fallbackMethod.clear();
213 configFilePath.clear();
218 if (configFilePath.isEmpty()) {
219 configFilePath = QFile::decodeName(qgetenv(
"QT_QUICK_CONTROLS_CONF"));
220 if (configFilePath.isEmpty() || !QFile::exists(configFilePath)) {
221 if (!configFilePath.isEmpty())
222 qWarning(
"QT_QUICK_CONTROLS_CONF=%s: No such file", qPrintable(configFilePath));
224 configFilePath = QStringLiteral(
":/qtquickcontrols2.conf");
227 return configFilePath;
246Q_GLOBAL_STATIC(QQuickStyleSpec, styleSpec)
249
250
251
252
253QString QQuickStylePrivate::style()
255 return styleSpec()->style;
258QString QQuickStylePrivate::effectiveStyleName(
const QString &styleName)
260 return !styleName.isEmpty() ? styleName : QLatin1String(
"Basic");
263QString QQuickStylePrivate::fallbackStyle()
265 return styleSpec()->fallbackStyle;
268bool QQuickStylePrivate::isCustomStyle()
270 return styleSpec()->custom;
273bool QQuickStylePrivate::isResolved()
275 return styleSpec()->resolved;
278bool QQuickStylePrivate::isUsingDefaultStyle()
280 return styleSpec()->usingDefaultStyle;
283void QQuickStylePrivate::init()
285 QQuickStyleSpec *spec = styleSpec();
289void QQuickStylePrivate::reset()
292 styleSpec()->reset();
295QString QQuickStylePrivate::configFilePath()
297 return styleSpec()->resolveConfigFilePath();
300QSharedPointer<QSettings> QQuickStylePrivate::settings(
const QString &group)
302#ifndef QT_NO_SETTINGS
303 const QString filePath = QQuickStylePrivate::configFilePath();
304 if (QFile::exists(filePath)) {
305 QFileSelector selector;
306 QSettings *settings =
new QSettings(selector.select(filePath), QSettings::IniFormat);
307 if (!group.isEmpty())
308 settings->beginGroup(group);
309 return QSharedPointer<QSettings>(settings);
313 return QSharedPointer<QSettings>();
316#if QT_CONFIG(settings)
317static void readValue(
const QSharedPointer<QSettings> &settings,
const QString &name, std::function<
void(
const QVariant &)> setValue)
319 const QVariant var = settings->value(name);
324template <
typename Enum>
325static Enum toEnumValue(
const QVariant &var)
335 return static_cast<Enum>(var.toInt());
338const QFont *QQuickStylePrivate::readFont(
const QSharedPointer<QSettings> &settings)
340 const QVariant var = settings->value(QStringLiteral(
"Font"));
342 return new QFont(var.value<QFont>());
345 settings->beginGroup(QStringLiteral(
"Font"));
346 readValue(settings, QStringLiteral(
"Family"), [&f](
const QVariant &var) { f.setFamilies(QStringList{var.toString()}); });
347 readValue(settings, QStringLiteral(
"PointSize"), [&f](
const QVariant &var) { f.setPointSizeF(var.toReal()); });
348 readValue(settings, QStringLiteral(
"PixelSize"), [&f](
const QVariant &var) { f.setPixelSize(var.toInt()); });
349 readValue(settings, QStringLiteral(
"StyleHint"), [&f](
const QVariant &var) { f.setStyleHint(toEnumValue<QFont::StyleHint>(var.toInt())); });
350 readValue(settings, QStringLiteral(
"Weight"), [&f](
const QVariant &var) { f.setWeight(toEnumValue<QFont::Weight>(var)); });
351 readValue(settings, QStringLiteral(
"Style"), [&f](
const QVariant &var) { f.setStyle(toEnumValue<QFont::Style>(var.toInt())); });
352 settings->endGroup();
356static void readColorGroup(
const QSharedPointer<QSettings> &settings, QPalette::ColorGroup group, QPalette *palette)
358 const QStringList keys = settings->childKeys();
362 static const int index = QPalette::staticMetaObject.indexOfEnumerator(
"ColorRole");
363 Q_ASSERT(index != -1);
364 QMetaEnum metaEnum = QPalette::staticMetaObject.enumerator(index);
366 for (
const QString &key : keys) {
368 int role = metaEnum.keyToValue(key.toUtf8(), &ok);
370 palette->setColor(group,
static_cast<QPalette::ColorRole>(role), settings->value(key).value<QColor>());
374const QPalette *QQuickStylePrivate::readPalette(
const QSharedPointer<QSettings> &settings)
377 settings->beginGroup(QStringLiteral(
"Palette"));
378 readColorGroup(settings, QPalette::All, &p);
380 settings->beginGroup(QStringLiteral(
"Normal"));
381 readColorGroup(settings, QPalette::Normal, &p);
382 settings->endGroup();
384 settings->beginGroup(QStringLiteral(
"Disabled"));
385 readColorGroup(settings, QPalette::Disabled, &p);
386 settings->endGroup();
387 return new QPalette(p);
391bool QQuickStylePrivate::isDarkSystemTheme()
393 const bool dark = [](){
394 if (
const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
395 if (theme->colorScheme() == Qt::ColorScheme::Unknown)
396 return theme->palette()->windowText().color().lightnessF() > theme->palette()->window().color().lightnessF();
397 return theme->colorScheme() == Qt::ColorScheme::Dark;
404QStringList QQuickStylePrivate::builtInStyles()
407 QLatin1String(
"Basic"),
408 QLatin1String(
"Fusion"),
409 QLatin1String(
"FluentWinUI3"),
410 QLatin1String(
"Imagine"),
412 QLatin1String(
"macOS"),
413 QLatin1String(
"iOS"),
416 QLatin1String(
"iOS"),
418 QLatin1String(
"Material"),
419 QLatin1String(
"Universal"),
421 QLatin1String(
"Windows")
427
428
429
430
431
432
433QString QQuickStyle::name()
435 return styleSpec()->name();
439
440
441
442
443
444
445
446void QQuickStyle::setStyle(
const QString &style)
448 qCDebug(lcQtQuickControlsStyle) <<
"setStyle called with" << style;
450 if (QQmlMetaType::matchingModuleVersion(
451 QStringLiteral(
"QtQuick.Controls"), QTypeRevision::fromVersion(2, 0)).isValid()) {
452 qWarning() <<
"ERROR: QQuickStyle::setStyle() must be called before loading QML that imports Qt Quick Controls 2.";
456 styleSpec()->setStyle(style);
460
461
462
463
464
465
466
467
468
469
470
471
472
473void QQuickStyle::setFallbackStyle(
const QString &style)
475 if (QQmlMetaType::matchingModuleVersion(
476 QStringLiteral(
"QtQuick.Controls"), QTypeRevision::fromVersion(2, 0)).isValid()) {
477 qWarning() <<
"ERROR: QQuickStyle::setFallbackStyle() must be called before loading QML that imports Qt Quick Controls 2.";
481 styleSpec()->setFallbackStyle(style,
"QQuickStyle::setFallbackStyle()");
QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcSynthesizedIterableAccess, "qt.iterable.synthesized", QtWarningMsg)
QByteArray fallbackMethod
void setFallbackStyle(const QString &fallback, const QByteArray &method)
QString resolveConfigFilePath()
void setStyle(const QString &s)