diff options
author | Mitch Curtis <mitch.curtis@qt.io> | 2020-04-17 14:32:55 +0200 |
---|---|---|
committer | Mitch Curtis <mitch.curtis@qt.io> | 2020-08-26 11:46:07 +0200 |
commit | 501bc44bb006ee8021cbaaa7a696e7c9263395d3 (patch) | |
tree | 6e266d07f3ef0b57dd19b4a7c505ed064ad01636 /tests/auto/qquickstyle | |
parent | 92879d8f6b8b840328813f29f758865a412af270 (diff) |
Use qmlRegisterModuleImport() to register styles
This patch completes the cumulative work done in previous patches.
- Uses qmlRegisterModuleImport() to register styles. This has some
added requirements:
- Each style must now be a QML module -- that is, it must have a
qmldir file.
- As a result of the above, the module must be available within the
QML import path in order to be found.
- The various forms of accepted style names have been reduced down to
one ("Material", "MyStyle", etc). See below for an explanation of
why.
- The following API in QQuickStyle is removed:
addStylePath(), availableStyles(), path(), stylePathList(). These
no longer make sense now that we reuse the existing QML import
system.
- Adds the tst_qquickstyleselector auto test back as "styleimports".
qmlRegisterModuleImport() vs resolvedUrl()
Previously we would use QQuickStyleSelector to select individual
QML files based on which style was set. We'd do this once when
QtQuick.Controls was first imported.
With Qt 6, and the requirement that each style be a proper QML
module, qmlRegisterModuleImport() was introduced. This allows us
to "link" one import with another. For an example of what this
looks like in practice, suppose the style was set to "MyStyle",
and the fallback to "Material". The "QtQuick.Controls" import
will be linked to "MyStyle", "MyStyle" to
"QtQuick.Controls.Material", and as a final fallback (for controls
like Action which only the Default style implements),
"QtQuick.Controls.Material" to "QtQuick.Controls.Default".
This is the same behavior as in Qt 5 (see qquickstyleselector.cpp):
// 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)
This is a necessary step to enable compilation of QML to C++.
Reducing the set of accepted style names
The problem
In QtQuickControls2Plugin() we need to call
QQuickStylePrivate::init(baseUrl()) in order to detect if the style
is a custom style in QQuickStyleSpec::resolve() (by checking if the
style path starts with the base URL). In Qt 5, init() is called in
QtQuickControls2Plugin::registerTypes(), but in Qt 6 that's too
late, because we need to call qmlRegisterModuleImport() in the
constructor. qmlRegisterModuleImport() itself requires the style to
have already been set in order to create the correct import URI
("QtQuick.Controls.X" for built-in styles, "MyCustomStyle" for
custom styles).
The solution
By reducing the valid forms for style names down to one:
./myapp -style MyStyle
we solve the problem of needing baseUrl() to determine if the
style is a custom style or not, but needing to call it too early
(since we now call qmlRegisterModuleImport() in
QtQuickControls2Plugin(), which itself requires the style to have
already been set). baseUrl() can't have been set before the
constructor is finished.
All of the various forms for _setting_ a style are still valid;
environment variables, qtquickcontrols2.conf, etc.
[ChangeLog][Important Behavior Changes] Custom styles must now have
a qmldir that lists the files that the style implements. For example,
for a style that only implements Button:
---
module MyStyle
Button 1.0 Button.qml
---
In addition, there is now only one valid, case-sensitive form for style
names: "Material", "MyStyle", etc.
These changes are done to help enable the compilation of QML code to
C++, as well as improve tooling capabilities.
[ChangeLog][Important Behavior Changes] The following API was removed:
- QQuickStyle::addStylePath()
- QQuickStyle::availableStyles()
- QQuickStyle::path()
- QQuickStyle::stylePathList()
- QT_QUICK_CONTROLS_STYLE_PATH
This API is no longer necessary and/or able to be provided now that
styles are treated as regular QML modules.
Task-number: QTBUG-82922
Change-Id: I3b281131903c7c3c1cf0616eb7486a872dccd730
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'tests/auto/qquickstyle')
-rw-r--r-- | tests/auto/qquickstyle/data/CmdLineArgStyle/Control.qml (renamed from tests/auto/qquickstyle/qrcStyles1/QrcStyle1/Button.qml) | 2 | ||||
-rw-r--r-- | tests/auto/qquickstyle/data/CmdLineArgStyle/qmldir | 2 | ||||
-rw-r--r-- | tests/auto/qquickstyle/data/Custom/Label.qml (renamed from tests/auto/qquickstyle/qrcStyles2/QrcStyle2/Button.qml) | 2 | ||||
-rw-r--r-- | tests/auto/qquickstyle/data/Custom/qmldir | 2 | ||||
-rw-r--r-- | tests/auto/qquickstyle/data/EnvVarFallbackStyle/Control.qml (renamed from tests/auto/qquickstyle/qrcStyles3/QrcStyle3/Button.qml) | 2 | ||||
-rw-r--r-- | tests/auto/qquickstyle/data/EnvVarFallbackStyle/qmldir | 2 | ||||
-rw-r--r-- | tests/auto/qquickstyle/data/EnvVarStyle/Control.qml (renamed from tests/auto/qquickstyle/qrcStyles4/QrcStyle4/Button.qml) | 2 | ||||
-rw-r--r-- | tests/auto/qquickstyle/data/EnvVarStyle/qmldir | 2 | ||||
-rw-r--r-- | tests/auto/qquickstyle/data/custom.conf | 2 | ||||
-rw-r--r-- | tests/auto/qquickstyle/qquickstyle.pro | 28 | ||||
-rw-r--r-- | tests/auto/qquickstyle/tst_qquickstyle.cpp | 190 |
11 files changed, 32 insertions, 204 deletions
diff --git a/tests/auto/qquickstyle/qrcStyles1/QrcStyle1/Button.qml b/tests/auto/qquickstyle/data/CmdLineArgStyle/Control.qml index dcacc011..744dcd8f 100644 --- a/tests/auto/qquickstyle/qrcStyles1/QrcStyle1/Button.qml +++ b/tests/auto/qquickstyle/data/CmdLineArgStyle/Control.qml @@ -1,2 +1,2 @@ import QtQuick.Templates as T -T.Button { } +T.Label {} diff --git a/tests/auto/qquickstyle/data/CmdLineArgStyle/qmldir b/tests/auto/qquickstyle/data/CmdLineArgStyle/qmldir new file mode 100644 index 00000000..c2cc85c2 --- /dev/null +++ b/tests/auto/qquickstyle/data/CmdLineArgStyle/qmldir @@ -0,0 +1,2 @@ +module CmdLineArgStyle +Control 1.0 Control.qml diff --git a/tests/auto/qquickstyle/qrcStyles2/QrcStyle2/Button.qml b/tests/auto/qquickstyle/data/Custom/Label.qml index dcacc011..744dcd8f 100644 --- a/tests/auto/qquickstyle/qrcStyles2/QrcStyle2/Button.qml +++ b/tests/auto/qquickstyle/data/Custom/Label.qml @@ -1,2 +1,2 @@ import QtQuick.Templates as T -T.Button { } +T.Label {} diff --git a/tests/auto/qquickstyle/data/Custom/qmldir b/tests/auto/qquickstyle/data/Custom/qmldir new file mode 100644 index 00000000..08de6fa8 --- /dev/null +++ b/tests/auto/qquickstyle/data/Custom/qmldir @@ -0,0 +1,2 @@ +module Custom +Label 1.0 Label.qml diff --git a/tests/auto/qquickstyle/qrcStyles3/QrcStyle3/Button.qml b/tests/auto/qquickstyle/data/EnvVarFallbackStyle/Control.qml index dcacc011..744dcd8f 100644 --- a/tests/auto/qquickstyle/qrcStyles3/QrcStyle3/Button.qml +++ b/tests/auto/qquickstyle/data/EnvVarFallbackStyle/Control.qml @@ -1,2 +1,2 @@ import QtQuick.Templates as T -T.Button { } +T.Label {} diff --git a/tests/auto/qquickstyle/data/EnvVarFallbackStyle/qmldir b/tests/auto/qquickstyle/data/EnvVarFallbackStyle/qmldir new file mode 100644 index 00000000..bebd8e07 --- /dev/null +++ b/tests/auto/qquickstyle/data/EnvVarFallbackStyle/qmldir @@ -0,0 +1,2 @@ +module EnvVarFallbackStyle +Control 1.0 Control.qml diff --git a/tests/auto/qquickstyle/qrcStyles4/QrcStyle4/Button.qml b/tests/auto/qquickstyle/data/EnvVarStyle/Control.qml index dcacc011..744dcd8f 100644 --- a/tests/auto/qquickstyle/qrcStyles4/QrcStyle4/Button.qml +++ b/tests/auto/qquickstyle/data/EnvVarStyle/Control.qml @@ -1,2 +1,2 @@ import QtQuick.Templates as T -T.Button { } +T.Label {} diff --git a/tests/auto/qquickstyle/data/EnvVarStyle/qmldir b/tests/auto/qquickstyle/data/EnvVarStyle/qmldir new file mode 100644 index 00000000..42223a19 --- /dev/null +++ b/tests/auto/qquickstyle/data/EnvVarStyle/qmldir @@ -0,0 +1,2 @@ +module EnvVarStyle +Control 1.0 Control.qml diff --git a/tests/auto/qquickstyle/data/custom.conf b/tests/auto/qquickstyle/data/custom.conf index 2230b452..ac79338c 100644 --- a/tests/auto/qquickstyle/data/custom.conf +++ b/tests/auto/qquickstyle/data/custom.conf @@ -1,5 +1,5 @@ [Controls] -Style=:/Custom +Style=Custom [Custom] Font\PixelSize=3 diff --git a/tests/auto/qquickstyle/qquickstyle.pro b/tests/auto/qquickstyle/qquickstyle.pro index ef1dd2e0..eed434b5 100644 --- a/tests/auto/qquickstyle/qquickstyle.pro +++ b/tests/auto/qquickstyle/qquickstyle.pro @@ -11,18 +11,16 @@ include (../shared/util.pri) TESTDATA = $$PWD/data/* -qrcStyles1.files = $$files(qrcStyles1/QrcStyle1/*.qml) -qrcStyles1.prefix = / -RESOURCES += qrcStyles1 - -qrcStyles2.files = $$files(qrcStyles2/QrcStyle2/*.qml) -qrcStyles2.prefix = / -RESOURCES += qrcStyles2 - -qrcStyles3.files = $$files(qrcStyles3/QrcStyle3/*.qml) -qrcStyles3.prefix = / -RESOURCES += qrcStyles3 - -qrcStyles4.files = $$files(qrcStyles4/QrcStyle4/*.qml) -qrcStyles4.prefix = / -RESOURCES += qrcStyles4 +OTHER_FILES += \ + data/CmdLineArgStyle/Control.qml \ + data/CmdLineArgStyle/qmldir \ + data/EnvVarStyle/Control.qml \ + data/EnvVarStyle/qmldir \ + data/EnvVarFallbackStyle/Control.qml \ + data/EnvVarFallbackStyle/qmldir + +custom.files = \ + data/Custom/Label.qml \ + data/Custom/qmldir +custom.prefix = / +RESOURCES += custom diff --git a/tests/auto/qquickstyle/tst_qquickstyle.cpp b/tests/auto/qquickstyle/tst_qquickstyle.cpp index 48cc88b7..e675d335 100644 --- a/tests/auto/qquickstyle/tst_qquickstyle.cpp +++ b/tests/auto/qquickstyle/tst_qquickstyle.cpp @@ -57,11 +57,6 @@ private slots: void configurationFile(); void commandLineArgument(); void environmentVariables(); - void availableStyles(); - void qrcStylePaths_data(); - void qrcStylePaths(); - void qrcInQtQuickControlsStylePathEnvVar_data(); - void qrcInQtQuickControlsStylePathEnvVar(); private: void loadControls(); @@ -74,7 +69,6 @@ void tst_QQuickStyle::cleanup() QGuiApplicationPrivate::styleOverride.clear(); qunsetenv("QT_QUICK_CONTROLS_STYLE"); - qunsetenv("QT_QUICK_CONTROLS_STYLE_PATH"); qunsetenv("QT_QUICK_CONTROLS_FALLBACK_STYLE"); qunsetenv("QT_QUICK_CONTROLS_CONF"); } @@ -82,6 +76,7 @@ void tst_QQuickStyle::cleanup() void tst_QQuickStyle::loadControls() { QQmlEngine engine; + engine.addImportPath(dataDirectory()); QQmlComponent component(&engine); component.setData("import QtQuick 2.0; import QtQuick.Controls 2.1; Control { }", QUrl()); @@ -97,11 +92,9 @@ void tst_QQuickStyle::unloadControls() void tst_QQuickStyle::lookup() { QVERIFY(QQuickStyle::name().isEmpty()); - QVERIFY(!QQuickStyle::path().isEmpty()); - QQuickStyle::setStyle("material"); + QQuickStyle::setStyle("Material"); QCOMPARE(QQuickStyle::name(), QString("Material")); - QVERIFY(!QQuickStyle::path().isEmpty()); loadControls(); @@ -110,7 +103,6 @@ void tst_QQuickStyle::lookup() QCOMPARE(QQuickTheme::instance()->font(QQuickTheme::TextArea).pixelSize(), 16); QCOMPARE(QQuickStyle::name(), QString("Material")); - QVERIFY(!QQuickStyle::path().isEmpty()); } void tst_QQuickStyle::configurationFile_data() @@ -137,6 +129,7 @@ void tst_QQuickStyle::configurationFile() // Load a control. The import causes the configuration file to be read. QQmlEngine engine; + engine.addImportPath(":/data"); QQmlComponent labelComponent(&engine); labelComponent.setData("import QtQuick 2.0; import QtQuick.Controls 2.12; Label {}", QUrl()); @@ -144,8 +137,6 @@ void tst_QQuickStyle::configurationFile() QVERIFY2(!object.isNull(), qPrintable(labelComponent.errorString())); QCOMPARE(QQuickStyle::name(), expectedStyle); - if (!expectedPath.isEmpty()) - QCOMPARE(QQuickStyle::path(), expectedPath); // Test that fonts and palettes specified in configuration files are respected. QQuickLabel *label = qobject_cast<QQuickLabel *>(object.data()); @@ -169,179 +160,10 @@ void tst_QQuickStyle::environmentVariables() { qputenv("QT_QUICK_CONTROLS_STYLE", "EnvVarStyle"); qputenv("QT_QUICK_CONTROLS_FALLBACK_STYLE", "EnvVarFallbackStyle"); + QTest::ignoreMessage(QtWarningMsg, "QT_QUICK_CONTROLS_FALLBACK_STYLE: the specified fallback style" \ + " \"EnvVarFallbackStyle\" is not one of the built-in Qt Quick Controls 2 styles"); QCOMPARE(QQuickStyle::name(), QString("EnvVarStyle")); - QCOMPARE(QQuickStylePrivate::fallbackStyle(), QString("EnvVarFallbackStyle")); -} - -void tst_QQuickStyle::availableStyles() -{ - QString path = QFINDTESTDATA("data"); - QVERIFY(!path.isEmpty()); - - QQuickStyle::addStylePath(path); - QStringList paths = QQuickStylePrivate::stylePaths(); -#ifndef Q_OS_WIN - QVERIFY(paths.contains(path)); -#else - QVERIFY(paths.contains(path, Qt::CaseInsensitive)); -#endif - - const QStringList styles = QQuickStyle::availableStyles(); - QVERIFY(!styles.isEmpty()); - QCOMPARE(styles.first(), QString("Default")); - QVERIFY(!styles.contains("designer")); - - // QTBUG-60973 - for (const QString &style : styles) { - QVERIFY2(!style.endsWith(".dSYM"), qPrintable(style)); - } -} - -void tst_QQuickStyle::qrcStylePaths_data() -{ - QTest::addColumn<QString>("stylePath"); - QTest::addColumn<QString>("expectedStyleName"); - - QTest::addRow("qrc:/qrcStyles1") << QString::fromLatin1("qrc:/qrcStyles1") << QString::fromLatin1("QrcStyle1"); - QTest::addRow(":/qrcStyles2") << QString::fromLatin1(":/qrcStyles2") << QString::fromLatin1("QrcStyle2"); -} - -void tst_QQuickStyle::qrcStylePaths() -{ - QFETCH(QString, stylePath); - QFETCH(QString, expectedStyleName); - - QQuickStyle::addStylePath(stylePath); - - const QStringList paths = QQuickStylePrivate::stylePaths(); - QString expectedStylePath = stylePath; - if (expectedStylePath.startsWith(QLatin1String("qrc"))) - expectedStylePath.remove(0, 3); - if (!paths.contains(expectedStylePath)) { - QString message; - QDebug stream(&message); - stream.nospace() << "QQuickStylePrivate::stylePaths() doesn't contain " << expectedStylePath << ":\n" << paths; - QFAIL(qPrintable(message)); - } - - const QStringList styles = QQuickStyle::availableStyles(); - QVERIFY(!styles.isEmpty()); - if (!styles.contains(expectedStyleName)) { - QString message; - QDebug stream(&message); - stream.nospace() << "QQuickStyle::availableStyles() doesn't contain " << expectedStyleName << ":\n" << styles; - QFAIL(qPrintable(message)); - } -} - -void tst_QQuickStyle::qrcInQtQuickControlsStylePathEnvVar_data() -{ - QTest::addColumn<QString>("environmentVariable"); - QTest::addColumn<QStringList>("expectedAvailableStyles"); - - const QChar listSeparator = QDir::listSeparator(); - const QStringList defaultAvailableStyles = QQuickStyle::availableStyles(); - - { - QString environmentVariable; - QDebug stream(&environmentVariable); - // We use qrcStyles3 and qrcStyles4 in order to not conflict with - // qrcStylePaths(), since we currently have no way of clearing customStylePaths. - stream.noquote().nospace() << "/some/bogus/path/" << listSeparator - << ":/qrcStyles3"; - - QStringList expectedAvailableStyles = defaultAvailableStyles; - // We need to keep the Default style at the start of the list, - // as that's what availableStyles() does. - expectedAvailableStyles.insert(1, QLatin1String("QrcStyle3")); - - QTest::addRow("%s", qPrintable(environmentVariable)) - << environmentVariable << expectedAvailableStyles; - } - - { - QString environmentVariable; - QDebug stream(&environmentVariable); - stream.noquote().nospace() << ":/qrcStyles4" << listSeparator - << "/some/bogus/path"; - - QStringList expectedAvailableStyles = defaultAvailableStyles; - expectedAvailableStyles.insert(1, QLatin1String("QrcStyle4")); - - QTest::addRow("%s", qPrintable(environmentVariable)) - << environmentVariable << expectedAvailableStyles; - } - - { - QString environmentVariable; - QDebug stream(&environmentVariable); - stream.noquote().nospace() << ":/qrcStyles3" << listSeparator - << ":/qrcStyles4" << listSeparator - << QFINDTESTDATA("data/dummyStyles"); - - QStringList expectedAvailableStyles = defaultAvailableStyles; - expectedAvailableStyles.insert(1, QLatin1String("DummyStyle")); - expectedAvailableStyles.insert(1, QLatin1String("QrcStyle4")); - expectedAvailableStyles.insert(1, QLatin1String("QrcStyle3")); - - QTest::addRow("%s", qPrintable(environmentVariable)) - << environmentVariable << expectedAvailableStyles; - } - - { - QString environmentVariable; - QDebug stream(&environmentVariable); - stream.noquote().nospace() << QFINDTESTDATA("data/dummyStyles") << listSeparator - << ":/qrcStyles3" << listSeparator - << ":/qrcStyles4"; - - QStringList expectedAvailableStyles = defaultAvailableStyles; - expectedAvailableStyles.insert(1, QLatin1String("QrcStyle4")); - expectedAvailableStyles.insert(1, QLatin1String("QrcStyle3")); - expectedAvailableStyles.insert(1, QLatin1String("DummyStyle")); - - QTest::addRow("%s", qPrintable(environmentVariable)) - << environmentVariable << expectedAvailableStyles; - } - - { - QString environmentVariable; - QDebug stream(&environmentVariable); - // Same as the last row, except it adds a superfluous separator - // to ensure that it handles it gracefully rather than failing an assertion. - stream.noquote().nospace() << QFINDTESTDATA("data/dummyStyles") << listSeparator - << ":/qrcStyles3" << listSeparator - << ":/qrcStyles4" << listSeparator; - - QStringList expectedAvailableStyles = defaultAvailableStyles; - expectedAvailableStyles.insert(1, QLatin1String("QrcStyle4")); - expectedAvailableStyles.insert(1, QLatin1String("QrcStyle3")); - expectedAvailableStyles.insert(1, QLatin1String("DummyStyle")); - - QTest::addRow("%s", qPrintable(environmentVariable)) - << environmentVariable << expectedAvailableStyles; - } -} - -/* - Tests that qrc paths work with QT_QUICK_CONTROLS_STYLE_PATH. -*/ -void tst_QQuickStyle::qrcInQtQuickControlsStylePathEnvVar() -{ - QFETCH(QString, environmentVariable); - QFETCH(QStringList, expectedAvailableStyles); - - qputenv("QT_QUICK_CONTROLS_STYLE_PATH", environmentVariable.toLocal8Bit()); - - const QStringList availableStyles = QQuickStyle::availableStyles(); - if (availableStyles != expectedAvailableStyles) { - QString failureMessage; - QDebug stream(&failureMessage); - stream << "Mismatch in actual vs expected available styles:" - << "\n Expected:" << expectedAvailableStyles - << "\n Actual:" << availableStyles; - QFAIL(qPrintable(failureMessage)); - } + QCOMPARE(QQuickStylePrivate::fallbackStyle(), QString()); } QTEST_MAIN(tst_QQuickStyle) |