diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp index fc925126350..777de1c3357 100644 --- a/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp +++ b/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp @@ -347,12 +347,6 @@ bool ensureDataStoreExists(bool &justCreated) if (qmlDirSaver.finalize()) { justCreated = true; - - // Force code model reset to notice changes to existing module - auto modelManager = QmlJS::ModelManagerInterface::instance(); - if (modelManager) - modelManager->resetCodeModel(); - return true; } diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp index 92a66e51bec..df4fee7a7ee 100644 --- a/src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp +++ b/src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp @@ -19,15 +19,16 @@ #include #include #include - -#include -#include -#include +#include #include #include #include +#include +#include +#include + namespace { inline bool isStudioCollectionModel(const QmlDesigner::ModelNode &node) @@ -139,6 +140,12 @@ void CollectionView::modelAttached(Model *model) resetDataStoreNode(); } +void CollectionView::modelAboutToBeDetached([[maybe_unused]] Model *model) +{ + m_libraryInfoIsUpdated = false; + disconnect(m_documentUpdateConnection); +} + void CollectionView::nodeReparented(const ModelNode &node, [[maybe_unused]] const NodeAbstractProperty &newPropertyParent, [[maybe_unused]] const NodeAbstractProperty &oldPropertyParent, @@ -292,6 +299,10 @@ void CollectionView::assignCollectionToNode(const QString &collectionName, const } NodeProperty delegateProperty = node.nodeProperty("delegate"); + // Remove the old model node if is available + if (delegateProperty.modelNode()) + delegateProperty.modelNode().destroy(); + delegateProperty.setModelNode(rowItem); } }); @@ -324,8 +335,29 @@ void CollectionView::ensureDataStoreExists() { bool filesJustCreated = false; bool filesExist = CollectionEditorUtils::ensureDataStoreExists(filesJustCreated); - if (filesExist && filesJustCreated) - resetDataStoreNode(); + if (filesExist) { + if (filesJustCreated) { + // Force code model reset to notice changes to existing module + auto modelManager = QmlJS::ModelManagerInterface::instance(); + if (modelManager) { + m_libraryInfoIsUpdated = false; + + m_expectedDocumentUpdates.clear(); + m_expectedDocumentUpdates << CollectionEditorUtils::dataStoreQmlFilePath() + << CollectionEditorUtils::dataStoreJsonFilePath(); + + m_documentUpdateConnection = connect(modelManager, + &QmlJS::ModelManagerInterface::documentUpdated, + this, + &CollectionView::onDocumentUpdated); + + modelManager->resetCodeModel(); + } + resetDataStoreNode(); + } else { + m_libraryInfoIsUpdated = true; + } + } } QString CollectionView::collectionNameFromDataStoreChildren(const PropertyName &childPropertyName) const @@ -387,9 +419,62 @@ void CollectionView::onItemLibraryNodeCreated(const ModelNode &node) sourceModel->addCollectionToSource(dataStoreNode(), newCollectionName, CollectionEditorUtils::defaultColorCollection()); - assignCollectionToNode(newCollectionName, node); m_widget->openCollection(newCollectionName); + new DelayedAssignCollectionToItem(this, node, newCollectionName); } } +void CollectionView::onDocumentUpdated(const QSharedPointer &doc) +{ + if (m_expectedDocumentUpdates.contains(doc->fileName())) + m_expectedDocumentUpdates.remove(doc->fileName()); + + if (m_expectedDocumentUpdates.isEmpty()) { + disconnect(m_documentUpdateConnection); + m_libraryInfoIsUpdated = true; + } +} + +DelayedAssignCollectionToItem::DelayedAssignCollectionToItem(CollectionView *parent, + const ModelNode &node, + const QString &collectionName) + : QObject(parent) + , m_collectionView(parent) + , m_node(node) + , m_name(collectionName) +{ + checkAndAssign(); +} + +void DelayedAssignCollectionToItem::checkAndAssign() +{ + AbstractView *view = m_node.view(); + + if (!m_node || !m_collectionView || !view || ++m_counter > 50) { + deleteLater(); + return; + } + + bool dataStoreFound = false; + + if (m_collectionView->isDataStoreReady()) { + for (const QmlTypeData &cppTypeData : view->rewriterView()->getQMLTypes()) { + if (cppTypeData.isSingleton && cppTypeData.typeName == "DataStore") + dataStoreFound = true; + } + if (!dataStoreFound && !m_rewriterAmended) { + m_collectionView->model()->rewriterView()->forceAmend(); + m_rewriterAmended = true; + } + } + + if (!dataStoreFound) { + QTimer::singleShot(100, this, &DelayedAssignCollectionToItem::checkAndAssign); + return; + } + + m_collectionView->assignCollectionToNode(m_name, m_node); + deleteLater(); +} + } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionview.h b/src/plugins/qmldesigner/components/collectioneditor/collectionview.h index db3964726b4..649b37f3beb 100644 --- a/src/plugins/qmldesigner/components/collectioneditor/collectionview.h +++ b/src/plugins/qmldesigner/components/collectioneditor/collectionview.h @@ -7,6 +7,9 @@ #include "datastoremodelnode.h" #include "modelnode.h" +namespace QmlJS { +class Document; +} namespace QmlDesigner { class CollectionWidget; @@ -23,6 +26,7 @@ public: WidgetInfo widgetInfo() override; void modelAttached(Model *model) override; + void modelAboutToBeDetached(Model *model) override; void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, @@ -58,14 +62,41 @@ public: void ensureDataStoreExists(); QString collectionNameFromDataStoreChildren(const PropertyName &childPropertyName) const; + bool isDataStoreReady() const { return m_libraryInfoIsUpdated; } + private: void refreshModel(); NodeMetaInfo jsonCollectionMetaInfo() const; NodeMetaInfo csvCollectionMetaInfo() const; void ensureStudioModelImport(); void onItemLibraryNodeCreated(const ModelNode &node); + void onDocumentUpdated(const QSharedPointer &doc); QPointer m_widget; std::unique_ptr m_dataStore; + QSet m_expectedDocumentUpdates; + QMetaObject::Connection m_documentUpdateConnection; + bool m_libraryInfoIsUpdated = false; }; + +class DelayedAssignCollectionToItem : public QObject +{ + Q_OBJECT + +public: + DelayedAssignCollectionToItem(CollectionView *parent, + const ModelNode &node, + const QString &collectionName); + +public slots: + void checkAndAssign(); + +private: + QPointer m_collectionView; + ModelNode m_node; + QString m_name; + int m_counter = 0; + bool m_rewriterAmended = false; +}; + } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.cpp b/src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.cpp index e5ddb1dd3a0..7a7a2f7d7a6 100644 --- a/src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.cpp +++ b/src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.cpp @@ -459,8 +459,16 @@ void DataStoreModelNode::assignCollectionToNode(AbstractView *view, view->executeInTransaction("assignCollectionToNode", [&]() { QString identifier = QString("DataStore.%1").arg(QString::fromLatin1(sourceProperty.name())); + + // Remove the old model node property if exists + NodeProperty modelNodeProperty = targetNode.nodeProperty("model"); + if (modelNodeProperty.modelNode()) + modelNodeProperty.modelNode().destroy(); + + // Assign the collection to the node BindingProperty modelProperty = targetNode.bindingProperty("model"); modelProperty.setExpression(identifier); + if (CollectionEditorUtils::hasTextRoleProperty(targetNode)) { VariantProperty textRoleProperty = targetNode.variantProperty("textRole"); const QVariant currentTextRoleValue = textRoleProperty.value(); diff --git a/src/plugins/qmldesigner/qtquickplugin/source/listview.qml b/src/plugins/qmldesigner/qtquickplugin/source/listview.qml index c76d9c535e2..ffda2e309e7 100644 --- a/src/plugins/qmldesigner/qtquickplugin/source/listview.qml +++ b/src/plugins/qmldesigner/qtquickplugin/source/listview.qml @@ -4,40 +4,38 @@ import QtQuick 1.0 ListView { - width: 110 - height: 160 + width: 160 + height: 80 model: ListModel { - ListElement { - name: "Grey" - colorCode: "grey" - } ListElement { name: "Red" colorCode: "red" } + ListElement { + name: "Green" + colorCode: "green" + } ListElement { name: "Blue" colorCode: "blue" } ListElement { - name: "Green" - colorCode: "green" + name: "White" + colorCode: "white" } } - delegate: Item { - width: 80 - height: 40 - x: 5 - Row { - id: row1 - spacing: 10 - Rectangle { width: 40; height: 40; color: colorCode; } - Text { - text: name - anchors.verticalCenter: parent.verticalCenter - font.bold: true - } + delegate: Row { + spacing: 5 + Rectangle { + width: 100 + height: 20 + color: colorCode + } + + Text { + width: 100 + text: name } } } diff --git a/src/plugins/qmldesigner/qtquickplugin/source/listviewv2.qml b/src/plugins/qmldesigner/qtquickplugin/source/listviewv2.qml index a11e3ee68da..20b08f7cfcf 100644 --- a/src/plugins/qmldesigner/qtquickplugin/source/listviewv2.qml +++ b/src/plugins/qmldesigner/qtquickplugin/source/listviewv2.qml @@ -4,40 +4,38 @@ import QtQuick 2.0 ListView { - width: 110 - height: 160 + width: 160 + height: 80 model: ListModel { - ListElement { - name: "Grey" - colorCode: "grey" - } ListElement { name: "Red" colorCode: "red" } + ListElement { + name: "Green" + colorCode: "green" + } ListElement { name: "Blue" colorCode: "blue" } ListElement { - name: "Green" - colorCode: "green" + name: "White" + colorCode: "white" } } - delegate: Item { - width: 80 - height: 40 - x: 5 - Row { - id: row1 - spacing: 10 - Rectangle { width: 40; height: 40; color: colorCode; } - Text { - text: name - anchors.verticalCenter: parent.verticalCenter - font.bold: true - } + delegate: Row { + spacing: 5 + Rectangle { + width: 100 + height: 20 + color: colorCode + } + + Text { + width: 100 + text: name } } }