aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/qmldesigner
diff options
context:
space:
mode:
authorAli Kianian <ali.kianian@qt.io>2024-02-29 23:46:39 +0200
committerAli Kianian <ali.kianian@qt.io>2024-03-01 13:17:42 +0000
commitf7530458c456e15d318578b1c18435409936d319 (patch)
treefc75c69ab800a42a573dca4736e3bb5d7a7d4b77 /src/plugins/qmldesigner
parent9f024eb5cd7abc95a462506ebea9274d0cdd3939 (diff)
QmlDesigner: Remove CollectionSourceModel
Task-number: QDS-12032 Change-Id: Id0b999500a0a8cae16a90a59d051cd725417e431 Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io> Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Diffstat (limited to 'src/plugins/qmldesigner')
-rw-r--r--src/plugins/qmldesigner/CMakeLists.txt1
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp9
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.h2
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionlistmodel.cpp371
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionlistmodel.h36
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.cpp738
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.h119
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp118
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionview.h17
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp14
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionwidget.h6
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.cpp22
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.h3
13 files changed, 434 insertions, 1022 deletions
diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt
index aa4750f81d..5498097c1d 100644
--- a/src/plugins/qmldesigner/CMakeLists.txt
+++ b/src/plugins/qmldesigner/CMakeLists.txt
@@ -838,7 +838,6 @@ extend_qtc_plugin(QmlDesigner
collectioneditorconstants.h
collectioneditorutils.cpp collectioneditorutils.h
collectionlistmodel.cpp collectionlistmodel.h
- collectionsourcemodel.cpp collectionsourcemodel.h
collectionview.cpp collectionview.h
collectionwidget.cpp collectionwidget.h
datastoremodelnode.cpp datastoremodelnode.h
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp
index ecc2544bcc..e1a17c51a1 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp
@@ -176,15 +176,6 @@ bool variantIslessThan(const QVariant &a, const QVariant &b, DataType type)
return std::visit(LessThanVisitor{}, valueToVariant(a, type), valueToVariant(b, type));
}
-CollectionEditorConstants::SourceFormat getSourceCollectionFormat(const ModelNode &node)
-{
- using namespace QmlDesigner;
- if (node.type() == CollectionEditorConstants::JSONCOLLECTIONMODEL_TYPENAME)
- return CollectionEditorConstants::SourceFormat::Json;
-
- return CollectionEditorConstants::SourceFormat::Unknown;
-}
-
QString getSourceCollectionType(const ModelNode &node)
{
using namespace QmlDesigner;
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.h b/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.h
index bd9e24d23c..5be1c51f00 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.h
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.h
@@ -19,8 +19,6 @@ namespace QmlDesigner::CollectionEditorUtils {
bool variantIslessThan(const QVariant &a, const QVariant &b, CollectionDetails::DataType type);
-CollectionEditorConstants::SourceFormat getSourceCollectionFormat(const QmlDesigner::ModelNode &node);
-
QString getSourceCollectionType(const QmlDesigner::ModelNode &node);
QString getSourceCollectionPath(const QmlDesigner::ModelNode &dataStoreNode);
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionlistmodel.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectionlistmodel.cpp
index 323f0e767f..d27a077d2a 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionlistmodel.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionlistmodel.cpp
@@ -6,8 +6,13 @@
#include "collectioneditorutils.h"
#include <utils/algorithm.h>
+#include <utils/fileutils.h>
#include <utils/qtcassert.h>
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QJsonParseError>
+
namespace {
template<typename ValueType>
@@ -20,14 +25,23 @@ bool containsItem(const std::initializer_list<ValueType> &container, const Value
return it != end;
}
+bool sameCollectionNames(QStringList a, QStringList b)
+{
+ if (a.size() != b.size())
+ return false;
+
+ a.sort(Qt::CaseSensitive);
+ b.sort(Qt::CaseSensitive);
+
+ return a == b;
+}
+
} // namespace
namespace QmlDesigner {
-CollectionListModel::CollectionListModel(const ModelNode &sourceModel)
+CollectionListModel::CollectionListModel()
: QAbstractListModel()
- , m_sourceNode(sourceModel)
- , m_sourceType(CollectionEditorUtils::getSourceCollectionType(sourceModel))
{
connect(this, &CollectionListModel::modelReset, this, &CollectionListModel::updateEmpty);
connect(this, &CollectionListModel::rowsRemoved, this, &CollectionListModel::updateEmpty);
@@ -59,18 +73,26 @@ bool CollectionListModel::setData(const QModelIndex &index, const QVariant &valu
return false;
if (containsItem<int>({Qt::EditRole, Qt::DisplayRole, NameRole}, role)) {
- if (contains(value.toString()))
+ if (collectionExists(value.toString()))
return false;
QString oldName = collectionNameAt(index.row());
bool nameChanged = value != data(index);
if (nameChanged) {
QString newName = value.toString();
- m_data.replace(index.row(), newName);
- emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole});
- emit this->collectionNameChanged(oldName, newName);
+ QString errorString;
+ if (renameCollectionInDataStore(oldName, newName, errorString)) {
+ m_data.replace(index.row(), newName);
+ emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole, NameRole});
+ emit this->collectionNameChanged(oldName, newName);
+ if (m_selectedCollectionName == oldName)
+ updateSelectedCollectionName();
+ return true;
+ } else {
+ emit warning("Rename Model", errorString);
+ return false;
+ }
}
- return nameChanged;
} else if (role == SelectedRole) {
if (value.toBool() != index.data(SelectedRole).toBool()) {
setSelectedIndex(value.toBool() ? index.row() : -1);
@@ -92,17 +114,27 @@ bool CollectionListModel::removeRows(int row, int count, const QModelIndex &pare
if (count < 1)
return false;
+ QString errorString;
QStringList removedCollections = m_data.mid(row, count);
+ if (removeCollectionsFromDataStore(removedCollections, errorString)) {
+ beginRemoveRows(parent, row, row + count - 1);
+ m_data.remove(row, count);
+ endRemoveRows();
+
+ emit collectionsRemoved(removedCollections);
+ if (m_selectedIndex >= row) {
+ int preferredIndex = m_selectedIndex - count;
+ if (preferredIndex < 0) // If the selected item is deleted, reset selection
+ selectCollectionIndex(-1);
+ selectCollectionIndex(preferredIndex, true);
+ }
- beginRemoveRows(parent, row, row + count - 1);
- m_data.remove(row, count);
- endRemoveRows();
-
- emit collectionsRemoved(removedCollections);
- if (m_selectedIndex >= row)
- selectCollectionIndex(m_selectedIndex - count, true);
-
- return true;
+ updateSelectedCollectionName();
+ return true;
+ } else {
+ emit warning("Remove Model", errorString);
+ return false;
+ }
}
QVariant CollectionListModel::data(const QModelIndex &index, int role) const
@@ -120,13 +152,10 @@ QVariant CollectionListModel::data(const QModelIndex &index, int role) const
}
}
-void CollectionListModel::resetModelData(const QStringList &collectionsList)
+void CollectionListModel::setDataStoreNode(const ModelNode &dataStoreNode)
{
- QString prevSelectedCollection = selectedIndex() > -1 ? m_data.at(selectedIndex()) : QString();
- beginResetModel();
- m_data = collectionsList;
- endResetModel();
- selectCollectionName(prevSelectedCollection);
+ m_dataStoreNode = dataStoreNode;
+ update();
}
int CollectionListModel::selectedIndex() const
@@ -136,15 +165,10 @@ int CollectionListModel::selectedIndex() const
ModelNode CollectionListModel::sourceNode() const
{
- return m_sourceNode;
-}
-
-QString CollectionListModel::sourceAddress() const
-{
- return CollectionEditorUtils::getSourceCollectionPath(m_sourceNode);
+ return m_dataStoreNode;
}
-bool CollectionListModel::contains(const QString &collectionName) const
+bool CollectionListModel::collectionExists(const QString &collectionName) const
{
return m_data.contains(collectionName);
}
@@ -154,6 +178,19 @@ QStringList CollectionListModel::collections() const
return m_data;
}
+QString CollectionListModel::getUniqueCollectionName(const QString &baseName) const
+{
+ QString name = baseName.isEmpty() ? "Model" : baseName;
+ QString nameTemplate = name + "%1";
+
+ int num = 0;
+
+ while (collectionExists(name))
+ name = nameTemplate.arg(++num, 2, 10, QChar('0'));
+
+ return name;
+}
+
void CollectionListModel::selectCollectionIndex(int idx, bool selectAtLeastOne)
{
int collectionCount = m_data.size();
@@ -168,11 +205,20 @@ void CollectionListModel::selectCollectionIndex(int idx, bool selectAtLeastOne)
setSelectedIndex(preferredIndex);
}
-void CollectionListModel::selectCollectionName(const QString &collectionName)
+void CollectionListModel::selectCollectionName(QString collectionName, bool selectAtLeastOne)
{
int idx = m_data.indexOf(collectionName);
if (idx > -1)
selectCollectionIndex(idx);
+ else
+ selectCollectionIndex(selectedIndex(), selectAtLeastOne);
+
+ collectionName = collectionNameAt(selectedIndex());
+ if (m_selectedCollectionName == collectionName)
+ return;
+
+ m_selectedCollectionName = collectionName;
+ emit selectedCollectionNameChanged(m_selectedCollectionName);
}
QString CollectionListModel::collectionNameAt(int idx) const
@@ -180,17 +226,76 @@ QString CollectionListModel::collectionNameAt(int idx) const
return index(idx).data(NameRole).toString();
}
-void CollectionListModel::addCollection(const QString &collectionName)
+QString CollectionListModel::selectedCollectionName() const
{
- if (m_data.contains(collectionName))
- return;
+ return m_selectedCollectionName;
+}
- int row = rowCount();
- beginInsertRows({}, row, row);
- m_data.append(collectionName);
- endInsertRows();
+void CollectionListModel::update()
+{
+ using Utils::FilePath;
+ using Utils::FileReader;
+
+ FileReader sourceFile;
+ QString sourceFileAddress = CollectionEditorUtils::getSourceCollectionPath(m_dataStoreNode);
+ FilePath path = FilePath::fromUserInput(sourceFileAddress);
+ bool fileRead = false;
+ if (path.exists()) {
+ fileRead = sourceFile.fetch(path);
+ if (!fileRead)
+ emit this->warning(tr("Model Editor"),
+ tr("Cannot read the dataStore file\n%1").arg(sourceFile.errorString()));
+ }
- emit collectionAdded(collectionName);
+ QStringList collectionNames;
+ if (fileRead) {
+ QJsonParseError parseError;
+ QJsonDocument document = QJsonDocument::fromJson(sourceFile.data(), &parseError);
+ if (parseError.error != QJsonParseError::NoError) {
+ emit this->warning(tr("Model Editor"),
+ tr("There is an error in the JSON file.\n%1")
+ .arg(parseError.errorString()));
+ } else {
+ if (document.isObject())
+ collectionNames = document.object().toVariantMap().keys();
+ else
+ emit this->warning(tr("Model Editor"), tr("The JSON document be an object."));
+ }
+ }
+
+ if (!sameCollectionNames(m_data, collectionNames)) {
+ QString prevSelectedCollection = selectedIndex() > -1 ? m_data.at(selectedIndex())
+ : QString();
+ beginResetModel();
+ m_data = collectionNames;
+ endResetModel();
+ emit this->collectionNamesChanged(collections());
+ selectCollectionName(prevSelectedCollection, true);
+ }
+}
+
+bool CollectionListModel::addCollection(const QString &collectionName,
+ const QJsonObject &localCollection)
+{
+ if (collectionExists(collectionName)) {
+ emit warning(tr("Add Model"), tr("Model \"%1\" already exists.").arg(collectionName));
+ return false;
+ }
+
+ QString errorMessage;
+ if (addCollectionToDataStore(collectionName, localCollection, errorMessage)) {
+ int row = rowCount();
+ beginInsertRows({}, row, row);
+ m_data.append(collectionName);
+ endInsertRows();
+
+ selectCollectionName(collectionName);
+ emit collectionAdded(collectionName);
+ return true;
+ } else {
+ emit warning(tr("Add Collection"), errorMessage);
+ }
+ return false;
}
void CollectionListModel::setSelectedIndex(int idx)
@@ -210,6 +315,187 @@ void CollectionListModel::setSelectedIndex(int idx)
emit dataChanged(newIndex, newIndex, {SelectedRole});
emit selectedIndexChanged(idx);
+ updateSelectedCollectionName();
+ }
+}
+
+bool CollectionListModel::removeCollectionsFromDataStore(const QStringList &removedCollections,
+ QString &error) const
+{
+ using Utils::FilePath;
+ using Utils::FileReader;
+ auto setErrorAndReturn = [&error](const QString &msg) -> bool {
+ error = msg;
+ return false;
+ };
+
+ if (m_dataStoreNode.type() != CollectionEditorConstants::JSONCOLLECTIONMODEL_TYPENAME)
+ return setErrorAndReturn(tr("Invalid node type"));
+
+ QString sourceFileAddress = CollectionEditorUtils::getSourceCollectionPath(m_dataStoreNode);
+
+ QFileInfo sourceFileInfo(sourceFileAddress);
+ if (!sourceFileInfo.isFile())
+ return setErrorAndReturn(tr("The selected node has an invalid source address"));
+
+ FilePath jsonPath = FilePath::fromUserInput(sourceFileAddress);
+ FileReader jsonFile;
+ if (!jsonFile.fetch(jsonPath)) {
+ return setErrorAndReturn(tr("Can't read file \"%1\".\n%2")
+ .arg(sourceFileInfo.absoluteFilePath(), jsonFile.errorString()));
+ }
+
+ QJsonParseError parseError;
+ QJsonDocument document = QJsonDocument::fromJson(jsonFile.data(), &parseError);
+ if (parseError.error != QJsonParseError::NoError) {
+ return setErrorAndReturn(tr("\"%1\" is corrupted.\n%2")
+ .arg(sourceFileInfo.absoluteFilePath(), parseError.errorString()));
+ }
+
+ if (document.isObject()) {
+ QJsonObject rootObject = document.object();
+
+ for (const QString &collectionName : removedCollections) {
+ bool sourceContainsCollection = rootObject.contains(collectionName);
+ if (sourceContainsCollection) {
+ rootObject.remove(collectionName);
+ } else {
+ setErrorAndReturn(tr("The model group doesn't contain the model name (%1).")
+ .arg(sourceContainsCollection));
+ }
+ }
+
+ document.setObject(rootObject);
+
+ if (CollectionEditorUtils::writeToJsonDocument(jsonPath, document)) {
+ error.clear();
+ return true;
+ } else {
+ return setErrorAndReturn(
+ tr("Can't write to \"%1\".").arg(sourceFileInfo.absoluteFilePath()));
+ }
+ } else {
+ return setErrorAndReturn(tr("Local Json Document should be an object"));
+ }
+
+ return false;
+}
+
+bool CollectionListModel::renameCollectionInDataStore(const QString &oldName,
+ const QString &newName,
+ QString &error)
+{
+ using Utils::FilePath;
+ using Utils::FileReader;
+ using Utils::FileSaver;
+
+ auto setErrorAndReturn = [&error](const QString &msg) -> bool {
+ error = msg;
+ return false;
+ };
+
+ if (m_dataStoreNode.type() != CollectionEditorConstants::JSONCOLLECTIONMODEL_TYPENAME)
+ return setErrorAndReturn(tr("Invalid node type"));
+
+ QString sourceFileAddress = CollectionEditorUtils::getSourceCollectionPath(m_dataStoreNode);
+
+ QFileInfo sourceFileInfo(sourceFileAddress);
+ if (!sourceFileInfo.isFile())
+ return setErrorAndReturn(tr("Selected node must have a valid source file address"));
+
+ FilePath jsonPath = FilePath::fromUserInput(sourceFileAddress);
+ FileReader jsonFile;
+ if (!jsonFile.fetch(jsonPath)) {
+ return setErrorAndReturn(
+ tr("Can't read \"%1\".\n%2").arg(sourceFileInfo.absoluteFilePath(), jsonFile.errorString()));
+ }
+
+ QJsonParseError parseError;
+ QJsonDocument document = QJsonDocument::fromJson(jsonFile.data(), &parseError);
+ if (parseError.error != QJsonParseError::NoError) {
+ return setErrorAndReturn(tr("\"%1\" is corrupted.\n%2")
+ .arg(sourceFileInfo.absoluteFilePath(), parseError.errorString()));
+ }
+
+ if (document.isObject()) {
+ QJsonObject rootObject = document.object();
+
+ bool collectionContainsOldName = rootObject.contains(oldName);
+ bool collectionContainsNewName = rootObject.contains(newName);
+
+ if (!collectionContainsOldName) {
+ return setErrorAndReturn(
+ tr("The model group doesn't contain the old model name (%1).").arg(oldName));
+ }
+
+ if (collectionContainsNewName) {
+ return setErrorAndReturn(
+ tr("The model name \"%1\" already exists in the model group.").arg(newName));
+ }
+
+ QJsonValue oldValue = rootObject.value(oldName);
+ rootObject.insert(newName, oldValue);
+ rootObject.remove(oldName);
+
+ document.setObject(rootObject);
+
+ if (CollectionEditorUtils::writeToJsonDocument(jsonPath, document)) {
+ error.clear();
+ return true;
+ } else {
+ return setErrorAndReturn(
+ tr("Can't write to \"%1\".").arg(sourceFileInfo.absoluteFilePath()));
+ }
+ } else {
+ return setErrorAndReturn(tr("Local Json Document should be an object"));
+ }
+ return false;
+}
+
+bool CollectionListModel::addCollectionToDataStore(const QString &collectionName,
+ const QJsonObject &localCollection,
+ QString &errorString) const
+{
+ using Utils::FilePath;
+ using Utils::FileReader;
+ auto returnError = [&errorString](const QString &msg) -> bool {
+ errorString = msg;
+ return false;
+ };
+
+ if (collectionExists(collectionName))
+ return returnError(tr("A model with the identical name already exists."));
+
+ QString sourceFileAddress = CollectionEditorUtils::getSourceCollectionPath(m_dataStoreNode);
+
+ QFileInfo sourceFileInfo(sourceFileAddress);
+ if (!sourceFileInfo.isFile())
+ return returnError(tr("Selected node must have a valid source file address"));
+
+ FilePath jsonPath = FilePath::fromUserInput(sourceFileAddress);
+ FileReader jsonFile;
+ if (!jsonFile.fetch(jsonPath)) {
+ return returnError(
+ tr("Can't read \"%1\".\n%2").arg(sourceFileInfo.absoluteFilePath(), jsonFile.errorString()));
+ }
+
+ QJsonParseError parseError;
+ QJsonDocument document = QJsonDocument::fromJson(jsonFile.data(), &parseError);
+ if (parseError.error != QJsonParseError::NoError)
+ return returnError(tr("\"%1\" is corrupted.\n%2")
+ .arg(sourceFileInfo.absoluteFilePath(), parseError.errorString()));
+
+ if (document.isObject()) {
+ QJsonObject sourceObject = document.object();
+ sourceObject.insert(collectionName, localCollection);
+ document.setObject(sourceObject);
+
+ if (CollectionEditorUtils::writeToJsonDocument(jsonPath, document))
+ return true;
+ else
+ return returnError(tr("Can't write to \"%1\".").arg(sourceFileInfo.absoluteFilePath()));
+ } else {
+ return returnError(tr("JSON document type should be an object containing models."));
}
}
@@ -225,4 +511,11 @@ void CollectionListModel::updateEmpty()
}
}
+void CollectionListModel::updateSelectedCollectionName()
+{
+ QString selectedCollectionByIndex = collectionNameAt(selectedIndex());
+ if (selectedCollectionByIndex != selectedCollectionName())
+ selectCollectionName(selectedCollectionByIndex);
+}
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionlistmodel.h b/src/plugins/qmldesigner/components/collectioneditor/collectionlistmodel.h
index 092dd1d6dc..7902fd5909 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionlistmodel.h
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionlistmodel.h
@@ -16,49 +16,63 @@ class CollectionListModel : public QAbstractListModel
Q_PROPERTY(int selectedIndex MEMBER m_selectedIndex NOTIFY selectedIndexChanged)
Q_PROPERTY(bool isEmpty MEMBER m_isEmpty NOTIFY isEmptyChanged)
- Q_PROPERTY(QString sourceType MEMBER m_sourceType CONSTANT)
+ Q_PROPERTY(QString selectedCollectionName
+ READ selectedCollectionName
+ WRITE selectCollectionName
+ NOTIFY selectedCollectionNameChanged)
public:
- enum Roles { IdRole = Qt::UserRole + 1, NameRole, SourceRole, SelectedRole, CollectionsRole };
+ enum Roles { IdRole = Qt::UserRole + 1, NameRole, SelectedRole };
- explicit CollectionListModel(const ModelNode &sourceModel);
+ explicit CollectionListModel();
QHash<int, QByteArray> roleNames() const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
bool removeRows(int row, int count, const QModelIndex &parent = {}) override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
- void resetModelData(const QStringList &collectionsList);
+ void setDataStoreNode(const ModelNode &dataStoreNode = {});
Q_INVOKABLE int selectedIndex() const;
Q_INVOKABLE ModelNode sourceNode() const;
- Q_INVOKABLE QString sourceAddress() const;
- Q_INVOKABLE bool contains(const QString &collectionName) const;
+ Q_INVOKABLE bool collectionExists(const QString &collectionName) const;
Q_INVOKABLE QStringList collections() const;
+ Q_INVOKABLE QString getUniqueCollectionName(const QString &baseName = {}) const;
void selectCollectionIndex(int idx, bool selectAtLeastOne = false);
- void selectCollectionName(const QString &collectionName);
+ void selectCollectionName(QString collectionName, bool selectAtLeastOne = false);
QString collectionNameAt(int idx) const;
- void addCollection(const QString &collectionName);
+ QString selectedCollectionName() const;
+
+ void update();
+ bool addCollection(const QString &collectionName, const QJsonObject &localCollection);
signals:
void selectedIndexChanged(int idx);
void isEmptyChanged(bool);
void collectionNameChanged(const QString &oldName, const QString &newName);
+ void collectionNamesChanged(const QStringList &collectionNames);
void collectionsRemoved(const QStringList &names);
void collectionAdded(const QString &name);
+ void selectedCollectionNameChanged(const QString &selectedCollectionName);
+ void warning(const QString &title, const QString &body);
private:
void setSelectedIndex(int idx);
+ bool removeCollectionsFromDataStore(const QStringList &removedCollections, QString &error) const;
+ bool renameCollectionInDataStore(const QString &oldName, const QString &newName, QString &error);
+ bool addCollectionToDataStore(const QString &collectionName,
+ const QJsonObject &localCollection,
+ QString &errorString) const;
void updateEmpty();
+ void updateSelectedCollectionName();
using Super = QAbstractListModel;
int m_selectedIndex = -1;
bool m_isEmpty = false;
- const ModelNode m_sourceNode;
- const QString m_sourceType;
-
+ ModelNode m_dataStoreNode;
+ QString m_selectedCollectionName;
QStringList m_data;
};
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.cpp
deleted file mode 100644
index 7760f46ff1..0000000000
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.cpp
+++ /dev/null
@@ -1,738 +0,0 @@
-// Copyright (C) 2023 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "collectionsourcemodel.h"
-
-#include "abstractview.h"
-#include "collectioneditorconstants.h"
-#include "collectioneditorutils.h"
-#include "collectionlistmodel.h"
-#include "variantproperty.h"
-
-#include <utils/fileutils.h>
-#include <utils/qtcassert.h>
-#include <qqml.h>
-
-#include <QFile>
-#include <QFileInfo>
-#include <QJsonArray>
-#include <QJsonDocument>
-#include <QJsonObject>
-#include <QJsonParseError>
-
-namespace {
-
-QSharedPointer<QmlDesigner::CollectionListModel> loadCollection(
- const QmlDesigner::ModelNode &sourceNode,
- QSharedPointer<QmlDesigner::CollectionListModel> initialCollection = {})
-{
- using namespace QmlDesigner::CollectionEditorConstants;
- using namespace QmlDesigner::CollectionEditorUtils;
- using Utils::FilePath;
- using Utils::FileReader;
- QString sourceFileAddress = getSourceCollectionPath(sourceNode);
-
- QSharedPointer<QmlDesigner::CollectionListModel> collectionsList;
- auto setupCollectionList = [&sourceNode, &initialCollection, &collectionsList]() {
- if (initialCollection.isNull())
- collectionsList.reset(new QmlDesigner::CollectionListModel(sourceNode));
- else if (initialCollection->sourceNode() == sourceNode)
- collectionsList = initialCollection;
- else
- collectionsList.reset(new QmlDesigner::CollectionListModel(sourceNode));
- };
-
- if (sourceNode.type() == JSONCOLLECTIONMODEL_TYPENAME) {
- FileReader sourceFile;
- if (!sourceFile.fetch(FilePath::fromUserInput(sourceFileAddress)))
- return {};
-
- QJsonParseError parseError;
- QJsonDocument document = QJsonDocument::fromJson(sourceFile.data(), &parseError);
- if (parseError.error != QJsonParseError::NoError)
- return {};
-
- setupCollectionList();
-
- if (document.isObject()) {
- const QJsonObject sourceObject = document.object();
- collectionsList->resetModelData(sourceObject.toVariantMap().keys());
- }
- }
-
- return collectionsList;
-}
-
-} // namespace
-
-namespace QmlDesigner {
-
-CollectionSourceModel::CollectionSourceModel(QObject *parent)
- : Super(parent)
-{}
-
-int CollectionSourceModel::rowCount(const QModelIndex &) const
-{
- return m_collectionSources.size();
-}
-
-QVariant CollectionSourceModel::data(const QModelIndex &index, int role) const
-{
- QTC_ASSERT(index.isValid(), return {});
-
- const ModelNode *collectionSource = &m_collectionSources.at(index.row());
-
- switch (role) {
- case NameRole: // Not used, to be removed
- return collectionSource->variantProperty("objectName").value().toString();
- case NodeRole:
- return QVariant::fromValue(*collectionSource);
- case CollectionTypeRole:
- return CollectionEditorUtils::getSourceCollectionType(*collectionSource);
- case SourceRole:
- return collectionSource->variantProperty(CollectionEditorConstants::SOURCEFILE_PROPERTY).value();
- case SelectedRole:
- return index.row() == m_selectedIndex;
- case CollectionsRole:
- return QVariant::fromValue(m_collectionList.at(index.row()).data());
- }
-
- return {};
-}
-
-bool CollectionSourceModel::setData(const QModelIndex &index, const QVariant &value, int role)
-{
- if (!index.isValid())
- return false;
-
- ModelNode collectionSource = m_collectionSources.at(index.row());
- switch (role) {
- case Qt::DisplayRole:
- case NameRole: {
- auto collectionName = collectionSource.variantProperty("objectName");
- if (collectionName.value() == value)
- return false;
-
- collectionName.setValue(value.toString());
- } break;
- case SourceRole: {
- auto sourceAddress = collectionSource.variantProperty(
- CollectionEditorConstants::SOURCEFILE_PROPERTY);
- if (sourceAddress.value() == value)
- return false;
-
- sourceAddress.setValue(value.toString());
- } break;
- case SelectedRole: {
- if (value.toBool() != index.data(SelectedRole).toBool())
- setSelectedIndex(value.toBool() ? index.row() : -1);
- else
- return false;
- } break;
- default:
- return false;
- }
-
- return true;
-}
-
-bool CollectionSourceModel::removeRows(int row, int count, [[maybe_unused]] const QModelIndex &parent)
-{
- const int rowMax = std::min(row + count, rowCount());
-
- if (row >= rowMax || row < 0)
- return false;
-
- AbstractView *view = m_collectionSources.at(row).view();
- if (!view)
- return false;
-
- count = rowMax - row;
-
- bool selectionUpdateNeeded = m_selectedIndex >= row && m_selectedIndex < rowMax;
-
- // It's better to remove the group of nodes here because of the performance issue for the list,
- // and update issue for the view
- beginRemoveRows({}, row, rowMax - 1);
-
- view->executeInTransaction(Q_FUNC_INFO, [row, count, this]() {
- for (ModelNode node : Utils::span<const ModelNode>(m_collectionSources).subspan(row, count)) {
- m_sourceIndexHash.remove(node.internalId());
- node.destroy();
- }
- m_collectionSources.remove(row, count);
- m_collectionList.remove(row, count);
- });
-
- int idx = row;
- for (const ModelNode &node : Utils::span<const ModelNode>(m_collectionSources).subspan(row))
- m_sourceIndexHash.insert(node.internalId(), ++idx);
-
- endRemoveRows();
-
- if (selectionUpdateNeeded)
- updateSelectedSource();
-
- updateEmpty();
- return true;
-}
-
-QHash<int, QByteArray> CollectionSourceModel::roleNames() const
-{
- static QHash<int, QByteArray> roles;
- if (roles.isEmpty()) {
- roles.insert(Super::roleNames());
- roles.insert({{NameRole, "sourceName"},
- {NodeRole, "sourceNode"},
- {CollectionTypeRole, "sourceCollectionType"},
- {SelectedRole, "sourceIsSelected"},
- {SourceRole, "sourceAddress"},
- {CollectionsRole, "internalModels"}});
- }
- return roles;
-}
-
-void CollectionSourceModel::setSource(const ModelNode &source)
-{
- beginResetModel();
- m_collectionSources = {source};
- m_sourceIndexHash.clear();
- m_collectionList.clear();
-
- // TODO: change m_collectionSources to only contain 1 source node
- m_sourceIndexHash.insert(source.internalId(), 0);
-
- auto loadedCollection = loadCollection(source);
- m_collectionList.append(loadedCollection);
-
- registerCollectionList(loadedCollection);
-
-
- updateEmpty();
- endResetModel();
-
- updateSelectedSource(true);
-}
-
-void CollectionSourceModel::reset()
-{
- beginResetModel();
- m_collectionSources.clear();
- m_sourceIndexHash.clear();
- m_collectionList.clear();
- m_previousSelectedList.clear();
- setSelectedCollectionName({});
-
- updateEmpty();
- endResetModel();
- updateSelectedSource();
-}
-
-int CollectionSourceModel::sourceIndex(const ModelNode &node) const
-{
- return m_sourceIndexHash.value(node.internalId(), -1);
-}
-
-void CollectionSourceModel::addSource(const ModelNode &node)
-{
- int newRowId = m_collectionSources.count();
- beginInsertRows({}, newRowId, newRowId);
- m_collectionSources.append(node);
- m_sourceIndexHash.insert(node.internalId(), newRowId);
-
- auto loadedCollection = loadCollection(node);
- m_collectionList.append(loadedCollection);
-
- registerCollectionList(loadedCollection);
-
- updateEmpty();
- endInsertRows();
- updateSelectedSource(true);
-}
-
-void CollectionSourceModel::selectSource(const ModelNode &node)
-{
- int nodePlace = m_sourceIndexHash.value(node.internalId(), -1);
- if (nodePlace < 0)
- return;
-
- selectSourceIndex(nodePlace, true);
-}
-
-bool CollectionSourceModel::collectionExists(const QString &collectionName) const
-{
- return m_collectionList.size() == 1 && m_collectionList.at(0)->contains(collectionName);
-}
-
-bool CollectionSourceModel::addCollectionToSource(const ModelNode &node,
- const QString &collectionName,
- const QJsonObject &newCollection,
- QString *errorString)
-{
- using Utils::FilePath;
- using Utils::FileReader;
- auto returnError = [errorString](const QString &msg) -> bool {
- if (errorString)
- *errorString = msg;
- return false;
- };
-
- int idx = sourceIndex(node);
- if (idx < 0)
- return returnError(tr("Node is not indexed in the models."));
-
- if (node.type() != CollectionEditorConstants::JSONCOLLECTIONMODEL_TYPENAME)
- return returnError(tr("Node should be a JSON model."));
-
- if (collectionExists(collectionName))
- return returnError(tr("A model with the identical name already exists."));
-
- QString sourceFileAddress = CollectionEditorUtils::getSourceCollectionPath(node);
-
- QFileInfo sourceFileInfo(sourceFileAddress);
- if (!sourceFileInfo.isFile())
- return returnError(tr("Selected node must have a valid source file address"));
-
- FilePath jsonPath = FilePath::fromUserInput(sourceFileAddress);
- FileReader jsonFile;
- if (!jsonFile.fetch(jsonPath)) {
- return returnError(
- tr("Can't read \"%1\".\n%2").arg(sourceFileInfo.absoluteFilePath(), jsonFile.errorString()));
- }
-
- QJsonParseError parseError;
- QJsonDocument document = QJsonDocument::fromJson(jsonFile.data(), &parseError);
- if (parseError.error != QJsonParseError::NoError)
- return returnError(tr("\"%1\" is corrupted.\n%2")
- .arg(sourceFileInfo.absoluteFilePath(), parseError.errorString()));
-
- if (document.isObject()) {
- QJsonObject sourceObject = document.object();
- sourceObject.insert(collectionName, newCollection);
- document.setObject(sourceObject);
-
- if (!CollectionEditorUtils::writeToJsonDocument(jsonPath, document))
- return returnError(tr("Can't write to \"%1\".").arg(sourceFileInfo.absoluteFilePath()));
-
- updateCollectionList(index(idx));
-
- auto collections = m_collectionList.at(idx);
- if (collections.isNull())
- return returnError(tr("No model is available for the JSON model group."));
-
- collections->selectCollectionName(collectionName);
- setSelectedCollectionName(collectionName);
- return true;
- } else {
- return returnError(tr("JSON document type should be an object containing models."));
- }
-}
-
-QmlDesigner::ModelNode CollectionSourceModel::sourceNodeAt(int idx)
-{
- QModelIndex data = index(idx);
- if (!data.isValid())
- return {};
-
- return m_collectionSources.at(idx);
-}
-
-CollectionListModel *CollectionSourceModel::selectedCollectionList()
-{
- QModelIndex idx = index(m_selectedIndex);
- if (!idx.isValid())
- return {};
-
- return idx.data(CollectionsRole).value<CollectionListModel *>();
-}
-
-void CollectionSourceModel::selectSourceIndex(int idx, bool selectAtLeastOne)
-{
- int collectionCount = m_collectionSources.size();
- int preferredIndex = -1;
- if (collectionCount) {
- if (selectAtLeastOne)
- preferredIndex = std::max(0, std::min(idx, collectionCount - 1));
- else if (idx > -1 && idx < collectionCount)
- preferredIndex = idx;
- }
-
- setSelectedIndex(preferredIndex);
-}
-
-void CollectionSourceModel::selectCollection(const QVariant &node, const QString &collectionName)
-{
- const ModelNode sourceNode = node.value<ModelNode>();
- const QModelIndex index = indexOfNode(sourceNode);
- if (!index.isValid())
- return;
-
- selectSource(sourceNode);
- auto collections = m_collectionList.at(index.row());
- if (collections.isNull())
- return;
-
- collections->selectCollectionName(collectionName);
-}
-
-void CollectionSourceModel::deselect()
-{
- setSelectedIndex(-1);
-}
-
-void CollectionSourceModel::updateSelectedSource(bool selectAtLeastOne)
-{
- int idx = m_selectedIndex;
- m_selectedIndex = -1;
- selectSourceIndex(idx, selectAtLeastOne);
-}
-
-QString CollectionSourceModel::getUniqueCollectionName(const QString &baseName) const
-{
- if (m_collectionList.isEmpty())
- return "Model01";
-
- CollectionListModel *collectionModel = m_collectionList.at(0).data();
-
- QString name = baseName.isEmpty() ? "Model" : baseName;
- QString nameTemplate = name + "%1";
-
- int num = 0;
-
- while (collectionModel->contains(name))
- name = nameTemplate.arg(++num, 2, 10, QChar('0'));
-
- return name;
-}
-
-void CollectionSourceModel::updateNodeName(const ModelNode &node)
-{
- QModelIndex index = indexOfNode(node);
- emit dataChanged(index, index, {NameRole, Qt::DisplayRole});
- updateCollectionList(index);
-}
-
-void CollectionSourceModel::updateNodeSource(const ModelNode &node)
-{
- QModelIndex index = indexOfNode(node);
- emit dataChanged(index, index, {SourceRole});
- updateCollectionList(index);
-}
-
-void CollectionSourceModel::onSelectedCollectionChanged(CollectionListModel *collectionList,
- int collectionIndex)
-{
- if (collectionIndex > -1) {
- if (m_previousSelectedList && m_previousSelectedList != collectionList)
- m_previousSelectedList->selectCollectionIndex(-1);
-
- m_previousSelectedList = collectionList;
-
- setSelectedCollectionName(collectionList->collectionNameAt(collectionIndex));
-
- selectSourceIndex(sourceIndex(collectionList->sourceNode()));
- } else {
- setSelectedCollectionName({});
- }
-}
-
-void CollectionSourceModel::onCollectionNameChanged(CollectionListModel *collectionList,
- const QString &oldName,
- const QString &newName)
-{
- using Utils::FilePath;
- using Utils::FileReader;
- using Utils::FileSaver;
-
- auto emitRenameWarning = [this](const QString &msg) -> void {
- emit warning(tr("Rename Model"), msg);
- };
-
- const ModelNode node = collectionList->sourceNode();
- const QModelIndex nodeIndex = indexOfNode(node);
-
- if (!nodeIndex.isValid()) {
- emitRenameWarning(tr("Invalid node"));
- return;
- }
-
- if (node.type() != CollectionEditorConstants::JSONCOLLECTIONMODEL_TYPENAME) {
- emitRenameWarning(tr("Invalid node type"));
- return;
- }
-
- QString sourceFileAddress = CollectionEditorUtils::getSourceCollectionPath(node);
-
- QFileInfo sourceFileInfo(sourceFileAddress);
- if (!sourceFileInfo.isFile()) {
- emitRenameWarning(tr("Selected node must have a valid source file address"));
- return;
- }
-
- FilePath jsonPath = FilePath::fromUserInput(sourceFileAddress);
- FileReader jsonFile;
- if (!jsonFile.fetch(jsonPath)) {
- emitRenameWarning(
- tr("Can't read \"%1\".\n%2").arg(sourceFileInfo.absoluteFilePath(), jsonFile.errorString()));
- return;
- }
-
- QJsonParseError parseError;
- QJsonDocument document = QJsonDocument::fromJson(jsonFile.data(), &parseError);
- if (parseError.error != QJsonParseError::NoError) {
- emitRenameWarning(tr("\"%1\" is corrupted.\n%2")
- .arg(sourceFileInfo.absoluteFilePath(), parseError.errorString()));
- return;
- }
-
- if (document.isObject()) {
- QJsonObject rootObject = document.object();
-
- bool collectionContainsOldName = rootObject.contains(oldName);
- bool collectionContainsNewName = rootObject.contains(newName);
-
- if (!collectionContainsOldName) {
- emitRenameWarning(
- tr("The model group doesn't contain the old model name (%1).").arg(oldName));
- return;
- }
-
- if (collectionContainsNewName) {
- emitRenameWarning(
- tr("The model name \"%1\" already exists in the model group.").arg(newName));
- return;
- }
-
- QJsonValue oldValue = rootObject.value(oldName);
- rootObject.insert(newName, oldValue);
- rootObject.remove(oldName);
-
- document.setObject(rootObject);
-
- if (!CollectionEditorUtils::writeToJsonDocument(jsonPath, document)) {
- emitRenameWarning(tr("Can't write to \"%1\".").arg(sourceFileInfo.absoluteFilePath()));
- return;
- }
-
- CollectionListModel *list = m_collectionList.at(nodeIndex.row()).data();
- bool updateSelectedNames = list && list == m_previousSelectedList.data();
- emit collectionRenamed(oldName, newName);
- updateCollectionList(nodeIndex);
-
- if (updateSelectedNames) {
- list = m_collectionList.at(nodeIndex.row()).data();
- if (m_selectedCollectionName == oldName) {
- list->selectCollectionName(newName);
- setSelectedCollectionName(newName);
- } else {
- // reselect to update ID if it's changed due to renaming and order changes
- list->selectCollectionName(m_selectedCollectionName);
- }
- }
- }
-}
-
-void CollectionSourceModel::onCollectionsRemoved(CollectionListModel *collectionList,
- const QStringList &removedCollections)
-{
- using Utils::FilePath;
- using Utils::FileReader;
- auto emitDeleteWarning = [this](const QString &msg) -> void {
- emit warning(tr("Delete Model"), msg);
- };
-
- const ModelNode node = collectionList->sourceNode();
- const QModelIndex nodeIndex = indexOfNode(node);
-
- if (!nodeIndex.isValid()) {
- emitDeleteWarning(tr("Invalid node"));
- return;
- }
-
- if (node.type() != CollectionEditorConstants::JSONCOLLECTIONMODEL_TYPENAME) {
- emitDeleteWarning(tr("Invalid node type"));
- return;
- }
-
- QString sourceFileAddress = CollectionEditorUtils::getSourceCollectionPath(node);
-
- QFileInfo sourceFileInfo(sourceFileAddress);
- if (!sourceFileInfo.isFile()) {
- emitDeleteWarning(tr("The selected node has an invalid source address"));
- return;
- }
-
- FilePath jsonPath = FilePath::fromUserInput(sourceFileAddress);
- FileReader jsonFile;
- if (!jsonFile.fetch(jsonPath)) {
- emitDeleteWarning(tr("Can't read or write \"%1\".\n%2")
- .arg(sourceFileInfo.absoluteFilePath(), jsonFile.errorString()));
- return;
- }
-
- QJsonParseError parseError;
- QJsonDocument document = QJsonDocument::fromJson(jsonFile.data(), &parseError);
- if (parseError.error != QJsonParseError::NoError) {
- emitDeleteWarning(tr("\"%1\" is corrupted.\n%2")
- .arg(sourceFileInfo.absoluteFilePath(), parseError.errorString()));
- return;
- }
-
- if (document.isObject()) {
- QJsonObject rootObject = document.object();
-
- QStringList collectionsRemovedFromDocument;
- for (const QString &collectionName : removedCollections) {
- bool sourceContainsCollection = rootObject.contains(collectionName);
- if (sourceContainsCollection) {
- rootObject.remove(collectionName);
- collectionsRemovedFromDocument << collectionName;
- } else {
- emitDeleteWarning(tr("The model group doesn't contain the model name (%1).")
- .arg(sourceContainsCollection));
- }
- }
-
- document.setObject(rootObject);
-
- if (!CollectionEditorUtils::writeToJsonDocument(jsonPath, document)) {
- emitDeleteWarning(tr("Can't write to \"%1\".").arg(sourceFileInfo.absoluteFilePath()));
- return;
- }
-
- for (const QString &collectionName : std::as_const(collectionsRemovedFromDocument))
- emit collectionRemoved(collectionName);
-
- updateCollectionList(nodeIndex);
- if (m_previousSelectedList == collectionList)
- onSelectedCollectionChanged(collectionList, collectionList->selectedIndex());
- }
-}
-
-void CollectionSourceModel::setSelectedIndex(int idx)
-{
- idx = (idx > -1 && idx < m_collectionSources.count()) ? idx : -1;
-
- if (m_selectedIndex != idx) {
- QModelIndex previousIndex = index(m_selectedIndex);
- QModelIndex newIndex = index(idx);
-
- m_selectedIndex = idx;
-
- if (previousIndex.isValid())
- emit dataChanged(previousIndex, previousIndex, {SelectedRole});
-
- if (newIndex.isValid())
- emit dataChanged(newIndex, newIndex, {SelectedRole});
-
- emit selectedIndexChanged(idx);
-
- if (idx > -1) {
- QPointer<CollectionListModel> relatedCollectionList = m_collectionList.at(idx).data();
- if (relatedCollectionList) {
- if (relatedCollectionList->selectedIndex() < 0)
- relatedCollectionList->selectCollectionIndex(0, true);
- } else if (m_previousSelectedList) {
- m_previousSelectedList->selectCollectionIndex(-1);
- m_previousSelectedList = {};
- setSelectedCollectionName({});
- }
- }
- }
-}
-
-void CollectionSourceModel::setSelectedCollectionName(const QString &collectionName)
-{
- if (m_selectedCollectionName != collectionName) {
- m_selectedCollectionName = collectionName;
- emit collectionSelected(m_selectedCollectionName);
- }
-}
-
-void CollectionSourceModel::updateEmpty()
-{
- bool isEmptyNow = m_collectionSources.isEmpty();
- if (m_isEmpty != isEmptyNow) {
- m_isEmpty = isEmptyNow;
- emit isEmptyChanged(m_isEmpty);
-
- if (m_isEmpty)
- setSelectedIndex(-1);
- }
-}
-
-void CollectionSourceModel::updateCollectionList(QModelIndex index)
-{
- if (!index.isValid())
- return;
-
- ModelNode sourceNode = sourceNodeAt(index.row());
- QSharedPointer<CollectionListModel> oldList = m_collectionList.at(index.row());
- QSharedPointer<CollectionListModel> newList = loadCollection(sourceNode, oldList);
- if (oldList != newList) {
- m_collectionList.replace(index.row(), newList);
- emit dataChanged(index, index, {CollectionsRole});
- registerCollectionList(newList);
- }
-}
-
-void CollectionSourceModel::registerCollectionList(
- const QSharedPointer<CollectionListModel> &sharedCollectionList)
-{
- CollectionListModel *collectionList = sharedCollectionList.data();
- if (collectionList == nullptr)
- return;
-
- if (!collectionList->property("_is_registered_in_sourceModel").toBool()) {
- collectionList->setProperty("_is_registered_in_sourceModel", true);
-
- connect(collectionList,
- &CollectionListModel::selectedIndexChanged,
- this,
- [this, collectionList](int idx) { onSelectedCollectionChanged(collectionList, idx); });
-
- connect(collectionList,
- &CollectionListModel::collectionNameChanged,
- this,
- [this, collectionList](const QString &oldName, const QString &newName) {
- onCollectionNameChanged(collectionList, oldName, newName);
- });
-
- connect(collectionList,
- &CollectionListModel::collectionsRemoved,
- this,
- [this, collectionList](const QStringList &removedCollections) {
- onCollectionsRemoved(collectionList, removedCollections);
- });
-
- connect(collectionList, &CollectionListModel::modelReset, this, [this, collectionList]() {
- emit collectionNamesInitialized(collectionList->collections());
- });
- }
-
- if (collectionList->sourceNode().isValid())
- emit collectionNamesInitialized(collectionList->collections());
-}
-
-QModelIndex CollectionSourceModel::indexOfNode(const ModelNode &node) const
-{
- return index(m_sourceIndexHash.value(node.internalId(), -1));
-}
-
-void CollectionJsonSourceFilterModel::registerDeclarativeType()
-{
- qmlRegisterType<CollectionJsonSourceFilterModel>("CollectionEditor",
- 1,
- 0,
- "CollectionJsonSourceFilterModel");
-}
-
-bool CollectionJsonSourceFilterModel::filterAcceptsRow(int source_row, const QModelIndex &) const
-{
- if (!sourceModel())
- return false;
- QModelIndex sourceItem = sourceModel()->index(source_row, 0, {});
- return sourceItem.data(CollectionSourceModel::Roles::CollectionTypeRole).toString() == "json";
-}
-
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.h b/src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.h
deleted file mode 100644
index f988935c98..0000000000
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.h
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright (C) 2023 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
-
-#pragma once
-
-#include "modelnode.h"
-
-#include <QAbstractListModel>
-#include <QHash>
-#include <QSortFilterProxyModel>
-
-namespace QmlDesigner {
-
-class CollectionJsonSourceFilterModel;
-class CollectionListModel;
-
-class CollectionSourceModel : public QAbstractListModel
-{
- Q_OBJECT
-
- Q_PROPERTY(int selectedIndex MEMBER m_selectedIndex NOTIFY selectedIndexChanged)
- Q_PROPERTY(bool isEmpty MEMBER m_isEmpty NOTIFY isEmptyChanged)
-
-public:
- enum Roles {
- NameRole = Qt::UserRole + 1,
- NodeRole,
- CollectionTypeRole,
- SourceRole,
- SelectedRole,
- CollectionsRole
- };
-
- explicit CollectionSourceModel(QObject *parent = nullptr);
-
- virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
- virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
- virtual bool setData(const QModelIndex &index,
- const QVariant &value,
- int role = Qt::EditRole) override;
-
- Q_INVOKABLE virtual bool removeRows(int row,
- int count = 1,
- const QModelIndex &parent = QModelIndex()) override;
-
- virtual QHash<int, QByteArray> roleNames() const override;
-
- void setSource(const ModelNode &source);
- void reset();
- int sourceIndex(const ModelNode &node) const;
- void addSource(const ModelNode &node);
- void selectSource(const ModelNode &node);
-
- bool addCollectionToSource(const ModelNode &node,
- const QString &collectionName,
- const QJsonObject &newCollection,
- QString *errorString = nullptr);
-
- ModelNode sourceNodeAt(int idx);
- CollectionListModel *selectedCollectionList();
-
- void updateNodeName(const ModelNode &node);
- void updateNodeSource(const ModelNode &node);
-
- Q_INVOKABLE void selectSourceIndex(int idx, bool selectAtLeastOne = false);
- Q_INVOKABLE void selectCollection(const QVariant &node, const QString &collectionName);
- Q_INVOKABLE void deselect();
- Q_INVOKABLE void updateSelectedSource(bool selectAtLeastOne = false);
- Q_INVOKABLE QString getUniqueCollectionName(const QString &baseName = {}) const;
- Q_INVOKABLE bool collectionExists(const QString &collectionName) const;
-
-signals:
- void selectedIndexChanged(int idx);
- void collectionSelected(const QString &collectionName);
- void collectionNamesInitialized(const QStringList &initialList);
- void collectionRenamed(const QString &oldname, const QString &newName);
- void collectionRemoved(const QString &collectionName);
-
- void isEmptyChanged(bool);
- void warning(const QString &title, const QString &body);
-
-private slots:
- void onSelectedCollectionChanged(CollectionListModel *collectionList, int collectionIndex);
- void onCollectionNameChanged(CollectionListModel *collectionList, const QString &oldName,
- const QString &newName);
- void onCollectionsRemoved(CollectionListModel *collectionList,
- const QStringList &removedCollections);
-
-private:
- void setSelectedIndex(int idx);
- void setSelectedCollectionName(const QString &collectionName);
- void updateEmpty();
- void updateCollectionList(QModelIndex index);
- void registerCollectionList(const QSharedPointer<CollectionListModel> &collectionList);
- QModelIndex indexOfNode(const ModelNode &node) const;
-
- using Super = QAbstractListModel;
-
- ModelNodes m_collectionSources;
- QHash<qint32, int> m_sourceIndexHash; // internalId -> index
- QList<QSharedPointer<CollectionListModel>> m_collectionList;
- QPointer<CollectionListModel> m_previousSelectedList;
- QString m_selectedCollectionName;
- int m_selectedIndex = -1;
- bool m_isEmpty = true;
-};
-
-class CollectionJsonSourceFilterModel : public QSortFilterProxyModel
-{
- Q_OBJECT
-
-public:
- static void registerDeclarativeType();
-
-protected:
- bool filterAcceptsRow(int source_row, const QModelIndex &) const override;
-};
-
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp
index 442a79cbd5..723d0beca8 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp
@@ -6,7 +6,7 @@
#include "collectiondetailsmodel.h"
#include "collectioneditorconstants.h"
#include "collectioneditorutils.h"
-#include "collectionsourcemodel.h"
+#include "collectionlistmodel.h"
#include "collectionwidget.h"
#include "datastoremodelnode.h"
#include "designmodecontext.h"
@@ -81,29 +81,33 @@ QmlDesigner::WidgetInfo CollectionView::widgetInfo()
auto collectionEditorContext = new Internal::CollectionEditorContext(m_widget.data());
Core::ICore::addContextObject(collectionEditorContext);
- CollectionSourceModel *sourceModel = m_widget->sourceModel().data();
+ CollectionListModel *listModel = m_widget->listModel().data();
- connect(sourceModel,
- &CollectionSourceModel::collectionSelected,
+ connect(listModel,
+ &CollectionListModel::selectedCollectionNameChanged,
this,
[this](const QString &collection) {
m_widget->collectionDetailsModel()->loadCollection(dataStoreNode(), collection);
});
- connect(sourceModel, &CollectionSourceModel::isEmptyChanged, this, [this](bool isEmpty) {
+ connect(listModel, &CollectionListModel::isEmptyChanged, this, [this](bool isEmpty) {
if (isEmpty)
m_widget->collectionDetailsModel()->loadCollection({}, {});
});
- connect(sourceModel,
- &CollectionSourceModel::collectionNamesInitialized,
+ connect(listModel, &CollectionListModel::modelReset, this, [this] {
+ CollectionListModel *listModel = m_widget->listModel().data();
+ if (listModel->sourceNode() == m_dataStore->modelNode())
+ m_dataStore->setCollectionNames(listModel->collections());
+ });
+
+ connect(listModel,
+ &CollectionListModel::collectionAdded,
this,
- [this](const QStringList &collectionNames) {
- m_dataStore->setCollectionNames(collectionNames);
- });
+ [this](const QString &collectionName) { m_dataStore->addCollection(collectionName); });
- connect(sourceModel,
- &CollectionSourceModel::collectionRenamed,
+ connect(listModel,
+ &CollectionListModel::collectionNameChanged,
this,
[this](const QString &oldName, const QString &newName) {
m_dataStore->renameCollection(oldName, newName);
@@ -112,13 +116,15 @@ QmlDesigner::WidgetInfo CollectionView::widgetInfo()
newName);
});
- connect(sourceModel,
- &CollectionSourceModel::collectionRemoved,
+ connect(listModel,
+ &CollectionListModel::collectionsRemoved,
this,
- [this](const QString &collectionName) {
- m_dataStore->removeCollection(collectionName);
- m_widget->collectionDetailsModel()->removeCollection(dataStoreNode(),
- collectionName);
+ [this](const QStringList &collectionNames) {
+ m_dataStore->removeCollections(collectionNames);
+ for (const QString &collectionName : collectionNames) {
+ m_widget->collectionDetailsModel()->removeCollection(dataStoreNode(),
+ collectionName);
+ }
});
}
@@ -144,29 +150,7 @@ void CollectionView::modelAboutToBeDetached([[maybe_unused]] Model *model)
m_dataStoreTypeFound = false;
disconnect(m_documentUpdateConnection);
QTC_ASSERT(m_delayedTasks.isEmpty(), m_delayedTasks.clear());
- m_widget->sourceModel()->reset();
-}
-
-void CollectionView::nodeRemoved(const ModelNode &removedNode,
- [[maybe_unused]] const NodeAbstractProperty &parentProperty,
- [[maybe_unused]] PropertyChangeFlags propertyChange)
-{
- if (isStudioCollectionModel(removedNode))
- m_widget->sourceModel()->updateSelectedSource(true);
-}
-
-void CollectionView::variantPropertiesChanged(const QList<VariantProperty> &propertyList,
- [[maybe_unused]] PropertyChangeFlags propertyChange)
-{
- for (const VariantProperty &property : propertyList) {
- ModelNode node(property.parentModelNode());
- if (isStudioCollectionModel(node)) {
- if (property.name() == "objectName")
- m_widget->sourceModel()->updateNodeName(node);
- else if (property.name() == CollectionEditorConstants::SOURCEFILE_PROPERTY)
- m_widget->sourceModel()->updateNodeSource(node);
- }
- }
+ m_widget->listModel()->setDataStoreNode();
}
void CollectionView::selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
@@ -190,11 +174,6 @@ void CollectionView::selectedNodesChanged(const QList<ModelNode> &selectedNodeLi
// More than one model is selected. So ignore them
if (selectedCollectionNodes.size() > 1)
return;
-
- if (selectedCollectionNodes.size() == 1) { // If exactly one model is selected
- m_widget->sourceModel()->selectSource(selectedCollectionNodes.first());
- return;
- }
}
void CollectionView::customNotification(const AbstractView *,
@@ -298,7 +277,7 @@ void CollectionView::assignCollectionToSelectedNode(const QString &collectionNam
void CollectionView::addNewCollection(const QString &collectionName, const QJsonObject &localCollection)
{
addTask(QSharedPointer<CollectionTask>(
- new AddCollectionTask(this, m_widget->sourceModel(), localCollection, collectionName)));
+ new AddCollectionTask(this, m_widget->listModel(), localCollection, collectionName)));
}
void CollectionView::openCollection(const QString &collectionName)
@@ -309,7 +288,6 @@ void CollectionView::openCollection(const QString &collectionName)
void CollectionView::registerDeclarativeType()
{
CollectionDetails::registerDeclarativeType();
- CollectionJsonSourceFilterModel::registerDeclarativeType();
}
void CollectionView::resetDataStoreNode()
@@ -317,7 +295,7 @@ void CollectionView::resetDataStoreNode()
m_dataStore->reloadModel();
ModelNode dataStore = m_dataStore->modelNode();
- if (!dataStore || m_widget->sourceModel()->sourceIndex(dataStore) > -1)
+ if (!dataStore || m_widget->listModel()->sourceNode() == dataStore)
return;
bool dataStoreSingletonFound = m_dataStoreTypeFound;
@@ -336,7 +314,7 @@ void CollectionView::resetDataStoreNode()
}
if (dataStoreSingletonFound) {
- m_widget->sourceModel()->setSource(dataStore);
+ m_widget->listModel()->setDataStoreNode(dataStore);
m_dataStoreTypeFound = true;
while (!m_delayedTasks.isEmpty())
@@ -415,7 +393,7 @@ void CollectionView::onItemLibraryNodeCreated(const ModelNode &node)
{
if (node.metaInfo().isQtQuickListView()) {
addTask(QSharedPointer<CollectionTask>(
- new DropListViewTask(this, m_widget->sourceModel(), node)));
+ new DropListViewTask(this, m_widget->listModel(), node)));
}
}
@@ -439,61 +417,49 @@ void CollectionView::addTask(QSharedPointer<CollectionTask> task)
m_delayedTasks << task;
}
-CollectionTask::CollectionTask(CollectionView *view, CollectionSourceModel *sourceModel)
+CollectionTask::CollectionTask(CollectionView *view, CollectionListModel *listModel)
: m_collectionView(view)
- , m_sourceModel(sourceModel)
+ , m_listModel(listModel)
{}
DropListViewTask::DropListViewTask(CollectionView *view,
- CollectionSourceModel *sourceModel,
+ CollectionListModel *listModel,
const ModelNode &node)
- : CollectionTask(view, sourceModel)
+ : CollectionTask(view, listModel)
, m_node(node)
{}
void DropListViewTask::process()
{
AbstractView *view = m_node.view();
- if (!m_node || !m_collectionView || !m_sourceModel || !view)
+ if (!m_node || !m_collectionView || !m_listModel || !view)
return;
- const QString newCollectionName = m_sourceModel->getUniqueCollectionName("ListModel");
- m_sourceModel->addCollectionToSource(m_collectionView->dataStoreNode(),
- newCollectionName,
- CollectionEditorUtils::defaultColorCollection());
+ const QString newCollectionName = m_listModel->getUniqueCollectionName("ListModel");
+ m_listModel->addCollection(newCollectionName, CollectionEditorUtils::defaultColorCollection());
m_collectionView->openCollection(newCollectionName);
m_collectionView->assignCollectionToNode(newCollectionName, m_node);
}
AddCollectionTask::AddCollectionTask(CollectionView *view,
- CollectionSourceModel *sourceModel,
+ CollectionListModel *listModel,
const QJsonObject &localJsonObject,
const QString &collectionName)
- : CollectionTask(view, sourceModel)
+ : CollectionTask(view, listModel)
, m_localJsonObject(localJsonObject)
, m_name(collectionName)
{}
void AddCollectionTask::process()
{
- if (!m_sourceModel)
+ if (!m_listModel)
return;
- QString errorMsg;
-
- const QString newCollectionName = m_sourceModel->collectionExists(m_name)
- ? m_sourceModel->getUniqueCollectionName(m_name)
+ const QString newCollectionName = m_listModel->collectionExists(m_name)
+ ? m_listModel->getUniqueCollectionName(m_name)
: m_name;
- bool added = m_sourceModel->addCollectionToSource(m_collectionView->dataStoreNode(),
- newCollectionName,
- m_localJsonObject,
- &errorMsg);
-
- if (!added) {
- emit m_sourceModel->warning(m_sourceModel->tr("Can not add a model to the JSON file"),
- errorMsg);
- }
+ m_listModel->addCollection(newCollectionName, m_localJsonObject);
}
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionview.h b/src/plugins/qmldesigner/components/collectioneditor/collectionview.h
index 5606ddc6b4..a4b16c4c27 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionview.h
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionview.h
@@ -16,7 +16,7 @@ class Document;
namespace QmlDesigner {
class CollectionDetails;
-class CollectionSourceModel;
+class CollectionListModel;
class CollectionTask;
class CollectionWidget;
class DataStoreModelNode;
@@ -34,13 +34,6 @@ public:
void modelAttached(Model *model) override;
void modelAboutToBeDetached(Model *model) override;
- void nodeRemoved(const ModelNode &removedNode,
- const NodeAbstractProperty &parentProperty,
- PropertyChangeFlags propertyChange) override;
-
- void variantPropertiesChanged(const QList<VariantProperty> &propertyList,
- PropertyChangeFlags propertyChange) override;
-
void selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
const QList<ModelNode> &lastSelectedNodeList) override;
@@ -87,7 +80,7 @@ private:
class CollectionTask
{
public:
- CollectionTask(CollectionView *view, CollectionSourceModel *sourceModel);
+ CollectionTask(CollectionView *view, CollectionListModel *listModel);
CollectionTask() = delete;
virtual ~CollectionTask() = default;
@@ -95,13 +88,13 @@ public:
protected:
QPointer<CollectionView> m_collectionView;
- QPointer<CollectionSourceModel> m_sourceModel;
+ QPointer<CollectionListModel> m_listModel;
};
class DropListViewTask : public CollectionTask
{
public:
- DropListViewTask(CollectionView *view, CollectionSourceModel *sourceModel, const ModelNode &node);
+ DropListViewTask(CollectionView *view, CollectionListModel *listModel, const ModelNode &node);
void process() override;
@@ -113,7 +106,7 @@ class AddCollectionTask : public CollectionTask
{
public:
AddCollectionTask(CollectionView *view,
- CollectionSourceModel *sourceModel,
+ CollectionListModel *listModel,
const QJsonObject &localJsonObject,
const QString &collectionName);
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp
index 3e1b2e0129..093729dc67 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp
@@ -7,7 +7,7 @@
#include "collectiondetailsmodel.h"
#include "collectiondetailssortfiltermodel.h"
#include "collectioneditorutils.h"
-#include "collectionsourcemodel.h"
+#include "collectionlistmodel.h"
#include "collectionview.h"
#include "designmodewidget.h"
#include "qmldesignerconstants.h"
@@ -56,7 +56,7 @@ namespace QmlDesigner {
CollectionWidget::CollectionWidget(CollectionView *view)
: QFrame()
, m_view(view)
- , m_sourceModel(new CollectionSourceModel)
+ , m_listModel(new CollectionListModel)
, m_collectionDetailsModel(new CollectionDetailsModel)
, m_collectionDetailsSortFilterModel(std::make_unique<CollectionDetailsSortFilterModel>())
, m_quickWidget(new StudioQuickWidget(this))
@@ -69,7 +69,7 @@ CollectionWidget::CollectionWidget(CollectionView *view)
icontext->setContext(context);
icontext->setWidget(this);
- connect(m_sourceModel, &CollectionSourceModel::warning, this, &CollectionWidget::warn);
+ connect(m_listModel, &CollectionListModel::warning, this, &CollectionWidget::warn);
m_collectionDetailsSortFilterModel->setSourceModel(m_collectionDetailsModel);
@@ -90,7 +90,7 @@ CollectionWidget::CollectionWidget(CollectionView *view)
auto map = m_quickWidget->registerPropertyMap("CollectionEditorBackend");
map->setProperties({
{"rootView", QVariant::fromValue(this)},
- {"model", QVariant::fromValue(m_sourceModel.data())},
+ {"model", QVariant::fromValue(m_listModel.data())},
{"collectionDetailsModel", QVariant::fromValue(m_collectionDetailsModel.data())},
{"collectionDetailsSortFilterModel",
QVariant::fromValue(m_collectionDetailsSortFilterModel.get())},
@@ -112,9 +112,9 @@ void CollectionWidget::contextHelp(const Core::IContext::HelpCallback &callback)
callback({});
}
-QPointer<CollectionSourceModel> CollectionWidget::sourceModel() const
+QPointer<CollectionListModel> CollectionWidget::listModel() const
{
- return m_sourceModel;
+ return m_listModel;
}
QPointer<CollectionDetailsModel> CollectionWidget::collectionDetailsModel() const
@@ -262,7 +262,7 @@ void CollectionWidget::assignCollectionToSelectedNode(const QString collectionNa
void CollectionWidget::openCollection(const QString &collectionName)
{
- m_sourceModel->selectCollection(QVariant::fromValue(m_view->dataStoreNode()), collectionName);
+ m_listModel->selectCollectionName(collectionName);
QmlDesignerPlugin::instance()->mainWidget()->showDockWidget("CollectionEditor", true);
}
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.h b/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.h
index a3218bd1bc..0957bd81e0 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.h
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.h
@@ -13,7 +13,7 @@ namespace QmlDesigner {
class CollectionDetailsModel;
class CollectionDetailsSortFilterModel;
-class CollectionSourceModel;
+class CollectionListModel;
class CollectionView;
class ModelNode;
@@ -27,7 +27,7 @@ public:
CollectionWidget(CollectionView *view);
void contextHelp(const Core::IContext::HelpCallback &callback) const;
- QPointer<CollectionSourceModel> sourceModel() const;
+ QPointer<CollectionListModel> listModel() const;
QPointer<CollectionDetailsModel> collectionDetailsModel() const;
void reloadQmlSource();
@@ -61,7 +61,7 @@ private:
QString generateUniqueCollectionName(const ModelNode &node, const QString &name);
QPointer<CollectionView> m_view;
- QPointer<CollectionSourceModel> m_sourceModel;
+ QPointer<CollectionListModel> m_listModel;
QPointer<CollectionDetailsModel> m_collectionDetailsModel;
std::unique_ptr<CollectionDetailsSortFilterModel> m_collectionDetailsSortFilterModel;
QScopedPointer<StudioQuickWidget> m_quickWidget;
diff --git a/src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.cpp b/src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.cpp
index 7712252655..503b3f1ea3 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.cpp
@@ -390,6 +390,14 @@ void DataStoreModelNode::setCollectionNames(const QStringList &newCollectionName
update();
}
+void DataStoreModelNode::addCollection(const QString &collectionName)
+{
+ if (!m_collectionPropertyNames.contains(collectionName)) {
+ m_collectionPropertyNames.insert(collectionName, {});
+ update();
+ }
+}
+
void DataStoreModelNode::renameCollection(const QString &oldName, const QString &newName)
{
ModelNode dataStoreNode = modelNode();
@@ -420,12 +428,18 @@ void DataStoreModelNode::renameCollection(const QString &oldName, const QString
<< QString("There is no old collection name registered with this name \"%1\"").arg(oldName);
}
-void DataStoreModelNode::removeCollection(const QString &collectionName)
+void DataStoreModelNode::removeCollections(const QStringList &collectionNames)
{
- if (m_collectionPropertyNames.contains(collectionName)) {
- m_collectionPropertyNames.remove(collectionName);
- update();
+ bool updateRequired = false;
+ for (const QString &collectionName : collectionNames) {
+ if (m_collectionPropertyNames.contains(collectionName)) {
+ m_collectionPropertyNames.remove(collectionName);
+ updateRequired = true;
+ }
}
+
+ if (updateRequired)
+ update();
}
void DataStoreModelNode::assignCollectionToNode(AbstractView *view,
diff --git a/src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.h b/src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.h
index d23908bc0c..6cd969edbe 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.h
+++ b/src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.h
@@ -31,8 +31,9 @@ public:
ModelNode modelNode() const;
void setCollectionNames(const QStringList &newCollectionNames);
+ void addCollection(const QString &collectionName);
void renameCollection(const QString &oldName, const QString &newName);
- void removeCollection(const QString &collectionName);
+ void removeCollections(const QStringList &collectionNames);
void assignCollectionToNode(AbstractView *view,
const ModelNode &targetNode,