aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorMitch Curtis <mitch.curtis@qt.io>2020-04-17 14:32:55 +0200
committerMitch Curtis <mitch.curtis@qt.io>2020-08-26 11:46:07 +0200
commit501bc44bb006ee8021cbaaa7a696e7c9263395d3 (patch)
tree6e266d07f3ef0b57dd19b4a7c505ed064ad01636 /tests
parent92879d8f6b8b840328813f29f758865a412af270 (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')
-rw-r--r--tests/auto/auto.pro1
-rw-r--r--tests/auto/customization/customization.pro2
-rw-r--r--tests/auto/customization/data/styles/empty/qmldir59
-rw-r--r--tests/auto/customization/data/styles/identified/qmldir59
-rw-r--r--tests/auto/customization/data/styles/incomplete/qmldir59
-rw-r--r--tests/auto/customization/data/styles/override/qmldir59
-rw-r--r--tests/auto/customization/data/styles/simple/qmldir59
-rw-r--r--tests/auto/customization/tst_customization.cpp14
-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/qmldir2
-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/qmldir2
-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/qmldir2
-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/qmldir2
-rw-r--r--tests/auto/qquickstyle/data/custom.conf2
-rw-r--r--tests/auto/qquickstyle/qquickstyle.pro28
-rw-r--r--tests/auto/qquickstyle/tst_qquickstyle.cpp190
-rw-r--r--tests/auto/sanity/BLACKLIST4
-rw-r--r--tests/auto/sanity/sanity.pro2
-rw-r--r--tests/auto/sanity/tst_sanity.cpp367
-rw-r--r--tests/auto/shared/qtest_quickcontrols.h3
-rw-r--r--tests/auto/shared/util.pri2
-rw-r--r--tests/auto/shared/visualtestutil.cpp17
-rw-r--r--tests/auto/shared/visualtestutil.h33
-rw-r--r--tests/auto/snippets/snippets.pro2
-rw-r--r--tests/auto/snippets/tst_snippets.cpp13
-rw-r--r--tests/auto/styleimports/ResourceStyle/Button.qml4
-rw-r--r--tests/auto/styleimports/ResourceStyle/qmldir2
-rw-r--r--tests/auto/styleimports/data/Action.qml4
-rw-r--r--tests/auto/styleimports/data/Button.qml4
-rw-r--r--tests/auto/styleimports/data/FileSystemStyle/Button.qml4
-rw-r--r--tests/auto/styleimports/data/FileSystemStyle/qmldir2
-rw-r--r--tests/auto/styleimports/data/Label.qml4
-rw-r--r--tests/auto/styleimports/data/PlatformStyle/+linux/Button.qml4
-rw-r--r--tests/auto/styleimports/data/PlatformStyle/+macos/Button.qml4
-rw-r--r--tests/auto/styleimports/data/PlatformStyle/+windows/Button.qml4
-rw-r--r--tests/auto/styleimports/data/PlatformStyle/Button.qml4
-rw-r--r--tests/auto/styleimports/data/PlatformStyle/qmldir2
-rw-r--r--tests/auto/styleimports/data/platformSelectors.qml64
-rw-r--r--tests/auto/styleimports/data/qmldir4
-rw-r--r--tests/auto/styleimports/styleimports.pro29
-rw-r--r--tests/auto/styleimports/tst_styleimports.cpp205
-rw-r--r--tests/benchmarks/creationtime/creationtime.pro2
-rw-r--r--tests/benchmarks/creationtime/tst_creationtime.cpp53
-rw-r--r--tests/benchmarks/objectcount/tst_objectcount.cpp2
-rw-r--r--tests/manual/testbench/main.cpp3
-rw-r--r--tests/manual/testbench/testbench.pro2
49 files changed, 1118 insertions, 279 deletions
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index e41723ea..28d00c2a 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -29,4 +29,5 @@ SUBDIRS += \
revisions \
sanity \
snippets \
+ styleimports \
translation
diff --git a/tests/auto/customization/customization.pro b/tests/auto/customization/customization.pro
index 472367a3..e40e4d05 100644
--- a/tests/auto/customization/customization.pro
+++ b/tests/auto/customization/customization.pro
@@ -4,7 +4,7 @@ SOURCES += tst_customization.cpp
macos:CONFIG -= app_bundle
-QT += core-private gui-private qml-private quick-private testlib quicktemplates2-private quickcontrols2
+QT += core-private gui-private qml-private quick-private testlib quicktemplates2-private quickcontrols2 quickcontrols2-private
include (../shared/util.pri)
diff --git a/tests/auto/customization/data/styles/empty/qmldir b/tests/auto/customization/data/styles/empty/qmldir
new file mode 100644
index 00000000..a5fcc4c7
--- /dev/null
+++ b/tests/auto/customization/data/styles/empty/qmldir
@@ -0,0 +1,59 @@
+module empty
+
+AbstractButton 6.0 AbstractButton.qml
+Action 6.0 Action.qml
+ActionGroup 6.0 ActionGroup.qml
+ApplicationWindow 6.0 ApplicationWindow.qml
+BusyIndicator 6.0 BusyIndicator.qml
+Button 6.0 Button.qml
+ButtonGroup 6.0 ButtonGroup.qml
+CheckBox 6.0 CheckBox.qml
+CheckDelegate 6.0 CheckDelegate.qml
+ComboBox 6.0 ComboBox.qml
+Container 6.0 Container.qml
+Control 6.0 Control.qml
+DelayButton 6.0 DelayButton.qml
+Dial 6.0 Dial.qml
+Dialog 6.0 Dialog.qml
+DialogButtonBox 6.0 DialogButtonBox.qml
+Drawer 6.0 Drawer.qml
+Frame 6.0 Frame.qml
+GroupBox 6.0 GroupBox.qml
+HorizontalHeaderView 6.0 HorizontalHeaderView.qml
+ItemDelegate 6.0 ItemDelegate.qml
+Label 6.0 Label.qml
+Menu 6.0 Menu.qml
+MenuBar 6.0 MenuBar.qml
+MenuBarItem 6.0 MenuBarItem.qml
+MenuItem 6.0 MenuItem.qml
+MenuSeparator 6.0 MenuSeparator.qml
+Page 6.0 Page.qml
+PageIndicator 6.0 PageIndicator.qml
+Pane 6.0 Pane.qml
+Popup 6.0 Popup.qml
+ProgressBar 6.0 ProgressBar.qml
+RadioButton 6.0 RadioButton.qml
+RadioDelegate 6.0 RadioDelegate.qml
+RangeSlider 6.0 RangeSlider.qml
+RoundButton 6.0 RoundButton.qml
+ScrollBar 6.0 ScrollBar.qml
+ScrollIndicator 6.0 ScrollIndicator.qml
+ScrollView 6.0 ScrollView.qml
+Slider 6.0 Slider.qml
+SpinBox 6.0 SpinBox.qml
+SplitView 6.0 SplitView.qml
+StackView 6.0 StackView.qml
+SwipeDelegate 6.0 SwipeDelegate.qml
+SwipeView 6.0 SwipeView.qml
+Switch 6.0 Switch.qml
+SwitchDelegate 6.0 SwitchDelegate.qml
+TabBar 6.0 TabBar.qml
+TabButton 6.0 TabButton.qml
+TextArea 6.0 TextArea.qml
+TextField 6.0 TextField.qml
+ToolBar 6.0 ToolBar.qml
+ToolButton 6.0 ToolButton.qml
+ToolSeparator 6.0 ToolSeparator.qml
+ToolTip 6.0 ToolTip.qml
+Tumbler 6.0 Tumbler.qml
+VerticalHeaderView 6.0 VerticalHeaderView.qml
diff --git a/tests/auto/customization/data/styles/identified/qmldir b/tests/auto/customization/data/styles/identified/qmldir
new file mode 100644
index 00000000..1ee2a92e
--- /dev/null
+++ b/tests/auto/customization/data/styles/identified/qmldir
@@ -0,0 +1,59 @@
+module identified
+
+AbstractButton 6.0 AbstractButton.qml
+Action 6.0 Action.qml
+ActionGroup 6.0 ActionGroup.qml
+ApplicationWindow 6.0 ApplicationWindow.qml
+BusyIndicator 6.0 BusyIndicator.qml
+Button 6.0 Button.qml
+ButtonGroup 6.0 ButtonGroup.qml
+CheckBox 6.0 CheckBox.qml
+CheckDelegate 6.0 CheckDelegate.qml
+ComboBox 6.0 ComboBox.qml
+Container 6.0 Container.qml
+Control 6.0 Control.qml
+DelayButton 6.0 DelayButton.qml
+Dial 6.0 Dial.qml
+Dialog 6.0 Dialog.qml
+DialogButtonBox 6.0 DialogButtonBox.qml
+Drawer 6.0 Drawer.qml
+Frame 6.0 Frame.qml
+GroupBox 6.0 GroupBox.qml
+HorizontalHeaderView 6.0 HorizontalHeaderView.qml
+ItemDelegate 6.0 ItemDelegate.qml
+Label 6.0 Label.qml
+Menu 6.0 Menu.qml
+MenuBar 6.0 MenuBar.qml
+MenuBarItem 6.0 MenuBarItem.qml
+MenuItem 6.0 MenuItem.qml
+MenuSeparator 6.0 MenuSeparator.qml
+Page 6.0 Page.qml
+PageIndicator 6.0 PageIndicator.qml
+Pane 6.0 Pane.qml
+Popup 6.0 Popup.qml
+ProgressBar 6.0 ProgressBar.qml
+RadioButton 6.0 RadioButton.qml
+RadioDelegate 6.0 RadioDelegate.qml
+RangeSlider 6.0 RangeSlider.qml
+RoundButton 6.0 RoundButton.qml
+ScrollBar 6.0 ScrollBar.qml
+ScrollIndicator 6.0 ScrollIndicator.qml
+ScrollView 6.0 ScrollView.qml
+Slider 6.0 Slider.qml
+SpinBox 6.0 SpinBox.qml
+SplitView 6.0 SplitView.qml
+StackView 6.0 StackView.qml
+SwipeDelegate 6.0 SwipeDelegate.qml
+SwipeView 6.0 SwipeView.qml
+Switch 6.0 Switch.qml
+SwitchDelegate 6.0 SwitchDelegate.qml
+TabBar 6.0 TabBar.qml
+TabButton 6.0 TabButton.qml
+TextArea 6.0 TextArea.qml
+TextField 6.0 TextField.qml
+ToolBar 6.0 ToolBar.qml
+ToolButton 6.0 ToolButton.qml
+ToolSeparator 6.0 ToolSeparator.qml
+ToolTip 6.0 ToolTip.qml
+Tumbler 6.0 Tumbler.qml
+VerticalHeaderView 6.0 VerticalHeaderView.qml
diff --git a/tests/auto/customization/data/styles/incomplete/qmldir b/tests/auto/customization/data/styles/incomplete/qmldir
new file mode 100644
index 00000000..e8813bd5
--- /dev/null
+++ b/tests/auto/customization/data/styles/incomplete/qmldir
@@ -0,0 +1,59 @@
+module incomplete
+
+AbstractButton 6.0 AbstractButton.qml
+Action 6.0 Action.qml
+ActionGroup 6.0 ActionGroup.qml
+ApplicationWindow 6.0 ApplicationWindow.qml
+BusyIndicator 6.0 BusyIndicator.qml
+Button 6.0 Button.qml
+ButtonGroup 6.0 ButtonGroup.qml
+CheckBox 6.0 CheckBox.qml
+CheckDelegate 6.0 CheckDelegate.qml
+ComboBox 6.0 ComboBox.qml
+Container 6.0 Container.qml
+Control 6.0 Control.qml
+DelayButton 6.0 DelayButton.qml
+Dial 6.0 Dial.qml
+Dialog 6.0 Dialog.qml
+DialogButtonBox 6.0 DialogButtonBox.qml
+Drawer 6.0 Drawer.qml
+Frame 6.0 Frame.qml
+GroupBox 6.0 GroupBox.qml
+HorizontalHeaderView 6.0 HorizontalHeaderView.qml
+ItemDelegate 6.0 ItemDelegate.qml
+Label 6.0 Label.qml
+Menu 6.0 Menu.qml
+MenuBar 6.0 MenuBar.qml
+MenuBarItem 6.0 MenuBarItem.qml
+MenuItem 6.0 MenuItem.qml
+MenuSeparator 6.0 MenuSeparator.qml
+Page 6.0 Page.qml
+PageIndicator 6.0 PageIndicator.qml
+Pane 6.0 Pane.qml
+Popup 6.0 Popup.qml
+ProgressBar 6.0 ProgressBar.qml
+RadioButton 6.0 RadioButton.qml
+RadioDelegate 6.0 RadioDelegate.qml
+RangeSlider 6.0 RangeSlider.qml
+RoundButton 6.0 RoundButton.qml
+ScrollBar 6.0 ScrollBar.qml
+ScrollIndicator 6.0 ScrollIndicator.qml
+ScrollView 6.0 ScrollView.qml
+Slider 6.0 Slider.qml
+SpinBox 6.0 SpinBox.qml
+SplitView 6.0 SplitView.qml
+StackView 6.0 StackView.qml
+SwipeDelegate 6.0 SwipeDelegate.qml
+SwipeView 6.0 SwipeView.qml
+Switch 6.0 Switch.qml
+SwitchDelegate 6.0 SwitchDelegate.qml
+TabBar 6.0 TabBar.qml
+TabButton 6.0 TabButton.qml
+TextArea 6.0 TextArea.qml
+TextField 6.0 TextField.qml
+ToolBar 6.0 ToolBar.qml
+ToolButton 6.0 ToolButton.qml
+ToolSeparator 6.0 ToolSeparator.qml
+ToolTip 6.0 ToolTip.qml
+Tumbler 6.0 Tumbler.qml
+VerticalHeaderView 6.0 VerticalHeaderView.qml
diff --git a/tests/auto/customization/data/styles/override/qmldir b/tests/auto/customization/data/styles/override/qmldir
new file mode 100644
index 00000000..f15ba96a
--- /dev/null
+++ b/tests/auto/customization/data/styles/override/qmldir
@@ -0,0 +1,59 @@
+module override
+
+AbstractButton 6.0 AbstractButton.qml
+Action 6.0 Action.qml
+ActionGroup 6.0 ActionGroup.qml
+ApplicationWindow 6.0 ApplicationWindow.qml
+BusyIndicator 6.0 BusyIndicator.qml
+Button 6.0 Button.qml
+ButtonGroup 6.0 ButtonGroup.qml
+CheckBox 6.0 CheckBox.qml
+CheckDelegate 6.0 CheckDelegate.qml
+ComboBox 6.0 ComboBox.qml
+Container 6.0 Container.qml
+Control 6.0 Control.qml
+DelayButton 6.0 DelayButton.qml
+Dial 6.0 Dial.qml
+Dialog 6.0 Dialog.qml
+DialogButtonBox 6.0 DialogButtonBox.qml
+Drawer 6.0 Drawer.qml
+Frame 6.0 Frame.qml
+GroupBox 6.0 GroupBox.qml
+HorizontalHeaderView 6.0 HorizontalHeaderView.qml
+ItemDelegate 6.0 ItemDelegate.qml
+Label 6.0 Label.qml
+Menu 6.0 Menu.qml
+MenuBar 6.0 MenuBar.qml
+MenuBarItem 6.0 MenuBarItem.qml
+MenuItem 6.0 MenuItem.qml
+MenuSeparator 6.0 MenuSeparator.qml
+Page 6.0 Page.qml
+PageIndicator 6.0 PageIndicator.qml
+Pane 6.0 Pane.qml
+Popup 6.0 Popup.qml
+ProgressBar 6.0 ProgressBar.qml
+RadioButton 6.0 RadioButton.qml
+RadioDelegate 6.0 RadioDelegate.qml
+RangeSlider 6.0 RangeSlider.qml
+RoundButton 6.0 RoundButton.qml
+ScrollBar 6.0 ScrollBar.qml
+ScrollIndicator 6.0 ScrollIndicator.qml
+ScrollView 6.0 ScrollView.qml
+Slider 6.0 Slider.qml
+SpinBox 6.0 SpinBox.qml
+SplitView 6.0 SplitView.qml
+StackView 6.0 StackView.qml
+SwipeDelegate 6.0 SwipeDelegate.qml
+SwipeView 6.0 SwipeView.qml
+Switch 6.0 Switch.qml
+SwitchDelegate 6.0 SwitchDelegate.qml
+TabBar 6.0 TabBar.qml
+TabButton 6.0 TabButton.qml
+TextArea 6.0 TextArea.qml
+TextField 6.0 TextField.qml
+ToolBar 6.0 ToolBar.qml
+ToolButton 6.0 ToolButton.qml
+ToolSeparator 6.0 ToolSeparator.qml
+ToolTip 6.0 ToolTip.qml
+Tumbler 6.0 Tumbler.qml
+VerticalHeaderView 6.0 VerticalHeaderView.qml
diff --git a/tests/auto/customization/data/styles/simple/qmldir b/tests/auto/customization/data/styles/simple/qmldir
new file mode 100644
index 00000000..e5159885
--- /dev/null
+++ b/tests/auto/customization/data/styles/simple/qmldir
@@ -0,0 +1,59 @@
+module simple
+
+AbstractButton 6.0 AbstractButton.qml
+Action 6.0 Action.qml
+ActionGroup 6.0 ActionGroup.qml
+ApplicationWindow 6.0 ApplicationWindow.qml
+BusyIndicator 6.0 BusyIndicator.qml
+Button 6.0 Button.qml
+ButtonGroup 6.0 ButtonGroup.qml
+CheckBox 6.0 CheckBox.qml
+CheckDelegate 6.0 CheckDelegate.qml
+ComboBox 6.0 ComboBox.qml
+Container 6.0 Container.qml
+Control 6.0 Control.qml
+DelayButton 6.0 DelayButton.qml
+Dial 6.0 Dial.qml
+Dialog 6.0 Dialog.qml
+DialogButtonBox 6.0 DialogButtonBox.qml
+Drawer 6.0 Drawer.qml
+Frame 6.0 Frame.qml
+GroupBox 6.0 GroupBox.qml
+HorizontalHeaderView 6.0 HorizontalHeaderView.qml
+ItemDelegate 6.0 ItemDelegate.qml
+Label 6.0 Label.qml
+Menu 6.0 Menu.qml
+MenuBar 6.0 MenuBar.qml
+MenuBarItem 6.0 MenuBarItem.qml
+MenuItem 6.0 MenuItem.qml
+MenuSeparator 6.0 MenuSeparator.qml
+Page 6.0 Page.qml
+PageIndicator 6.0 PageIndicator.qml
+Pane 6.0 Pane.qml
+Popup 6.0 Popup.qml
+ProgressBar 6.0 ProgressBar.qml
+RadioButton 6.0 RadioButton.qml
+RadioDelegate 6.0 RadioDelegate.qml
+RangeSlider 6.0 RangeSlider.qml
+RoundButton 6.0 RoundButton.qml
+ScrollBar 6.0 ScrollBar.qml
+ScrollIndicator 6.0 ScrollIndicator.qml
+ScrollView 6.0 ScrollView.qml
+Slider 6.0 Slider.qml
+SpinBox 6.0 SpinBox.qml
+SplitView 6.0 SplitView.qml
+StackView 6.0 StackView.qml
+SwipeDelegate 6.0 SwipeDelegate.qml
+SwipeView 6.0 SwipeView.qml
+Switch 6.0 Switch.qml
+SwitchDelegate 6.0 SwitchDelegate.qml
+TabBar 6.0 TabBar.qml
+TabButton 6.0 TabButton.qml
+TextArea 6.0 TextArea.qml
+TextField 6.0 TextField.qml
+ToolBar 6.0 ToolBar.qml
+ToolButton 6.0 ToolButton.qml
+ToolSeparator 6.0 ToolSeparator.qml
+ToolTip 6.0 ToolTip.qml
+Tumbler 6.0 Tumbler.qml
+VerticalHeaderView 6.0 VerticalHeaderView.qml
diff --git a/tests/auto/customization/tst_customization.cpp b/tests/auto/customization/tst_customization.cpp
index 6cb3d82c..add48cc7 100644
--- a/tests/auto/customization/tst_customization.cpp
+++ b/tests/auto/customization/tst_customization.cpp
@@ -42,6 +42,7 @@
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickwindow.h>
#include <QtQuickControls2/qquickstyle.h>
+#include <QtQuickControls2/private/qquickstyle_p.h>
#include <QtQuickTemplates2/private/qquickcontrol_p_p.h>
#include "../shared/visualtestutil.h"
@@ -227,6 +228,7 @@ void tst_customization::cleanupTestCase()
void tst_customization::init()
{
engine = new QQmlEngine(this);
+ engine->addImportPath(testFile("styles"));
qtHookData[QHooks::AddQObject] = reinterpret_cast<quintptr>(&qt_addQObject);
qtHookData[QHooks::RemoveQObject] = reinterpret_cast<quintptr>(&qt_removeQObject);
@@ -296,7 +298,7 @@ void tst_customization::creation()
QFETCH(QString, type);
QFETCH(QStringList, delegates);
- QQuickStyle::setStyle(testFile("styles/" + style));
+ QQuickStyle::setStyle(style);
QString error;
QScopedPointer<QObject> control(createControl(type, "", &error));
@@ -363,7 +365,7 @@ void tst_customization::override_data()
#ifndef Q_OS_MACOS // QTBUG-65671
// test that the built-in styles don't have undesired IDs in their delegates
- const QStringList styles = QStringList() << "Default" << "Fusion" << "Material" << "Universal"; // ### TODO: QQuickStyle::availableStyles();
+ const QStringList styles = QQuickStylePrivate::builtInStyles();
for (const QString &style : styles) {
for (const ControlInfo &control : ControlInfos)
QTest::newRow(qPrintable(style + ":" + control.type)) << style << control.type << control.delegates << "" << false;
@@ -380,11 +382,7 @@ void tst_customization::override()
QFETCH(QString, nonDeferred);
QFETCH(bool, identify);
- const QString testStyle = testFile("styles/" + style);
- if (QDir(testStyle).exists())
- QQuickStyle::setStyle(testStyle);
- else
- QQuickStyle::setStyle(style);
+ QQuickStyle::setStyle(style);
QString qml;
qml += QString("objectName: '%1-%2-override'; ").arg(type.toLower()).arg(style);
@@ -478,7 +476,7 @@ void tst_customization::override()
void tst_customization::comboPopup()
{
- QQuickStyle::setStyle(testFile("styles/simple"));
+ QQuickStyle::setStyle("simple");
{
// test that ComboBox::popup is created when accessed
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)
diff --git a/tests/auto/sanity/BLACKLIST b/tests/auto/sanity/BLACKLIST
index 2a157b87..d6d4b0d9 100644
--- a/tests/auto/sanity/BLACKLIST
+++ b/tests/auto/sanity/BLACKLIST
@@ -2,9 +2,9 @@
*
[attachedObjects:material/SwitchDelegate.qml]
*
-[ids:controls/HorizontalHeaderView.qml]
+[ids:default/HorizontalHeaderView.qml]
*
-[ids:controls/VerticalHeaderView.qml]
+[ids:default/VerticalHeaderView.qml]
*
[ids:fusion/HorizontalHeaderView.qml]
*
diff --git a/tests/auto/sanity/sanity.pro b/tests/auto/sanity/sanity.pro
index c792c073..d7bf5d87 100644
--- a/tests/auto/sanity/sanity.pro
+++ b/tests/auto/sanity/sanity.pro
@@ -1,7 +1,7 @@
TEMPLATE = app
TARGET = tst_sanity
-QT += qml testlib core-private qml-private
+QT += qml testlib core-private qml-private quickcontrols2
CONFIG += testcase
macos:CONFIG -= app_bundle
diff --git a/tests/auto/sanity/tst_sanity.cpp b/tests/auto/sanity/tst_sanity.cpp
index f2135fa4..5dc0676c 100644
--- a/tests/auto/sanity/tst_sanity.cpp
+++ b/tests/auto/sanity/tst_sanity.cpp
@@ -37,6 +37,9 @@
#include <QtTest>
#include <QtQml>
#include <QtCore/private/qhooks_p.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qscopedpointer.h>
+#include <QtCore/qset.h>
#include <QtQml/private/qqmljsengine_p.h>
#include <QtQml/private/qqmljslexer_p.h>
#include <QtQml/private/qqmljsparser_p.h>
@@ -81,8 +84,9 @@ private slots:
void ids_data();
private:
- QQmlEngine engine;
- QMap<QString, QString> files;
+ QMap<QString, QString> sourceQmlFiles;
+ QMap<QString, QString> installedQmlFiles;
+ QQuickStyleHelper styleHelper;
};
void tst_Sanity::init()
@@ -160,19 +164,34 @@ void tst_Sanity::initTestCase()
const QStringList qmlTypeNames = QQmlMetaType::qmlTypeNames();
+ // Collect the files from each style in the source tree.
QDirIterator it(QQC2_IMPORT_PATH, QStringList() << "*.qml" << "*.js", QDir::Files, QDirIterator::Subdirectories);
while (it.hasNext()) {
it.next();
QFileInfo info = it.fileInfo();
if (qmlTypeNames.contains(QStringLiteral("QtQuick.Templates/") + info.baseName()))
- files.insert(info.dir().dirName() + "/" + info.fileName(), info.filePath());
+ sourceQmlFiles.insert(info.dir().dirName() + "/" + info.fileName(), info.filePath());
+ }
+
+ // Then, collect the files from each installed style directory.
+ const QVector<QPair<QString, QString>> styleRelativePaths = {
+ { "controls/default", "QtQuick/Controls/Default" },
+ { "controls/fusion", "QtQuick/Controls/Fusion" },
+ { "controls/material", "QtQuick/Controls/Material" },
+ { "controls/universal", "QtQuick/Controls/Universal" },
+ };
+ for (const auto stylePathPair : styleRelativePaths) {
+ forEachControl(&engine, stylePathPair.first, stylePathPair.second, QStringList(),
+ [&](const QString &relativePath, const QUrl &absoluteUrl) {
+ installedQmlFiles.insert(relativePath, absoluteUrl.toLocalFile());
+ });
}
}
void tst_Sanity::jsFiles()
{
QMap<QString, QString>::const_iterator it;
- for (it = files.constBegin(); it != files.constEnd(); ++it) {
+ for (it = sourceQmlFiles.constBegin(); it != sourceQmlFiles.constEnd(); ++it) {
if (QFileInfo(it.value()).suffix() == QStringLiteral("js"))
QFAIL(qPrintable(it.value() + ": JS files are not allowed"));
}
@@ -204,7 +223,7 @@ void tst_Sanity::functions_data()
QTest::addColumn<QString>("filePath");
QMap<QString, QString>::const_iterator it;
- for (it = files.constBegin(); it != files.constEnd(); ++it)
+ for (it = sourceQmlFiles.constBegin(); it != sourceQmlFiles.constEnd(); ++it)
QTest::newRow(qPrintable(it.key())) << it.key() << it.value();
}
@@ -241,7 +260,7 @@ void tst_Sanity::signalHandlers_data()
QTest::addColumn<QString>("filePath");
QMap<QString, QString>::const_iterator it;
- for (it = files.constBegin(); it != files.constEnd(); ++it)
+ for (it = sourceQmlFiles.constBegin(); it != sourceQmlFiles.constEnd(); ++it)
QTest::newRow(qPrintable(it.key())) << it.key() << it.value();
}
@@ -273,7 +292,7 @@ void tst_Sanity::anchors_data()
QTest::addColumn<QString>("filePath");
QMap<QString, QString>::const_iterator it;
- for (it = files.constBegin(); it != files.constEnd(); ++it)
+ for (it = sourceQmlFiles.constBegin(); it != sourceQmlFiles.constEnd(); ++it)
QTest::newRow(qPrintable(it.key())) << it.key() << it.value();
}
@@ -338,37 +357,339 @@ void tst_Sanity::ids_data()
QTest::addColumn<QString>("filePath");
QMap<QString, QString>::const_iterator it;
- for (it = files.constBegin(); it != files.constEnd(); ++it)
+ for (it = sourceQmlFiles.constBegin(); it != sourceQmlFiles.constEnd(); ++it)
QTest::newRow(qPrintable(it.key())) << it.key() << it.value();
}
+typedef QPair<QString, QString> StringPair;
+typedef QSet<StringPair> StringPairSet;
+
void tst_Sanity::attachedObjects()
{
- QFETCH(QUrl, url);
+ QFETCH(QStringList, ignoredAttachedClassNames);
+ QFETCH(StringPairSet, expectedAttachedClassNames);
- QQmlComponent component(&engine);
- component.loadUrl(url);
+ const QString tagStr = QString::fromLatin1(QTest::currentDataTag());
+ QStringList styleAndFileName = tagStr.split('/');
+ QCOMPARE(styleAndFileName.size(), 2);
+ QString style = styleAndFileName.first();
+
+ if (styleHelper.updateStyle(style))
+ qt_qobjects->clear();
+
+ // Turn e.g. "Default/Button.qml" into "default/Button.qml".
+ QString styleRelativePath = tagStr;
+ styleRelativePath[0] = styleRelativePath.at(0).toLower();
+ // Get the absolute path to the installed file.
+ const QString controlFilePath = installedQmlFiles.value(styleRelativePath);
+
+ QQmlComponent component(styleHelper.engine.data());
+ component.loadUrl(QUrl::fromLocalFile(controlFilePath));
- QSet<QString> classNames;
QScopedPointer<QObject> object(component.create());
QVERIFY2(object.data(), qPrintable(component.errorString()));
- for (QObject *object : qAsConst(*qt_qobjects)) {
- if (object->parent() == &engine)
+
+ // The goal of this test is to check that every unique attached type is used only once
+ // within each QML file. To track this, we remove expected pairs of class names as we
+ // encounter them, so that we know when something unexpected shows up.
+ StringPairSet remainingAttachedClassNames = expectedAttachedClassNames;
+
+ // Intentional copy, as QDebug creates a QObject-derived instance which would modify the list.
+ const auto qobjectsCopy = *qt_qobjects;
+ for (QObject *object : qobjectsCopy) {
+ const QString attachedClassName = object->metaObject()->className();
+ if (object->parent() == styleHelper.engine.data())
continue; // allow "global" instances
- QString className = object->metaObject()->className();
- if (className.endsWith("Attached") || className.endsWith("Style"))
- QVERIFY2(!classNames.contains(className), qPrintable(QString("Multiple %1 instances").arg(className)));
- classNames.insert(className);
+
+ // objects without parents would be singletons such as QQuickFusionStyle, and we're not interested in them.
+ if ((attachedClassName.endsWith("Attached") || attachedClassName.endsWith("Style")) && object->parent()) {
+ QString attacheeClassName = QString::fromLatin1(object->parent()->metaObject()->className());
+ const QString qmlTypeToken = QStringLiteral("QMLTYPE");
+ if (attacheeClassName.contains(qmlTypeToken)) {
+ // Remove the numbers from the class name, as they can change between runs; e.g.:
+ // Menu_QMLTYPE_222 => Menu_QMLTYPE
+ const int qmlTypeTokenIndex = attacheeClassName.indexOf(qmlTypeToken);
+ QVERIFY(qmlTypeTokenIndex != -1);
+ attacheeClassName = attacheeClassName.mid(0, attacheeClassName.indexOf(qmlTypeToken) + qmlTypeToken.size());
+ }
+
+ const StringPair classNamePair = { attachedClassName, attacheeClassName };
+ QVERIFY2(remainingAttachedClassNames.contains(classNamePair), qPrintable(QString::fromLatin1(
+ "Found an unexpected usage of an attached type: %1 is attached to %2. Either an incorrect usage was added, or the list of expected usages needs to be updated. Expected attached class names for %3 are:\n %4")
+ .arg(attachedClassName).arg(attacheeClassName).arg(tagStr).arg(QDebug::toString(expectedAttachedClassNames))));
+ remainingAttachedClassNames.remove(classNamePair);
+ }
}
+
+ QVERIFY2(remainingAttachedClassNames.isEmpty(), qPrintable(QString::fromLatin1(
+ "Not all expected attached class name usages were found; the following usages are missing:\n %1")
+ .arg(QDebug::toString(remainingAttachedClassNames))));
}
void tst_Sanity::attachedObjects_data()
{
- QTest::addColumn<QUrl>("url");
- addTestRowForEachControl(&engine, "controls/default", "QtQuick/Controls/Default");
- addTestRowForEachControl(&engine, "controls/fusion", "QtQuick/Controls/Fusion", QStringList() << "CheckIndicator" << "RadioIndicator" << "SliderGroove" << "SliderHandle" << "SwitchIndicator");
- addTestRowForEachControl(&engine, "controls/material", "QtQuick/Controls/Material", QStringList() << "Ripple" << "SliderHandle" << "CheckIndicator" << "RadioIndicator" << "SwitchIndicator" << "BoxShadow" << "ElevationEffect" << "CursorDelegate");
- addTestRowForEachControl(&engine, "controls/universal", "QtQuick/Controls/Universal", QStringList() << "CheckIndicator" << "RadioIndicator" << "SwitchIndicator");
+ QTest::addColumn<QStringList>("ignoredAttachedClassNames");
+ QTest::addColumn<StringPairSet>("expectedAttachedClassNames");
+
+ QStringList ignoredNames;
+
+ // We used to just check that there were no duplicate QMetaObject class names,
+ // but that doesn't account for attached objects loaded by composite controls,
+ // such as DialogButtonBox, which is loaded by Dialog.
+ // So now we list all controls and the attached types we expect them to use.
+
+ QTest::newRow("Default/AbstractButton.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/Action.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/ActionGroup.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/ApplicationWindow.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/BusyIndicator.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/Button.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/ButtonGroup.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/CheckBox.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/CheckDelegate.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/ComboBox.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/Container.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/Control.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/DelayButton.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/Dial.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/Dialog.qml") << ignoredNames << StringPairSet {{ "QQuickOverlayAttached", "Dialog_QMLTYPE" }};
+ QTest::newRow("Default/DialogButtonBox.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/Drawer.qml") << ignoredNames << StringPairSet {{ "QQuickOverlayAttached", "Drawer_QMLTYPE" }};
+ QTest::newRow("Default/Frame.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/GroupBox.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/HorizontalHeaderView.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/ItemDelegate.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/Label.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/Menu.qml") << ignoredNames << StringPairSet {
+ { "QQuickOverlayAttached", "Menu_QMLTYPE" },
+ { "QQuickScrollIndicatorAttached", "QQuickListView" },
+ { "QQuickWindowAttached", "QQuickListView" }
+ };
+ QTest::newRow("Default/MenuBar.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/MenuBarItem.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/MenuItem.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/MenuSeparator.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/Page.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/PageIndicator.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/Pane.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/Popup.qml") << ignoredNames << StringPairSet {{ "QQuickOverlayAttached", "Popup_QMLTYPE" }};
+ QTest::newRow("Default/ProgressBar.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/RadioButton.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/RadioDelegate.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/RangeSlider.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/RoundButton.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/ScrollBar.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/ScrollIndicator.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/ScrollView.qml") << ignoredNames << StringPairSet {{ "QQuickScrollBarAttached", "ScrollView_QMLTYPE" }};
+ QTest::newRow("Default/Slider.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/SpinBox.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/SplitView.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/StackView.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/SwipeDelegate.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/SwipeView.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/Switch.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/SwitchDelegate.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/TabBar.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/TabButton.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/TextArea.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/TextField.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/ToolBar.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/ToolButton.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/ToolSeparator.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/ToolTip.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/Tumbler.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Default/VerticalHeaderView.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/ApplicationWindow.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/BusyIndicator.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/Button.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/CheckBox.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/CheckDelegate.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/ComboBox.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/DelayButton.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/Dial.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/Dialog.qml") << ignoredNames << StringPairSet {{ "QQuickOverlayAttached", "Dialog_QMLTYPE" }};
+ QTest::newRow("Fusion/DialogButtonBox.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/Drawer.qml") << ignoredNames << StringPairSet {{ "QQuickOverlayAttached", "Drawer_QMLTYPE" }};
+ QTest::newRow("Fusion/Frame.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/GroupBox.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/HorizontalHeaderView.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/ItemDelegate.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/Label.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/Menu.qml") << ignoredNames << StringPairSet {
+ { "QQuickOverlayAttached", "Menu_QMLTYPE" },
+ { "QQuickScrollIndicatorAttached", "QQuickListView" },
+ { "QQuickWindowAttached", "QQuickListView" }
+ };
+ QTest::newRow("Fusion/MenuBar.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/MenuBarItem.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/MenuItem.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/MenuSeparator.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/Page.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/PageIndicator.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/Pane.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/Popup.qml") << ignoredNames << StringPairSet {{ "QQuickOverlayAttached", "Popup_QMLTYPE" }};
+ QTest::newRow("Fusion/ProgressBar.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/RadioButton.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/RadioDelegate.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/RangeSlider.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/RoundButton.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/ScrollBar.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/ScrollIndicator.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/Slider.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/SpinBox.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/SplitView.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/SwipeDelegate.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/Switch.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/SwitchDelegate.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/TabBar.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/TabButton.qml") << ignoredNames << StringPairSet {{ "QQuickTabBarAttached", "TabButton_QMLTYPE" }};
+ QTest::newRow("Fusion/TextArea.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/TextField.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/ToolBar.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/ToolButton.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/ToolSeparator.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/ToolTip.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/Tumbler.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Fusion/VerticalHeaderView.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Material/ApplicationWindow.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "ApplicationWindow_QMLTYPE" }};
+ QTest::newRow("Material/BusyIndicator.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "BusyIndicator_QMLTYPE" }};
+ QTest::newRow("Material/Button.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "Button_QMLTYPE" }};
+ QTest::newRow("Material/CheckBox.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "CheckBox_QMLTYPE" }};
+ QTest::newRow("Material/CheckDelegate.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "CheckDelegate_QMLTYPE" }};
+ QTest::newRow("Material/ComboBox.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "ComboBox_QMLTYPE" }};
+ QTest::newRow("Material/DelayButton.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "DelayButton_QMLTYPE" }};
+ QTest::newRow("Material/Dial.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "Dial_QMLTYPE" }};
+ QTest::newRow("Material/Dialog.qml") << ignoredNames << StringPairSet {
+ { "QQuickMaterialStyle", "DialogButtonBox_QMLTYPE" },
+ { "QQuickOverlayAttached", "Dialog_QMLTYPE" },
+ { "QQuickMaterialStyle", "Dialog_QMLTYPE" },
+ { "QQuickMaterialStyle", "Label_QMLTYPE" }
+ };
+ QTest::newRow("Material/DialogButtonBox.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "DialogButtonBox_QMLTYPE" }};
+ QTest::newRow("Material/Drawer.qml") << ignoredNames << StringPairSet {
+ { "QQuickOverlayAttached", "Drawer_QMLTYPE" },
+ { "QQuickMaterialStyle", "Drawer_QMLTYPE" }
+ };
+ QTest::newRow("Material/Frame.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "Frame_QMLTYPE" }};
+ QTest::newRow("Material/GroupBox.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "GroupBox_QMLTYPE" }};
+ QTest::newRow("Material/HorizontalHeaderView.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Material/ItemDelegate.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "ItemDelegate_QMLTYPE" }};
+ QTest::newRow("Material/Label.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "Label_QMLTYPE" }};
+ QTest::newRow("Material/Menu.qml") << ignoredNames << StringPairSet {
+ { "QQuickOverlayAttached", "Menu_QMLTYPE" },
+ { "QQuickMaterialStyle", "Menu_QMLTYPE" },
+ { "QQuickScrollIndicatorAttached", "QQuickListView" },
+ { "QQuickWindowAttached", "QQuickListView" },
+ { "QQuickMaterialStyle", "ScrollIndicator_QMLTYPE" }
+ };
+ QTest::newRow("Material/MenuBar.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "MenuBar_QMLTYPE" }};
+ QTest::newRow("Material/MenuBarItem.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "MenuBarItem_QMLTYPE" }};
+ QTest::newRow("Material/MenuItem.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "MenuItem_QMLTYPE" }};
+ QTest::newRow("Material/MenuSeparator.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "MenuSeparator_QMLTYPE" }};
+ QTest::newRow("Material/Page.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "Page_QMLTYPE" }};
+ QTest::newRow("Material/PageIndicator.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Material/Pane.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "Pane_QMLTYPE" }};
+ QTest::newRow("Material/Popup.qml") << ignoredNames << StringPairSet {
+ { "QQuickOverlayAttached", "Popup_QMLTYPE" },
+ { "QQuickMaterialStyle", "Popup_QMLTYPE" }
+ };
+ QTest::newRow("Material/ProgressBar.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "ProgressBar_QMLTYPE" }};
+ QTest::newRow("Material/RadioButton.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "RadioButton_QMLTYPE" }};
+ QTest::newRow("Material/RadioDelegate.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "RadioDelegate_QMLTYPE" }};
+ QTest::newRow("Material/RangeSlider.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "RangeSlider_QMLTYPE" }};
+ QTest::newRow("Material/RoundButton.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "RoundButton_QMLTYPE" }};
+ QTest::newRow("Material/ScrollBar.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "ScrollBar_QMLTYPE" }};
+ QTest::newRow("Material/ScrollIndicator.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "ScrollIndicator_QMLTYPE" }};
+ QTest::newRow("Material/Slider.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "Slider_QMLTYPE" }};
+ QTest::newRow("Material/SpinBox.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "SpinBox_QMLTYPE" }};
+ QTest::newRow("Material/SplitView.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Material/StackView.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Material/SwipeDelegate.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "SwipeDelegate_QMLTYPE" }};
+ QTest::newRow("Material/SwipeView.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Material/Switch.qml") << ignoredNames << StringPairSet {
+ { "QQuickMaterialStyle", "SwitchIndicator_QMLTYPE" },
+ { "QQuickMaterialStyle", "Switch_QMLTYPE" }
+ };
+ QTest::newRow("Material/SwitchDelegate.qml") << ignoredNames << StringPairSet {
+ { "QQuickMaterialStyle", "SwitchDelegate_QMLTYPE" },
+ { "QQuickMaterialStyle", "SwitchIndicator_QMLTYPE" }
+ };
+ QTest::newRow("Material/TabBar.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "TabBar_QMLTYPE" }};
+ QTest::newRow("Material/TabButton.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "TabButton_QMLTYPE" }};
+ QTest::newRow("Material/TextArea.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "TextArea_QMLTYPE" }};
+ QTest::newRow("Material/TextField.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "TextField_QMLTYPE" }};
+ QTest::newRow("Material/ToolBar.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "ToolBar_QMLTYPE" }};
+ QTest::newRow("Material/ToolButton.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "ToolButton_QMLTYPE" }};
+ QTest::newRow("Material/ToolSeparator.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "ToolSeparator_QMLTYPE" }};
+ QTest::newRow("Material/ToolTip.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "ToolTip_QMLTYPE" }};
+ QTest::newRow("Material/Tumbler.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Material/VerticalHeaderView.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Universal/ApplicationWindow.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "ApplicationWindow_QMLTYPE" }};
+ QTest::newRow("Universal/BusyIndicator.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "BusyIndicator_QMLTYPE" }};
+ QTest::newRow("Universal/Button.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "Button_QMLTYPE" }};
+ QTest::newRow("Universal/CheckBox.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "CheckBox_QMLTYPE" }};
+ QTest::newRow("Universal/CheckDelegate.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "CheckDelegate_QMLTYPE" }};
+ QTest::newRow("Universal/ComboBox.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "ComboBox_QMLTYPE" }};
+ QTest::newRow("Universal/DelayButton.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "DelayButton_QMLTYPE" }};
+ QTest::newRow("Universal/Dial.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "Dial_QMLTYPE" }};
+ QTest::newRow("Universal/Dialog.qml") << ignoredNames << StringPairSet {
+ { "QQuickOverlayAttached", "Dialog_QMLTYPE" },
+ { "QQuickUniversalStyle", "Label_QMLTYPE" },
+ { "QQuickUniversalStyle", "Dialog_QMLTYPE" },
+ { "QQuickUniversalStyle", "DialogButtonBox_QMLTYPE" }
+ };
+ QTest::newRow("Universal/DialogButtonBox.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "DialogButtonBox_QMLTYPE" }};
+ QTest::newRow("Universal/Drawer.qml") << ignoredNames << StringPairSet {
+ { "QQuickOverlayAttached", "Drawer_QMLTYPE" },
+ { "QQuickUniversalStyle", "Drawer_QMLTYPE" }
+ };
+ QTest::newRow("Universal/Frame.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "Frame_QMLTYPE" }};
+ QTest::newRow("Universal/GroupBox.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "GroupBox_QMLTYPE" }};
+ QTest::newRow("Universal/HorizontalHeaderView.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Universal/ItemDelegate.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "ItemDelegate_QMLTYPE" }};
+ QTest::newRow("Universal/Label.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "Label_QMLTYPE" }};
+ QTest::newRow("Universal/Menu.qml") << ignoredNames << StringPairSet {
+ { "QQuickOverlayAttached", "Menu_QMLTYPE" },
+ { "QQuickUniversalStyle", "Menu_QMLTYPE" },
+ { "QQuickScrollIndicatorAttached", "QQuickListView" },
+ { "QQuickWindowAttached", "QQuickListView" },
+ { "QQuickUniversalStyle", "ScrollIndicator_QMLTYPE" }
+ };
+ QTest::newRow("Universal/MenuBar.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "MenuBar_QMLTYPE" }};
+ QTest::newRow("Universal/MenuBarItem.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "MenuBarItem_QMLTYPE" }};
+ QTest::newRow("Universal/MenuItem.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "MenuItem_QMLTYPE" }};
+ QTest::newRow("Universal/MenuSeparator.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "MenuSeparator_QMLTYPE" }};
+ QTest::newRow("Universal/Page.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "Page_QMLTYPE" }};
+ QTest::newRow("Universal/PageIndicator.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Universal/Pane.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "Pane_QMLTYPE" }};
+ QTest::newRow("Universal/Popup.qml") << ignoredNames << StringPairSet {
+ { "QQuickOverlayAttached", "Popup_QMLTYPE" },
+ { "QQuickUniversalStyle", "Popup_QMLTYPE" }
+ };
+ QTest::newRow("Universal/ProgressBar.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "ProgressBar_QMLTYPE" }};
+ QTest::newRow("Universal/RadioButton.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "RadioButton_QMLTYPE" }};
+ QTest::newRow("Universal/RadioDelegate.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "RadioDelegate_QMLTYPE" }};
+ QTest::newRow("Universal/RangeSlider.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "RangeSlider_QMLTYPE" }};
+ QTest::newRow("Universal/RoundButton.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "RoundButton_QMLTYPE" }};
+ QTest::newRow("Universal/ScrollBar.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "ScrollBar_QMLTYPE" }};
+ QTest::newRow("Universal/ScrollIndicator.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "ScrollIndicator_QMLTYPE" }};
+ QTest::newRow("Universal/Slider.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "Slider_QMLTYPE" }};
+ QTest::newRow("Universal/SpinBox.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "SpinBox_QMLTYPE" }};
+ QTest::newRow("Universal/SplitView.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Universal/StackView.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Universal/SwipeDelegate.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "SwipeDelegate_QMLTYPE" }};
+ QTest::newRow("Universal/Switch.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "Switch_QMLTYPE" }};
+ QTest::newRow("Universal/SwitchDelegate.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "SwitchDelegate_QMLTYPE" }};
+ QTest::newRow("Universal/TabBar.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "TabBar_QMLTYPE" }};
+ QTest::newRow("Universal/TabButton.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "TabButton_QMLTYPE" }};
+ QTest::newRow("Universal/TextArea.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "TextArea_QMLTYPE" }};
+ QTest::newRow("Universal/TextField.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "TextField_QMLTYPE" }};
+ QTest::newRow("Universal/ToolBar.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "ToolBar_QMLTYPE" }};
+ QTest::newRow("Universal/ToolButton.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "ToolButton_QMLTYPE" }};
+ QTest::newRow("Universal/ToolSeparator.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "ToolSeparator_QMLTYPE" }};
+ QTest::newRow("Universal/ToolTip.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "ToolTip_QMLTYPE" }};
+ QTest::newRow("Universal/Tumbler.qml") << ignoredNames << StringPairSet {};
+ QTest::newRow("Universal/VerticalHeaderView.qml") << ignoredNames << StringPairSet {};
}
QTEST_MAIN(tst_Sanity)
diff --git a/tests/auto/shared/qtest_quickcontrols.h b/tests/auto/shared/qtest_quickcontrols.h
index 4a06c021..17e5a6d2 100644
--- a/tests/auto/shared/qtest_quickcontrols.h
+++ b/tests/auto/shared/qtest_quickcontrols.h
@@ -42,11 +42,12 @@
#include <QtGui/qguiapplication.h>
#include <QtQml/qqml.h>
#include <QtQuickControls2/qquickstyle.h>
+#include <QtQuickControls2/private/qquickstyle_p.h>
static QStringList testStyles()
{
if (QQuickStyle::name().isEmpty())
- return QQuickStyle::availableStyles();
+ return QQuickStylePrivate::builtInStyles();
return QStringList(QQuickStyle::name());
}
diff --git a/tests/auto/shared/util.pri b/tests/auto/shared/util.pri
index 99607a66..c2eb9f0a 100644
--- a/tests/auto/shared/util.pri
+++ b/tests/auto/shared/util.pri
@@ -1,4 +1,4 @@
-QT += testlib-private core-private gui-private qml-private quick-private quicktemplates2-private quickcontrols2
+QT += testlib-private core-private gui-private qml-private quick-private quicktemplates2-private quickcontrols2 quickcontrols2-private
HEADERS += $$PWD/visualtestutil.h \
$$PWD/util.h \
diff --git a/tests/auto/shared/visualtestutil.cpp b/tests/auto/shared/visualtestutil.cpp
index 1740a6a6..bfbf0a17 100644
--- a/tests/auto/shared/visualtestutil.cpp
+++ b/tests/auto/shared/visualtestutil.cpp
@@ -95,12 +95,12 @@ void QQuickVisualTestUtil::centerOnScreen(QQuickWindow *window)
window->setFramePosition(screenGeometry.center() - offset);
}
-void QQuickVisualTestUtil::addTestRowForEachControl(QQmlEngine *engine, const QString &sourcePath, const QString &targetPath, const QStringList &skiplist)
+void QQuickVisualTestUtil::forEachControl(QQmlEngine *engine, const QString &sourcePath, const QString &targetPath, const QStringList &skipList, QQuickVisualTestUtil::ForEachCallback callback)
{
// We cannot use QQmlComponent to load QML files directly from the source tree.
// For styles that use internal QML types (eg. material/Ripple.qml), the source
// dir would be added as an "implicit" import path overriding the actual import
- // path (qtbase/qml/QtQuick/Controls/Material). => The QML engine fails to load
+ // path (qtbase/qml/QtQuick/Controls.2/Material). => The QML engine fails to load
// the style C++ plugin from the implicit import path (the source dir).
//
// Therefore we only use the source tree for finding out the set of QML files that
@@ -111,7 +111,7 @@ void QQuickVisualTestUtil::addTestRowForEachControl(QQmlEngine *engine, const QS
const QFileInfoList entries = QDir(QQC2_IMPORT_PATH "/" + sourcePath).entryInfoList(QStringList("*.qml"), QDir::Files);
for (const QFileInfo &entry : entries) {
QString name = entry.baseName();
- if (!skiplist.contains(name)) {
+ if (!skipList.contains(name)) {
const auto importPathList = engine->importPathList();
for (const QString &importPath : importPathList) {
QString name = entry.dir().dirName() + "/" + entry.fileName();
@@ -119,13 +119,13 @@ void QQuickVisualTestUtil::addTestRowForEachControl(QQmlEngine *engine, const QS
if (filePath.startsWith(":"))
filePath.prepend("qrc");
if (QFile::exists(filePath)) {
- QTest::newRow(qPrintable(name)) << QUrl::fromLocalFile(filePath);
+ callback(name, QUrl::fromLocalFile(filePath));
break;
} else {
QUrl url(filePath);
filePath = QQmlFile::urlToLocalFileOrQrc(filePath);
if (!filePath.isEmpty() && QFile::exists(filePath)) {
- QTest::newRow(qPrintable(name)) << url;
+ callback(name, url);
break;
}
}
@@ -133,3 +133,10 @@ void QQuickVisualTestUtil::addTestRowForEachControl(QQmlEngine *engine, const QS
}
}
}
+
+void QQuickVisualTestUtil::addTestRowForEachControl(QQmlEngine *engine, const QString &sourcePath, const QString &targetPath, const QStringList &skipList)
+{
+ forEachControl(engine, sourcePath, targetPath, skipList, [&](const QString &relativePath, const QUrl &absoluteUrl) {
+ QTest::newRow(qPrintable(relativePath)) << absoluteUrl;
+ });
+}
diff --git a/tests/auto/shared/visualtestutil.h b/tests/auto/shared/visualtestutil.h
index e3f4075d..726daa27 100644
--- a/tests/auto/shared/visualtestutil.h
+++ b/tests/auto/shared/visualtestutil.h
@@ -37,11 +37,12 @@
#ifndef QQUICKVISUALTESTUTIL_H
#define QQUICKVISUALTESTUTIL_H
+#include <functional>
+
#include <QtQuick/QQuickItem>
#include <QtQml/QQmlExpression>
-
#include <QtQuick/private/qquickitem_p.h>
-
+#include <QtQuickControls2/qquickstyle.h>
#include <QtQuickTemplates2/private/qquickapplicationwindow_p.h>
#include "util.h"
@@ -162,7 +163,33 @@ namespace QQuickVisualTestUtil
QByteArray errorMessage;
};
- void addTestRowForEachControl(QQmlEngine *engine, const QString &sourcePath, const QString &targetPath, const QStringList &skiplist = QStringList());
+ struct QQuickStyleHelper
+ {
+ bool updateStyle(const QString &style)
+ {
+ // If it's not the first time a style has been set and the new style is not different, do nothing.
+ if (!currentStyle.isEmpty() && style == currentStyle)
+ return false;
+
+ engine.reset(new QQmlEngine);
+ currentStyle = style;
+ qmlClearTypeRegistrations();
+ QQuickStyle::setStyle(style);
+
+ QQmlComponent component(engine.data());
+ component.setData(QString("import QtQuick\nimport QtQuick.Controls\n Control { }").toUtf8(), QUrl());
+
+ return true;
+ }
+
+ QString currentStyle;
+ QScopedPointer<QQmlEngine> engine;
+ };
+
+ typedef std::function<void(const QString &/*relativePath*/, const QUrl &/*absoluteUrl*/)> ForEachCallback;
+
+ void forEachControl(QQmlEngine *engine, const QString &sourcePath, const QString &targetPath, const QStringList &skipList, ForEachCallback callback);
+ void addTestRowForEachControl(QQmlEngine *engine, const QString &sourcePath, const QString &targetPath, const QStringList &skipList = QStringList());
}
#define QQUICK_VERIFY_POLISH(item) \
diff --git a/tests/auto/snippets/snippets.pro b/tests/auto/snippets/snippets.pro
index 6f366f23..9fa65055 100644
--- a/tests/auto/snippets/snippets.pro
+++ b/tests/auto/snippets/snippets.pro
@@ -1,7 +1,7 @@
TEMPLATE = app
TARGET = tst_snippets
-QT += quick quickcontrols2 testlib
+QT += quick quickcontrols2 quickcontrols2-private testlib
CONFIG += testcase
macos:CONFIG -= app_bundle
diff --git a/tests/auto/snippets/tst_snippets.cpp b/tests/auto/snippets/tst_snippets.cpp
index 107759ce..1c420edb 100644
--- a/tests/auto/snippets/tst_snippets.cpp
+++ b/tests/auto/snippets/tst_snippets.cpp
@@ -36,7 +36,8 @@
#include <QtTest>
#include <QtQuick>
-#include <QtQuickControls2>
+#include <QtQuickControls2/qquickstyle.h>
+#include <QtQuickControls2/private/qquickstyle_p.h>
typedef QPair<QString, QString> QStringPair;
@@ -114,14 +115,14 @@ void tst_Snippets::verify()
if (takeScreenshots) {
const QString currentDataTag = QLatin1String(QTest::currentDataTag());
static const QString applicationStyle = QQuickStyle::name().isEmpty() ? "Default" : QQuickStyle::name();
- static const QStringList availableStyles = QQuickStyle::availableStyles();
+ static const QStringList builtInStyles = QQuickStylePrivate::builtInStyles();
bool isStyledSnippet = false;
const QString snippetStyle = currentDataTag.section("-", 1, 1);
- for (const QString &availableStyle : availableStyles) {
- if (!snippetStyle.compare(availableStyle, Qt::CaseInsensitive)) {
- if (applicationStyle != availableStyle)
- QSKIP(qPrintable(QString("%1 style specific snippet. Running with the %2 style.").arg(availableStyle, applicationStyle)));
+ for (const QString &style : builtInStyles) {
+ if (!snippetStyle.compare(style, Qt::CaseInsensitive)) {
+ if (applicationStyle != style)
+ QSKIP(qPrintable(QString("%1 style specific snippet. Running with the %2 style.").arg(style, applicationStyle)));
isStyledSnippet = true;
}
}
diff --git a/tests/auto/styleimports/ResourceStyle/Button.qml b/tests/auto/styleimports/ResourceStyle/Button.qml
new file mode 100644
index 00000000..2b9e5bb7
--- /dev/null
+++ b/tests/auto/styleimports/ResourceStyle/Button.qml
@@ -0,0 +1,4 @@
+import QtQuick.Templates 2.15 as T
+T.Button {
+ objectName: "ResourceStyle"
+}
diff --git a/tests/auto/styleimports/ResourceStyle/qmldir b/tests/auto/styleimports/ResourceStyle/qmldir
new file mode 100644
index 00000000..4cb1a835
--- /dev/null
+++ b/tests/auto/styleimports/ResourceStyle/qmldir
@@ -0,0 +1,2 @@
+module ResourceStyle
+Button 2.15 Button.qml
diff --git a/tests/auto/styleimports/data/Action.qml b/tests/auto/styleimports/data/Action.qml
new file mode 100644
index 00000000..62501292
--- /dev/null
+++ b/tests/auto/styleimports/data/Action.qml
@@ -0,0 +1,4 @@
+import QtQuick.Templates 2.15 as T
+T.Action {
+ objectName: "data"
+}
diff --git a/tests/auto/styleimports/data/Button.qml b/tests/auto/styleimports/data/Button.qml
new file mode 100644
index 00000000..f67719e3
--- /dev/null
+++ b/tests/auto/styleimports/data/Button.qml
@@ -0,0 +1,4 @@
+import QtQuick.Templates 2.15 as T
+T.Button {
+ objectName: "data"
+}
diff --git a/tests/auto/styleimports/data/FileSystemStyle/Button.qml b/tests/auto/styleimports/data/FileSystemStyle/Button.qml
new file mode 100644
index 00000000..a5719dd8
--- /dev/null
+++ b/tests/auto/styleimports/data/FileSystemStyle/Button.qml
@@ -0,0 +1,4 @@
+import QtQuick.Templates 2.15 as T
+T.Button {
+ objectName: "FileSystemStyle"
+}
diff --git a/tests/auto/styleimports/data/FileSystemStyle/qmldir b/tests/auto/styleimports/data/FileSystemStyle/qmldir
new file mode 100644
index 00000000..3c401588
--- /dev/null
+++ b/tests/auto/styleimports/data/FileSystemStyle/qmldir
@@ -0,0 +1,2 @@
+module FileSystemStyle
+Button 2.15 Button.qml
diff --git a/tests/auto/styleimports/data/Label.qml b/tests/auto/styleimports/data/Label.qml
new file mode 100644
index 00000000..b6d434ad
--- /dev/null
+++ b/tests/auto/styleimports/data/Label.qml
@@ -0,0 +1,4 @@
+import QtQuick.Templates 2.15 as T
+T.Label {
+ objectName: "data"
+}
diff --git a/tests/auto/styleimports/data/PlatformStyle/+linux/Button.qml b/tests/auto/styleimports/data/PlatformStyle/+linux/Button.qml
new file mode 100644
index 00000000..74e2a6f4
--- /dev/null
+++ b/tests/auto/styleimports/data/PlatformStyle/+linux/Button.qml
@@ -0,0 +1,4 @@
+import QtQuick.Templates 2.15 as T
+T.Button {
+ objectName: "PlatformStyle/+linux"
+}
diff --git a/tests/auto/styleimports/data/PlatformStyle/+macos/Button.qml b/tests/auto/styleimports/data/PlatformStyle/+macos/Button.qml
new file mode 100644
index 00000000..47fd788b
--- /dev/null
+++ b/tests/auto/styleimports/data/PlatformStyle/+macos/Button.qml
@@ -0,0 +1,4 @@
+import QtQuick.Templates 2.15 as T
+T.Button {
+ objectName: "PlatformStyle/+macos"
+}
diff --git a/tests/auto/styleimports/data/PlatformStyle/+windows/Button.qml b/tests/auto/styleimports/data/PlatformStyle/+windows/Button.qml
new file mode 100644
index 00000000..e5b56653
--- /dev/null
+++ b/tests/auto/styleimports/data/PlatformStyle/+windows/Button.qml
@@ -0,0 +1,4 @@
+import QtQuick.Templates 2.15 as T
+T.Button {
+ objectName: "PlatformStyle/+windows"
+}
diff --git a/tests/auto/styleimports/data/PlatformStyle/Button.qml b/tests/auto/styleimports/data/PlatformStyle/Button.qml
new file mode 100644
index 00000000..fd1dc83d
--- /dev/null
+++ b/tests/auto/styleimports/data/PlatformStyle/Button.qml
@@ -0,0 +1,4 @@
+import QtQuick.Templates 2.15 as T
+T.Button {
+ objectName: "PlatformStyle/Button.qml"
+}
diff --git a/tests/auto/styleimports/data/PlatformStyle/qmldir b/tests/auto/styleimports/data/PlatformStyle/qmldir
new file mode 100644
index 00000000..ce254517
--- /dev/null
+++ b/tests/auto/styleimports/data/PlatformStyle/qmldir
@@ -0,0 +1,2 @@
+module PlatformStyle
+Button 2.15 Button.qml
diff --git a/tests/auto/styleimports/data/platformSelectors.qml b/tests/auto/styleimports/data/platformSelectors.qml
new file mode 100644
index 00000000..ba6af22c
--- /dev/null
+++ b/tests/auto/styleimports/data/platformSelectors.qml
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ title: "Test Application Window"
+ width: 400
+ height: 400
+
+ property alias button: button
+
+ Button {
+ id: button
+ }
+}
diff --git a/tests/auto/styleimports/data/qmldir b/tests/auto/styleimports/data/qmldir
new file mode 100644
index 00000000..9e9df940
--- /dev/null
+++ b/tests/auto/styleimports/data/qmldir
@@ -0,0 +1,4 @@
+module data
+Action 2.15 Action.qml
+Button 2.15 Button.qml
+Label 2.15 Label.qml
diff --git a/tests/auto/styleimports/styleimports.pro b/tests/auto/styleimports/styleimports.pro
new file mode 100644
index 00000000..774d93e9
--- /dev/null
+++ b/tests/auto/styleimports/styleimports.pro
@@ -0,0 +1,29 @@
+CONFIG += testcase
+TARGET = tst_styleimports
+SOURCES += tst_styleimports.cpp
+
+macos:CONFIG -= app_bundle
+
+QT += core-private gui-private qml-private quick-private quickcontrols2-private testlib
+
+include (../shared/util.pri)
+
+resourcestyle.prefix = /
+resourcestyle.files += \
+ $$PWD/ResourceStyle/Button.qml \
+ $$PWD/ResourceStyle/qmldir
+RESOURCES += resourcestyle
+
+TESTDATA = data/*
+
+OTHER_FILES += \
+ data/*.qml \
+ data/qmldir \
+ data/FileSystemStyle/*.qml \
+ data/FileSystemStyle/qmldir \
+ data/PlatformStyle/*.qml \
+ data/PlatformStyle/+linux/*.qml \
+ data/PlatformStyle/+macos/*.qml \
+ data/PlatformStyle/+windows/*.qml \
+ data/PlatformStyle/qmldir
+
diff --git a/tests/auto/styleimports/tst_styleimports.cpp b/tests/auto/styleimports/tst_styleimports.cpp
new file mode 100644
index 00000000..04acbb21
--- /dev/null
+++ b/tests/auto/styleimports/tst_styleimports.cpp
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qregularexpression.h>
+#include <QtTest/qtest.h>
+#include <QtQml/qqmlcomponent.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlapplicationengine.h>
+#include <QtQml/qqmlengine.h>
+#include <QtQuick/qquickwindow.h>
+#include <QtQuickControls2/qquickstyle.h>
+#include <QtQuickControls2/private/qquickstyle_p.h>
+
+#include "../shared/util.h"
+
+class tst_StyleImports : public QQmlDataTest
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+
+ void cleanup();
+
+ void select_data();
+ void select();
+
+ void platformSelectors();
+};
+
+void tst_StyleImports::initTestCase()
+{
+ QQmlDataTest::initTestCase();
+}
+
+void tst_StyleImports::cleanup()
+{
+ qmlClearTypeRegistrations();
+}
+
+void tst_StyleImports::select_data()
+{
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<QString>("style");
+ QTest::addColumn<QString>("fallback");
+ QTest::addColumn<QString>("expected");
+
+ // Action.qml exists in the "data" style and the Default style.
+ QTest::newRow("control=Action,style=empty,fallback=empty") << "Action.qml" << "" << "" << "Default";
+ QTest::newRow("control=Action,style=fs,fallback=empty") << "Action.qml" << "FileSystemStyle" << "" << "Default";
+ QTest::newRow("control=Action,style=qrc,fallback=empty") << "Action.qml" << "ResourceStyle" << "" << "Default";
+ QTest::newRow("control=Action,style=nosuch,fallback=empty") << "Action.qml" << "NoSuchStyle" << "" << "Default";
+ QTest::newRow("control=Action,style=data,fallback=empty") << "Action.qml" << "data" << "" << "data";
+
+ QTest::newRow("control=Action,style=empty,fallback=mat") << "Action.qml" << "" << "Material" << "";
+ QTest::newRow("control=Action,style=fs,fallback=mat") << "Action.qml" << "FileSystemStyle" << "Material" << "Default";
+ QTest::newRow("control=Action,style=qrc,fallback=mat") << "Action.qml" << "ResourceStyle" << "Material" << "Default";
+ QTest::newRow("control=Action,style=nosuch,fallback=mat") << "Action.qml" << "NoSuchStyle" << "Material" << "Default";
+ QTest::newRow("control=Action,style=data,fallback=mat") << "Action.qml" << "data" << "Material" << "data";
+
+ // ScrollView.qml only exists in the Default style.
+ QTest::newRow("control=ScrollView,style=empty,fallback=empty") << "ScrollView.qml" << "" << "" << "Default";
+ QTest::newRow("control=ScrollView,style=fs,fallback=empty") << "ScrollView.qml" << "FileSystemStyle" << "" << "Default";
+ QTest::newRow("control=ScrollView,style=qrc,fallback=empty") << "ScrollView.qml" << "ResourceStyle" << "" << "Default";
+ QTest::newRow("control=ScrollView,style=nosuch,fallback=empty") << "ScrollView.qml" << "NoSuchStyle" << "" << "Default";
+ QTest::newRow("control=ScrollView,style=data,fallback=empty") << "ScrollView.qml" << "data" << "" << "Default";
+
+ QTest::newRow("control=ScrollView,style=empty,fallback=mat") << "ScrollView.qml" << "" << "Material" << "Default";
+ QTest::newRow("control=ScrollView,style=fs,fallback=mat") << "ScrollView.qml" << "FileSystemStyle" << "Material" << "Default";
+ QTest::newRow("control=ScrollView,style=qrc,fallback=mat") << "ScrollView.qml" << "ResourceStyle" << "Material" << "Default";
+ QTest::newRow("control=ScrollView,style=nosuch,fallback=mat") << "ScrollView.qml" << "NoSuchStyle" << "Material" << "Default";
+ QTest::newRow("control=ScrollView,style=data,fallback=mat") << "ScrollView.qml" << "data" << "Material" << "Default";
+
+ // Label.qml exists in the "data", Default and Material styles.
+ QTest::newRow("control=Label,style=none,fallback=none") << "Label.qml" << "" << "" << "Default";
+ QTest::newRow("control=Label,style=fs,fallback=none") << "Label.qml" << "FileSystemStyle" << "" << "Default";
+ QTest::newRow("control=Label,style=qrc,fallback=none") << "Label.qml" << "ResourceStyle" << "" << "Default";
+ QTest::newRow("control=Label,style=nosuch,fallback=none") << "Label.qml" << "NoSuchStyle" << "" << "Default";
+ QTest::newRow("control=Label,style=data,fallback=none") << "Label.qml" << "data" << "" << "data";
+
+ QTest::newRow("control=Label,style=none,fallback=mat") << "Label.qml" << "" << "Material" << "Default";
+ QTest::newRow("control=Label,style=fs,fallback=mat") << "Label.qml" << "FileSystemStyle" << "Material" << "Default";
+ QTest::newRow("control=Label,style=qrc,fallback=mat") << "Label.qml" << "ResourceStyle" << "Material" << "Default";
+ QTest::newRow("control=Label,style=nosuch,fallback=mat") << "Label.qml" << "NoSuchStyle" << "Material" << "Default";
+ QTest::newRow("control=Label,style=data,fallback=mat") << "Label.qml" << "data" << "Material" << "data";
+
+ // Button.qml exists in all styles including the fs and qrc styles
+ QTest::newRow("control=Button,style=none,fallback=none") << "Button.qml" << "" << "" << "Default";
+ QTest::newRow("control=Button,style=fs,fallback=none") << "Button.qml" << "FileSystemStyle" << "" << "FileSystemStyle";
+ QTest::newRow("control=Button,style=qrc,fallback=none") << "Button.qml" << "ResourceStyle" << "" << "ResourceStyle";
+ QTest::newRow("control=Button,style=nosuch,fallback=none") << "Button.qml" << "NoSuchStyle" << "" << "Default";
+ QTest::newRow("control=Button,style=data,fallback=none") << "Button.qml" << "data" << "" << "data";
+
+ QTest::newRow("control=Button,style=none,fallback=mat") << "Button.qml" << "" << "Material" << "Default";
+ QTest::newRow("control=Button,style=fs,fallback=mat") << "Button.qml" << "FileSystemStyle" << "Material" << "FileSystemStyle";
+ QTest::newRow("control=Button,style=qrc,fallback=mat") << "Button.qml" << "ResourceStyle" << "Material" << "ResourceStyle";
+ QTest::newRow("control=Button,style=nosuch,fallback=mat") << "Button.qml" << "NoSuchStyle" << "Material" << "Default";
+ QTest::newRow("control=Button,style=data,fallback=mat") << "Button.qml" << "data" << "Material" << "data";
+}
+
+void tst_StyleImports::select()
+{
+ QFETCH(QString, file);
+ QFETCH(QString, style);
+ QFETCH(QString, fallback);
+ QFETCH(QString, expected);
+
+ // In Qt 5, there were several accepted forms for style names.
+ // In Qt 6, the only accepted form is the base name of the style directory.
+ const bool invalidStyleName = style.contains(QLatin1Char('/'));
+ if (invalidStyleName)
+ QTest::ignoreMessage(QtWarningMsg,
+ "Style names must not contain paths; see the \"Definition of a Style\" documentation for more information");
+ QQuickStyle::setStyle(style);
+ QQuickStyle::setFallbackStyle(fallback);
+
+ QQmlEngine engine;
+ engine.addImportPath(directory());
+ engine.addImportPath(dataDirectory());
+ QQmlComponent component(&engine);
+ const QString controlName = file.mid(0, file.indexOf(QLatin1Char('.')));
+ component.setData(QString::fromLatin1("import QtQuick 2.15; import QtQuick.Controls 2.15; %1 { }").arg(controlName).toUtf8(), QUrl());
+
+ const bool nonExistentStyle = style == QLatin1String("NoSuchStyle");
+ if (nonExistentStyle)
+ QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
+ QScopedPointer<QObject> object(component.create());
+ if (nonExistentStyle) {
+ QVERIFY(object.isNull());
+ return;
+ }
+
+ QVERIFY2(!object.isNull(), qPrintable(component.errorString()));
+
+ // TODO: test built-in styles below too
+ // We can't check for the attached style object since that API is in a plugin,
+ // and it's not possible to use e.g. the baseUrl of the QQmlContext
+ // nor the metaObject to test it either.
+
+ if (!QQuickStylePrivate::builtInStyles().contains(expected)) {
+ // We're expecting a custom style.
+ QCOMPARE(object->objectName(), expected);
+ }
+}
+
+void tst_StyleImports::platformSelectors()
+{
+ QQuickStyle::setStyle(QLatin1String("PlatformStyle"));
+
+ QQmlApplicationEngine engine;
+ engine.addImportPath(dataDirectory());
+ engine.load(testFileUrl("platformSelectors.qml"));
+ QQuickWindow *window = qobject_cast<QQuickWindow*>(engine.rootObjects().first());
+ QVERIFY(window);
+
+ QObject *button = window->property("button").value<QObject*>();
+ QVERIFY(button);
+
+#if defined(Q_OS_LINUX)
+ QCOMPARE(button->objectName(), "PlatformStyle/+linux");
+#elif defined(Q_OS_MACOS)
+ QCOMPARE(button->objectName(), "PlatformStyle/+macos");
+#elif defined(Q_OS_WIN)
+ QCOMPARE(button->objectName(), "PlatformStyle/+windows");
+#else
+ QCOMPARE(button->objectName(), "PlatformStyle/Button.qml");
+#endif
+}
+
+QTEST_MAIN(tst_StyleImports)
+
+#include "tst_styleimports.moc"
diff --git a/tests/benchmarks/creationtime/creationtime.pro b/tests/benchmarks/creationtime/creationtime.pro
index a594027e..613cf60d 100644
--- a/tests/benchmarks/creationtime/creationtime.pro
+++ b/tests/benchmarks/creationtime/creationtime.pro
@@ -1,7 +1,7 @@
TEMPLATE = app
TARGET = tst_creationtime
-QT += qml testlib
+QT += qml testlib quickcontrols2
CONFIG += testcase
macos:CONFIG -= app_bundle
diff --git a/tests/benchmarks/creationtime/tst_creationtime.cpp b/tests/benchmarks/creationtime/tst_creationtime.cpp
index f243cc5c..d186dc83 100644
--- a/tests/benchmarks/creationtime/tst_creationtime.cpp
+++ b/tests/benchmarks/creationtime/tst_creationtime.cpp
@@ -34,8 +34,10 @@
**
****************************************************************************/
-#include <QtQml>
+#include <QtCore/qscopedpointer.h>
#include <QtTest>
+#include <QtQml>
+#include <QtQuickControls2/qquickstyle.h>
#include "../../auto/shared/visualtestutil.h"
@@ -46,10 +48,11 @@ class tst_CreationTime : public QObject
Q_OBJECT
private slots:
+ void initTestCase();
void init();
- void controls();
- void controls_data();
+ void defaultStyle();
+ void defaultStyle_data();
void fusion();
void fusion_data();
@@ -64,17 +67,29 @@ private slots:
void universal_data();
private:
- QQmlEngine engine;
+ QQuickStyleHelper styleHelper;
};
+void tst_CreationTime::initTestCase()
+{
+ styleHelper.engine.reset(new QQmlEngine);
+}
+
void tst_CreationTime::init()
{
- engine.clearComponentCache();
+ styleHelper.engine->clearComponentCache();
}
-static void doBenchmark(QQmlEngine *engine, const QUrl &url)
+static void doBenchmark(QQuickStyleHelper &styleHelper, const QUrl &url)
{
- QQmlComponent component(engine);
+ const QString tagStr = QString::fromLatin1(QTest::currentDataTag());
+ QStringList styleAndFileName = tagStr.split('/');
+ QCOMPARE(styleAndFileName.size(), 2);
+ QString style = styleAndFileName.first();
+ style[0] = style.at(0).toUpper();
+ styleHelper.updateStyle(style);
+
+ QQmlComponent component(styleHelper.engine.data());
component.loadUrl(url);
QObjectList objects;
@@ -87,64 +102,64 @@ static void doBenchmark(QQmlEngine *engine, const QUrl &url)
qDeleteAll(objects);
}
-void tst_CreationTime::controls()
+void tst_CreationTime::defaultStyle()
{
QFETCH(QUrl, url);
- doBenchmark(&engine, url);
+ doBenchmark(styleHelper, url);
}
-void tst_CreationTime::controls_data()
+void tst_CreationTime::defaultStyle_data()
{
QTest::addColumn<QUrl>("url");
- addTestRowForEachControl(&engine, "controls", "QtQuick/Controls", QStringList() << "ApplicationWindow");
+ addTestRowForEachControl(styleHelper.engine.data(), "controls/default", "QtQuick/Controls/Default", QStringList() << "ApplicationWindow");
}
void tst_CreationTime::fusion()
{
QFETCH(QUrl, url);
- doBenchmark(&engine, url);
+ doBenchmark(styleHelper, url);
}
void tst_CreationTime::fusion_data()
{
QTest::addColumn<QUrl>("url");
- addTestRowForEachControl(&engine, "controls/fusion", "QtQuick/Controls/Fusion", QStringList() << "ApplicationWindow" << "ButtonPanel" << "CheckIndicator" << "RadioIndicator" << "SliderGroove" << "SliderHandle" << "SwitchIndicator");
+ addTestRowForEachControl(styleHelper.engine.data(), "controls/fusion", "QtQuick/Controls/Fusion", QStringList() << "ApplicationWindow" << "ButtonPanel" << "CheckIndicator" << "RadioIndicator" << "SliderGroove" << "SliderHandle" << "SwitchIndicator");
}
void tst_CreationTime::imagine()
{
QFETCH(QUrl, url);
- doBenchmark(&engine, url);
+ doBenchmark(styleHelper, url);
}
void tst_CreationTime::imagine_data()
{
QTest::addColumn<QUrl>("url");
- addTestRowForEachControl(&engine, "controls/imagine", "QtQuick/Controls/Imagine", QStringList() << "ApplicationWindow");
+ addTestRowForEachControl(styleHelper.engine.data(), "controls/imagine", "QtQuick/Controls/Imagine", QStringList() << "ApplicationWindow");
}
void tst_CreationTime::material()
{
QFETCH(QUrl, url);
- doBenchmark(&engine, url);
+ doBenchmark(styleHelper, url);
}
void tst_CreationTime::material_data()
{
QTest::addColumn<QUrl>("url");
- addTestRowForEachControl(&engine, "controls/material", "QtQuick/Controls/Material", QStringList() << "ApplicationWindow" << "Ripple" << "SliderHandle" << "CheckIndicator" << "RadioIndicator" << "SwitchIndicator" << "BoxShadow" << "ElevationEffect" << "CursorDelegate");
+ addTestRowForEachControl(styleHelper.engine.data(), "controls/material", "QtQuick/Controls/Material", QStringList() << "ApplicationWindow" << "Ripple" << "SliderHandle" << "CheckIndicator" << "RadioIndicator" << "SwitchIndicator" << "BoxShadow" << "ElevationEffect" << "CursorDelegate");
}
void tst_CreationTime::universal()
{
QFETCH(QUrl, url);
- doBenchmark(&engine, url);
+ doBenchmark(styleHelper, url);
}
void tst_CreationTime::universal_data()
{
QTest::addColumn<QUrl>("url");
- addTestRowForEachControl(&engine, "controls/universal", "QtQuick/Controls/Universal", QStringList() << "ApplicationWindow" << "CheckIndicator" << "RadioIndicator" << "SwitchIndicator");
+ addTestRowForEachControl(styleHelper.engine.data(), "controls/universal", "QtQuick/Controls/Universal", QStringList() << "ApplicationWindow" << "CheckIndicator" << "RadioIndicator" << "SwitchIndicator");
}
QTEST_MAIN(tst_CreationTime)
diff --git a/tests/benchmarks/objectcount/tst_objectcount.cpp b/tests/benchmarks/objectcount/tst_objectcount.cpp
index c1194c10..cb5a0956 100644
--- a/tests/benchmarks/objectcount/tst_objectcount.cpp
+++ b/tests/benchmarks/objectcount/tst_objectcount.cpp
@@ -93,7 +93,7 @@ void tst_ObjectCount::cleanup()
static void initTestRows(QQmlEngine *engine)
{
- addTestRowForEachControl(engine, "controls", "QtQuick/Controls");
+ addTestRowForEachControl(engine, "controls/default", "QtQuick/Controls/Default");
addTestRowForEachControl(engine, "controls/fusion", "QtQuick/Controls/Fusion", QStringList() << "ButtonPanel" << "CheckIndicator" << "RadioIndicator" << "SliderGroove" << "SliderHandle" << "SwitchIndicator");
addTestRowForEachControl(engine, "controls/imagine", "QtQuick/Controls/Imagine");
addTestRowForEachControl(engine, "controls/material", "QtQuick/Controls/Material", QStringList() << "Ripple" << "SliderHandle" << "CheckIndicator" << "RadioIndicator" << "SwitchIndicator" << "BoxShadow" << "ElevationEffect" << "CursorDelegate");
diff --git a/tests/manual/testbench/main.cpp b/tests/manual/testbench/main.cpp
index 0287537d..0584bd6d 100644
--- a/tests/manual/testbench/main.cpp
+++ b/tests/manual/testbench/main.cpp
@@ -55,6 +55,7 @@
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQuickStyle>
+#include <QtQuickControls2/private/qquickstyle_p.h>
#include "assetfixer.h"
#include "clipboard.h"
@@ -85,7 +86,7 @@ int main(int argc, char *argv[])
qmlRegisterType<Clipboard>("App", 1, 0, "Clipboard");
qmlRegisterType<DirectoryValidator>("App", 1, 0, "DirectoryValidator");
- engine.rootContext()->setContextProperty("availableStyles", QQuickStyle::availableStyles());
+ engine.rootContext()->setContextProperty("availableStyles", QQuickStylePrivate::builtInStyles());
engine.load(QUrl(QStringLiteral("qrc:/testbench.qml")));
diff --git a/tests/manual/testbench/testbench.pro b/tests/manual/testbench/testbench.pro
index 829bcbde..4509f496 100644
--- a/tests/manual/testbench/testbench.pro
+++ b/tests/manual/testbench/testbench.pro
@@ -1,6 +1,6 @@
TEMPLATE = app
-QT += qml quick quickcontrols2
+QT += qml quick quickcontrols2 quickcontrols2-private
CONFIG += c++11
HEADERS += \