aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarco Bubke <marco.bubke@qt.io>2020-08-06 10:45:02 +0200
committerMarco Bubke <marco.bubke@qt.io>2020-08-10 09:40:26 +0000
commitb4027b7943e52374141ec6b66e9ec0ceadfe81e9 (patch)
tree2afce2c687266f25682678d45afdf5e26f2d8ad8
parent97cc02b78105f1f6f478764ee0c6a56cc806fb07 (diff)
QmlDesigner: Fix crash for list view model
There was a type, so it crashed. The code is now under tests so we cannot break it anymore. Task-number: QDS-2563 Change-Id: I81426a9f8a568b217b7bf9c8c261b24be14ff61a Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
-rw-r--r--src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp34
-rw-r--r--src/plugins/qmldesigner/components/listmodeleditor/listmodeleditormodel.cpp31
-rw-r--r--src/plugins/qmldesigner/components/listmodeleditor/listmodeleditormodel.h16
-rw-r--r--tests/unit/unittest/listmodeleditor-test.cpp40
4 files changed, 96 insertions, 25 deletions
diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
index fb7d4ce202..e0978df21c 100644
--- a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
@@ -363,32 +363,30 @@ public:
bool isEnabled(const SelectionContext &) const override { return true; }
- static ModelNode listModelNode(const ModelNode &listViewNode)
- {
- if (listViewNode.hasProperty("model")) {
- if (listViewNode.hasBindingProperty("model"))
- return listViewNode.bindingProperty("model").resolveToModelNode();
- else if (listViewNode.hasNodeProperty("model"))
- return listViewNode.nodeProperty("model").modelNode();
- }
-
- ModelNode newModel = listViewNode.view()->createModelNode("QtQml.Models.ListModel", 2, 15);
- listViewNode.nodeProperty("mode").reparentHere(newModel);
-
- return newModel;
- }
-
static void openDialog(const SelectionContext &selectionState)
{
- ListModelEditorModel model;
-
ModelNode targetNode = selectionState.targetNode();
if (!targetNode.isValid())
targetNode = selectionState.currentSingleSelectedNode();
if (!targetNode.isValid())
return;
- model.setListModel(listModelNode(targetNode));
+ AbstractView *view = targetNode.view();
+ NodeMetaInfo modelMetaInfo = view->model()->metaInfo("ListModel");
+ NodeMetaInfo elementMetaInfo = view->model()->metaInfo("ListElement");
+
+ ListModelEditorModel model{[&] {
+ return view->createModelNode(modelMetaInfo.typeName(),
+ modelMetaInfo.majorVersion(),
+ modelMetaInfo.minorVersion());
+ },
+ [&] {
+ return view->createModelNode(elementMetaInfo.typeName(),
+ elementMetaInfo.majorVersion(),
+ elementMetaInfo.minorVersion());
+ }};
+
+ model.setListView(targetNode);
ListModelEditorDialog dialog{Core::ICore::mainWindow()};
dialog.setModel(&model);
diff --git a/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditormodel.cpp b/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditormodel.cpp
index 0aeabb8b89..48b1ad6fc9 100644
--- a/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditormodel.cpp
+++ b/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditormodel.cpp
@@ -26,7 +26,9 @@
#include "listmodeleditormodel.h"
#include <abstractview.h>
+#include <bindingproperty.h>
#include <nodelistproperty.h>
+#include <nodeproperty.h>
#include <variantproperty.h>
#include <QVariant>
@@ -185,6 +187,22 @@ void renameProperties(const QStandardItemModel *model,
static_cast<ListModelItem *>(model->item(rowIndex, columnIndex))->renameProperty(newPropertyName);
}
+ModelNode listModelNode(const ModelNode &listViewNode,
+ const std::function<ModelNode()> &createModelCallback)
+{
+ if (listViewNode.hasProperty("model")) {
+ if (listViewNode.hasBindingProperty("model"))
+ return listViewNode.bindingProperty("model").resolveToModelNode();
+ else if (listViewNode.hasNodeProperty("model"))
+ return listViewNode.nodeProperty("model").modelNode();
+ }
+
+ ModelNode newModel = createModelCallback();
+ listViewNode.nodeProperty("model").reparentHere(newModel);
+
+ return newModel;
+}
+
} // namespace
void ListModelEditorModel::populateModel()
@@ -214,9 +232,20 @@ void ListModelEditorModel::appendItems(const ModelNode &listElementNode)
appendRow(row);
}
+void ListModelEditorModel::setListModel(ModelNode node)
+{
+ m_listModelNode = node;
+ populateModel();
+}
+
+void ListModelEditorModel::setListView(ModelNode listView)
+{
+ setListModel(listModelNode(listView, m_createModelCallback));
+}
+
void ListModelEditorModel::addRow()
{
- auto newElement = m_listModelNode.view()->createModelNode("QtQml.Models.ListElement", 2, 15);
+ auto newElement = m_createElementCallback();
m_listModelNode.defaultNodeListProperty().reparentHere(newElement);
appendItems(newElement);
diff --git a/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditormodel.h b/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditormodel.h
index 3056d32dbb..97bd9c18d8 100644
--- a/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditormodel.h
+++ b/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditormodel.h
@@ -38,11 +38,15 @@ class ListModelEditorModel : public QStandardItemModel
using QStandardItemModel::removeRows;
public:
- void setListModel(ModelNode node)
- {
- m_listModelNode = node;
- populateModel();
- }
+ ListModelEditorModel(std::function<ModelNode()> createModelCallback,
+ std::function<ModelNode()> createElementCallback)
+ : m_createModelCallback(std::move(createModelCallback))
+ , m_createElementCallback(std::move(createElementCallback))
+ {}
+
+ void setListModel(ModelNode node);
+
+ void setListView(ModelNode listView);
void addRow();
void addColumn(const QString &columnName);
@@ -70,6 +74,8 @@ private:
private:
ModelNode m_listModelNode;
QList<QmlDesigner::PropertyName> m_propertyNames;
+ std::function<ModelNode()> m_createModelCallback;
+ std::function<ModelNode()> m_createElementCallback;
};
} // namespace QmlDesigner
diff --git a/tests/unit/unittest/listmodeleditor-test.cpp b/tests/unit/unittest/listmodeleditor-test.cpp
index af4009ae9b..0a5a91327a 100644
--- a/tests/unit/unittest/listmodeleditor-test.cpp
+++ b/tests/unit/unittest/listmodeleditor-test.cpp
@@ -31,8 +31,10 @@
#include <qmldesigner/components/listmodeleditor/listmodeleditormodel.h>
#include <qmldesigner/designercore/include/abstractview.h>
+#include <qmldesigner/designercore/include/bindingproperty.h>
#include <qmldesigner/designercore/include/model.h>
#include <qmldesigner/designercore/include/nodelistproperty.h>
+#include <qmldesigner/designercore/include/nodeproperty.h>
#include <qmldesigner/designercore/include/variantproperty.h>
namespace {
@@ -94,6 +96,7 @@ public:
emptyListModelNode = mockView.createModelNode("QtQml.Models.ListModel", 2, 15);
+ listViewNode = mockView.createModelNode("QtQuick.ListView", 2, 15);
listModelNode = mockView.createModelNode("QtQml.Models.ListModel", 2, 15);
mockView.rootModelNode().defaultNodeListProperty().reparentHere(listModelNode);
element1 = createElement({{"name", "foo"}, {"value", 1}, {"value2", 42}});
@@ -183,7 +186,10 @@ public:
protected:
std::unique_ptr<QmlDesigner::Model> designerModel{QmlDesigner::Model::create("QtQuick.Item", 1, 1)};
NiceMock<MockListModelEditorView> mockView;
- QmlDesigner::ListModelEditorModel model;
+ QmlDesigner::ListModelEditorModel model{
+ [&] { return mockView.createModelNode("QtQml.Models.ListModel", 2, 15); },
+ [&] { return mockView.createModelNode("QtQml.Models.ListElement", 2, 15); }};
+ ModelNode listViewNode;
ModelNode listModelNode;
ModelNode emptyListModelNode;
ModelNode element1;
@@ -1272,4 +1278,36 @@ TEST_F(ListModelEditor, SelectionAfterMoveRowsUp)
index(2, 3)));
}
+TEST_F(ListModelEditor, ListViewHasNoModel)
+{
+ model.setListView(listViewNode);
+
+ ASSERT_THAT(listViewNode.nodeProperty("model").modelNode().type(), Eq("QtQml.Models.ListModel"));
+}
+
+TEST_F(ListModelEditor, ListViewHasModelInside)
+{
+ listViewNode.nodeProperty("model").reparentHere(listModelNode);
+
+ model.setListView(listViewNode);
+
+ ASSERT_THAT(displayValues(),
+ ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42),
+ ElementsAre("pic.png", "bar", 4, IsInvalid()),
+ ElementsAre("pic.png", "poo", 111, IsInvalid())));
+}
+
+TEST_F(ListModelEditor, ListViewHasModelBinding)
+{
+ listModelNode.setIdWithoutRefactoring("listModel");
+ listViewNode.bindingProperty("model").setExpression("listModel");
+
+ model.setListView(listViewNode);
+
+ ASSERT_THAT(displayValues(),
+ ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42),
+ ElementsAre("pic.png", "bar", 4, IsInvalid()),
+ ElementsAre("pic.png", "poo", 111, IsInvalid())));
+}
+
} // namespace