aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/imports/controls/qtquickcontrols2plugin.cpp7
-rw-r--r--src/quickcontrols2/qquickstyle.cpp17
-rw-r--r--src/quickcontrols2/qquickstyle_p.h2
-rw-r--r--src/quickcontrols2/qquickstyleselector.cpp122
-rw-r--r--src/quickcontrols2/qquickstyleselector_p.h9
-rw-r--r--src/quickcontrols2/qquickstyleselector_p_p.h9
-rw-r--r--tests/auto/qquickstyleselector/tst_qquickstyleselector.cpp11
7 files changed, 82 insertions, 95 deletions
diff --git a/src/imports/controls/qtquickcontrols2plugin.cpp b/src/imports/controls/qtquickcontrols2plugin.cpp
index c495b6b2..d0018901 100644
--- a/src/imports/controls/qtquickcontrols2plugin.cpp
+++ b/src/imports/controls/qtquickcontrols2plugin.cpp
@@ -98,12 +98,17 @@ QtQuickControls2Plugin::~QtQuickControls2Plugin()
void QtQuickControls2Plugin::registerTypes(const char *uri)
{
QQuickStylePrivate::init(typeUrl());
+
const QString style = QQuickStyle::name();
+ const QString fallback = QQuickStylePrivate::fallbackStyle();
if (!style.isEmpty())
QFileSelectorPrivate::addStatics(QStringList() << style.toLower());
QQuickStyleSelector selector;
- selector.setBaseUrl(typeUrl());
+ selector.addSelector(style);
+ if (!fallback.isEmpty())
+ selector.addSelector(fallback);
+ selector.setPaths(QQuickStylePrivate::stylePaths(true));
qmlRegisterModule(uri, 2, QT_VERSION_MINOR - 7); // Qt 5.7->2.0, 5.8->2.1, 5.9->2.2...
diff --git a/src/quickcontrols2/qquickstyle.cpp b/src/quickcontrols2/qquickstyle.cpp
index 5a295b6c..139e65f1 100644
--- a/src/quickcontrols2/qquickstyle.cpp
+++ b/src/quickcontrols2/qquickstyle.cpp
@@ -117,7 +117,7 @@ static QStringList defaultImportPathList()
importPaths.reserve(3);
importPaths += QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath);
importPaths += envPathList("QML2_IMPORT_PATH");
- importPaths += QStringLiteral("qrc:/qt-project.org/imports");
+ importPaths += QStringLiteral(":/qt-project.org/imports");
importPaths += QCoreApplication::applicationDirPath();
return importPaths;
}
@@ -264,10 +264,20 @@ struct QQuickStyleSpec
Q_GLOBAL_STATIC(QQuickStyleSpec, styleSpec)
-QStringList QQuickStylePrivate::stylePaths()
+QStringList QQuickStylePrivate::stylePaths(bool resolve)
{
+ // user-requested style path
+ QStringList paths;
+ if (resolve) {
+ QString path = styleSpec->path();
+ if (path.endsWith(QLatin1Char('/')))
+ path.chop(1);
+ if (!path.isEmpty())
+ paths += path;
+ }
+
// system/custom style paths
- QStringList paths = envPathList("QT_QUICK_CONTROLS_STYLE_PATH");
+ paths += envPathList("QT_QUICK_CONTROLS_STYLE_PATH");
// built-in import paths
const QString targetPath = QStringLiteral("QtQuick/Controls.2");
@@ -278,6 +288,7 @@ QStringList QQuickStylePrivate::stylePaths()
paths += dir.absolutePath();
}
+ paths.removeDuplicates();
return paths;
}
diff --git a/src/quickcontrols2/qquickstyle_p.h b/src/quickcontrols2/qquickstyle_p.h
index b92df3c2..f6034fa0 100644
--- a/src/quickcontrols2/qquickstyle_p.h
+++ b/src/quickcontrols2/qquickstyle_p.h
@@ -59,7 +59,7 @@ class QSettings;
class Q_QUICKCONTROLS2_PRIVATE_EXPORT QQuickStylePrivate
{
public:
- static QStringList stylePaths();
+ static QStringList stylePaths(bool resolve = false);
static QString fallbackStyle();
static bool isCustomStyle();
static void init(const QUrl &baseUrl);
diff --git a/src/quickcontrols2/qquickstyleselector.cpp b/src/quickcontrols2/qquickstyleselector.cpp
index d5543c17..1dee4dcc 100644
--- a/src/quickcontrols2/qquickstyleselector.cpp
+++ b/src/quickcontrols2/qquickstyleselector.cpp
@@ -40,33 +40,16 @@
#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>
QT_BEGIN_NAMESPACE
-static bool isLocalScheme(const QString &scheme)
-{
- bool local = scheme == QLatin1String("qrc");
-#ifdef Q_OS_ANDROID
- local |= scheme == QLatin1String("assets");
-#endif
- return local;
-}
-
static QString ensureSlash(const QString &path)
{
- if (path.endsWith(QLatin1Char('/')))
+ if (path.isEmpty() || path.endsWith(QLatin1Char('/')))
return path;
return path + QLatin1Char('/');
}
@@ -79,105 +62,90 @@ static QStringList prefixedPlatformSelectors(const QChar &prefix)
return selectors;
}
-static QStringList allSelectors(const QString &style = QString())
+static QStringList allSelectors()
{
static const QStringList platformSelectors = prefixedPlatformSelectors(QLatin1Char('+'));
QStringList selectors = platformSelectors;
const QString locale = QLocale().name();
if (!locale.isEmpty())
selectors += QLatin1Char('+') + locale;
- if (!style.isEmpty())
- selectors.prepend(style);
return selectors;
}
-QString QQuickStyleSelectorPrivate::select(const QString &filePath) const
+QUrl QQuickStyleSelectorPrivate::select(const QString &filePath) const
{
QFileInfo fi(filePath);
// If file doesn't exist, don't select
if (!fi.exists())
- return filePath;
+ return QUrl();
- const QString path = fi.path();
- const QString ret = QFileSelectorPrivate::selectionHelper(path.isEmpty() ? QString() : path + QLatin1Char('/'),
- fi.fileName(), allSelectors(styleName), QChar());
+ const QString selected = QFileSelectorPrivate::selectionHelper(ensureSlash(fi.canonicalPath()),
+ fi.fileName(), allSelectors(), QChar());
- if (!ret.isEmpty())
- return ret;
- return filePath;
-}
+ if (selected.startsWith(QLatin1Char(':')))
+ return QUrl(QLatin1String("qrc") + selected);
-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();
+ return QUrl::fromLocalFile(selected.isEmpty() ? filePath : selected);
}
QQuickStyleSelector::QQuickStyleSelector() : d_ptr(new QQuickStyleSelectorPrivate)
{
- Q_D(QQuickStyleSelector);
- d->styleName = QQuickStyle::name();
- d->stylePath = QQuickStyle::path();
}
QQuickStyleSelector::~QQuickStyleSelector()
{
}
-QUrl QQuickStyleSelector::baseUrl() const
+QStringList QQuickStyleSelector::selectors() const
{
Q_D(const QQuickStyleSelector);
- return d->baseUrl;
+ return d->selectors;
}
-void QQuickStyleSelector::setBaseUrl(const QUrl &url)
+void QQuickStyleSelector::addSelector(const QString &selector)
{
Q_D(QQuickStyleSelector);
- d->baseUrl = url;
- d->basePath = QQmlFile::urlToLocalFileOrQrc(url.toString(QUrl::StripTrailingSlash) + QLatin1Char('/'));
+ if (d->selectors.contains(selector))
+ return;
+
+ d->selectors += selector;
}
-QString QQuickStyleSelector::select(const QString &fileName) const
+QStringList QQuickStyleSelector::paths() const
{
Q_D(const QQuickStyleSelector);
+ return d->paths;
+}
- // 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;
- }
+void QQuickStyleSelector::setPaths(const QStringList &paths)
+{
+ Q_D(QQuickStyleSelector);
+ d->paths = paths;
+}
- // 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 QQuickStyleSelector::select(const QString &fileName) const
+{
+ Q_D(const QQuickStyleSelector);
+ // The lookup order is
+ // 1) requested style (e.g. "MyStyle", included in d->selectors)
+ // 2) fallback style (e.g. "Material", included in d->selectors)
+ // 3) default style (empty selector, not in d->selectors)
+
+ int to = d->selectors.count() - 1;
+ if (d->selectors.isEmpty() || !d->selectors.first().isEmpty())
+ ++to; // lookup #3 unless #1 is also empty (redundant)
+
+ // NOTE: last iteration intentionally out of bounds => empty selector
+ for (int i = 0; i <= to; ++i) {
+ const QString selector = d->selectors.value(i);
+ for (const QString &path : d->paths) {
+ const QUrl selectedUrl = d->select(ensureSlash(path) + selector + QLatin1Char('/') + fileName);
+ if (selectedUrl.isValid())
+ return selectedUrl;
+ }
}
- // 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);
- url.setPath(selectedPath.remove(0, 1));
- } else if (url.isLocalFile()) {
- url = QUrl::fromLocalFile(d->select(url.toLocalFile()));
- }
- return url.toString(QUrl::NormalizePathSegments);
+ return fileName;
}
QT_END_NAMESPACE
diff --git a/src/quickcontrols2/qquickstyleselector_p.h b/src/quickcontrols2/qquickstyleselector_p.h
index 29dba836..c4c0f540 100644
--- a/src/quickcontrols2/qquickstyleselector_p.h
+++ b/src/quickcontrols2/qquickstyleselector_p.h
@@ -67,10 +67,13 @@ public:
QQuickStyleSelector();
~QQuickStyleSelector();
- QUrl baseUrl() const;
- void setBaseUrl(const QUrl &url);
+ QStringList selectors() const;
+ void addSelector(const QString &selector);
- QString select(const QString &fileName) const;
+ QStringList paths() const;
+ void setPaths(const QStringList &paths);
+
+ QUrl select(const QString &fileName) const;
private:
Q_DISABLE_COPY(QQuickStyleSelector)
diff --git a/src/quickcontrols2/qquickstyleselector_p_p.h b/src/quickcontrols2/qquickstyleselector_p_p.h
index e940cd87..e69e7db2 100644
--- a/src/quickcontrols2/qquickstyleselector_p_p.h
+++ b/src/quickcontrols2/qquickstyleselector_p_p.h
@@ -59,13 +59,10 @@ QT_BEGIN_NAMESPACE
class QQuickStyleSelectorPrivate
{
public:
- QString select(const QString &filePath) const;
- QString trySelect(const QString &filePath, const QString &fallback = QString()) const;
+ QUrl select(const QString &filePath) const;
- QUrl baseUrl;
- QString basePath;
- QString styleName;
- QString stylePath;
+ QStringList paths;
+ QStringList selectors;
};
QT_END_NAMESPACE
diff --git a/tests/auto/qquickstyleselector/tst_qquickstyleselector.cpp b/tests/auto/qquickstyleselector/tst_qquickstyleselector.cpp
index e90a8bd9..ce2e2e99 100644
--- a/tests/auto/qquickstyleselector/tst_qquickstyleselector.cpp
+++ b/tests/auto/qquickstyleselector/tst_qquickstyleselector.cpp
@@ -96,7 +96,7 @@ void tst_QQuickStyleSelector::select_data()
QTest::newRow("nosuch/label") << "Label.qml" << "NoSuchStyle" << "data" << "" << testFileUrl("Label.qml").toString();
QTest::newRow("/nosuch/label") << "Label.qml" << "NoSuchStyle" << dataDirectory() << "" << testFileUrl("Label.qml").toString();
- QTest::newRow("label->base") << "Label.qml" << "" << "data" << "FallbackStyle" << testFileUrl("FallbackStyle/Label.qml").toString();
+ QTest::newRow("label->base") << "Label.qml" << "" << "data" << "FallbackStyle" << testFileUrl("Label.qml").toString();
QTest::newRow("/label->base") << "Label.qml" << "" << dataDirectory() << "FallbackStyle" << testFileUrl("Label.qml").toString();
QTest::newRow("fs/label->base") << "Label.qml" << "FileSystemStyle" << "data" << "FallbackStyle" << testFileUrl("FallbackStyle/Label.qml").toString();
QTest::newRow("/fs/label->base") << "Label.qml" << "FileSystemStyle" << dataDirectory() << "FallbackStyle" << testFileUrl("FallbackStyle/Label.qml").toString();
@@ -115,7 +115,7 @@ void tst_QQuickStyleSelector::select_data()
QTest::newRow("nosuch/button") << "Button.qml" << "NoSuchStyle" << "data" << "" << testFileUrl("Button.qml").toString();
QTest::newRow("/nosuch/button") << "Button.qml" << "NoSuchStyle" << dataDirectory() << "" << testFileUrl("Button.qml").toString();
- QTest::newRow("button->base") << "Button.qml" << "" << "data" << "FallbackStyle" << testFileUrl("FallbackStyle/Button.qml").toString();
+ QTest::newRow("button->base") << "Button.qml" << "" << "data" << "FallbackStyle" << testFileUrl("Button.qml").toString();
QTest::newRow("/button->base") << "Button.qml" << "" << dataDirectory() << "FallbackStyle" << testFileUrl("Button.qml").toString();
QTest::newRow("fs/button->base") << "Button.qml" << "FileSystemStyle" << "data" << "FallbackStyle" << testFileUrl("FileSystemStyle/Button.qml").toString();
QTest::newRow("/fs/button->base") << "Button.qml" << "FileSystemStyle" << dataDirectory() << "FallbackStyle" << testFileUrl("FileSystemStyle/Button.qml").toString();
@@ -137,7 +137,9 @@ void tst_QQuickStyleSelector::select()
QQuickStyle::setFallbackStyle(fallback);
QQuickStyleSelector selector;
- selector.setBaseUrl(dataDirectoryUrl());
+ selector.addSelector(style);
+ selector.addSelector(fallback);
+ selector.setPaths(QStringList() << dataDirectory() << ":/");
QCOMPARE(selector.select(file), expected);
}
@@ -146,7 +148,8 @@ void tst_QQuickStyleSelector::platformSelectors()
QQuickStyle::setStyle(QDir(dataDirectory()).filePath("PlatformStyle"));
QQuickStyleSelector selector;
- selector.setBaseUrl(dataDirectoryUrl());
+ selector.addSelector("PlatformStyle");
+ selector.setPaths(QStringList() << dataDirectory());
#if defined(Q_OS_LINUX)
QCOMPARE(selector.select("Button.qml"), testFileUrl("PlatformStyle/+linux/Button.qml").toString());