aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAli Kianian <ali.kianian@qt.io>2024-02-09 14:14:19 +0200
committerAli Kianian <ali.kianian@qt.io>2024-02-20 11:02:17 +0000
commitbb63198f8ada23c9c1e0ba20555077d332185cc6 (patch)
tree011e05b3419d7c03d4ddf276c4a0cc55d97be3e7
parent0f9782070ab33897815e1fcaff3718de86cd9e9d (diff)
QmlDesigner: Open collection editor for dropped ListView
* A default color model will be created and assigned to the ListView when a ListView is dropped to the view. * The user can edit the assigned collection of the list model by having access to an action in the context menu of the form editor. Task-number: QDS-11671 Fixes: QDS-11792 Change-Id: I70252f6e34ccbc95d8b700459f45a11a76c81c50 Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io> Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io> Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
-rw-r--r--share/qtcreator/qmldesigner/studio_templates/projects/shared-plugin/name/Colors.json.tpl18
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp23
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.h2
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionlistmodel.cpp79
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionlistmodel.h15
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.cpp59
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.h4
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp58
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionview.h9
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp13
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionwidget.h2
-rw-r--r--src/plugins/qmldesigner/components/componentcore/componentcore_constants.h4
-rw-r--r--src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp28
-rw-r--r--src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.h12
-rw-r--r--src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp24
-rw-r--r--src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h1
-rw-r--r--src/plugins/qmldesigner/components/formeditor/dragtool.cpp7
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp4
-rw-r--r--src/plugins/qmldesigner/designercore/include/nodemetainfo.h1
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp10
20 files changed, 318 insertions, 55 deletions
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/shared-plugin/name/Colors.json.tpl b/share/qtcreator/qmldesigner/studio_templates/projects/shared-plugin/name/Colors.json.tpl
new file mode 100644
index 0000000000..052b7abd01
--- /dev/null
+++ b/share/qtcreator/qmldesigner/studio_templates/projects/shared-plugin/name/Colors.json.tpl
@@ -0,0 +1,18 @@
+[
+ {
+ "colorCode": "#ff0000",
+ "name": "Red"
+ },
+ {
+ "colorCode": "#00ff00",
+ "name": "Green"
+ },
+ {
+ "colorCode": "#0000ff",
+ "name": "Blue"
+ },
+ {
+ "colorCode": "#ffffff",
+ "name": "White"
+ }
+]
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp
index 7fc6eec379..fc92512635 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp
@@ -381,6 +381,29 @@ QJsonObject defaultCollection()
return collectionObject;
}
+QJsonObject defaultColorCollection()
+{
+ using Utils::FilePath;
+ using Utils::FileReader;
+ const FilePath templatePath = findFile(Core::ICore::resourcePath(), "Colors.json.tpl");
+
+ FileReader fileReader;
+ if (!fileReader.fetch(templatePath)) {
+ qWarning() << Q_FUNC_INFO << __LINE__ << "Can't read the content of the file" << templatePath;
+ return {};
+ }
+
+ QJsonParseError parseError;
+ const CollectionDetails collection = CollectionDetails::fromImportedJson(fileReader.data(),
+ &parseError);
+ if (parseError.error != QJsonParseError::NoError) {
+ qWarning() << Q_FUNC_INFO << __LINE__ << "Error in template file" << parseError.errorString();
+ return {};
+ }
+
+ return collection.toLocalJson();
+}
+
QString dataTypeToString(CollectionDetails::DataType dataType)
{
static const QHash<DataType, QString> typeStringHash = CollectionDataTypeHelper::typeToStringHash();
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.h b/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.h
index 35a036c4e3..bd9e24d23c 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.h
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.h
@@ -43,6 +43,8 @@ bool hasTextRoleProperty(const ModelNode &node);
QJsonObject defaultCollection();
+QJsonObject defaultColorCollection();
+
QString dataTypeToString(CollectionDetails::DataType dataType);
CollectionDetails::DataType dataTypeFromString(const QString &dataType);
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionlistmodel.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectionlistmodel.cpp
index 214ece078a..323f0e767f 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionlistmodel.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionlistmodel.cpp
@@ -3,9 +3,7 @@
#include "collectionlistmodel.h"
-#include "collectioneditorconstants.h"
#include "collectioneditorutils.h"
-#include "variantproperty.h"
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
@@ -27,7 +25,7 @@ bool containsItem(const std::initializer_list<ValueType> &container, const Value
namespace QmlDesigner {
CollectionListModel::CollectionListModel(const ModelNode &sourceModel)
- : QStringListModel()
+ : QAbstractListModel()
, m_sourceNode(sourceModel)
, m_sourceType(CollectionEditorUtils::getSourceCollectionType(sourceModel))
{
@@ -50,6 +48,11 @@ QHash<int, QByteArray> CollectionListModel::roleNames() const
return roles;
}
+int CollectionListModel::rowCount([[maybe_unused]] const QModelIndex &parent) const
+{
+ return m_data.count();
+}
+
bool CollectionListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (!index.isValid())
@@ -60,9 +63,11 @@ bool CollectionListModel::setData(const QModelIndex &index, const QVariant &valu
return false;
QString oldName = collectionNameAt(index.row());
- bool nameChanged = Super::setData(index, value);
+ bool nameChanged = value != data(index);
if (nameChanged) {
- QString newName = collectionNameAt(index.row());
+ QString newName = value.toString();
+ m_data.replace(index.row(), newName);
+ emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole});
emit this->collectionNameChanged(oldName, newName);
}
return nameChanged;
@@ -78,22 +83,26 @@ bool CollectionListModel::setData(const QModelIndex &index, const QVariant &valu
bool CollectionListModel::removeRows(int row, int count, const QModelIndex &parent)
{
const int rows = rowCount(parent);
- if (count < 1 || row >= rows)
+ if (row >= rows)
return false;
row = qBound(0, row, rows - 1);
- count = qBound(1, count, rows - row);
+ count = qBound(0, count, rows - row);
- QStringList removedCollections = stringList().mid(row, count);
+ if (count < 1)
+ return false;
- bool itemsRemoved = Super::removeRows(row, count, parent);
- if (itemsRemoved) {
- emit collectionsRemoved(removedCollections);
- if (m_selectedIndex >= row)
- selectCollectionIndex(m_selectedIndex - count, true);
- }
+ QStringList removedCollections = m_data.mid(row, count);
- return itemsRemoved;
+ 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;
}
QVariant CollectionListModel::data(const QModelIndex &index, int role) const
@@ -103,13 +112,21 @@ QVariant CollectionListModel::data(const QModelIndex &index, int role) const
switch (role) {
case IdRole:
return index.row();
- case NameRole:
- return Super::data(index);
case SelectedRole:
return index.row() == m_selectedIndex;
+ case NameRole:
+ default:
+ return m_data.at(index.row());
}
+}
- return Super::data(index, role);
+void CollectionListModel::resetModelData(const QStringList &collectionsList)
+{
+ QString prevSelectedCollection = selectedIndex() > -1 ? m_data.at(selectedIndex()) : QString();
+ beginResetModel();
+ m_data = collectionsList;
+ endResetModel();
+ selectCollectionName(prevSelectedCollection);
}
int CollectionListModel::selectedIndex() const
@@ -129,12 +146,17 @@ QString CollectionListModel::sourceAddress() const
bool CollectionListModel::contains(const QString &collectionName) const
{
- return stringList().contains(collectionName);
+ return m_data.contains(collectionName);
+}
+
+QStringList CollectionListModel::collections() const
+{
+ return m_data;
}
void CollectionListModel::selectCollectionIndex(int idx, bool selectAtLeastOne)
{
- int collectionCount = stringList().size();
+ int collectionCount = m_data.size();
int preferredIndex = -1;
if (collectionCount) {
if (selectAtLeastOne)
@@ -148,7 +170,7 @@ void CollectionListModel::selectCollectionIndex(int idx, bool selectAtLeastOne)
void CollectionListModel::selectCollectionName(const QString &collectionName)
{
- int idx = stringList().indexOf(collectionName);
+ int idx = m_data.indexOf(collectionName);
if (idx > -1)
selectCollectionIndex(idx);
}
@@ -158,6 +180,19 @@ QString CollectionListModel::collectionNameAt(int idx) const
return index(idx).data(NameRole).toString();
}
+void CollectionListModel::addCollection(const QString &collectionName)
+{
+ if (m_data.contains(collectionName))
+ return;
+
+ int row = rowCount();
+ beginInsertRows({}, row, row);
+ m_data.append(collectionName);
+ endInsertRows();
+
+ emit collectionAdded(collectionName);
+}
+
void CollectionListModel::setSelectedIndex(int idx)
{
idx = (idx > -1 && idx < rowCount()) ? idx : -1;
@@ -180,7 +215,7 @@ void CollectionListModel::setSelectedIndex(int idx)
void CollectionListModel::updateEmpty()
{
- bool isEmptyNow = stringList().isEmpty();
+ bool isEmptyNow = m_data.isEmpty();
if (m_isEmpty != isEmptyNow) {
m_isEmpty = isEmptyNow;
emit isEmptyChanged(m_isEmpty);
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionlistmodel.h b/src/plugins/qmldesigner/components/collectioneditor/collectionlistmodel.h
index c65af750d8..092dd1d6dc 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionlistmodel.h
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionlistmodel.h
@@ -3,14 +3,14 @@
#pragma once
+#include <QAbstractListModel>
#include <QHash>
-#include <QStringListModel>
#include "modelnode.h"
namespace QmlDesigner {
-class CollectionListModel : public QStringListModel
+class CollectionListModel : public QAbstractListModel
{
Q_OBJECT
@@ -22,37 +22,44 @@ public:
enum Roles { IdRole = Qt::UserRole + 1, NameRole, SourceRole, SelectedRole, CollectionsRole };
explicit CollectionListModel(const ModelNode &sourceModel);
- virtual QHash<int, QByteArray> roleNames() const override;
+ 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);
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 QStringList collections() const;
void selectCollectionIndex(int idx, bool selectAtLeastOne = false);
void selectCollectionName(const QString &collectionName);
QString collectionNameAt(int idx) const;
+ void addCollection(const QString &collectionName);
signals:
void selectedIndexChanged(int idx);
void isEmptyChanged(bool);
void collectionNameChanged(const QString &oldName, const QString &newName);
void collectionsRemoved(const QStringList &names);
+ void collectionAdded(const QString &name);
private:
void setSelectedIndex(int idx);
void updateEmpty();
- using Super = QStringListModel;
+ using Super = QAbstractListModel;
int m_selectedIndex = -1;
bool m_isEmpty = false;
const ModelNode m_sourceNode;
const QString m_sourceType;
+
+ QStringList m_data;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.cpp
index a76d4a0b24..13accfba0e 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.cpp
@@ -56,13 +56,13 @@ QSharedPointer<QmlDesigner::CollectionListModel> loadCollection(
if (document.isObject()) {
const QJsonObject sourceObject = document.object();
- collectionsList->setStringList(sourceObject.toVariantMap().keys());
+ collectionsList->resetModelData(sourceObject.toVariantMap().keys());
}
} else if (sourceNode.type() == CSVCOLLECTIONMODEL_TYPENAME) {
QmlDesigner::VariantProperty collectionNameProperty = sourceNode.variantProperty(
"objectName");
setupCollectionList();
- collectionsList->setStringList({collectionNameProperty.value().toString()});
+ collectionsList->resetModelData({collectionNameProperty.value().toString()});
}
return collectionsList;
}
@@ -209,7 +209,7 @@ void CollectionSourceModel::setSources(const ModelNodes &sources)
auto loadedCollection = loadCollection(collectionSource);
m_collectionList.append(loadedCollection);
- registerCollection(loadedCollection);
+ registerCollectionList(loadedCollection);
}
updateEmpty();
@@ -242,7 +242,7 @@ void CollectionSourceModel::addSource(const ModelNode &node)
auto loadedCollection = loadCollection(node);
m_collectionList.append(loadedCollection);
- registerCollection(loadedCollection);
+ registerCollectionList(loadedCollection);
updateEmpty();
endInsertRows();
@@ -353,6 +353,26 @@ CollectionListModel *CollectionSourceModel::selectedCollectionList()
return idx.data(CollectionsRole).value<CollectionListModel *>();
}
+QString CollectionSourceModel::generateCollectionName(const ModelNode &node,
+ const QString &baseCollectionName) const
+{
+ int idx = sourceIndex(node);
+ if (idx < 0)
+ return {};
+
+ auto collections = m_collectionList.at(idx);
+ if (collections.isNull())
+ return {};
+
+ const int maxNumber = std::numeric_limits<int>::max();
+ for (int i = 1; i < maxNumber; ++i) {
+ const QString name = QLatin1String("%1_%2").arg(baseCollectionName).arg(i);
+ if (!collections->contains(name))
+ return name;
+ }
+ return {};
+}
+
void CollectionSourceModel::selectSourceIndex(int idx, bool selectAtLeastOne)
{
int collectionCount = m_collectionSources.size();
@@ -367,6 +387,21 @@ void CollectionSourceModel::selectSourceIndex(int idx, bool selectAtLeastOne)
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);
@@ -416,7 +451,8 @@ void CollectionSourceModel::onSelectedCollectionChanged(CollectionListModel *col
}
void CollectionSourceModel::onCollectionNameChanged(CollectionListModel *collectionList,
- const QString &oldName, const QString &newName)
+ const QString &oldName,
+ const QString &newName)
{
using Utils::FilePath;
using Utils::FileReader;
@@ -657,13 +693,14 @@ void CollectionSourceModel::updateCollectionList(QModelIndex index)
if (oldList != newList) {
m_collectionList.replace(index.row(), newList);
emit dataChanged(index, index, {CollectionsRole});
- registerCollection(newList);
+ registerCollectionList(newList);
}
}
-void CollectionSourceModel::registerCollection(const QSharedPointer<CollectionListModel> &collection)
+void CollectionSourceModel::registerCollectionList(
+ const QSharedPointer<CollectionListModel> &sharedCollectionList)
{
- CollectionListModel *collectionList = collection.data();
+ CollectionListModel *collectionList = sharedCollectionList.data();
if (collectionList == nullptr)
return;
@@ -688,10 +725,14 @@ void CollectionSourceModel::registerCollection(const QSharedPointer<CollectionLi
[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(collection->stringList());
+ emit collectionNamesInitialized(collectionList->collections());
}
QModelIndex CollectionSourceModel::indexOfNode(const ModelNode &node) const
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.h b/src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.h
index ac01c0de22..1909b77c9a 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.h
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.h
@@ -59,8 +59,10 @@ public:
ModelNode sourceNodeAt(int idx);
CollectionListModel *selectedCollectionList();
+ QString generateCollectionName(const ModelNode &node, const QString &baseCollectionName) const;
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 bool collectionExists(const QVariant &node, const QString &collectionName) const;
@@ -90,7 +92,7 @@ private:
void setSelectedCollectionName(const QString &collectionName);
void updateEmpty();
void updateCollectionList(QModelIndex index);
- void registerCollection(const QSharedPointer<CollectionListModel> &collection);
+ void registerCollectionList(const QSharedPointer<CollectionListModel> &collectionList);
QModelIndex indexOfNode(const ModelNode &node) const;
using Super = QAbstractListModel;
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp
index 9933ac3817..9e9405be3d 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp
@@ -12,6 +12,7 @@
#include "designmodecontext.h"
#include "nodeabstractproperty.h"
#include "nodemetainfo.h"
+#include "nodeproperty.h"
#include "qmldesignerplugin.h"
#include "variantproperty.h"
@@ -192,6 +193,17 @@ void CollectionView::selectedNodesChanged(const QList<ModelNode> &selectedNodeLi
}
}
+void CollectionView::customNotification(const AbstractView *,
+ const QString &identifier,
+ const QList<ModelNode> &nodeList,
+ const QList<QVariant> &data)
+{
+ if (identifier == QLatin1String("item_library_created_by_drop") && !nodeList.isEmpty())
+ onItemLibraryNodeCreated(nodeList.first());
+ else if (identifier == QLatin1String("open_collection_by_id") && !data.isEmpty())
+ m_widget->openCollection(collectionNameFromDataStoreChildren(data.first().toByteArray()));
+}
+
void CollectionView::addResource(const QUrl &url, const QString &name, const QString &type)
{
executeInTransaction(Q_FUNC_INFO, [this, &url, &name, &type]() {
@@ -221,12 +233,11 @@ void CollectionView::addResource(const QUrl &url, const QString &name, const QSt
});
}
-void CollectionView::assignCollectionToSelectedNode(const QString &collectionName)
+void CollectionView::assignCollectionToNode(const QString &collectionName, const ModelNode &node)
{
- QTC_ASSERT(dataStoreNode() && hasSingleSelectedModelNode(), return);
m_dataStore->assignCollectionToNode(
this,
- singleSelectedModelNode(),
+ node,
collectionName,
[&](const QString &collectionName, const QString &columnName) -> bool {
const CollectionReference reference{dataStoreNode(), collectionName};
@@ -238,6 +249,12 @@ void CollectionView::assignCollectionToSelectedNode(const QString &collectionNam
});
}
+void CollectionView::assignCollectionToSelectedNode(const QString &collectionName)
+{
+ QTC_ASSERT(dataStoreNode() && hasSingleSelectedModelNode(), return);
+ assignCollectionToNode(collectionName, singleSelectedModelNode());
+}
+
void CollectionView::registerDeclarativeType()
{
CollectionDetails::registerDeclarativeType();
@@ -255,6 +272,25 @@ ModelNode CollectionView::dataStoreNode() const
return m_dataStore->modelNode();
}
+void CollectionView::ensureDataStoreExists()
+{
+ bool filesJustCreated = false;
+ bool filesExist = CollectionEditorUtils::ensureDataStoreExists(filesJustCreated);
+ if (filesExist && filesJustCreated)
+ resetDataStoreNode();
+}
+
+QString CollectionView::collectionNameFromDataStoreChildren(const PropertyName &childPropertyName) const
+{
+ return dataStoreNode()
+ .nodeProperty(childPropertyName)
+ .modelNode()
+ .property(CollectionEditorConstants::JSONCHILDMODELNAME_PROPERTY)
+ .toVariantProperty()
+ .value()
+ .toString();
+}
+
void CollectionView::refreshModel()
{
if (!model())
@@ -292,4 +328,20 @@ void CollectionView::ensureStudioModelImport()
});
}
+void CollectionView::onItemLibraryNodeCreated(const ModelNode &node)
+{
+ ensureDataStoreExists();
+ CollectionSourceModel *sourceModel = m_widget->sourceModel();
+
+ if (node.metaInfo().isQtQuickListView()) {
+ const QString newCollectionName = sourceModel->generateCollectionName(dataStoreNode(),
+ "ListModel");
+ sourceModel->addCollectionToSource(dataStoreNode(),
+ newCollectionName,
+ CollectionEditorUtils::defaultColorCollection());
+ assignCollectionToNode(newCollectionName, node);
+ m_widget->openCollection(newCollectionName);
+ }
+}
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionview.h b/src/plugins/qmldesigner/components/collectioneditor/collectionview.h
index c08368b0c3..db3964726b 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionview.h
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionview.h
@@ -41,20 +41,29 @@ public:
void selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
const QList<ModelNode> &lastSelectedNodeList) override;
+ void customNotification(const AbstractView *view,
+ const QString &identifier,
+ const QList<ModelNode> &nodeList,
+ const QList<QVariant> &data) override;
+
void addResource(const QUrl &url, const QString &name, const QString &type);
+ void assignCollectionToNode(const QString &collectionName, const ModelNode &node);
void assignCollectionToSelectedNode(const QString &collectionName);
static void registerDeclarativeType();
void resetDataStoreNode();
ModelNode dataStoreNode() const;
+ void ensureDataStoreExists();
+ QString collectionNameFromDataStoreChildren(const PropertyName &childPropertyName) const;
private:
void refreshModel();
NodeMetaInfo jsonCollectionMetaInfo() const;
NodeMetaInfo csvCollectionMetaInfo() const;
void ensureStudioModelImport();
+ void onItemLibraryNodeCreated(const ModelNode &node);
QPointer<CollectionWidget> m_widget;
std::unique_ptr<DataStoreModelNode> m_dataStore;
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp
index 79d3d563a2..d17cbb5bfd 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp
@@ -9,6 +9,7 @@
#include "collectioneditorutils.h"
#include "collectionsourcemodel.h"
#include "collectionview.h"
+#include "designmodewidget.h"
#include "qmldesignerconstants.h"
#include "qmldesignerplugin.h"
#include "theme.h"
@@ -204,7 +205,7 @@ bool CollectionWidget::isValidUrlToImport(const QUrl &url) const
bool CollectionWidget::importFile(const QString &collectionName, const QUrl &url)
{
using Utils::FilePath;
- ensureDataStoreExists();
+ m_view->ensureDataStoreExists();
const ModelNode node = dataStoreNode();
if (!node.isValid()) {
@@ -264,7 +265,7 @@ bool CollectionWidget::importFile(const QString &collectionName, const QUrl &url
bool CollectionWidget::addCollectionToDataStore(const QString &collectionName)
{
- ensureDataStoreExists();
+ m_view->ensureDataStoreExists();
const ModelNode node = dataStoreNode();
if (!node.isValid()) {
warn(tr("Can not import to the main model"), tr("The default model node is not available."));
@@ -288,12 +289,10 @@ void CollectionWidget::assignCollectionToSelectedNode(const QString collectionNa
m_view->assignCollectionToSelectedNode(collectionName);
}
-void CollectionWidget::ensureDataStoreExists()
+void CollectionWidget::openCollection(const QString &collectionName)
{
- bool filesJustCreated = false;
- bool filesExist = CollectionEditorUtils::ensureDataStoreExists(filesJustCreated);
- if (filesExist && filesJustCreated)
- m_view->resetDataStoreNode();
+ m_sourceModel->selectCollection(QVariant::fromValue(m_view->dataStoreNode()), collectionName);
+ QmlDesignerPlugin::instance()->mainWidget()->showDockWidget("CollectionEditor", true);
}
ModelNode CollectionWidget::dataStoreNode() const
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.h b/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.h
index 23f4ad8dbf..b4a6578580 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.h
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.h
@@ -43,7 +43,7 @@ public:
Q_INVOKABLE bool importFile(const QString &collectionName, const QUrl &url);
Q_INVOKABLE bool addCollectionToDataStore(const QString &collectionName);
Q_INVOKABLE void assignCollectionToSelectedNode(const QString collectionName);
- Q_INVOKABLE void ensureDataStoreExists();
+ Q_INVOKABLE void openCollection(const QString &collectionName);
Q_INVOKABLE ModelNode dataStoreNode() const;
void warn(const QString &title, const QString &body);
diff --git a/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h b/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h
index 17ba5aa970..6a8833ef29 100644
--- a/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h
+++ b/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h
@@ -69,6 +69,7 @@ const char mergeTemplateCommandId[] = "MergeTemplate";
const char goToImplementationCommandId[] = "GoToImplementation";
const char makeComponentCommandId[] = "MakeComponent";
const char editMaterialCommandId[] = "EditMaterial";
+const char editCollectionCommandId[] = "EditCollection";
const char addItemToStackedContainerCommandId[] = "AddItemToStackedContainer";
const char addTabBarToStackedContainerCommandId[] = "AddTabBarToStackedContainer";
const char increaseIndexOfStackedContainerCommandId[] = "IncreaseIndexOfStackedContainer";
@@ -126,6 +127,7 @@ const char mergeTemplateDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMen
const char goToImplementationDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Go to Implementation");
const char makeComponentDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Create Component");
const char editMaterialDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Edit Material");
+const char editCollectionDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Edit Model");
const char editAnnotationsDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Edit Annotations");
const char addMouseAreaFillDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Add Mouse Area");
@@ -209,6 +211,8 @@ enum PrioritiesEnum : int {
SelectionCategory,
ArrangeCategory,
EditCategory,
+ EditListModel,
+ EditCollection,
/******** Section *****************************/
PositionSection = 2000,
SnappingCategory,
diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
index 6e4b1a1efd..6441d11b73 100644
--- a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
@@ -840,16 +840,22 @@ public:
{},
ComponentCoreConstants::rootCategory,
QKeySequence("Alt+e"),
- 1001,
+ ComponentCoreConstants::Priorities::EditListModel,
&openDialog,
- &isListViewInBaseState,
- &isListViewInBaseState)
+ &isListViewInBaseStateAndHasListModel,
+ &isListViewInBaseStateAndHasListModel)
{}
- static bool isListViewInBaseState(const SelectionContext &selectionState)
+ static bool isListViewInBaseStateAndHasListModel(const SelectionContext &selectionState)
{
- return selectionState.isInBaseState() && selectionState.singleNodeIsSelected()
- && selectionState.currentSingleSelectedNode().metaInfo().isListOrGridView();
+ if (!selectionState.isInBaseState() || !selectionState.singleNodeIsSelected())
+ return false;
+
+ const ModelNode singleSelectedNode = selectionState.currentSingleSelectedNode();
+
+ return singleSelectedNode.metaInfo().isListOrGridView()
+ && singleSelectedNode.property("model").toNodeProperty().modelNode().type()
+ == "QtQml.Models.ListModel";
}
bool isEnabled(const SelectionContext &) const override { return true; }
@@ -1977,6 +1983,16 @@ void DesignerActionManager::createDefaultDesignerActions()
addDesignerAction(new EditListModelAction);
+ addDesignerAction(new ModelNodeContextMenuAction(editCollectionCommandId,
+ editCollectionDisplayName,
+ contextIcon(DesignerIcons::EditIcon),
+ rootCategory,
+ QKeySequence("Alt+e"),
+ ComponentCoreConstants::Priorities::EditCollection,
+ &editCollection,
+ &hasCollectionAsModel,
+ &hasCollectionAsModel));
+
addDesignerAction(new ModelNodeContextMenuAction(openSignalDialogCommandId,
openSignalDialogDisplayName,
{},
diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.h b/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.h
index 6bc9c703bc..e7224f9edd 100644
--- a/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.h
+++ b/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.h
@@ -69,6 +69,18 @@ inline bool modelHasMaterial(const SelectionContext &selectionState)
return prop.exists() && (!prop.expression().isEmpty() || !prop.resolveToModelNodeList().empty());
}
+inline bool hasCollectionAsModel(const SelectionContext &selectionState)
+{
+ if (!selectionState.isInBaseState() || !selectionState.singleNodeIsSelected())
+ return false;
+
+ const ModelNode singleSelectedNode = selectionState.currentSingleSelectedNode();
+
+ return singleSelectedNode.metaInfo().isQtQuickListView()
+ && singleSelectedNode.property("model").toBindingProperty().expression().startsWith(
+ "DataStore.");
+}
+
inline bool selectionEnabled(const SelectionContext &selectionState)
{
return selectionState.showSelectionTools();
diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
index ae8f879017..98e0e4aef5 100644
--- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
@@ -833,6 +833,30 @@ void editMaterial(const SelectionContext &selectionContext)
}
}
+// Open a collection in the collection editor
+void editCollection(const SelectionContext &selectionContext)
+{
+ ModelNode modelNode = selectionContext.targetNode();
+
+ if (!modelNode)
+ modelNode = selectionContext.currentSingleSelectedNode();
+
+ if (!modelNode)
+ return;
+
+ const QString dataStoreExpression = "DataStore.";
+
+ BindingProperty prop = modelNode.bindingProperty("model");
+ if (!prop.exists() || !prop.expression().startsWith(dataStoreExpression))
+ return;
+
+ AbstractView *view = selectionContext.view();
+ const QString collectionId = prop.expression().mid(dataStoreExpression.size());
+
+ // to CollectionEditor...
+ view->emitCustomNotification("open_collection_by_id", {}, {collectionId});
+}
+
void addItemToStackedContainer(const SelectionContext &selectionContext)
{
AbstractView *view = selectionContext.view();
diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h
index 196dd4922c..4556462f30 100644
--- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h
+++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h
@@ -92,6 +92,7 @@ void layoutGridLayout(const SelectionContext &selectionState);
void goImplementation(const SelectionContext &selectionState);
void addNewSignalHandler(const SelectionContext &selectionState);
void editMaterial(const SelectionContext &selectionContext);
+void editCollection(const SelectionContext &selectionContext);
void addSignalHandlerOrGotoImplementation(const SelectionContext &selectionState, bool addAlwaysNewSlot);
void removeLayout(const SelectionContext &selectionContext);
void removePositioner(const SelectionContext &selectionContext);
diff --git a/src/plugins/qmldesigner/components/formeditor/dragtool.cpp b/src/plugins/qmldesigner/components/formeditor/dragtool.cpp
index e363e9bb11..0b7d199b50 100644
--- a/src/plugins/qmldesigner/components/formeditor/dragtool.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/dragtool.cpp
@@ -274,6 +274,11 @@ void DragTool::dropEvent(const QList<QGraphicsItem *> &itemList, QGraphicsSceneD
nodeList.append(node);
}
view()->setSelectedModelNodes(nodeList);
+
+ bool itemLibraryJustCreated = hasItemLibraryInfo(event->mimeData())
+ && nodeList.size() == 1;
+ if (itemLibraryJustCreated)
+ view()->emitCustomNotification("item_library_created_by_drop", nodeList);
}
m_dragNodes.clear();
}
@@ -382,7 +387,7 @@ void DragTool::dragMoveEvent(const QList<QGraphicsItem *> &itemList, QGraphicsSc
}
}
-void DragTool::end()
+void DragTool::end()
{
m_moveManipulator.end();
clear();
diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
index 7cf02c7259..5ae3d5d720 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
@@ -796,8 +796,10 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in
moveNodesInteractive(targetProperty, newModelNodeList, targetRowNumber);
}
- if (newQmlObjectNode.isValid())
+ if (newQmlObjectNode.isValid()) {
m_view->setSelectedModelNode(newQmlObjectNode.modelNode());
+ m_view->emitCustomNotification("item_library_created_by_drop", {newQmlObjectNode});
+ }
}
}
}
diff --git a/src/plugins/qmldesigner/designercore/include/nodemetainfo.h b/src/plugins/qmldesigner/designercore/include/nodemetainfo.h
index 58cdeba228..7e171c5445 100644
--- a/src/plugins/qmldesigner/designercore/include/nodemetainfo.h
+++ b/src/plugins/qmldesigner/designercore/include/nodemetainfo.h
@@ -166,6 +166,7 @@ public:
bool isQtQuick3DLight() const;
bool isQtQuickListElement() const;
bool isQtQuickListModel() const;
+ bool isQtQuickListView() const;
bool isQtQuick3DMaterial() const;
bool isQtQuick3DModel() const;
bool isQtQuick3DNode() const;
diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
index c695f488b1..975b12ddd1 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
@@ -2766,6 +2766,16 @@ bool NodeMetaInfo::isQtQuickListModel() const
}
}
+bool NodeMetaInfo::isQtQuickListView() const
+{
+ if constexpr (useProjectStorage()) {
+ using namespace Storage::Info;
+ return isBasedOnCommonType<QtQuick, ListView>(m_projectStorage, m_typeId);
+ } else {
+ return isValid() && (isSubclassOf("QtQuick.ListView"));
+ }
+}
+
bool NodeMetaInfo::isQtQuick3DInstanceList() const
{
if constexpr (useProjectStorage()) {