Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qquickstyle.cpp
Go to the documentation of this file.
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 "qquickstyle.h"
5#include "qquickstyle_p.h"
6
7#include <QtCore/qdir.h>
8#include <QtCore/qfile.h>
9#include <QtCore/qdebug.h>
10#if QT_CONFIG(settings)
11#include <QtCore/qsettings.h>
12#endif
13#include <QtCore/qfileselector.h>
14#include <QtCore/qlibraryinfo.h>
15#include <QtCore/qloggingcategory.h>
16#include <QtCore/qmetaobject.h>
17#include <QtGui/qcolor.h>
18#include <QtGui/qfont.h>
19#include <QtGui/qpalette.h>
20#include <QtGui/private/qguiapplication_p.h>
21#include <QtGui/qpa/qplatformtheme.h>
22#include <QtQml/private/qqmlmetatype_p.h>
23#include <QtQml/qqmlengine.h>
24#include <QtQml/qqmlfile.h>
25
26#include <functional>
27
29
30Q_LOGGING_CATEGORY(lcQtQuickControlsStyle, "qt.quick.controls.style")
31
32
81{
83
85 {
86 if (!resolved)
87 resolve();
88 return style.mid(style.lastIndexOf(QLatin1Char('/')) + 1);
89 }
90
92 {
93 if (!resolved)
94 resolve();
95 QString s = style;
98 return s.left(s.lastIndexOf(QLatin1Char('/')) + 1);
99 }
100
101 void setStyle(const QString &s)
102 {
103 qCDebug(lcQtQuickControlsStyle) << "style" << s << "set on QQuickStyleSpec";
104 if (s.contains(QLatin1Char('/'))) {
105 qWarning() << "Style names must not contain paths; see the \"Definition of a Style\" documentation for more information";
106 return;
107 }
108
109 qCDebug(lcQtQuickControlsStyle) << "clearing resolved flag and resolving";
110 style = s;
111 resolved = false;
112 resolve();
113 }
114
115 void setFallbackStyle(const QString &fallback, const QByteArray &method)
116 {
117 if (!fallback.isEmpty())
118 qCDebug(lcQtQuickControlsStyle) << "fallback style" << fallback << "set on QQuickStyleSpec via" << method;
119
120 fallbackStyle = fallback;
121 fallbackMethod = method;
122 }
123
124 void resolve()
125 {
126 qCDebug(lcQtQuickControlsStyle) << "resolving style";
127
128 if (style.isEmpty())
130 if (style.isEmpty())
131 style = QString::fromLocal8Bit(qgetenv("QT_QUICK_CONTROLS_STYLE"));
132 if (fallbackStyle.isEmpty())
133 setFallbackStyle(QString::fromLocal8Bit(qgetenv("QT_QUICK_CONTROLS_FALLBACK_STYLE")), "QT_QUICK_CONTROLS_FALLBACK_STYLE");
134#if QT_CONFIG(settings)
135 if (style.isEmpty() || fallbackStyle.isEmpty()) {
137 if (settings) {
138 if (style.isEmpty())
139 style = settings->value(QStringLiteral("Style")).toString();
140 if (fallbackStyle.isEmpty())
141 setFallbackStyle(settings->value(QStringLiteral("FallbackStyle")).toString(), ":/qtquickcontrols2.conf");
142 }
143 }
144#endif
145
146 auto builtInStyleList = QQuickStylePrivate::builtInStyles();
147 if (!fallbackStyle.isEmpty() && !builtInStyleList.contains(fallbackStyle)) {
148 qWarning().nospace().noquote() << fallbackMethod << ": the specified fallback style \"" <<
149 fallbackStyle << "\" is not one of the built-in Qt Quick Controls 2 styles";
150 fallbackStyle.clear();
151 }
152
153 // Find the config file.
154 resolveConfigFilePath();
155
156 usingDefaultStyle = false;
157
158 if (style.isEmpty() || style.toLower() == QStringLiteral("default")) {
159 usingDefaultStyle = true;
160 style.clear();
161
162 qCDebug(lcQtQuickControlsStyle) << "no style (or Default) was specified;"
163 << "checking if we have an appropriate style for this platform";
164
165 // If these defaults are changed, ensure that the "Using Styles in Qt Quick Controls"
166 // section of qtquickcontrols-styles.qdoc is updated.
167#if defined(Q_OS_MACOS)
168 style = QLatin1String("macOS");
169#elif defined(Q_OS_WINDOWS)
170 style = QLatin1String("Windows");
171#elif defined(Q_OS_ANDROID)
172 style = QLatin1String("Material");
173#elif defined(Q_OS_LINUX)
174 style = QLatin1String("Fusion");
175#elif defined(Q_OS_IOS)
176 style = QLatin1String("iOS");
177#endif
178 if (!style.isEmpty())
179 qCDebug(lcQtQuickControlsStyle) << "using" << style << "as a default";
180 else
181 qCDebug(lcQtQuickControlsStyle) << "no appropriate style found; using Basic as a default";
182 }
183
184 // If it's still empty by this point, then it means we have no native style available for this platform,
185 // as is the case on e.g. embedded. In that case, we want to default to the Basic style,
186 // which is what effectiveStyleName() returns when "style" is empty.
187 custom = !builtInStyleList.contains(QQuickStylePrivate::effectiveStyleName(style));
188
189 resolved = true;
190
191 qCDebug(lcQtQuickControlsStyle).nospace() << "done resolving:"
192 << "\n style=" << style
193 << "\n custom=" << custom
194 << "\n resolved=" << resolved
195 << "\n fallbackStyle=" << fallbackStyle
196 << "\n fallbackMethod=" << fallbackMethod
197 << "\n configFilePath=" << configFilePath;
198 }
199
200 void reset()
201 {
202 qCDebug(lcQtQuickControlsStyle) << "resetting values to their defaults";
203
204 custom = false;
205 resolved = false;
206 usingDefaultStyle = false;
207 style.clear();
208 fallbackStyle.clear();
209 fallbackMethod.clear();
210 configFilePath.clear();
211 }
212
214 {
215 if (configFilePath.isEmpty()) {
216 configFilePath = QFile::decodeName(qgetenv("QT_QUICK_CONTROLS_CONF"));
217 if (configFilePath.isEmpty() || !QFile::exists(configFilePath)) {
218 if (!configFilePath.isEmpty())
219 qWarning("QT_QUICK_CONTROLS_CONF=%s: No such file", qPrintable(configFilePath));
220
221 configFilePath = QStringLiteral(":/qtquickcontrols2.conf");
222 }
223 }
224 return configFilePath;
225 }
226
227 // Is this a custom style defined by the user and not "built-in" style?
228 bool custom = false;
229 // Have we resolved the style yet?
230 bool resolved = false;
231 // Are we using the default style for this platform (because no style was specified)?
232 bool usingDefaultStyle = false;
233 // The name of the style.
235 // The built-in style to use if the requested style cannot be found.
237 // A description of the way in which fallbackStyle was set, used in e.g. warning messages shown to the user.
239 // The path to the qtquickcontrols2.conf file.
241};
242
244
245/*
246 Note that most of these functions (with the exception of e.g. isResolved())
247 should not be called before the style has been resolved, as it's only after
248 that happens that they will have been set.
249*/
251{
252 return styleSpec()->style;
253}
254
256{
257 return !styleName.isEmpty() ? styleName : QLatin1String("Basic");
258}
259
261{
262 return styleSpec()->fallbackStyle;
263}
264
266{
267 return styleSpec()->custom;
268}
269
271{
272 return styleSpec()->resolved;
273}
274
276{
277 return styleSpec()->usingDefaultStyle;
278}
279
281{
282 QQuickStyleSpec *spec = styleSpec();
283 spec->resolve();
284}
285
287{
288 if (styleSpec())
289 styleSpec()->reset();
290}
291
293{
294 return styleSpec()->resolveConfigFilePath();
295}
296
298{
299#ifndef QT_NO_SETTINGS
301 if (QFile::exists(filePath)) {
304 if (!group.isEmpty())
307 }
308#endif // QT_NO_SETTINGS
310}
311
312#if QT_CONFIG(settings)
313static void readValue(const QSharedPointer<QSettings> &settings, const QString &name, std::function<void(const QVariant &)> setValue)
314{
315 const QVariant var = settings->value(name);
316 if (var.isValid())
317 setValue(var);
318}
319
320template <typename Enum>
321static Enum toEnumValue(const QVariant &var)
322{
323 // ### TODO: expose QFont enums to the meta object system using Q_ENUM
324 //QMetaEnum enumeration = QMetaEnum::fromType<Enum>();
325 //bool ok = false;
326 //int value = enumeration.keyToValue(var.toByteArray(), &ok);
327 //if (!ok)
328 // value = var.toInt();
329 //return static_cast<Enum>(value);
330
331 return static_cast<Enum>(var.toInt());
332}
333
335{
336 const QVariant var = settings->value(QStringLiteral("Font"));
337 if (var.isValid())
338 return new QFont(var.value<QFont>());
339
340 QFont f;
342 readValue(settings, QStringLiteral("Family"), [&f](const QVariant &var) { f.setFamilies(QStringList{var.toString()}); });
343 readValue(settings, QStringLiteral("PointSize"), [&f](const QVariant &var) { f.setPointSizeF(var.toReal()); });
344 readValue(settings, QStringLiteral("PixelSize"), [&f](const QVariant &var) { f.setPixelSize(var.toInt()); });
345 readValue(settings, QStringLiteral("StyleHint"), [&f](const QVariant &var) { f.setStyleHint(toEnumValue<QFont::StyleHint>(var.toInt())); });
346 readValue(settings, QStringLiteral("Weight"), [&f](const QVariant &var) { f.setWeight(toEnumValue<QFont::Weight>(var)); });
347 readValue(settings, QStringLiteral("Style"), [&f](const QVariant &var) { f.setStyle(toEnumValue<QFont::Style>(var.toInt())); });
349 return new QFont(f);
350}
351
353{
355 if (keys.isEmpty())
356 return;
357
358 static const int index = QPalette::staticMetaObject.indexOfEnumerator("ColorRole");
359 Q_ASSERT(index != -1);
360 QMetaEnum metaEnum = QPalette::staticMetaObject.enumerator(index);
361
362 for (const QString &key : keys) {
363 bool ok = false;
364 int role = metaEnum.keyToValue(key.toUtf8(), &ok);
365 if (ok)
366 palette->setColor(group, static_cast<QPalette::ColorRole>(role), settings->value(key).value<QColor>());
367 }
368}
369
371{
372 QPalette p;
374 readColorGroup(settings, QPalette::All, &p);
375
377 readColorGroup(settings, QPalette::Normal, &p);
379
380 settings->beginGroup(QStringLiteral("Disabled"));
381 readColorGroup(settings, QPalette::Disabled, &p);
383 return new QPalette(p);
384}
385#endif // QT_CONFIG(settings)
386
388{
389 const bool dark = [](){
391 return theme->colorScheme() == Qt::ColorScheme::Dark;
392 return false;
393 }();
394 return dark;
395}
396
398{
399 return {
400 QLatin1String("Basic"),
401 QLatin1String("Fusion"),
402 QLatin1String("Imagine"),
403#ifdef Q_OS_MACOS
404 QLatin1String("macOS"),
405 QLatin1String("iOS"),
406#endif
407#ifdef Q_OS_IOS
408 QLatin1String("iOS"),
409#endif
410 QLatin1String("Material"),
411 QLatin1String("Universal"),
412#ifdef Q_OS_WINDOWS
413 QLatin1String("Windows")
414#endif
415 };
416}
417
426{
427 return styleSpec()->name();
428}
429
439{
440 qCDebug(lcQtQuickControlsStyle) << "setStyle called with" << style;
441
443 QStringLiteral("QtQuick.Controls"), QTypeRevision::fromVersion(2, 0)).isValid()) {
444 qWarning() << "ERROR: QQuickStyle::setStyle() must be called before loading QML that imports Qt Quick Controls 2.";
445 return;
446 }
447
448 styleSpec()->setStyle(style);
449}
450
466{
468 QStringLiteral("QtQuick.Controls"), QTypeRevision::fromVersion(2, 0)).isValid()) {
469 qWarning() << "ERROR: QQuickStyle::setFallbackStyle() must be called before loading QML that imports Qt Quick Controls 2.";
470 return;
471 }
472
473 styleSpec()->setFallbackStyle(style, "QQuickStyle::setFallbackStyle()");
474}
475
\inmodule QtCore
Definition qbytearray.h:57
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
\inmodule QtCore
QString select(const QString &filePath) const
This function returns the selected version of the path, based on the conditions at runtime.
static QString decodeName(const QByteArray &localFileName)
This does the reverse of QFile::encodeName() using localFileName.
Definition qfile.h:162
bool exists() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qfile.cpp:351
\reentrant
Definition qfont.h:20
static QPlatformTheme * platformTheme()
\inmodule QtCore
int keyToValue(const char *key, bool *ok=nullptr) const
Returns the integer value of the given enumeration key, or -1 if key is not defined.
The QPalette class contains color groups for each widget state.
Definition qpalette.h:19
ColorGroup
\value Disabled \value Active \value Inactive \value Normal synonym for Active
Definition qpalette.h:48
@ Disabled
Definition qpalette.h:48
The QPlatformTheme class allows customizing the UI based on themes.
static bool isLocalFile(const QString &url)
Returns true if url is a local file that can be opened with QFile.
Definition qqmlfile.cpp:549
static QString urlToLocalFileOrQrc(const QString &)
If url is a local file returns a path suitable for passing to QFile.
Definition qqmlfile.cpp:643
static QTypeRevision matchingModuleVersion(const QString &module, QTypeRevision version)
static QString effectiveStyleName(const QString &styleName)
static QStringList builtInStyles()
static bool isCustomStyle()
static void reset()
static void init()
static const QFont * readFont(const QSharedPointer< QSettings > &settings)
static bool isResolved()
static QSharedPointer< QSettings > settings(const QString &group=QString())
static bool isDarkSystemTheme()
static QString style()
static const QPalette * readPalette(const QSharedPointer< QSettings > &settings)
static QString fallbackStyle()
static bool isUsingDefaultStyle()
static QString configFilePath()
static void setFallbackStyle(const QString &style)
static void setStyle(const QString &style)
Sets the application style to style.
static QString name()
Returns the name of the application style.
\inmodule QtCore
Definition qsettings.h:30
void endGroup()
Resets the group to what it was before the corresponding beginGroup() call.
QVariant value(QAnyStringView key, const QVariant &defaultValue) const
Returns the value for setting key.
QStringList childKeys() const
Returns a list of all top-level keys that can be read using the QSettings object.
void beginGroup(QAnyStringView prefix)
Appends prefix to the current group.
\inmodule QtCore
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5788
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
static constexpr QTypeRevision fromVersion(Major majorVersion, Minor minorVersion)
Produces a QTypeRevision from the given majorVersion and minorVersion, both of which need to be a val...
\inmodule QtCore
Definition qvariant.h:64
T value() const &
Definition qvariant.h:511
qreal toReal(bool *ok=nullptr) const
Returns the variant as a qreal if the variant has userType() \l QMetaType::Double,...
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:707
int toInt(bool *ok=nullptr) const
Returns the variant as an int if the variant has userType() \l QMetaType::Int, \l QMetaType::Bool,...
QString toString() const
Returns the variant as a QString if the variant has a userType() including, but not limited to:
Combined button and popup list for selecting options.
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char * method
static quint32 readValue(QDataStream &s, quint32 size)
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define qWarning
Definition qlogging.h:162
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
GLuint64 key
GLuint index
[2]
GLfloat GLfloat f
GLboolean GLuint group
GLuint name
GLdouble s
[6]
Definition qopenglext.h:235
GLfloat GLfloat p
[1]
static Enum toEnumValue(const QByteArray &value, bool *ok)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define qPrintable(string)
Definition qstring.h:1391
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
QFileSelector selector
[1]
QSettings settings("MySoft", "Star Runner")
[0]
settings setValue("DataPump/bgcolor", color)
QStringList keys
char * toString(const MyType &t)
[31]
\inmodule QtCore \reentrant
Definition qchar.h:17
QByteArray fallbackMethod
void setFallbackStyle(const QString &fallback, const QByteArray &method)
QString resolveConfigFilePath()
void setStyle(const QString &s)