summaryrefslogtreecommitdiff
path: root/src/plugins/qmldesigner/components
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/qmldesigner/components')
-rw-r--r--src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp2
-rw-r--r--src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h2
-rw-r--r--src/plugins/qmldesigner/components/bindingeditor/actioneditor.cpp64
-rw-r--r--src/plugins/qmldesigner/components/bindingeditor/actioneditor.h5
-rw-r--r--src/plugins/qmldesigner/components/componentcore/componentcore_constants.h3
-rw-r--r--src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp302
-rw-r--r--src/plugins/qmldesigner/components/debugview/debugview.cpp10
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp2
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h2
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/bundleimporter.cpp9
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/bundlematerial.cpp8
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/bundlematerial.h5
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/materialbrowserbundlemodel.cpp20
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp9
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp164
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h5
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp2
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h2
-rw-r--r--src/plugins/qmldesigner/components/stateseditornew/stateseditorview.cpp5
19 files changed, 541 insertions, 80 deletions
diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp
index c1108ffc5e..4d5c0b2cd2 100644
--- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp
+++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp
@@ -166,7 +166,7 @@ QList<QToolButton *> AssetsLibraryWidget::createToolBarWidgets()
return {};
}
-void AssetsLibraryWidget::handleSearchfilterChanged(const QString &filterText)
+void AssetsLibraryWidget::handleSearchFilterChanged(const QString &filterText)
{
if (filterText == m_filterText || (m_assetsModel->isEmpty() && filterText.contains(m_filterText)))
return;
diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h
index f361c58e1a..d78345460f 100644
--- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h
+++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h
@@ -56,7 +56,7 @@ public:
Q_INVOKABLE void startDragAsset(const QStringList &assetPaths, const QPointF &mousePos);
Q_INVOKABLE void handleAddAsset();
- Q_INVOKABLE void handleSearchfilterChanged(const QString &filterText);
+ Q_INVOKABLE void handleSearchFilterChanged(const QString &filterText);
Q_INVOKABLE void handleExtFilesDrop(const QList<QUrl> &simpleFilePaths,
const QList<QUrl> &complexFilePaths,
const QString &targetDirPath = {});
diff --git a/src/plugins/qmldesigner/components/bindingeditor/actioneditor.cpp b/src/plugins/qmldesigner/components/bindingeditor/actioneditor.cpp
index ba507e2458..1d09f30d18 100644
--- a/src/plugins/qmldesigner/components/bindingeditor/actioneditor.cpp
+++ b/src/plugins/qmldesigner/components/bindingeditor/actioneditor.cpp
@@ -292,4 +292,68 @@ void ActionEditor::updateWindowName(const QString &targetName)
}
}
+void ActionEditor::invokeEditor(SignalHandlerProperty signalHandler,
+ std::function<void(SignalHandlerProperty)> onReject,
+ QObject * parent)
+{
+ if (!signalHandler.isValid())
+ return;
+
+ ModelNode connectionNode = signalHandler.parentModelNode();
+ if (!connectionNode.isValid())
+ return;
+
+ if (!connectionNode.bindingProperty("target").isValid())
+ return;
+
+ ModelNode targetNode = connectionNode.bindingProperty("target").resolveToModelNode();
+ if (!targetNode.isValid())
+ return;
+
+ const QString source = signalHandler.source();
+
+ QPointer<ActionEditor> editor = new ActionEditor(parent);
+
+ editor->showWidget();
+ editor->setModelNode(connectionNode);
+ editor->setConnectionValue(source);
+ editor->prepareConnections();
+ editor->updateWindowName(targetNode.validId() + "." + signalHandler.name());
+
+ QObject::connect(editor, &ActionEditor::accepted, [=]() {
+ if (!editor)
+ return;
+ if (editor->m_modelNode.isValid()) {
+ editor->m_modelNode.view()->executeInTransaction("ActionEditor::"
+ "invokeEditorAccepted",
+ [=]() {
+ editor->m_modelNode
+ .signalHandlerProperty(
+ signalHandler.name())
+ .setSource(
+ editor->connectionValue());
+ });
+ }
+
+ //closing editor widget somewhy triggers rejected() signal. Lets disconect before it affects us:
+ editor->disconnect();
+ editor->deleteLater();
+ });
+
+ QObject::connect(editor, &ActionEditor::rejected, [=]() {
+ if (!editor)
+ return;
+
+ if (onReject) {
+ editor->m_modelNode.view()->executeInTransaction("ActionEditor::"
+ "invokeEditorOnRejectFunc",
+ [=]() { onReject(signalHandler); });
+ }
+
+ //closing editor widget somewhy triggers rejected() signal 2nd time. Lets disconect before it affects us:
+ editor->disconnect();
+ editor->deleteLater();
+ });
+}
+
} // QmlDesigner namespace
diff --git a/src/plugins/qmldesigner/components/bindingeditor/actioneditor.h b/src/plugins/qmldesigner/components/bindingeditor/actioneditor.h
index ec2f8fb9c1..3cab2cef63 100644
--- a/src/plugins/qmldesigner/components/bindingeditor/actioneditor.h
+++ b/src/plugins/qmldesigner/components/bindingeditor/actioneditor.h
@@ -7,6 +7,7 @@
#include <bindingeditor/actioneditordialog.h>
#include <qmldesignercorelib_global.h>
#include <modelnode.h>
+#include <signalhandlerproperty.h>
#include <QtQml>
#include <QObject>
@@ -44,6 +45,10 @@ public:
Q_INVOKABLE void updateWindowName(const QString &targetName = {});
+ static void invokeEditor(SignalHandlerProperty signalHandler,
+ std::function<void(SignalHandlerProperty)> onReject = nullptr,
+ QObject *parent = nullptr);
+
signals:
void accepted();
void rejected();
diff --git a/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h b/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h
index 1133af1065..c876ea170d 100644
--- a/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h
+++ b/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h
@@ -12,6 +12,7 @@ namespace ComponentCoreConstants {
const char rootCategory[] = "";
const char selectionCategory[] = "Selection";
+const char connectionsCategory[] = "Connections";
const char arrangeCategory[] = "Arrange";
const char qmlPreviewCategory[] = "QmlPreview";
const char editCategory[] = "Edit";
@@ -76,6 +77,7 @@ const char openSignalDialogCommandId[] = "OpenSignalDialog";
const char update3DAssetCommandId[] = "Update3DAsset";
const char selectionCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Selection");
+const char connectionsCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Connections");
const char flowConnectionCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Connect");
const char selectEffectDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Select Effect");
const char arrangeCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Arrange");
@@ -183,6 +185,7 @@ const char editListModelDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMen
const int priorityFirst = 280;
const int prioritySelectionCategory = 220;
+const int priorityConnectionsCategory = 210;
const int priorityQmlPreviewCategory = 200;
const int priorityStackCategory = 180;
const int priorityEditCategory = 160;
diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
index 72b6f704c4..fb64084076 100644
--- a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
@@ -22,6 +22,7 @@
#include <documentmanager.h>
#include <qmldesignerplugin.h>
#include <viewmanager.h>
+#include <actioneditor.h>
#include <listmodeleditor/listmodeleditordialog.h>
#include <listmodeleditor/listmodeleditormodel.h>
@@ -433,6 +434,302 @@ public:
}
};
+QString prependSignal(QString signalHandlerName)
+{
+ if (signalHandlerName.isNull() || signalHandlerName.isEmpty())
+ return {};
+
+ QChar firstChar = signalHandlerName.at(0).toUpper();
+ signalHandlerName[0] = firstChar;
+ signalHandlerName.prepend(QLatin1String("on"));
+
+ return signalHandlerName;
+}
+
+QStringList getSignalsList(const ModelNode &node)
+{
+ if (!node.isValid())
+ return {};
+
+ if (!node.hasMetaInfo())
+ return {};
+
+ QStringList signalsList;
+ NodeMetaInfo nodeMetaInfo = node.metaInfo();
+
+ for (const auto &signalName : nodeMetaInfo.signalNames()) {
+ signalsList << QString::fromUtf8(signalName);
+ }
+
+ //on...Changed are the most regular signals, we assign them the lowest priority,
+ //we don't need them right now
+// QStringList signalsWithChanged = signalsList.filter("Changed");
+
+ //these are item specific, like MouseArea.clicked, they have higher priority
+ QStringList signalsWithoutChanged = signalsList;
+ signalsWithoutChanged.removeIf([](QString str) {
+ if (str.endsWith("Changed"))
+ return true;
+ return false;
+ });
+
+ QStringList finalResult;
+ finalResult.append(signalsWithoutChanged);
+
+
+ if (finalResult.isEmpty())
+ finalResult = signalsList;
+
+ finalResult.removeDuplicates();
+
+ return finalResult;
+}
+
+struct SlotEntry
+{
+ QString category;
+ QString name;
+ std::function<void(SignalHandlerProperty)> action;
+};
+
+QList<SlotEntry> getSlotsLists(const ModelNode &node)
+{
+ if (!node.isValid())
+ return {};
+
+ if (!node.view()->rootModelNode().isValid())
+ return {};
+
+ QList<SlotEntry> resultList;
+
+ ModelNode rootNode = node.view()->rootModelNode();
+ QmlObjectNode rootObjectNode(rootNode);
+
+ const QString stateCategory = "Change State";
+
+ //For now we are using category as part of the state name
+ //We should change it, once we extend number of categories
+ const SlotEntry defaultState = {stateCategory,
+ (stateCategory + " to " + "Default State"),
+ [rootNode](SignalHandlerProperty signalHandler) {
+ signalHandler.setSource(
+ QString("%1.state = \"\"").arg(rootNode.id()));
+ }};
+ resultList.push_back(defaultState);
+
+ for (const auto &stateName : rootObjectNode.states().names()) {
+ SlotEntry entry = {stateCategory,
+ (stateCategory + " to " + stateName),
+ [rootNode, stateName](SignalHandlerProperty signalHandler) {
+ signalHandler.setSource(
+ QString("%1.state = \"%2\"").arg(rootNode.id(), stateName));
+ }};
+
+ resultList.push_back(entry);
+ }
+
+ return resultList;
+}
+
+//creates connection without signalHandlerProperty
+ModelNode createNewConnection(ModelNode targetNode)
+{
+ NodeMetaInfo connectionsMetaInfo = targetNode.view()->model()->metaInfo("QtQuick.Connections");
+ ModelNode newConnectionNode = targetNode.view()
+ ->createModelNode("QtQuick.Connections",
+ connectionsMetaInfo.majorVersion(),
+ connectionsMetaInfo.minorVersion());
+ if (QmlItemNode::isValidQmlItemNode(targetNode))
+ targetNode.nodeAbstractProperty("data").reparentHere(newConnectionNode);
+
+ newConnectionNode.bindingProperty("target").setExpression(targetNode.id());
+
+ return newConnectionNode;
+}
+
+void removeSignal(SignalHandlerProperty signalHandler)
+{
+ auto connectionNode = signalHandler.parentModelNode();
+ auto connectionSignals = connectionNode.signalProperties();
+ if (connectionSignals.size() > 1) {
+ if (connectionSignals.contains(signalHandler))
+ connectionNode.removeProperty(signalHandler.name());
+ } else {
+ connectionNode.destroy();
+ }
+}
+
+class ConnectionsModelNodeActionGroup : public ActionGroup
+{
+public:
+ ConnectionsModelNodeActionGroup(const QString &displayName,
+ const QByteArray &menuId,
+ int priority)
+ : ActionGroup(displayName,
+ menuId,
+ priority,
+ &SelectionContextFunctors::always,
+ &SelectionContextFunctors::selectionEnabled)
+ {}
+
+ void updateContext() override
+ {
+ menu()->clear();
+
+ const auto selection = selectionContext();
+ if (!selection.isValid())
+ return;
+ if (!selection.singleNodeIsSelected())
+ return;
+ if (!action()->isEnabled())
+ return;
+
+ ModelNode currentNode = selection.currentSingleSelectedNode();
+ QmlObjectNode currentObjectNode(currentNode);
+
+ QStringList signalsList = getSignalsList(currentNode);
+ QList<SlotEntry> slotsList = getSlotsLists(currentNode);
+ currentNode.validId();
+
+ for (const ModelNode &connectionNode : currentObjectNode.getAllConnections()) {
+ for (const AbstractProperty &property : connectionNode.properties()) {
+ if (property.isSignalHandlerProperty() && property.name() != "target") {
+ const auto signalHandler = property.toSignalHandlerProperty();
+
+ const QString propertyName = QString::fromUtf8(signalHandler.name());
+
+ QMenu *activeSignalHandlerGroup = new QMenu(propertyName, menu());
+
+ QMenu *editSignalGroup = new QMenu("Change Signal", menu());
+
+ for (const auto &signalStr : signalsList) {
+ if (prependSignal(signalStr).toUtf8() == signalHandler.name())
+ continue;
+
+ ActionTemplate *newSignalAction = new ActionTemplate(
+ (signalStr + "Id").toLatin1(),
+ signalStr,
+ [signalStr, signalHandler](const SelectionContext &) {
+ signalHandler.parentModelNode().view()->executeInTransaction(
+ "ConnectionsModelNodeActionGroup::"
+ "changeSignal",
+ [signalStr, signalHandler]() {
+ auto connectionNode = signalHandler.parentModelNode();
+ auto newHandler = connectionNode.signalHandlerProperty(
+ prependSignal(signalStr).toLatin1());
+ newHandler.setSource(signalHandler.source());
+ connectionNode.removeProperty(signalHandler.name());
+ });
+ });
+ editSignalGroup->addAction(newSignalAction);
+ }
+
+ activeSignalHandlerGroup->addMenu(editSignalGroup);
+
+ if (!slotsList.isEmpty()) {
+ QMenu *editSlotGroup = new QMenu("Change Slot", menu());
+
+ for (const auto &slot : slotsList) {
+ ActionTemplate *newSlotAction = new ActionTemplate(
+ (slot.name + "Id").toLatin1(),
+ slot.name,
+ [slot, signalHandler](const SelectionContext &) {
+ signalHandler.parentModelNode()
+ .view()
+ ->executeInTransaction("ConnectionsModelNodeActionGroup::"
+ "changeSlot",
+ [slot, signalHandler]() {
+ slot.action(signalHandler);
+ });
+ });
+ editSlotGroup->addAction(newSlotAction);
+ }
+ activeSignalHandlerGroup->addMenu(editSlotGroup);
+ }
+
+ ActionTemplate *openEditorAction = new ActionTemplate(
+ (propertyName + "OpenEditorId").toLatin1(),
+ QString(
+ QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Open Connections Editor")),
+ [=](const SelectionContext &) {
+ signalHandler.parentModelNode().view()->executeInTransaction(
+ "ConnectionsModelNodeActionGroup::"
+ "openConnectionsEditor",
+ [signalHandler]() { ActionEditor::invokeEditor(signalHandler); });
+ });
+
+ activeSignalHandlerGroup->addAction(openEditorAction);
+
+ ActionTemplate *removeSignalHandlerAction = new ActionTemplate(
+ (propertyName + "RemoveSignalHandlerId").toLatin1(),
+ QString(QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Remove this handler")),
+ [signalHandler](const SelectionContext &) {
+ signalHandler.parentModelNode().view()->executeInTransaction(
+ "ConnectionsModelNodeActionGroup::"
+ "removeSignalHandler",
+ [signalHandler]() {
+ removeSignal(signalHandler);
+ });
+ });
+
+ activeSignalHandlerGroup->addAction(removeSignalHandlerAction);
+
+ menu()->addMenu(activeSignalHandlerGroup);
+ }
+ }
+ }
+
+ //singular add connection:
+ QMenu *addConnection = new QMenu(QString(QT_TRANSLATE_NOOP("QmlDesignerContextMenu",
+ "Add signal handler")),
+ menu());
+
+ for (const auto &signalStr : signalsList) {
+ QMenu *newSignal = new QMenu(signalStr, addConnection);
+
+ for (const auto &slot : slotsList) {
+ ActionTemplate *newSlot = new ActionTemplate(
+ QString(signalStr + slot.name + "Id").toLatin1(),
+ slot.name,
+ [=](const SelectionContext &) {
+ currentNode.view()->executeInTransaction(
+ "ConnectionsModelNodeActionGroup::addConnection", [=]() {
+ ModelNode newConnectionNode = createNewConnection(currentNode);
+ slot.action(newConnectionNode.signalHandlerProperty(
+ prependSignal(signalStr).toLatin1()));
+ });
+ });
+ newSignal->addAction(newSlot);
+ }
+
+ ActionTemplate *openEditorAction = new ActionTemplate(
+ (signalStr + "OpenEditorId").toLatin1(),
+ QString(QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Open Connections Editor")),
+ [=](const SelectionContext &) {
+ currentNode.view()->executeInTransaction(
+ "ConnectionsModelNodeActionGroup::"
+ "openConnectionsEditor",
+ [=]() {
+ ModelNode newConnectionNode = createNewConnection(currentNode);
+
+ SignalHandlerProperty newHandler
+ = newConnectionNode.signalHandlerProperty(
+ prependSignal(signalStr).toLatin1());
+
+ newHandler.setSource(
+ QString("console.log(\"%1.%2\")").arg(currentNode.id(), signalStr));
+ ActionEditor::invokeEditor(newHandler, removeSignal);
+ });
+ });
+ newSignal->addAction(openEditorAction);
+
+ addConnection->addMenu(newSignal);
+ }
+
+ menu()->addMenu(addConnection);
+ }
+};
+
class DocumentError : public std::exception
{
public:
@@ -953,6 +1250,11 @@ void DesignerActionManager::createDefaultDesignerActions()
selectionCategory,
prioritySelectionCategory));
+ addDesignerAction(new ConnectionsModelNodeActionGroup(
+ connectionsCategoryDisplayName,
+ connectionsCategory,
+ priorityConnectionsCategory));
+
addDesignerAction(new ActionGroup(
arrangeCategoryDisplayName,
arrangeCategory,
diff --git a/src/plugins/qmldesigner/components/debugview/debugview.cpp b/src/plugins/qmldesigner/components/debugview/debugview.cpp
index 48ef33ca39..fd6ef9f435 100644
--- a/src/plugins/qmldesigner/components/debugview/debugview.cpp
+++ b/src/plugins/qmldesigner/components/debugview/debugview.cpp
@@ -527,9 +527,17 @@ void DebugView::instancesToken(const QString &/*tokenName*/, int /*tokenNumber*/
}
-void DebugView::currentStateChanged(const ModelNode &/*node*/)
+void DebugView::currentStateChanged(const ModelNode &node)
{
+ if (isDebugViewEnabled()) {
+ QTextStream message;
+ QString string;
+ message.setString(&string);
+ message << node;
+
+ log("::currentStateChanged:", string);
+ }
}
void DebugView::nodeOrderChanged([[maybe_unused]] const NodeListProperty &listProperty)
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
index 5a359693f2..cb955174af 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
@@ -205,7 +205,7 @@ QList<QToolButton *> ItemLibraryWidget::createToolBarWidgets()
}
-void ItemLibraryWidget::handleSearchfilterChanged(const QString &filterText)
+void ItemLibraryWidget::handleSearchFilterChanged(const QString &filterText)
{
if (filterText != m_filterText) {
m_filterText = filterText;
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h
index 696ce9f168..16673849be 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h
@@ -69,7 +69,7 @@ public:
Q_INVOKABLE void startDragAndDrop(const QVariant &itemLibEntry, const QPointF &mousePos);
Q_INVOKABLE void removeImport(const QString &importUrl);
Q_INVOKABLE void addImportForItem(const QString &importUrl);
- Q_INVOKABLE void handleSearchfilterChanged(const QString &filterText);
+ Q_INVOKABLE void handleSearchFilterChanged(const QString &filterText);
Q_INVOKABLE void handleAddImport(int index);
Q_INVOKABLE void goIntoComponent(const QString &source);
diff --git a/src/plugins/qmldesigner/components/materialbrowser/bundleimporter.cpp b/src/plugins/qmldesigner/components/materialbrowser/bundleimporter.cpp
index 422288c8b2..7dae1e900f 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/bundleimporter.cpp
+++ b/src/plugins/qmldesigner/components/materialbrowser/bundleimporter.cpp
@@ -97,8 +97,9 @@ QString BundleImporter::importComponent(const QString &qmlFile,
FilePath qmlSourceFile = bundleImportPath.resolvePath(FilePath::fromString(qmlFile));
const bool qmlFileExists = qmlSourceFile.exists();
const QString qmlType = qmlSourceFile.baseName();
- m_pendingTypes.append(QStringLiteral("%1.%2")
- .arg(QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER).mid(1), qmlType));
+ m_pendingTypes.append(QStringLiteral("%1.%2.%3")
+ .arg(QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER).mid(1),
+ m_bundleId, qmlType));
if (!qmldirContent.contains(qmlFile)) {
qmldirContent.append(qmlType);
qmldirContent.append(" 1.0 ");
@@ -159,10 +160,6 @@ QString BundleImporter::importComponent(const QString &qmlFile,
// If import is not yet possible, import statement needs to be added asynchronously to
// avoid errors, as code model update takes a while.
m_importAddPending = true;
-
- // Full reset is not necessary if new import directory appearing will trigger scanning,
- // but if directory existed but was not valid possible import, we need to do a reset.
- m_fullReset = bundleImportPathExists;
}
}
m_importTimerCount = 0;
diff --git a/src/plugins/qmldesigner/components/materialbrowser/bundlematerial.cpp b/src/plugins/qmldesigner/components/materialbrowser/bundlematerial.cpp
index 75549945f4..b5bc19e785 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/bundlematerial.cpp
+++ b/src/plugins/qmldesigner/components/materialbrowser/bundlematerial.cpp
@@ -30,9 +30,10 @@ namespace QmlDesigner {
BundleMaterial::BundleMaterial(QObject *parent,
const QString &name,
const QString &qml,
+ const TypeName &type,
const QUrl &icon,
const QStringList &files)
- : QObject(parent), m_name(name), m_qml(qml), m_icon(icon), m_files(files) {}
+ : QObject(parent), m_name(name), m_qml(qml), m_type(type), m_icon(icon), m_files(files) {}
bool BundleMaterial::filter(const QString &searchText)
{
@@ -54,6 +55,11 @@ QString BundleMaterial::qml() const
return m_qml;
}
+TypeName BundleMaterial::type() const
+{
+ return m_type;
+}
+
QStringList BundleMaterial::files() const
{
return m_files;
diff --git a/src/plugins/qmldesigner/components/materialbrowser/bundlematerial.h b/src/plugins/qmldesigner/components/materialbrowser/bundlematerial.h
index 04f4ae2656..ae74a13d75 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/bundlematerial.h
+++ b/src/plugins/qmldesigner/components/materialbrowser/bundlematerial.h
@@ -25,6 +25,8 @@
#pragma once
+#include "qmldesignercorelib_global.h"
+
#include <QDataStream>
#include <QObject>
#include <QUrl>
@@ -43,6 +45,7 @@ public:
BundleMaterial(QObject *parent,
const QString &name,
const QString &qml,
+ const TypeName &type,
const QUrl &icon,
const QStringList &files);
@@ -50,6 +53,7 @@ public:
QUrl icon() const;
QString qml() const;
+ TypeName type() const;
QStringList files() const;
bool visible() const;
@@ -59,6 +63,7 @@ signals:
private:
QString m_name;
QString m_qml;
+ TypeName m_type;
QUrl m_icon;
QStringList m_files;
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserbundlemodel.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserbundlemodel.cpp
index 452093aba0..4e70008f1a 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserbundlemodel.cpp
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserbundlemodel.cpp
@@ -28,6 +28,7 @@
#include "bundleimporter.h"
#include "bundlematerial.h"
#include "bundlematerialcategory.h"
+#include "qmldesignerconstants.h"
#include "utils/qtcassert.h"
#include <QCoreApplication>
@@ -121,6 +122,8 @@ void MaterialBrowserBundleModel::loadMaterialBundle()
m_matBundleExists = true;
+ const QString bundleId = m_matBundleObj.value("id").toString();
+
const QJsonObject catsObj = m_matBundleObj.value("categories").toObject();
const QStringList categories = catsObj.keys();
for (const QString &cat : categories) {
@@ -136,8 +139,14 @@ void MaterialBrowserBundleModel::loadMaterialBundle()
for (const auto /*QJson{Const,}ValueRef*/ &asset : assetsArr)
files.append(asset.toString());
- auto bundleMat = new BundleMaterial(category, mat, matObj.value("qml").toString(),
- QUrl::fromLocalFile(matBundleDir.filePath(matObj.value("icon").toString())), files);
+ QUrl icon = QUrl::fromLocalFile(matBundleDir.filePath(matObj.value("icon").toString()));
+ QString qml = matObj.value("qml").toString();
+ TypeName type = QLatin1String("%1.%2.%3").arg(
+ QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER).mid(1),
+ bundleId,
+ qml.chopped(4)).toLatin1(); // chopped(4): remove .qml
+
+ auto bundleMat = new BundleMaterial(category, mat, qml, type, icon, files);
category->addBundleMaterial(bundleMat);
}
@@ -149,7 +158,7 @@ void MaterialBrowserBundleModel::loadMaterialBundle()
for (const auto /*QJson{Const,}ValueRef*/ &file : sharedFilesArr)
sharedFiles.append(file.toString());
- m_importer = new Internal::BundleImporter(matBundleDir.path(), "MaterialBundle", sharedFiles);
+ m_importer = new Internal::BundleImporter(matBundleDir.path(), bundleId, sharedFiles);
connect(m_importer, &Internal::BundleImporter::importFinished, this, [&](const QmlDesigner::NodeMetaInfo &metaInfo) {
if (metaInfo.isValid())
emit addBundleMaterialToProjectRequested(metaInfo);
@@ -223,7 +232,10 @@ void MaterialBrowserBundleModel::applyToSelected(BundleMaterial *mat, bool add)
void MaterialBrowserBundleModel::addMaterial(BundleMaterial *mat)
{
- m_importer->importComponent(mat->qml(), mat->files());
+ QString err = m_importer->importComponent(mat->qml(), mat->files());
+
+ if (!err.isEmpty())
+ qWarning() << __FUNCTION__ << err;
}
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp
index bbe47ec94c..1f1dff4eef 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp
@@ -266,8 +266,7 @@ void MaterialBrowserModel::removeMaterial(const ModelNode &material)
void MaterialBrowserModel::deleteSelectedMaterial()
{
- if (isValidIndex(m_selectedIndex))
- m_materialList[m_selectedIndex].destroy();
+ deleteMaterial(m_selectedIndex);
}
void MaterialBrowserModel::updateSelectedMaterial()
@@ -365,7 +364,11 @@ void MaterialBrowserModel::pasteMaterialProperties(int idx)
void MaterialBrowserModel::deleteMaterial(int idx)
{
- m_materialList[idx].destroy();
+ if (isValidIndex(idx)) {
+ ModelNode node = m_materialList[idx];
+ if (node.isValid())
+ QmlObjectNode(node).destroy();
+ }
}
void MaterialBrowserModel::renameMaterial(int idx, const QString &newName)
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp
index f0bdf4d906..791b42a059 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp
@@ -93,6 +93,8 @@ WidgetInfo MaterialBrowserView::widgetInfo()
mat.setVariantProperty(prop.name(), prop.toVariantProperty().value());
else if (prop.isBindingProperty())
mat.setBindingProperty(prop.name(), prop.toBindingProperty().expression());
+ else if (!all)
+ mat.removeProperty(prop.name());
}
});
});
@@ -105,70 +107,23 @@ WidgetInfo MaterialBrowserView::widgetInfo()
MaterialBrowserBundleModel *matBrowserBundleModel = m_widget->materialBrowserBundleModel().data();
connect(matBrowserBundleModel, &MaterialBrowserBundleModel::applyToSelectedTriggered, this,
- [&] (BundleMaterial *material, bool add) {
+ [&] (BundleMaterial *bundleMat, bool add) {
if (!m_selectedModel.isValid())
return;
m_bundleMaterialDropTarget = m_selectedModel;
m_bundleMaterialAddToSelected = add;
- m_widget->materialBrowserBundleModel()->addMaterial(material);
+
+ ModelNode defaultMat = getBundleMaterialDefaultInstance(bundleMat->type());
+ if (defaultMat.isValid())
+ applyBundleMaterialToDropTarget(defaultMat);
+ else
+ m_widget->materialBrowserBundleModel()->addMaterial(bundleMat);
});
connect(matBrowserBundleModel, &MaterialBrowserBundleModel::addBundleMaterialToProjectRequested, this,
[&] (const QmlDesigner::NodeMetaInfo &metaInfo) {
- ModelNode matLib = materialLibraryNode();
- if (!matLib.isValid())
- return;
-
- executeInTransaction("MaterialBrowserView::widgetInfo", [&] {
- ModelNode newMatNode = createModelNode(metaInfo.typeName(), metaInfo.majorVersion(),
- metaInfo.minorVersion());
- matLib.defaultNodeListProperty().reparentHere(newMatNode);
-
- static QRegularExpression rgx("([A-Z])([a-z]*)");
- QString newName = QString::fromLatin1(metaInfo.simplifiedTypeName()).replace(rgx, " \\1\\2").trimmed();
- QString newId = model()->generateIdFromName(newName, "material");
- newMatNode.setIdWithRefactoring(newId);
-
- VariantProperty objNameProp = newMatNode.variantProperty("objectName");
- objNameProp.setValue(newName);
-
- if (m_bundleMaterialDropTarget.isValid()) {
- QmlObjectNode qmlObjNode(m_bundleMaterialDropTarget);
- if (m_bundleMaterialAddToSelected) {
- // TODO: unify this logic as it exist elsewhere also
- auto expToList = [](const QString &exp) {
- QString copy = exp;
- copy = copy.remove("[").remove("]");
-
- QStringList tmp = copy.split(',', Qt::SkipEmptyParts);
- for (QString &str : tmp)
- str = str.trimmed();
-
- return tmp;
- };
-
- auto listToExp = [](QStringList &stringList) {
- if (stringList.size() > 1)
- return QString("[" + stringList.join(",") + "]");
-
- if (stringList.size() == 1)
- return stringList.first();
-
- return QString();
- };
- QStringList matList = expToList(qmlObjNode.expression("materials"));
- matList.append(newMatNode.id());
- QString updatedExp = listToExp(matList);
- qmlObjNode.setBindingProperty("materials", updatedExp);
- } else {
- qmlObjNode.setBindingProperty("materials", newMatNode.id());
- }
- m_bundleMaterialDropTarget = {};
- }
-
- m_bundleMaterialAddToSelected = false;
- });
+ applyBundleMaterialToDropTarget({}, metaInfo);
});
}
@@ -179,6 +134,74 @@ WidgetInfo MaterialBrowserView::widgetInfo()
tr("Material Browser"));
}
+void MaterialBrowserView::applyBundleMaterialToDropTarget(const ModelNode &bundleMat,
+ const NodeMetaInfo &metaInfo)
+{
+ if (!bundleMat.isValid() && !metaInfo.isValid())
+ return;
+
+ ModelNode matLib = materialLibraryNode();
+ if (!matLib.isValid())
+ return;
+
+ executeInTransaction("MaterialBrowserView::applyBundleMaterialToDropTarget", [&] {
+ ModelNode newMatNode;
+ if (metaInfo.isValid()) {
+ newMatNode = createModelNode(metaInfo.typeName(), metaInfo.majorVersion(),
+ metaInfo.minorVersion());
+ matLib.defaultNodeListProperty().reparentHere(newMatNode);
+
+ static QRegularExpression rgx("([A-Z])([a-z]*)");
+ QString newName = QString::fromLatin1(metaInfo.simplifiedTypeName()).replace(rgx, " \\1\\2").trimmed();
+ if (newName.endsWith(" Material"))
+ newName.chop(9); // remove trailing " Material"
+ QString newId = model()->generateIdFromName(newName, "material");
+ newMatNode.setIdWithRefactoring(newId);
+
+ VariantProperty objNameProp = newMatNode.variantProperty("objectName");
+ objNameProp.setValue(newName);
+ } else {
+ newMatNode = bundleMat;
+ }
+
+ if (m_bundleMaterialDropTarget.isValid()) {
+ QmlObjectNode qmlObjNode(m_bundleMaterialDropTarget);
+ if (m_bundleMaterialAddToSelected) {
+ // TODO: unify this logic as it exist elsewhere also
+ auto expToList = [](const QString &exp) {
+ QString copy = exp;
+ copy = copy.remove("[").remove("]");
+
+ QStringList tmp = copy.split(',', Qt::SkipEmptyParts);
+ for (QString &str : tmp)
+ str = str.trimmed();
+
+ return tmp;
+ };
+
+ auto listToExp = [](QStringList &stringList) {
+ if (stringList.size() > 1)
+ return QString("[" + stringList.join(",") + "]");
+
+ if (stringList.size() == 1)
+ return stringList.first();
+
+ return QString();
+ };
+ QStringList matList = expToList(qmlObjNode.expression("materials"));
+ matList.append(newMatNode.id());
+ QString updatedExp = listToExp(matList);
+ qmlObjNode.setBindingProperty("materials", updatedExp);
+ } else {
+ qmlObjNode.setBindingProperty("materials", newMatNode.id());
+ }
+
+ m_bundleMaterialDropTarget = {};
+ m_bundleMaterialAddToSelected = false;
+ }
+ });
+}
+
void MaterialBrowserView::modelAttached(Model *model)
{
AbstractView::modelAttached(model);
@@ -347,6 +370,28 @@ void QmlDesigner::MaterialBrowserView::loadPropertyGroups()
m_propertyGroupsLoaded = m_widget->materialBrowserModel()->loadPropertyGroups(matPropsPath);
}
+ModelNode MaterialBrowserView::getBundleMaterialDefaultInstance(const TypeName &type)
+{
+ const QList<ModelNode> materials = m_widget->materialBrowserModel()->materials();
+ for (const ModelNode &mat : materials) {
+ if (mat.type() == type) {
+ bool isDefault = true;
+ const QList<AbstractProperty> props = mat.properties();
+ for (const AbstractProperty &prop : props) {
+ if (prop.name() != "objectName") {
+ isDefault = false;
+ break;
+ }
+ }
+
+ if (isDefault)
+ return mat;
+ }
+ }
+
+ return {};
+}
+
void MaterialBrowserView::importsChanged([[maybe_unused]] const QList<Import> &addedImports,
[[maybe_unused]] const QList<Import> &removedImports)
{
@@ -383,7 +428,14 @@ void MaterialBrowserView::customNotification(const AbstractView *view,
m_widget->materialBrowserModel()->deleteSelectedMaterial();
} else if (identifier == "drop_bundle_material") {
m_bundleMaterialDropTarget = nodeList.first();
- m_widget->materialBrowserBundleModel()->addMaterial(m_draggedBundleMaterial);
+
+
+ ModelNode defaultMat = getBundleMaterialDefaultInstance(m_draggedBundleMaterial->type());
+ if (defaultMat.isValid())
+ applyBundleMaterialToDropTarget(defaultMat);
+ else
+ m_widget->materialBrowserBundleModel()->addMaterial(m_draggedBundleMaterial);
+
m_draggedBundleMaterial = nullptr;
}
}
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h
index d163b5fa3f..31b0310f4c 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h
@@ -3,7 +3,8 @@
#pragma once
-#include <abstractview.h>
+#include "abstractview.h"
+#include "nodemetainfo.h"
#include <QPointer>
@@ -45,6 +46,8 @@ private:
void refreshModel(bool updateImages);
bool isMaterial(const ModelNode &node) const;
void loadPropertyGroups();
+ void applyBundleMaterialToDropTarget(const ModelNode &bundleMat, const NodeMetaInfo &metaInfo = {});
+ ModelNode getBundleMaterialDefaultInstance(const TypeName &type);
QPointer<MaterialBrowserWidget> m_widget;
ModelNode m_bundleMaterialDropTarget;
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp
index c8473e5856..9df4a39b6e 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp
@@ -192,7 +192,7 @@ void MaterialBrowserWidget::contextHelp(const Core::IContext::HelpCallback &call
callback({});
}
-void MaterialBrowserWidget::handleSearchfilterChanged(const QString &filterText)
+void MaterialBrowserWidget::handleSearchFilterChanged(const QString &filterText)
{
if (filterText != m_filterText) {
m_filterText = filterText;
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h
index 1767286b49..925e7bc260 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h
@@ -51,7 +51,7 @@ public:
QPointer<MaterialBrowserBundleModel> materialBrowserBundleModel() const;
void updateMaterialPreview(const ModelNode &node, const QPixmap &pixmap);
- Q_INVOKABLE void handleSearchfilterChanged(const QString &filterText);
+ Q_INVOKABLE void handleSearchFilterChanged(const QString &filterText);
Q_INVOKABLE void startDragMaterial(int index, const QPointF &mousePos);
Q_INVOKABLE void startDragBundleMaterial(QmlDesigner::BundleMaterial *bundleMat, const QPointF &mousePos);
diff --git a/src/plugins/qmldesigner/components/stateseditornew/stateseditorview.cpp b/src/plugins/qmldesigner/components/stateseditornew/stateseditorview.cpp
index 65d021eb05..a8e28f62e0 100644
--- a/src/plugins/qmldesigner/components/stateseditornew/stateseditorview.cpp
+++ b/src/plugins/qmldesigner/components/stateseditornew/stateseditorview.cpp
@@ -720,7 +720,7 @@ void StatesEditorView::propertiesRemoved(const QList<AbstractProperty>& property
for (const AbstractProperty &property : propertyList) {
if (property.name() == "states" && property.parentModelNode() == activeStateGroup().modelNode())
resetModel();
- if (property.name() == "when"
+ if ((property.name() == "when" || property.name() == "name")
&& QmlModelState::isValidQmlModelState(property.parentModelNode()))
resetModel();
if (property.name() == "extend")
@@ -848,7 +848,8 @@ void StatesEditorView::variantPropertiesChanged(const QList<VariantProperty> &pr
auto guard = qScopeGuard([&]() { m_block = false; });
for (const VariantProperty &property : propertyList) {
- if (property.name() == "name" && QmlModelState::isValidQmlModelState(property.parentModelNode()))
+ if (property.name() == "name"
+ && QmlModelState::isValidQmlModelState(property.parentModelNode()))
resetModel();
else if (property.name() == "state"
&& property.parentModelNode() == activeStateGroup().modelNode())