diff options
author | J-P Nurmi <jpnurmi@qt.io> | 2016-10-25 21:21:53 +0200 |
---|---|---|
committer | J-P Nurmi <jpnurmi@qt.io> | 2016-10-25 21:27:02 +0200 |
commit | eb9bde6d803b1b46ff3bd63fd1a6b40758cd7f4f (patch) | |
tree | 267db1fcbd31d5d2b0202b1dc4463037ff9227aa /src/quickcontrols2 | |
parent | 1d8bf6d1f4ef0aa84ca7e4c1233bedeee0f606f9 (diff) | |
parent | 791d521a3008695f834d5aa8c9bb61f9075b37a8 (diff) |
Merge remote-tracking branch 'origin/5.8' into dev
Change-Id: If48d66d89172db94ee1839063396156a3a947601
Diffstat (limited to 'src/quickcontrols2')
-rw-r--r-- | src/quickcontrols2/qquickstyle.cpp | 85 | ||||
-rw-r--r-- | src/quickcontrols2/qquickstyle.h | 1 | ||||
-rw-r--r-- | src/quickcontrols2/qquickstyle_p.h | 3 | ||||
-rw-r--r-- | src/quickcontrols2/qquickstyleselector.cpp | 63 | ||||
-rw-r--r-- | src/quickcontrols2/qquickstyleselector_p_p.h | 5 |
5 files changed, 132 insertions, 25 deletions
diff --git a/src/quickcontrols2/qquickstyle.cpp b/src/quickcontrols2/qquickstyle.cpp index 489eee15..80a7abef 100644 --- a/src/quickcontrols2/qquickstyle.cpp +++ b/src/quickcontrols2/qquickstyle.cpp @@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE /*! \class QQuickStyle - \brief The QQQuickStyle class allows configuring the application style. + \brief The QQuickStyle class allows configuring the application style. \inmodule QtQuickControls2 \since 5.7 @@ -85,7 +85,7 @@ QT_BEGIN_NAMESPACE struct QQuickStyleSpec { - QQuickStyleSpec() : resolved(false) { } + QQuickStyleSpec() : custom(false), resolved(false) { } QString name() { @@ -111,6 +111,12 @@ struct QQuickStyleSpec 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); @@ -135,11 +141,18 @@ struct QQuickStyleSpec 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"); + } } + custom = style.contains(QLatin1Char('/')); if (baseUrl.isValid()) { QString path = QQmlFile::urlToLocalFileOrQrc(baseUrl); @@ -151,7 +164,7 @@ struct QQuickStyleSpec } if (QGuiApplication::instance()) { - if (!style.contains(QLatin1Char('/'))) { + if (!custom) { const QString targetPath = QStringLiteral("QtQuick/Controls.2"); const QStringList importPaths = QQmlEngine().importPathList(); @@ -168,15 +181,54 @@ struct QQuickStyleSpec } } + void reset() + { + custom = false; + resolved = false; + style.clear(); + fallbackStyle.clear(); + fallbackMethod.clear(); + } + + bool custom; bool resolved; QString style; + QString fallbackStyle; + QByteArray fallbackMethod; }; Q_GLOBAL_STATIC(QQuickStyleSpec, styleSpec) +QString QQuickStylePrivate::fallbackStyle() +{ + return styleSpec()->fallbackStyle; +} + +bool QQuickStylePrivate::isCustomStyle() +{ + return styleSpec()->custom; +} + void QQuickStylePrivate::init(const QUrl &baseUrl) { - styleSpec()->resolve(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(); } /*! @@ -220,4 +272,23 @@ void QQuickStyle::setStyle(const QString &style) styleSpec()->setStyle(style); } +/*! + \since 5.9 + 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. +*/ +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 diff --git a/src/quickcontrols2/qquickstyle.h b/src/quickcontrols2/qquickstyle.h index 4476a29a..d2e7faf1 100644 --- a/src/quickcontrols2/qquickstyle.h +++ b/src/quickcontrols2/qquickstyle.h @@ -49,6 +49,7 @@ public: static QString name(); static QString path(); static void setStyle(const QString &style); + static void setFallbackStyle(const QString &style); }; QT_END_NAMESPACE diff --git a/src/quickcontrols2/qquickstyle_p.h b/src/quickcontrols2/qquickstyle_p.h index 594e71c8..cfe87fbb 100644 --- a/src/quickcontrols2/qquickstyle_p.h +++ b/src/quickcontrols2/qquickstyle_p.h @@ -56,7 +56,10 @@ QT_BEGIN_NAMESPACE class Q_QUICKCONTROLS2_PRIVATE_EXPORT QQuickStylePrivate { public: + static QString fallbackStyle(); + static bool isCustomStyle(); static void init(const QUrl &baseUrl); + static void reset(); }; QT_END_NAMESPACE diff --git a/src/quickcontrols2/qquickstyleselector.cpp b/src/quickcontrols2/qquickstyleselector.cpp index 866280a7..8dbbc064 100644 --- a/src/quickcontrols2/qquickstyleselector.cpp +++ b/src/quickcontrols2/qquickstyleselector.cpp @@ -35,12 +35,14 @@ #include "qquickstyleselector_p.h" #include "qquickstyleselector_p_p.h" #include "qquickstyle.h" +#include "qquickstyle_p.h" #include <QtCore/qdir.h> #include <QtCore/qfile.h> #include <QtCore/qfileinfo.h> #include <QtCore/qsysinfo.h> #include <QtCore/qlocale.h> +#include <QtQml/qqmlfile.h> #include <QtCore/private/qfileselector_p.h> #include <QtGui/private/qguiapplication_p.h> @@ -56,6 +58,13 @@ static bool isLocalScheme(const QString &scheme) return local; } +static QString ensureSlash(const QString &path) +{ + if (path.endsWith(QLatin1Char('/'))) + return path; + return path + QLatin1Char('/'); +} + static QStringList allSelectors(const QString &style = QString()) { static const QStringList platformSelectors = QFileSelectorPrivate::platformSelectors(); @@ -75,17 +84,34 @@ QString QQuickStyleSelectorPrivate::select(const QString &filePath) const const QString path = fi.path(); const QString ret = QFileSelectorPrivate::selectionHelper(path.isEmpty() ? QString() : path + QLatin1Char('/'), - fi.fileName(), allSelectors(style), QChar()); + fi.fileName(), allSelectors(styleName), QChar()); if (!ret.isEmpty()) return ret; return filePath; } +QString QQuickStyleSelectorPrivate::trySelect(const QString &filePath, const QString &fallback) const +{ + QFileInfo fi(filePath); + if (!fi.exists()) + return fallback; + + // the path contains the name of the custom/fallback style, so exclude it from + // the selectors. the rest of the selectors (os, locale) are still valid, though. + const QString path = fi.path(); + const QString selectedPath = QFileSelectorPrivate::selectionHelper(path.isEmpty() ? QString() : path + QLatin1Char('/'), + fi.fileName(), allSelectors(), QChar()); + if (selectedPath.startsWith(QLatin1Char(':'))) + return QLatin1String("qrc") + selectedPath; + return QUrl::fromLocalFile(QFileInfo(selectedPath).absoluteFilePath()).toString(); +} + QQuickStyleSelector::QQuickStyleSelector() : d_ptr(new QQuickStyleSelectorPrivate) { Q_D(QQuickStyleSelector); - d->style = QQuickStyle::name(); + d->styleName = QQuickStyle::name(); + d->stylePath = QQuickStyle::path(); } QQuickStyleSelector::~QQuickStyleSelector() @@ -102,29 +128,32 @@ void QQuickStyleSelector::setBaseUrl(const QUrl &url) { Q_D(QQuickStyleSelector); d->baseUrl = url; + d->basePath = QQmlFile::urlToLocalFileOrQrc(url.toString(QUrl::StripTrailingSlash) + QLatin1Char('/')); } QString QQuickStyleSelector::select(const QString &fileName) const { Q_D(const QQuickStyleSelector); - const QString overridePath = QQuickStyle::path(); - if (!overridePath.isEmpty()) { - const QString stylePath = overridePath + d->style + QLatin1Char('/'); - if (QFile::exists(stylePath + fileName)) { - // the style name is included to the path, so exclude it from the selectors. - // the rest of the selectors (os, locale) are still valid, though. - const QString selectedPath = QFileSelectorPrivate::selectionHelper(stylePath, fileName, allSelectors(), QChar()); - if (selectedPath.startsWith(QLatin1Char(':'))) - return QLatin1String("qrc") + selectedPath; - return QUrl::fromLocalFile(QFileInfo(selectedPath).absoluteFilePath()).toString(); - } + + // 1) try selecting from a custom style path, for example ":/mystyle" + if (QQuickStylePrivate::isCustomStyle()) { + // NOTE: this path may contain a subset of controls + const QString selectedPath = d->trySelect(ensureSlash(d->stylePath) + d->styleName + QLatin1Char('/') + fileName); + if (!selectedPath.isEmpty()) + return selectedPath; } - QString base = d->baseUrl.toString(); - if (!base.isEmpty() && !base.endsWith(QLatin1Char('/'))) - base += QLatin1Char('/'); + // 2) try selecting from the fallback style path, for example QT_INSTALL_QML/QtQuick/Controls.2/Material + const QString fallbackStyle = QQuickStylePrivate::fallbackStyle(); + if (!fallbackStyle.isEmpty()) { + // NOTE: this path may also contain a subset of controls + const QString selectedPath = d->trySelect(ensureSlash(d->basePath) + fallbackStyle + QLatin1Char('/') + fileName); + if (!selectedPath.isEmpty()) + return selectedPath; + } - QUrl url(base + fileName); + // 3) fallback to the default style that is guaranteed to contain all controls + QUrl url(ensureSlash(d->baseUrl.toString()) + fileName); if (isLocalScheme(url.scheme())) { QString equivalentPath = QLatin1Char(':') + url.path(); QString selectedPath = d->select(equivalentPath); diff --git a/src/quickcontrols2/qquickstyleselector_p_p.h b/src/quickcontrols2/qquickstyleselector_p_p.h index cc3f0a58..4ff28d5d 100644 --- a/src/quickcontrols2/qquickstyleselector_p_p.h +++ b/src/quickcontrols2/qquickstyleselector_p_p.h @@ -54,9 +54,12 @@ class QQuickStyleSelectorPrivate { public: QString select(const QString &filePath) const; + QString trySelect(const QString &filePath, const QString &fallback = QString()) const; QUrl baseUrl; - QString style; + QString basePath; + QString styleName; + QString stylePath; }; QT_END_NAMESPACE |