Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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()) {
136 QSharedPointer<QSettings> settings = QQuickStylePrivate::settings(QStringLiteral("Controls"));
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
297QSharedPointer<QSettings> QQuickStylePrivate::settings(const QString &group)
298{
299#ifndef QT_NO_SETTINGS
301 if (QFile::exists(filePath)) {
304 if (!group.isEmpty())
306 return QSharedPointer<QSettings>(settings);
307 }
308#endif // QT_NO_SETTINGS
310 return QSharedPointer<QSettings>();
311}
312
313#if QT_CONFIG(settings)
314static void readValue(const QSharedPointer<QSettings> &settings, const QString &name, std::function<void(const QVariant &)> setValue)
315{
316 const QVariant var = settings->value(name);
317 if (var.isValid())
318 setValue(var);
319}
320
321template <typename Enum>
322static Enum toEnumValue(const QVariant &var)
323{
324 // ### TODO: expose QFont enums to the meta object system using Q_ENUM
325 //QMetaEnum enumeration = QMetaEnum::fromType<Enum>();
326 //bool ok = false;
327 //int value = enumeration.keyToValue(var.toByteArray(), &ok);
328 //if (!ok)
329 // value = var.toInt();
330 //return static_cast<Enum>(value);
331
332 return static_cast<Enum>(var.toInt());
333}
334
335const QFont *QQuickStylePrivate::readFont(const QSharedPointer<QSettings> &settings)
336{
337 const QVariant var = settings->value(QStringLiteral("Font"));
338 if (var.isValid())
339 return new QFont(var.value<QFont>());
340
341 QFont f;
343 readValue(settings, QStringLiteral("Family"), [&f](const QVariant &var) { f.setFamilies(QStringList{var.toString()}); });
344 readValue(settings, QStringLiteral("PointSize"), [&f](const QVariant &var) { f.setPointSizeF(var.toReal()); });
345 readValue(settings, QStringLiteral("PixelSize"), [&f](const QVariant &var) { f.setPixelSize(var.toInt()); });
346 readValue(settings, QStringLiteral("StyleHint"), [&f](const QVariant &var) { f.setStyleHint(toEnumValue<QFont::StyleHint>(var.toInt())); });
347 readValue(settings, QStringLiteral("Weight"), [&f](const QVariant &var) { f.setWeight(toEnumValue<QFont::Weight>(var)); });
348 readValue(settings, QStringLiteral("Style"), [&f](const QVariant &var) { f.setStyle(toEnumValue<QFont::Style>(var.toInt())); });
350 return new QFont(f);
351}
352
353static void readColorGroup(const QSharedPointer<QSettings> &settings, QPalette::ColorGroup group, QPalette *palette)
354{
356 if (keys.isEmpty())
357 return;
358
359 static const int index = QPalette::staticMetaObject.indexOfEnumerator("ColorRole");
360 Q_ASSERT(index != -1);
361 QMetaEnum metaEnum = QPalette::staticMetaObject.enumerator(index);
362
363 for (const QString &key : keys) {
364 bool ok = false;
365 int role = metaEnum.keyToValue(key.toUtf8(), &ok);
366 if (ok)
367 palette->setColor(group, static_cast<QPalette::ColorRole>(role), settings->value(key).value<QColor>());
368 }
369}
370
371const QPalette *QQuickStylePrivate::readPalette(const QSharedPointer<QSettings> &settings)
372{
373 QPalette p;
375 readColorGroup(settings, QPalette::All, &p);
376
378 readColorGroup(settings, QPalette::Normal, &p);
380
381 settings->beginGroup(QStringLiteral("Disabled"));
382 readColorGroup(settings, QPalette::Disabled, &p);
384 return new QPalette(p);
385}
386#endif // QT_CONFIG(settings)
387
389{
390 const bool dark = [](){
392 return theme->colorScheme() == Qt::ColorScheme::Dark;
393 return false;
394 }();
395 return dark;
396}
397
399{
400 return {
401 QLatin1String("Basic"),
402 QLatin1String("Fusion"),
403 QLatin1String("Imagine"),
404#ifdef Q_OS_MACOS
405 QLatin1String("macOS"),
406 QLatin1String("iOS"),
407#endif
408#ifdef Q_OS_IOS
409 QLatin1String("iOS"),
410#endif
411 QLatin1String("Material"),
412 QLatin1String("Universal"),
413#ifdef Q_OS_WINDOWS
414 QLatin1String("Windows")
415#endif
416 };
417}
418
427{
428 return styleSpec()->name();
429}
430
440{
441 qCDebug(lcQtQuickControlsStyle) << "setStyle called with" << style;
442
444 QStringLiteral("QtQuick.Controls"), QTypeRevision::fromVersion(2, 0)).isValid()) {
445 qWarning() << "ERROR: QQuickStyle::setStyle() must be called before loading QML that imports Qt Quick Controls 2.";
446 return;
447 }
448
449 styleSpec()->setStyle(style);
450}
451
467{
469 QStringLiteral("QtQuick.Controls"), QTypeRevision::fromVersion(2, 0)).isValid()) {
470 qWarning() << "ERROR: QQuickStyle::setFallbackStyle() must be called before loading QML that imports Qt Quick Controls 2.";
471 return;
472 }
473
474 styleSpec()->setFallbackStyle(style, "QQuickStyle::setFallbackStyle()");
475}
476
\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:22
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:49
@ Disabled
Definition qpalette.h:49
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 \l{QFile}.
Definition qqmlfile.cpp:644
static QString urlToLocalFileOrQrc(const QString &)
If url is a local file returns a path suitable for passing to \l{QFile}.
Definition qqmlfile.cpp:742
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
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5949
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
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:65
T value() const &
Definition qvariant.h:516
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:714
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:166
#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 const QQmlJSScope * resolve(const QQmlJSScope *current, const QStringList &names)
static Enum toEnumValue(const QByteArray &value, bool *ok)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define qPrintable(string)
Definition qstring.h:1531
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
#define Q_UNUSED(x)
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:18
QByteArray fallbackMethod
void setFallbackStyle(const QString &fallback, const QByteArray &method)
QString resolveConfigFilePath()
void setStyle(const QString &s)