aboutsummaryrefslogtreecommitdiffstats
path: root/src/quickcontrols2/qquickstyle.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quickcontrols2/qquickstyle.cpp')
-rw-r--r--src/quickcontrols2/qquickstyle.cpp183
1 files changed, 160 insertions, 23 deletions
diff --git a/src/quickcontrols2/qquickstyle.cpp b/src/quickcontrols2/qquickstyle.cpp
index 143f599a..3ad7c074 100644
--- a/src/quickcontrols2/qquickstyle.cpp
+++ b/src/quickcontrols2/qquickstyle.cpp
@@ -35,6 +35,7 @@
****************************************************************************/
#include "qquickstyle.h"
+#include "qquickstyle_p.h"
#include "qquickstyleattached_p.h"
#include <QtCore/qdir.h>
@@ -80,6 +81,19 @@ QT_BEGIN_NAMESPACE
Qt Quick Controls 2. It is not possible to change the style after the QML
types have been registered.
+ The style can also be specified as a path to a custom style, such as
+ \c ":/mystyle". See \l {Creating a Custom Style} for more details about
+ building custom styles. Custom styles do not need to implement all controls.
+ By default, the styling system uses the \l {Default style} as a fallback
+ for controls that a custom style does not provide. It is possible to
+ specify a different fallback style to customize or extend one of the
+ built-in styles.
+
+ \code
+ QQuickStyle::setStyle(":/mystyle");
+ QQuickStyle::setFallbackStyle("Material");
+ \endcode
+
\sa {Styling Qt Quick Controls 2}
*/
@@ -102,7 +116,7 @@ static QStringList defaultImportPathList()
struct QQuickStyleSpec
{
- QQuickStyleSpec() : resolved(false) { }
+ QQuickStyleSpec() : custom(false), resolved(false) { }
QString name()
{
@@ -128,54 +142,155 @@ struct QQuickStyleSpec
resolve();
}
- void resolve()
+ void setFallbackStyle(const QString &fallback, const QByteArray &method)
+ {
+ fallbackStyle = fallback;
+ fallbackMethod = method;
+ }
+
+ static QString findStyle(const QString &path, const QString &name)
+ {
+ QDir dir(path);
+ if (!dir.exists())
+ return QString();
+
+ if (name.isEmpty())
+ return dir.absolutePath() + QLatin1Char('/');
+
+ const QStringList entries = dir.entryList(QStringList(), QDir::Dirs | QDir::NoDotAndDotDot);
+ for (const QString &entry : entries) {
+ if (entry.compare(name, Qt::CaseInsensitive) == 0)
+ return dir.absoluteFilePath(entry);
+ }
+
+ return QString();
+ }
+
+ void resolve(const QUrl &baseUrl = QUrl())
{
if (style.isEmpty())
style = QGuiApplicationPrivate::styleOverride;
if (style.isEmpty())
style = QString::fromLatin1(qgetenv("QT_QUICK_CONTROLS_STYLE"));
- if (style.isEmpty()) {
+ if (fallbackStyle.isEmpty())
+ setFallbackStyle(QString::fromLatin1(qgetenv("QT_QUICK_CONTROLS_FALLBACK_STYLE")), "QT_QUICK_CONTROLS_FALLBACK_STYLE");
+ if (style.isEmpty() || fallbackStyle.isEmpty()) {
QSharedPointer<QSettings> settings = QQuickStyleAttached::settings(QStringLiteral("Controls"));
- if (settings)
- style = settings->value(QStringLiteral("Style")).toString();
+ if (settings) {
+ if (style.isEmpty())
+ style = settings->value(QStringLiteral("Style")).toString();
+ if (fallbackStyle.isEmpty())
+ setFallbackStyle(settings->value(QStringLiteral("FallbackStyle")).toString(), ":/qtquickcontrols2.conf");
+ }
+ }
+
+ // resolve a path relative to the config
+ QString configPath = QFileInfo(resolveConfigFilePath()).path();
+ QString stylePath = findStyle(configPath, style);
+ if (!stylePath.isEmpty()) {
+ style = stylePath;
+ resolved = true;
+ }
+
+ custom = style.contains(QLatin1Char('/'));
+
+ if (baseUrl.isValid()) {
+ QString path = QQmlFile::urlToLocalFileOrQrc(baseUrl);
+ QString stylePath = findStyle(path, style);
+ if (!stylePath.isEmpty()) {
+ style = stylePath;
+ resolved = true;
+ }
}
if (QGuiApplication::instance()) {
- if (!style.contains(QLatin1Char('/'))) {
+ if (!custom) {
const QString targetPath = QStringLiteral("QtQuick/Controls.2");
const QStringList importPaths = defaultImportPathList();
for (const QString &importPath : importPaths) {
- QDir importDir(importPath);
- if (importDir.cd(targetPath)) {
- if (style.isEmpty()) {
- style = importDir.absolutePath() + QLatin1Char('/');
- resolved = true;
- break;
- }
- const QStringList entries = importDir.entryList(QStringList(), QDir::Dirs | QDir::NoDotAndDotDot);
- for (const QString &entry : entries) {
- if (entry.compare(style, Qt::CaseInsensitive) == 0) {
- style = importDir.absoluteFilePath(entry);
- resolved = true;
- break;
- }
- }
- }
- if (resolved)
+ QString stylePath = findStyle(importPath + QLatin1Char('/') + targetPath, style);
+ if (!stylePath.isEmpty()) {
+ style = stylePath;
+ resolved = true;
break;
+ }
}
}
resolved = true;
}
}
+ void reset()
+ {
+ custom = false;
+ resolved = false;
+ style.clear();
+ fallbackStyle.clear();
+ fallbackMethod.clear();
+ }
+
+ QString resolveConfigFilePath()
+ {
+ if (configFilePath.isEmpty()) {
+ configFilePath = QFile::decodeName(qgetenv("QT_QUICK_CONTROLS_CONF"));
+ if (!QFile::exists(configFilePath)) {
+ if (!configFilePath.isEmpty())
+ qWarning("QT_QUICK_CONTROLS_CONF=%s: No such file", qPrintable(configFilePath));
+
+ configFilePath = QStringLiteral(":/qtquickcontrols2.conf");
+ }
+ }
+ return configFilePath;
+ }
+
+ bool custom;
bool resolved;
QString style;
+ QString fallbackStyle;
+ QByteArray fallbackMethod;
+ QString configFilePath;
};
Q_GLOBAL_STATIC(QQuickStyleSpec, styleSpec)
+QString QQuickStylePrivate::fallbackStyle()
+{
+ return styleSpec()->fallbackStyle;
+}
+
+bool QQuickStylePrivate::isCustomStyle()
+{
+ return styleSpec()->custom;
+}
+
+void QQuickStylePrivate::init(const QUrl &baseUrl)
+{
+ QQuickStyleSpec *spec = styleSpec();
+ spec->resolve(baseUrl);
+
+ if (!spec->fallbackStyle.isEmpty()) {
+ QString fallbackStyle = spec->findStyle(baseUrl.toLocalFile(), spec->fallbackStyle);
+ if (fallbackStyle.isEmpty()) {
+ if (spec->fallbackStyle.compare(QStringLiteral("Default")) != 0) {
+ qWarning() << "ERROR: unable to locate fallback style" << spec->fallbackStyle;
+ qInfo().nospace().noquote() << spec->fallbackMethod << ": the fallback style must be the name of one of the built-in Qt Quick Controls 2 styles.";
+ }
+ spec->fallbackStyle.clear();
+ }
+ }
+}
+
+void QQuickStylePrivate::reset()
+{
+ styleSpec()->reset();
+}
+
+QString QQuickStylePrivate::configFilePath()
+{
+ return styleSpec()->resolveConfigFilePath();
+}
+
/*!
Returns the name of the application style.
@@ -217,4 +332,26 @@ void QQuickStyle::setStyle(const QString &style)
styleSpec()->setStyle(style);
}
+/*!
+ \since 5.8
+ Sets the application fallback style to \a style.
+
+ \note The fallback style must be the name of one of the built-in Qt Quick Controls 2 styles, e.g. "Material".
+
+ \note The style must be configured \b before loading QML that imports Qt Quick Controls 2.
+ It is not possible to change the style after the QML types have been registered.
+
+ The fallback style can be also specified by setting the \c QT_QUICK_CONTROLS_FALLBACK_STYLE
+ \l {Supported Environment Variables in Qt Quick Controls 2}{environment variable}.
+*/
+void QQuickStyle::setFallbackStyle(const QString &style)
+{
+ if (QQmlMetaType::isModule(QStringLiteral("QtQuick.Controls"), 2, 0)) {
+ qWarning() << "ERROR: QQuickStyle::setFallbackStyle() must be called before loading QML that imports Qt Quick Controls 2.";
+ return;
+ }
+
+ styleSpec()->setFallbackStyle(style, "QQuickStyle::setFallbackStyle()");
+}
+
QT_END_NAMESPACE