aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/customization/tst_customization.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/customization/tst_customization.cpp')
-rw-r--r--tests/auto/customization/tst_customization.cpp456
1 files changed, 273 insertions, 183 deletions
diff --git a/tests/auto/customization/tst_customization.cpp b/tests/auto/customization/tst_customization.cpp
index 4d68d0c5..b20b89d1 100644
--- a/tests/auto/customization/tst_customization.cpp
+++ b/tests/auto/customization/tst_customization.cpp
@@ -46,17 +46,81 @@
using namespace QQuickVisualTestUtil;
+struct ControlInfo
+{
+ QString type;
+ QStringList delegates;
+};
+
+static const ControlInfo ControlInfos[] = {
+ { "AbstractButton", QStringList() << "background" << "contentItem" << "indicator" },
+ { "ApplicationWindow", QStringList() << "background" },
+ { "BusyIndicator", QStringList() << "background" << "contentItem" },
+ { "Button", QStringList() << "background" << "contentItem" },
+ { "CheckBox", QStringList() << "contentItem" << "indicator" },
+ { "CheckDelegate", QStringList() << "background" << "contentItem" << "indicator" },
+ { "ComboBox", QStringList() << "background" << "contentItem" << "indicator" }, // popup not created until needed
+ { "Container", QStringList() << "background" << "contentItem" },
+ { "Control", QStringList() << "background" << "contentItem" },
+ { "DelayButton", QStringList() << "background" << "contentItem" },
+ { "Dial", QStringList() << "background" << "handle" },
+ { "Dialog", QStringList() << "background" << "contentItem" },
+ { "DialogButtonBox", QStringList() << "background" << "contentItem" },
+ { "Drawer", QStringList() << "background" << "contentItem" },
+ { "Frame", QStringList() << "background" << "contentItem" },
+ { "GroupBox", QStringList() << "background" << "contentItem" << "label" },
+ { "ItemDelegate", QStringList() << "background" << "contentItem" },
+ { "Label", QStringList() << "background" },
+ { "Menu", QStringList() << "background" << "contentItem" },
+ { "MenuItem", QStringList() << "background" << "contentItem" << "indicator" },
+ { "MenuSeparator", QStringList() << "background" << "contentItem" },
+ { "Page", QStringList() << "background" << "contentItem" },
+ { "PageIndicator", QStringList() << "background" << "contentItem" },
+ { "Pane", QStringList() << "background" << "contentItem" },
+ { "Popup", QStringList() << "background" << "contentItem" },
+ { "ProgressBar", QStringList() << "background" << "contentItem" },
+ { "RadioButton", QStringList() << "contentItem" << "indicator" },
+ { "RadioDelegate", QStringList() << "background" << "contentItem" << "indicator" },
+ { "RangeSlider", QStringList() << "background" << "first.handle" << "second.handle" },
+ { "RoundButton", QStringList() << "background" << "contentItem" },
+ { "ScrollBar", QStringList() << "background" << "contentItem" },
+ { "ScrollIndicator", QStringList() << "background" << "contentItem" },
+ { "ScrollView", QStringList() << "background" },
+ { "Slider", QStringList() << "background" << "handle" },
+ { "SpinBox", QStringList() << "background" << "contentItem" << "up.indicator" << "down.indicator" },
+ { "StackView", QStringList() << "background" << "contentItem" },
+ { "SwipeDelegate", QStringList() << "background" << "contentItem" },
+ { "SwipeView", QStringList() << "background" << "contentItem" },
+ { "Switch", QStringList() << "contentItem" << "indicator" },
+ { "SwitchDelegate", QStringList() << "background" << "contentItem" << "indicator" },
+ { "TabBar", QStringList() << "background" << "contentItem" },
+ { "TabButton", QStringList() << "background" << "contentItem" },
+ { "TextField", QStringList() << "background" },
+ { "TextArea", QStringList() << "background" },
+ { "ToolBar", QStringList() << "background" << "contentItem" },
+ { "ToolButton", QStringList() << "background" << "contentItem" },
+ { "ToolSeparator", QStringList() << "background" << "contentItem" },
+ { "ToolTip", QStringList() << "background" << "contentItem" },
+ // { "Tumbler", QStringList() << "background" << "contentItem" } ### TODO: fix and enable deferred execution
+};
+
class tst_customization : public QQmlDataTest
{
Q_OBJECT
private slots:
+ void initTestCase();
+ void cleanupTestCase();
+
void init();
void cleanup();
void creation_data();
void creation();
+ void override_data();
+ void override();
+
void comboPopup();
private:
@@ -64,7 +128,7 @@ private:
void addHooks();
void removeHooks();
- QObject* createControl(const QString &type, QString *error);
+ QObject* createControl(const QString &type, const QString &qml, QString *error);
QQmlEngine *engine = nullptr;
};
@@ -73,6 +137,39 @@ typedef QHash<QObject *, QString> QObjectNameHash;
Q_GLOBAL_STATIC(QObjectNameHash, qt_objectNames)
Q_GLOBAL_STATIC(QStringList, qt_createdQObjects)
Q_GLOBAL_STATIC(QStringList, qt_destroyedQObjects)
+Q_GLOBAL_STATIC(QStringList, qt_destroyedParentQObjects)
+static int qt_unparentedItemCount = 0;
+
+class ItemParentListener : public QQuickItem
+{
+ Q_OBJECT
+
+public:
+ ItemParentListener()
+ {
+ m_slotIndex = metaObject()->indexOfSlot("onParentChanged()");
+ m_signalIndex = QMetaObjectPrivate::signalIndex(QMetaMethod::fromSignal(&QQuickItem::parentChanged));
+ }
+
+ int signalIndex() const { return m_signalIndex; }
+ int slotIndex() const { return m_slotIndex; }
+
+public slots:
+ void onParentChanged()
+ {
+ const QQuickItem *item = qobject_cast<QQuickItem *>(sender());
+ if (!item)
+ return;
+
+ if (!item->parentItem())
+ ++qt_unparentedItemCount;
+ }
+
+private:
+ int m_slotIndex;
+ int m_signalIndex;
+};
+static ItemParentListener *qt_itemParentListener = nullptr;
extern "C" Q_DECL_EXPORT void qt_addQObject(QObject *object)
{
@@ -86,6 +183,12 @@ extern "C" Q_DECL_EXPORT void qt_addQObject(QObject *object)
qt_objectNames()->insert(object, objectName);
}
});
+
+ if (qt_itemParentListener) {
+ static const int signalIndex = qt_itemParentListener->signalIndex();
+ static const int slotIndex = qt_itemParentListener->slotIndex();
+ QMetaObject::connect(object, signalIndex, qt_itemParentListener, slotIndex);
+ }
}
extern "C" Q_DECL_EXPORT void qt_removeQObject(QObject *object)
@@ -94,6 +197,26 @@ extern "C" Q_DECL_EXPORT void qt_removeQObject(QObject *object)
if (!objectName.isEmpty())
qt_destroyedQObjects()->append(objectName);
qt_objectNames()->remove(object);
+
+ QObject *parent = object->parent();
+ if (parent) {
+ QString parentName = parent->objectName();
+ if (!parentName.isEmpty())
+ qt_destroyedParentQObjects()->append(parentName);
+ }
+}
+
+void tst_customization::initTestCase()
+{
+ QQmlDataTest::initTestCase();
+
+ qt_itemParentListener = new ItemParentListener;
+}
+
+void tst_customization::cleanupTestCase()
+{
+ delete qt_itemParentListener;
+ qt_itemParentListener = nullptr;
}
void tst_customization::init()
@@ -119,14 +242,16 @@ void tst_customization::cleanup()
void tst_customization::reset()
{
+ qt_unparentedItemCount = 0;
qt_createdQObjects()->clear();
qt_destroyedQObjects()->clear();
+ qt_destroyedParentQObjects()->clear();
}
-QObject* tst_customization::createControl(const QString &name, QString *error)
+QObject* tst_customization::createControl(const QString &name, const QString &qml, QString *error)
{
QQmlComponent component(engine);
- component.setData("import QtQuick.Controls 2.2; " + name.toUtf8() + " { }", QUrl());
+ component.setData("import QtQuick 2.9; import QtQuick.Window 2.2; import QtQuick.Controls 2.2; " + name.toUtf8() + " { " + qml.toUtf8() + " }", QUrl());
QObject *obj = component.create();
if (!obj)
*error = component.errorString();
@@ -140,188 +265,24 @@ void tst_customization::creation_data()
QTest::addColumn<QStringList>("delegates");
// the "empty" style does not contain any delegates
- QTest::newRow("empty:AbstractButton") << "empty" << "AbstractButton"<< QStringList();
- QTest::newRow("empty:ApplicationWindow") << "empty" << "ApplicationWindow"<< QStringList();
- QTest::newRow("empty:BusyIndicator") << "empty" << "BusyIndicator"<< QStringList();
- QTest::newRow("empty:Button") << "empty" << "Button"<< QStringList();
- QTest::newRow("empty:CheckBox") << "empty" << "CheckBox" << QStringList();
- QTest::newRow("empty:CheckDelegate") << "empty" << "CheckDelegate" << QStringList();
- QTest::newRow("empty:ComboBox") << "empty" << "ComboBox" << QStringList();
- QTest::newRow("empty:Container") << "empty" << "Container"<< QStringList();
- QTest::newRow("empty:Control") << "empty" << "Control"<< QStringList();
- QTest::newRow("empty:DelayButton") << "empty" << "DelayButton"<< QStringList();
- QTest::newRow("empty:Dial") << "empty" << "Dial" << QStringList();
- QTest::newRow("empty:DialogButtonBox") << "empty" << "DialogButtonBox" << QStringList();
- QTest::newRow("empty:Frame") << "empty" << "Frame"<< QStringList();
- QTest::newRow("empty:GroupBox") << "empty" << "GroupBox"<< QStringList();
- QTest::newRow("empty:ItemDelegate") << "empty" << "ItemDelegate" << QStringList();
- QTest::newRow("empty:Label") << "empty" << "Label"<< QStringList();
- QTest::newRow("empty:MenuItem") << "empty" << "MenuItem"<< QStringList();
- QTest::newRow("empty:MenuSeparator") << "empty" << "MenuSeparator"<< QStringList();
- QTest::newRow("empty:Page") << "empty" << "Page"<< QStringList();
- QTest::newRow("empty:PageIndicator") << "empty" << "PageIndicator"<< QStringList();
- QTest::newRow("empty:Pane") << "empty" << "Pane"<< QStringList();
- QTest::newRow("empty:ProgressBar") << "empty" << "ProgressBar"<< QStringList();
- QTest::newRow("empty:RadioButton") << "empty" << "RadioButton" << QStringList();
- QTest::newRow("empty:RadioDelegate") << "empty" << "RadioDelegate" << QStringList();
- QTest::newRow("empty:RangeSlider") << "empty" << "RangeSlider" << QStringList();
- QTest::newRow("empty:RoundButton") << "empty" << "RoundButton" << QStringList();
- QTest::newRow("empty:ScrollBar") << "empty" << "ScrollBar"<< QStringList();
- QTest::newRow("empty:ScrollIndicator") << "empty" << "ScrollIndicator"<< QStringList();
- QTest::newRow("empty:ScrollView") << "empty" << "ScrollView"<< QStringList();
- QTest::newRow("empty:Slider") << "empty" << "Slider" << QStringList();
- QTest::newRow("empty:SpinBox") << "empty" << "SpinBox" << QStringList();
- QTest::newRow("empty:StackView") << "empty" << "StackView" << QStringList();
- QTest::newRow("empty:SwipeDelegate") << "empty" << "SwipeDelegate" << QStringList();
- QTest::newRow("empty:SwipeView") << "empty" << "SwipeView" << QStringList();
- QTest::newRow("empty:Switch") << "empty" << "Switch" << QStringList();
- QTest::newRow("empty:SwitchDelegate") << "empty" << "SwitchDelegate" << QStringList();
- QTest::newRow("empty:TabBar") << "empty" << "TabBar"<< QStringList();
- QTest::newRow("empty:TabButton") << "empty" << "TabButton"<< QStringList();
- QTest::newRow("empty:TextField") << "empty" << "TextField"<< QStringList();
- QTest::newRow("empty:TextArea") << "empty" << "TextArea"<< QStringList();
- QTest::newRow("empty:ToolBar") << "empty" << "ToolBar"<< QStringList();
- QTest::newRow("empty:ToolButton") << "empty" << "ToolButton"<< QStringList();
- QTest::newRow("empty:ToolSeparator") << "empty" << "ToolSeparator"<< QStringList();
- // QTest::newRow("empty:Tumbler") << "empty" << "Tumbler"<< QStringList(); // ### TODO: fix crash with contentItem-less Tumbler
+ for (const ControlInfo &control : ControlInfos)
+ QTest::newRow(qPrintable("empty:" + control.type)) << "empty" << control.type << QStringList();
// the "incomplete" style is missing bindings to the delegates (must be created regardless)
- QTest::newRow("incomplete:AbstractButton") << "incomplete" << "AbstractButton" << (QStringList() << "background" << "contentItem" << "indicator");
- QTest::newRow("incomplete:ApplicationWindow") << "incomplete" << "ApplicationWindow" << (QStringList() << "background");
- QTest::newRow("incomplete:BusyIndicator") << "incomplete" << "BusyIndicator" << (QStringList() << "background" << "contentItem");
- QTest::newRow("incomplete:Button") << "incomplete" << "Button" << (QStringList() << "background" << "contentItem");
- QTest::newRow("incomplete:CheckBox") << "incomplete" << "CheckBox" << (QStringList() << "background" << "contentItem" << "indicator");
- QTest::newRow("incomplete:CheckDelegate") << "incomplete" << "CheckDelegate" << (QStringList() << "background" << "contentItem" << "indicator");
- QTest::newRow("incomplete:ComboBox") << "incomplete" << "ComboBox" << (QStringList() << "background" << "contentItem" << "indicator"); // popup not created until needed
- QTest::newRow("incomplete:Container") << "incomplete" << "Container" << (QStringList() << "background" << "contentItem");
- QTest::newRow("incomplete:Control") << "incomplete" << "Control" << (QStringList() << "background" << "contentItem");
- QTest::newRow("incomplete:DelayButton") << "incomplete" << "DelayButton" << (QStringList() << "background" << "contentItem");
- QTest::newRow("incomplete:Dial") << "incomplete" << "Dial" << (QStringList() << "background" << "contentItem" << "handle");
- QTest::newRow("incomplete:DialogButtonBox") << "incomplete" << "DialogButtonBox" << (QStringList() << "background" << "contentItem");
- QTest::newRow("incomplete:Frame") << "incomplete" << "Frame"<< (QStringList() << "background" << "contentItem");
- QTest::newRow("incomplete:GroupBox") << "incomplete" << "GroupBox"<< (QStringList() << "background" << "contentItem" << "label");
- QTest::newRow("incomplete:ItemDelegate") << "incomplete" << "ItemDelegate" << (QStringList() << "background" << "contentItem");
- QTest::newRow("incomplete:Label") << "incomplete" << "Label" << (QStringList() << "background");
- QTest::newRow("incomplete:MenuItem") << "incomplete" << "MenuItem" << (QStringList() << "background" << "contentItem" << "indicator");
- QTest::newRow("incomplete:MenuSeparator") << "incomplete" << "MenuSeparator" << (QStringList() << "background" << "contentItem");
- QTest::newRow("incomplete:Page") << "incomplete" << "Page" << (QStringList() << "background" << "contentItem");
- QTest::newRow("incomplete:PageIndicator") << "incomplete" << "PageIndicator" << (QStringList() << "background" << "contentItem");
- QTest::newRow("incomplete:Pane") << "incomplete" << "Pane" << (QStringList() << "background" << "contentItem");
- QTest::newRow("incomplete:ProgressBar") << "incomplete" << "ProgressBar" << (QStringList() << "background" << "contentItem");
- QTest::newRow("incomplete:RadioButton") << "incomplete" << "RadioButton" << (QStringList() << "background" << "contentItem" << "indicator");
- QTest::newRow("incomplete:RadioDelegate") << "incomplete" << "RadioDelegate" << (QStringList() << "background" << "contentItem" << "indicator");
- QTest::newRow("incomplete:RangeSlider") << "incomplete" << "RangeSlider" << (QStringList() << "background" << "contentItem" << "first.handle" << "second.handle");
- QTest::newRow("incomplete:RoundButton") << "incomplete" << "RoundButton" << (QStringList() << "background" << "contentItem");
- QTest::newRow("incomplete:ScrollBar") << "incomplete" << "ScrollBar" << (QStringList() << "background" << "contentItem");
- QTest::newRow("incomplete:ScrollIndicator") << "incomplete" << "ScrollIndicator" << (QStringList() << "background" << "contentItem");
- QTest::newRow("incomplete:ScrollView") << "incomplete" << "ScrollView" << (QStringList() << "background" << "contentItem");
- QTest::newRow("incomplete:Slider") << "incomplete" << "Slider" << (QStringList() << "background" << "contentItem" << "handle");
- QTest::newRow("incomplete:SpinBox") << "incomplete" << "SpinBox" << (QStringList() << "background" << "contentItem" << "up.indicator" << "down.indicator");
- QTest::newRow("incomplete:StackView") << "incomplete" << "StackView" << (QStringList() << "background" << "contentItem");
- QTest::newRow("incomplete:SwipeDelegate") << "incomplete" << "SwipeDelegate" << (QStringList() << "background" << "contentItem");
- QTest::newRow("incomplete:SwipeView") << "incomplete" << "SwipeView" << (QStringList() << "background" << "contentItem");
- QTest::newRow("incomplete:Switch") << "incomplete" << "Switch" << (QStringList() << "background" << "contentItem" << "indicator");
- QTest::newRow("incomplete:SwitchDelegate") << "incomplete" << "SwitchDelegate" << (QStringList() << "background" << "contentItem" << "indicator");
- QTest::newRow("incomplete:TabBar") << "incomplete" << "TabBar"<< (QStringList() << "background" << "contentItem");
- QTest::newRow("incomplete:TabButton") << "incomplete" << "TabButton"<< (QStringList() << "background" << "contentItem");
- QTest::newRow("incomplete:TextField") << "incomplete" << "TextField" << (QStringList() << "background");
- QTest::newRow("incomplete:TextArea") << "incomplete" << "TextArea" << (QStringList() << "background");
- QTest::newRow("incomplete:ToolBar") << "incomplete" << "ToolBar"<< (QStringList() << "background" << "contentItem");
- QTest::newRow("incomplete:ToolButton") << "incomplete" << "ToolButton"<< (QStringList() << "background" << "contentItem");
- QTest::newRow("incomplete:ToolSeparator") << "incomplete" << "ToolSeparator"<< (QStringList() << "background" << "contentItem");
- QTest::newRow("incomplete:Tumbler") << "incomplete" << "Tumbler"<< (QStringList() << "background" << "contentItem");
+ for (const ControlInfo &control : ControlInfos)
+ QTest::newRow(qPrintable("incomplete:" + control.type)) << "incomplete" << control.type << control.delegates;
+
+ // the "identified" style has IDs in the delegates (prevents deferred execution)
+ for (const ControlInfo &control : ControlInfos)
+ QTest::newRow(qPrintable("identified:" + control.type)) << "identified" << control.type << control.delegates;
// the "simple" style simulates a proper style and contains bindings to/in delegates
- QTest::newRow("simple:AbstractButton") << "simple" << "AbstractButton" << (QStringList() << "background" << "contentItem" << "indicator");
- QTest::newRow("simple:ApplicationWindow") << "simple" << "ApplicationWindow" << (QStringList() << "background");
- QTest::newRow("simple:BusyIndicator") << "simple" << "BusyIndicator" << (QStringList() << "background" << "contentItem");
- QTest::newRow("simple:Button") << "simple" << "Button" << (QStringList() << "background" << "contentItem");
- QTest::newRow("simple:CheckBox") << "simple" << "CheckBox" << (QStringList() << "contentItem" << "indicator");
- QTest::newRow("simple:CheckDelegate") << "simple" << "CheckDelegate" << (QStringList() << "background" << "contentItem" << "indicator");
- QTest::newRow("simple:ComboBox") << "simple" << "ComboBox" << (QStringList() << "background" << "contentItem" << "indicator"); // popup not created until needed
- QTest::newRow("simple:Container") << "simple" << "Container" << (QStringList() << "background" << "contentItem");
- QTest::newRow("simple:Control") << "simple" << "Control" << (QStringList() << "background" << "contentItem");
- QTest::newRow("simple:DelayButton") << "simple" << "DelayButton" << (QStringList() << "background" << "contentItem");
- QTest::newRow("simple:Dial") << "simple" << "Dial" << (QStringList() << "background" << "handle");
- QTest::newRow("simple:DialogButtonBox") << "simple" << "DialogButtonBox" << (QStringList() << "background" << "contentItem");
- QTest::newRow("simple:Frame") << "simple" << "Frame"<< (QStringList() << "background" << "contentItem");
- QTest::newRow("simple:GroupBox") << "simple" << "GroupBox"<< (QStringList() << "background" << "contentItem" << "label");
- QTest::newRow("simple:ItemDelegate") << "simple" << "ItemDelegate" << (QStringList() << "background" << "contentItem");
- QTest::newRow("simple:Label") << "simple" << "Label" << (QStringList() << "background");
- QTest::newRow("simple:MenuItem") << "simple" << "MenuItem" << (QStringList() << "background" << "contentItem" << "indicator");
- QTest::newRow("simple:MenuSeparator") << "simple" << "MenuSeparator" << (QStringList() << "background" << "contentItem");
- QTest::newRow("simple:Page") << "simple" << "Page" << (QStringList() << "background" << "contentItem");
- QTest::newRow("simple:PageIndicator") << "simple" << "PageIndicator" << (QStringList() << "background" << "contentItem");
- QTest::newRow("simple:Pane") << "simple" << "Pane" << (QStringList() << "background" << "contentItem");
- QTest::newRow("simple:ProgressBar") << "simple" << "ProgressBar" << (QStringList() << "background" << "contentItem");
- QTest::newRow("simple:RadioButton") << "simple" << "RadioButton" << (QStringList() << "contentItem" << "indicator");
- QTest::newRow("simple:RadioDelegate") << "simple" << "RadioDelegate" << (QStringList() << "background" << "contentItem" << "indicator");
- QTest::newRow("simple:RangeSlider") << "simple" << "RangeSlider" << (QStringList() << "background" << "first.handle" << "second.handle");
- QTest::newRow("simple:RoundButton") << "simple" << "RoundButton" << (QStringList() << "background" << "contentItem");
- QTest::newRow("simple:ScrollBar") << "simple" << "ScrollBar" << (QStringList() << "background" << "contentItem");
- QTest::newRow("simple:ScrollIndicator") << "simple" << "ScrollIndicator" << (QStringList() << "background" << "contentItem");
- QTest::newRow("simple:ScrollView") << "simple" << "ScrollView" << (QStringList() << "background" << "contentItem");
- QTest::newRow("simple:Slider") << "simple" << "Slider" << (QStringList() << "background" << "handle");
- QTest::newRow("simple:SpinBox") << "simple" << "SpinBox" << (QStringList() << "background" << "contentItem" << "up.indicator" << "down.indicator");
- QTest::newRow("simple:StackView") << "simple" << "StackView" << (QStringList() << "background" << "contentItem");
- QTest::newRow("simple:SwipeDelegate") << "simple" << "SwipeDelegate" << (QStringList() << "background" << "contentItem");
- QTest::newRow("simple:SwipeView") << "simple" << "SwipeView" << (QStringList() << "background" << "contentItem");
- QTest::newRow("simple:Switch") << "simple" << "Switch" << (QStringList() << "contentItem" << "indicator");
- QTest::newRow("simple:SwitchDelegate") << "simple" << "SwitchDelegate" << (QStringList() << "background" << "contentItem" << "indicator");
- QTest::newRow("simple:TabBar") << "simple" << "TabBar"<< (QStringList() << "background" << "contentItem");
- QTest::newRow("simple:TabButton") << "simple" << "TabButton"<< (QStringList() << "background" << "contentItem");
- QTest::newRow("simple:TextField") << "simple" << "TextField" << (QStringList() << "background");
- QTest::newRow("simple:TextArea") << "simple" << "TextArea" << (QStringList() << "background");
- QTest::newRow("simple:ToolBar") << "simple" << "ToolBar"<< (QStringList() << "background" << "contentItem");
- QTest::newRow("simple:ToolButton") << "simple" << "ToolButton"<< (QStringList() << "background" << "contentItem");
- QTest::newRow("simple:ToolSeparator") << "simple" << "ToolSeparator"<< (QStringList() << "background" << "contentItem");
- QTest::newRow("simple:Tumbler") << "simple" << "Tumbler"<< (QStringList() << "background" << "contentItem");
+ for (const ControlInfo &control : ControlInfos)
+ QTest::newRow(qPrintable("simple:" + control.type)) << "simple" << control.type << control.delegates;
// the "override" style overrides all delegates in the "simple" style
- QTest::newRow("override:AbstractButton") << "override" << "AbstractButton" << (QStringList() << "background" << "contentItem" << "indicator");
- QTest::newRow("override:ApplicationWindow") << "override" << "ApplicationWindow" << (QStringList() << "background");
- QTest::newRow("override:BusyIndicator") << "override" << "BusyIndicator" << (QStringList() << "background" << "contentItem");
- QTest::newRow("override:Button") << "override" << "Button" << (QStringList() << "background" << "contentItem");
- QTest::newRow("override:CheckBox") << "override" << "CheckBox" << (QStringList() << "background" << "contentItem" << "indicator");
- QTest::newRow("override:CheckDelegate") << "override" << "CheckDelegate" << (QStringList() << "background" << "contentItem" << "indicator");
- QTest::newRow("override:ComboBox") << "override" << "ComboBox" << (QStringList() << "background" << "contentItem" << "indicator"); // popup not created until needed
- QTest::newRow("override:Container") << "override" << "Container" << (QStringList() << "background" << "contentItem");
- QTest::newRow("override:Control") << "override" << "Control" << (QStringList() << "background" << "contentItem");
- QTest::newRow("override:DelayButton") << "override" << "DelayButton" << (QStringList() << "background" << "contentItem");
- QTest::newRow("override:Dial") << "override" << "Dial" << (QStringList() << "background" << "contentItem" << "handle");
- QTest::newRow("override:DialogButtonBox") << "override" << "DialogButtonBox" << (QStringList() << "background" << "contentItem");
- QTest::newRow("override:Frame") << "override" << "Frame"<< (QStringList() << "background" << "contentItem");
- QTest::newRow("override:GroupBox") << "override" << "GroupBox"<< (QStringList() << "background" << "contentItem" << "label");
- QTest::newRow("override:ItemDelegate") << "override" << "ItemDelegate" << (QStringList() << "background" << "contentItem");
- QTest::newRow("override:Label") << "override" << "Label" << (QStringList() << "background");
- QTest::newRow("override:MenuItem") << "override" << "MenuItem" << (QStringList() << "background" << "contentItem" << "indicator");
- QTest::newRow("override:MenuSeparator") << "override" << "MenuSeparator" << (QStringList() << "background" << "contentItem");
- QTest::newRow("override:Page") << "override" << "Page" << (QStringList() << "background" << "contentItem");
- QTest::newRow("override:PageIndicator") << "override" << "PageIndicator" << (QStringList() << "background" << "contentItem");
- QTest::newRow("override:Pane") << "override" << "Pane" << (QStringList() << "background" << "contentItem");
- QTest::newRow("override:ProgressBar") << "override" << "ProgressBar" << (QStringList() << "background" << "contentItem");
- QTest::newRow("override:RadioButton") << "override" << "RadioButton" << (QStringList() << "background" << "contentItem" << "indicator");
- QTest::newRow("override:RadioDelegate") << "override" << "RadioDelegate" << (QStringList() << "background" << "contentItem" << "indicator");
- QTest::newRow("override:RangeSlider") << "override" << "RangeSlider" << (QStringList() << "background" << "contentItem" << "first.handle" << "second.handle");
- QTest::newRow("override:RoundButton") << "override" << "RoundButton" << (QStringList() << "background" << "contentItem");
- QTest::newRow("override:ScrollBar") << "override" << "ScrollBar" << (QStringList() << "background" << "contentItem");
- QTest::newRow("override:ScrollIndicator") << "override" << "ScrollIndicator" << (QStringList() << "background" << "contentItem");
- QTest::newRow("override:ScrollView") << "override" << "ScrollView" << (QStringList() << "background" << "contentItem");
- QTest::newRow("override:Slider") << "override" << "Slider" << (QStringList() << "background" << "contentItem" << "handle");
- QTest::newRow("override:SpinBox") << "override" << "SpinBox" << (QStringList() << "background" << "contentItem" << "up.indicator" << "down.indicator");
- QTest::newRow("override:StackView") << "override" << "StackView" << (QStringList() << "background" << "contentItem");
- QTest::newRow("override:SwipeDelegate") << "override" << "SwipeDelegate" << (QStringList() << "background" << "contentItem");
- QTest::newRow("override:SwipeView") << "override" << "SwipeView" << (QStringList() << "background" << "contentItem");
- QTest::newRow("override:Switch") << "override" << "Switch" << (QStringList() << "background" << "contentItem" << "indicator");
- QTest::newRow("override:SwitchDelegate") << "override" << "SwitchDelegate" << (QStringList() << "background" << "contentItem" << "indicator");
- QTest::newRow("override:TabBar") << "override" << "TabBar"<< (QStringList() << "background" << "contentItem");
- QTest::newRow("override:TabButton") << "override" << "TabButton"<< (QStringList() << "background" << "contentItem");
- QTest::newRow("override:TextField") << "override" << "TextField" << (QStringList() << "background");
- QTest::newRow("override:TextArea") << "override" << "TextArea" << (QStringList() << "background");
- QTest::newRow("override:ToolBar") << "override" << "ToolBar"<< (QStringList() << "background" << "contentItem");
- QTest::newRow("override:ToolButton") << "override" << "ToolButton"<< (QStringList() << "background" << "contentItem");
- QTest::newRow("override:ToolSeparator") << "override" << "ToolSeparator"<< (QStringList() << "background" << "contentItem");
- QTest::newRow("override:Tumbler") << "override" << "Tumbler"<< (QStringList() << "background" << "contentItem");
+ for (const ControlInfo &control : ControlInfos)
+ QTest::newRow(qPrintable("override:" + control.type)) << "override" << control.type << control.delegates;
}
void tst_customization::creation()
@@ -333,27 +294,156 @@ void tst_customization::creation()
QQuickStyle::setStyle(testFile("styles/" + style));
QString error;
- QScopedPointer<QObject> control(createControl(type, &error));
+ QScopedPointer<QObject> control(createControl(type, "", &error));
QVERIFY2(control, qPrintable(error));
QByteArray templateType = "QQuick" + type.toUtf8();
QVERIFY2(control->inherits(templateType), qPrintable(type + " does not inherit " + templateType + " (" + control->metaObject()->className() + ")"));
+ // <control>-<style>
QString controlName = type.toLower() + "-" + style;
+ QCOMPARE(control->objectName(), controlName);
QVERIFY2(qt_createdQObjects()->removeOne(controlName), qPrintable(controlName + " was not created as expected"));
for (QString delegate : qAsConst(delegates)) {
- if (!delegate.contains("-"))
- delegate.append("-" + style);
+ QStringList properties = delegate.split(".", QString::SkipEmptyParts);
+
+ // <control>-<delegate>-<style>(-<override>)
+ delegate.append("-" + style);
delegate.prepend(type.toLower() + "-");
QVERIFY2(qt_createdQObjects()->removeOne(delegate), qPrintable(delegate + " was not created as expected"));
+
+ // verify that the delegate instance has the expected object name
+ // in case of grouped properties, we must query the properties step by step
+ QObject *instance = control.data();
+ while (!properties.isEmpty()) {
+ QString property = properties.takeFirst();
+ instance = instance->property(property.toUtf8()).value<QObject *>();
+ QVERIFY2(instance, qPrintable("property was null: " + property));
+ }
+ QCOMPARE(instance->objectName(), delegate);
}
- QEXPECT_FAIL("override:Tumbler", "TODO", Abort);
+ QEXPECT_FAIL("identified:ComboBox", "ComboBox::popup with an ID is created at construction time", Continue);
QVERIFY2(qt_createdQObjects()->isEmpty(), qPrintable("unexpectedly created: " + qt_createdQObjects->join(", ")));
QVERIFY2(qt_destroyedQObjects()->isEmpty(), qPrintable("unexpectedly destroyed: " + qt_destroyedQObjects->join(", ") + " were unexpectedly destroyed"));
+
+ QVERIFY2(qt_destroyedParentQObjects()->isEmpty(), qPrintable("delegates/children of: " + qt_destroyedParentQObjects->join(", ") + " were unexpectedly destroyed"));
+}
+
+void tst_customization::override_data()
+{
+ QTest::addColumn<QString>("style");
+ QTest::addColumn<QString>("type");
+ QTest::addColumn<QStringList>("delegates");
+ QTest::addColumn<QString>("nonDeferred");
+ QTest::addColumn<bool>("identify");
+
+ // NOTE: delegates with IDs prevent deferred execution
+
+ // default delegates with IDs, override with custom delegates with no IDs
+ for (const ControlInfo &control : ControlInfos)
+ QTest::newRow(qPrintable("identified:" + control.type)) << "identified" << control.type << control.delegates << "identified" << false;
+
+ // default delegates with no IDs, override with custom delegates with IDs
+ for (const ControlInfo &control : ControlInfos)
+ QTest::newRow(qPrintable("simple:" + control.type)) << "simple" << control.type << control.delegates << "" << true;
+
+ // default delegates with IDs, override with custom delegates with IDs
+ for (const ControlInfo &control : ControlInfos)
+ QTest::newRow(qPrintable("overidentified:" + control.type)) << "identified" << control.type << control.delegates << "identified" << true;
+
+#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" << "Material" << "Universal"; // ### TODO: QQuickStyle::availableStyles();
+ for (const QString &style : styles) {
+ for (const ControlInfo &control : ControlInfos)
+ QTest::newRow(qPrintable(style + ":" + control.type)) << style << control.type << control.delegates << "" << false;
+ }
+
+#endif
+}
+
+void tst_customization::override()
+{
+ QFETCH(QString, style);
+ QFETCH(QString, type);
+ QFETCH(QStringList, delegates);
+ QFETCH(QString, nonDeferred);
+ QFETCH(bool, identify);
+
+ const QString testStyle = testFile("styles/" + style);
+ if (QDir(testStyle).exists())
+ QQuickStyle::setStyle(testStyle);
+ else
+ QQuickStyle::setStyle(style);
+
+ QString qml;
+ qml += QString("objectName: '%1-%2-override'; ").arg(type.toLower()).arg(style);
+ for (const QString &delegate : delegates) {
+ QString id = identify ? QString("id: %1;").arg(delegate) : QString();
+ qml += QString("%1: Item { %2 objectName: '%3-%1-%4-override' } ").arg(delegate).arg(id.replace(".", "")).arg(type.toLower()).arg(style);
+ }
+
+ QString error;
+ QScopedPointer<QObject> control(createControl(type, qml, &error));
+ QVERIFY2(control, qPrintable(error));
+
+ // If there are no intentional IDs in the default delegates nor in the overridden custom
+ // delegates, no item should get un-parented during the creation process. An item being
+ // unparented means that a delegate got destroyed, so there must be an internal ID in one
+ // of the delegates in the tested style.
+ if (!identify && nonDeferred.isEmpty()) {
+ QEXPECT_FAIL("Universal:ApplicationWindow", "ApplicationWindow.qml contains an intentionally unparented FocusRectangle", Continue);
+ QCOMPARE(qt_unparentedItemCount, 0);
+ }
+
+ // <control>-<style>-override
+ QString controlName = type.toLower() + "-" + style + "-override";
+ QCOMPARE(control->objectName(), controlName);
+ QVERIFY2(qt_createdQObjects()->removeOne(controlName), qPrintable(controlName + " was not created as expected"));
+
+ for (QString delegate : qAsConst(delegates)) {
+ QStringList properties = delegate.split(".", QString::SkipEmptyParts);
+
+ // <control>-<delegate>-<style>(-override)
+ delegate.append("-" + style);
+ delegate.prepend(type.toLower() + "-");
+
+ if (!nonDeferred.isEmpty())
+ QVERIFY2(qt_createdQObjects()->removeOne(delegate), qPrintable(delegate + " was not created as expected"));
+
+ delegate.append("-override");
+ QVERIFY2(qt_createdQObjects()->removeOne(delegate), qPrintable(delegate + " was not created as expected"));
+
+ // verify that the delegate instance has the expected object name
+ // in case of grouped properties, we must query the properties step by step
+ QObject *instance = control.data();
+ while (!properties.isEmpty()) {
+ QString property = properties.takeFirst();
+ instance = instance->property(property.toUtf8()).value<QObject *>();
+ QVERIFY2(instance, qPrintable("property was null: " + property));
+ }
+ QCOMPARE(instance->objectName(), delegate);
+ }
+
+ QEXPECT_FAIL("identified:ComboBox", "ComboBox::popup with an ID is created at construction time", Continue);
+ QEXPECT_FAIL("overidentified:ComboBox", "ComboBox::popup with an ID is created at construction time", Continue);
+ QVERIFY2(qt_createdQObjects()->isEmpty(), qPrintable("unexpectedly created: " + qt_createdQObjects->join(", ")));
+
+ if (!nonDeferred.isEmpty()) {
+ for (QString delegate : qAsConst(delegates)) {
+ if (!delegate.contains("-"))
+ delegate.append("-" + nonDeferred);
+ delegate.prepend(type.toLower() + "-");
+ QVERIFY2(qt_destroyedQObjects()->removeOne(delegate), qPrintable(delegate + " was not destroyed as expected"));
+ }
+ }
+
+ QVERIFY2(qt_destroyedQObjects()->isEmpty(), qPrintable("unexpectedly destroyed: " + qt_destroyedQObjects->join(", ")));
}
void tst_customization::comboPopup()