diff options
author | Eike Ziller <eike.ziller@qt.io> | 2022-09-27 10:03:37 +0200 |
---|---|---|
committer | Eike Ziller <eike.ziller@qt.io> | 2022-09-27 10:03:37 +0200 |
commit | 7eaa36e6e58a7c4ff8ec8a691c2a5abc39ae5f30 (patch) | |
tree | 872b997978f8065ec1d58df52301d9e1b308683c /src/plugins | |
parent | 21c5d3499ba143f4ff703410174e27c11f7ddda3 (diff) | |
parent | 4da66867051b27354b71ff6b4690d4e2d1e53bd6 (diff) | |
download | qt-creator-7eaa36e6e58a7c4ff8ec8a691c2a5abc39ae5f30.tar.gz |
Merge remote-tracking branch 'origin/8.0' into 9.0
Conflicts:
src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp
src/plugins/qmldesigner/designercore/imagecache/meshimagecachecollector.cpp
Change-Id: I38f196e8f42cf11f7b613e7a723745600e35c5e9
Diffstat (limited to 'src/plugins')
28 files changed, 587 insertions, 89 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()) diff --git a/src/plugins/qmldesigner/designercore/imagecache/meshimagecachecollector.cpp b/src/plugins/qmldesigner/designercore/imagecache/meshimagecachecollector.cpp index 88aa4efd40..0a9cd7d6d3 100644 --- a/src/plugins/qmldesigner/designercore/imagecache/meshimagecachecollector.cpp +++ b/src/plugins/qmldesigner/designercore/imagecache/meshimagecachecollector.cpp @@ -35,10 +35,12 @@ void MeshImageCacheCollector::start(Utils::SmallStringView name, if (file.open()) { QString qtQuickVersion; QString qtQuick3DVersion; - QtSupport::QtVersion *qtVersion = QtSupport::QtKitAspect::qtVersion(target()->kit()); - if (qtVersion && qtVersion->qtVersion() < QVersionNumber(6, 0, 0)) { - qtQuickVersion = "2.15"; - qtQuick3DVersion = "1.15"; + if (target()) { + QtSupport::QtVersion *qtVersion = QtSupport::QtKitAspect::qtVersion(target()->kit()); + if (qtVersion && qtVersion->qtVersion() < QVersionNumber(6, 0, 0)) { + qtQuickVersion = "2.15"; + qtQuick3DVersion = "1.15"; + } } QString content{ diff --git a/src/plugins/qmldesigner/designercore/include/stylesheetmerger.h b/src/plugins/qmldesigner/designercore/include/stylesheetmerger.h index 547a660361..e4dc67cd5d 100644 --- a/src/plugins/qmldesigner/designercore/include/stylesheetmerger.h +++ b/src/plugins/qmldesigner/designercore/include/stylesheetmerger.h @@ -3,6 +3,8 @@ #ifndef STYLESHEETMERGER_H #define STYLESHEETMERGER_H +#include "qmldesignercorelib_global.h" + #include <QString> #include <QHash> #include <modelnode.h> @@ -19,8 +21,8 @@ struct ReparentInfo { bool alreadyReparented; }; - -class StylesheetMerger { +class QMLDESIGNERCORE_EXPORT StylesheetMerger +{ public: StylesheetMerger(AbstractView*, AbstractView*); void merge(); diff --git a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp index aac2e6fd11..f3790dad83 100644 --- a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp +++ b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp @@ -5,13 +5,13 @@ #include "texttomodelmerger.h" #include "modeltotextmerger.h" +#include "model_p.h" #include <bindingproperty.h> #include <customnotifications.h> #include <filemanager/astobjecttextextractor.h> #include <filemanager/firstdefinitionfinder.h> #include <filemanager/objectlengthcalculator.h> -#include <model_p.h> #include <modelnode.h> #include <modelnodepositionstorage.h> #include <nodeproperty.h> diff --git a/src/plugins/qmldesigner/qtquickplugin/images/timer-16px.png b/src/plugins/qmldesigner/qtquickplugin/images/timer-16px.png Binary files differnew file mode 100644 index 0000000000..c675d5a707 --- /dev/null +++ b/src/plugins/qmldesigner/qtquickplugin/images/timer-16px.png diff --git a/src/plugins/qmldesigner/qtquickplugin/images/timer-24px.png b/src/plugins/qmldesigner/qtquickplugin/images/timer-24px.png Binary files differnew file mode 100644 index 0000000000..bd9419aaa0 --- /dev/null +++ b/src/plugins/qmldesigner/qtquickplugin/images/timer-24px.png diff --git a/src/plugins/qmldesigner/qtquickplugin/images/timer-24px@2x.png b/src/plugins/qmldesigner/qtquickplugin/images/timer-24px@2x.png Binary files differnew file mode 100644 index 0000000000..ff2d487cc9 --- /dev/null +++ b/src/plugins/qmldesigner/qtquickplugin/images/timer-24px@2x.png diff --git a/src/plugins/qmldesigner/qtquickplugin/qtquickplugin.qrc b/src/plugins/qmldesigner/qtquickplugin/qtquickplugin.qrc index 7cdc3309cb..1e78c02b77 100644 --- a/src/plugins/qmldesigner/qtquickplugin/qtquickplugin.qrc +++ b/src/plugins/qmldesigner/qtquickplugin/qtquickplugin.qrc @@ -98,5 +98,8 @@ <file>images/timeline-16px.png</file> <file>images/keyframe-16px.png</file> <file>images/timeline-animation-16px.png</file> + <file>images/timer-16px.png</file> + <file>images/timer-24px.png</file> + <file>images/timer-24px@2x.png</file> </qresource> </RCC> diff --git a/src/plugins/qmldesigner/qtquickplugin/quick.metainfo b/src/plugins/qmldesigner/qtquickplugin/quick.metainfo index 4b766f715c..c45db41b8d 100644 --- a/src/plugins/qmldesigner/qtquickplugin/quick.metainfo +++ b/src/plugins/qmldesigner/qtquickplugin/quick.metainfo @@ -488,6 +488,25 @@ MetaInfo { } Type { + name: "QtQml.Timer" + icon: ":/qtquickplugin/images/timer-16px.png" + + Hints { + visibleInNavigator: true + canBeDroppedInNavigator: true + canBeDroppedInFormEditor: false + canBeContainer: false + } + + ItemLibraryEntry { + name: "Timer" + category: "d.Qt Quick - Animation" + libraryIcon: ":/qtquickplugin/images/timer-24px.png" + version: "2.0" + } + } + + Type { name: "QtQml.Component" icon: ":/qtquickplugin/images/component-icon16.png" diff --git a/src/plugins/studiowelcome/userpresets.cpp b/src/plugins/studiowelcome/userpresets.cpp index a643df3fdd..86fdb2e557 100644 --- a/src/plugins/studiowelcome/userpresets.cpp +++ b/src/plugins/studiowelcome/userpresets.cpp @@ -21,7 +21,14 @@ FileStoreIo::FileStoreIo(const QString &fileName) QByteArray FileStoreIo::read() const { - m_file->open(QFile::ReadOnly | QFile::Text); + if (!m_file->exists()) + return {}; + + if (!m_file->open(QFile::ReadOnly | QFile::Text)) { + qWarning() << "Cannot load User Preset(s)"; + return {}; + } + QByteArray data = m_file->readAll(); m_file->close(); @@ -30,7 +37,11 @@ QByteArray FileStoreIo::read() const void FileStoreIo::write(const QByteArray &data) { - m_file->open(QFile::WriteOnly | QFile::Text); + if (!m_file->open(QFile::WriteOnly | QFile::Text)) { + qWarning() << "Cannot save User Preset(s)"; + return; + } + m_file->write(data); m_file->close(); } |