From c4381e573bb7ebfd9e5873ed9213c2f69a38492e Mon Sep 17 00:00:00 2001 From: Ali Kianian Date: Mon, 17 Mar 2025 16:20:14 +0200 Subject: [PATCH] QmlDesigner: Remove MaterialEditor * For editing materials, the material is forced to be opened by property editor. It means that if property editor is locked, the locked would be ignored. Task-number: QDS-14625 Change-Id: I271cc862750cecb6b2480c66d26e6aa5c6f62d55 Reviewed-by: Mahmoud Badri Reviewed-by: Miikka Heikkinen --- .../ColorEditorPopup.qml | 63 - .../EmptyMaterialEditorPane.qml | 56 - .../MaterialEditorPane.qml | 155 --- .../MaterialEditorPreview.qml | 259 ---- .../MaterialEditorToolBar.qml | 56 - .../MaterialEditorTopSection.qml | 93 -- .../workspacePresets/Advanced-3D.wrk | 1 - .../qmldesigner/workspacePresets/Basic-3D.wrk | 1 - src/plugins/qmldesigner/CMakeLists.txt | 14 +- .../componentcore/modelnodeoperations.cpp | 6 +- .../components/componentcore/utils3d.cpp | 28 +- .../components/componentcore/utils3d.h | 6 +- .../components/componentcore/viewmanager.cpp | 5 - .../edit3d/edit3dmaterialsaction.cpp | 3 +- .../components/integration/componentview.cpp | 19 +- .../materialbrowser/materialbrowserview.cpp | 1 - .../materialbrowser/materialbrowserwidget.cpp | 3 +- .../materialeditorcontextobject.cpp | 555 -------- .../materialeditorcontextobject.h | 182 --- ...erialeditordynamicpropertiesproxymodel.cpp | 47 - ...aterialeditordynamicpropertiesproxymodel.h | 41 - .../materialeditorimageprovider.cpp | 82 -- .../materialeditorimageprovider.h | 37 - .../materialeditorqmlbackend.cpp | 299 ---- .../materialeditor/materialeditorqmlbackend.h | 80 -- .../materialeditortransaction.cpp | 51 - .../materialeditortransaction.h | 32 - .../materialeditor/materialeditorview.cpp | 1233 ----------------- .../materialeditor/materialeditorview.h | 154 -- .../images/defaultmaterialpreview.png | Bin .../propertyeditor/instanceimageprovider.cpp | 2 +- .../propertyeditor.qrc} | 2 +- .../propertyeditor/propertyeditorview.cpp | 23 + .../propertyeditor/propertyeditorview.h | 5 + .../textureeditortransaction.cpp | 3 +- .../textureeditor/textureeditorview.cpp | 5 +- src/plugins/qmldesigner/designmodewidget.cpp | 8 +- .../qmldesigner/qmldesignerconstants.h | 2 - 38 files changed, 60 insertions(+), 3552 deletions(-) delete mode 100644 share/qtcreator/qmldesigner/materialEditorQmlSources/ColorEditorPopup.qml delete mode 100644 share/qtcreator/qmldesigner/materialEditorQmlSources/EmptyMaterialEditorPane.qml delete mode 100644 share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorPane.qml delete mode 100644 share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorPreview.qml delete mode 100644 share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorToolBar.qml delete mode 100644 share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorTopSection.qml delete mode 100644 src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.cpp delete mode 100644 src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.h delete mode 100644 src/plugins/qmldesigner/components/materialeditor/materialeditordynamicpropertiesproxymodel.cpp delete mode 100644 src/plugins/qmldesigner/components/materialeditor/materialeditordynamicpropertiesproxymodel.h delete mode 100644 src/plugins/qmldesigner/components/materialeditor/materialeditorimageprovider.cpp delete mode 100644 src/plugins/qmldesigner/components/materialeditor/materialeditorimageprovider.h delete mode 100644 src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.cpp delete mode 100644 src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.h delete mode 100644 src/plugins/qmldesigner/components/materialeditor/materialeditortransaction.cpp delete mode 100644 src/plugins/qmldesigner/components/materialeditor/materialeditortransaction.h delete mode 100644 src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp delete mode 100644 src/plugins/qmldesigner/components/materialeditor/materialeditorview.h rename src/plugins/qmldesigner/components/{materialeditor => propertyeditor}/images/defaultmaterialpreview.png (100%) rename src/plugins/qmldesigner/components/{materialeditor/materialeditor.qrc => propertyeditor/propertyeditor.qrc} (67%) diff --git a/share/qtcreator/qmldesigner/materialEditorQmlSources/ColorEditorPopup.qml b/share/qtcreator/qmldesigner/materialEditorQmlSources/ColorEditorPopup.qml deleted file mode 100644 index 7f2250c5940..00000000000 --- a/share/qtcreator/qmldesigner/materialEditorQmlSources/ColorEditorPopup.qml +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (C) 2024 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -import QtQuick -import HelperWidgets as HelperWidgets -import StudioControls as StudioControls - -StudioControls.PopupDialog { - id: colorPopup - - property QtObject loaderItem: loader.item - property color originalColor - required property color currentColor - - signal activateColor(color : color) - - width: 260 - - onOriginalColorChanged: loader.updateOriginalColor() - onClosing: loader.active = false - - function open(showItem) { - loader.ensureActive() - colorPopup.show(showItem) - - loader.updateOriginalColor() - } - - Loader { - id: loader - - function ensureActive() { - if (!loader.active) - loader.active = true - } - - function updateOriginalColor() { - if (loader.status === Loader.Ready) - loader.item.originalColor = colorPopup.originalColor - } - - sourceComponent: StudioControls.ColorEditorPopup { - width: colorPopup.contentWidth - visible: colorPopup.visible - - onActivateColor: (color) => { - colorPopup.activateColor(color) - } - } - - Binding { - target: loader.item - property: "color" - value: colorPopup.currentColor - when: loader.status === Loader.Ready - } - - onLoaded: { - loader.updateOriginalColor() - colorPopup.titleBar = loader.item.titleBarContent - } - } -} diff --git a/share/qtcreator/qmldesigner/materialEditorQmlSources/EmptyMaterialEditorPane.qml b/share/qtcreator/qmldesigner/materialEditorQmlSources/EmptyMaterialEditorPane.qml deleted file mode 100644 index 0c6d7e39b28..00000000000 --- a/share/qtcreator/qmldesigner/materialEditorQmlSources/EmptyMaterialEditorPane.qml +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -import QtQuick -import HelperWidgets -import StudioTheme as StudioTheme - -PropertyEditorPane { - id: root - - width: 420 - height: 420 - - signal toolBarAction(int action) - signal previewEnvChanged(string env) - signal previewModelChanged(string model) - - // Called from C++, dummy methods to avoid warnings - function closeContextMenu() {} - function initPreviewData(env, model) {} - - Column { - id: col - - MaterialEditorToolBar { - width: root.width - - onToolBarAction: (action) => root.toolBarAction(action) - } - - Item { - width: root.width - 2 * col.padding - height: 150 - - Text { - text: { - if (!isQt6Project) - qsTr("Material Editor is not supported in Qt5 projects.") - else if (!hasQuick3DImport) - qsTr("To use Material Editor, first add the QtQuick3D module in the Components view.") - else if (!hasMaterialLibrary) - qsTr("Material Editor is disabled inside a non-visual component.") - else - qsTr("There are no materials in this project.
Select '+' to create one.") - } - textFormat: Text.RichText - color: StudioTheme.Values.themeTextColor - font.pixelSize: StudioTheme.Values.mediumFontSize - horizontalAlignment: Text.AlignHCenter - wrapMode: Text.WordWrap - width: root.width - anchors.centerIn: parent - } - } - } -} diff --git a/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorPane.qml b/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorPane.qml deleted file mode 100644 index 300c453c674..00000000000 --- a/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorPane.qml +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -import QtQuick -import QtQuick.Controls -import QtCore -import HelperWidgets -import StudioControls 1.0 as StudioControls - -Item { - id: root - - property string __previewEnv - property string __previewModel - - width: 420 - height: 420 - - signal toolBarAction(int action) - signal previewEnvChanged(string env) - signal previewModelChanged(string model) - - // invoked from C++ to refresh material preview image - signal refreshPreview() - - // Called from C++ to close context menu on focus out - function closeContextMenu() - { - Controller.closeContextMenu() - } - - // Called from C++ to initialize preview menu checkmarks - function initPreviewData(env, model) { - root.__previewEnv = env - root.__previewModel = model - } - - MaterialEditorToolBar { - id: toolbar - - width: parent.width - - onToolBarAction: (action) => root.toolBarAction(action) - } - - Settings { - id: settings - - property var topSection - property bool dockMode - } - - StudioControls.SplitView { - id: splitView - - readonly property bool isHorizontal: splitView.orientation == Qt.Horizontal - - anchors.top: toolbar.bottom - anchors.bottom: parent.bottom - width: parent.width - orientation: splitView.width > 1000 ? Qt.Horizontal : Qt.Vertical - clip: true - - Loader { - id: leftSideView - - SplitView.fillWidth: leftSideView.visible - SplitView.fillHeight: leftSideView.visible - SplitView.minimumWidth: leftSideView.visible ? 300 : 0 - SplitView.minimumHeight: leftSideView.visible ? 300 : 0 - - active: splitView.isHorizontal - visible: leftSideView.active && leftSideView.item - - sourceComponent: PreviewComponent {} - } - - PropertyEditorPane { - id: itemPane - - clip: true - SplitView.fillWidth: !leftSideView.visible - SplitView.fillHeight: true - SplitView.minimumWidth: leftSideView.visible ? 400 : 0 - SplitView.maximumWidth: leftSideView.visible ? 800 : -1 - - headerDocked: !leftSideView.visible && settings.dockMode - - headerComponent: MaterialEditorTopSection { - id: topSection - - Component.onCompleted: topSection.restoreState(settings.topSection) - Component.onDestruction: settings.topSection = topSection.saveState() - previewComponent: PreviewComponent {} - showImage: !splitView.isHorizontal - } - - DynamicPropertiesSection { - propertiesModel: MaterialEditorDynamicPropertiesModel {} - } - - Loader { - id: specificsTwo - - property string theSource: specificQmlData - - width: itemPane.width - visible: specificsTwo.theSource !== "" - sourceComponent: specificQmlComponent - - onTheSourceChanged: { - specificsTwo.active = false - specificsTwo.active = true - } - } - - Item { // spacer - width: 1 - height: 10 - visible: specificsTwo.visible - } - - Loader { - id: specificsOne - width: itemPane.width - source: specificsUrl - } - } - } - - component PreviewComponent : MaterialEditorPreview { - id: previewItem - - onPreviewEnvChanged: root.previewEnvChanged(previewEnv) - onPreviewModelChanged: root.previewModelChanged(previewModel) - - pinned: settings.dockMode - showPinButton: !leftSideView.visible - onPinnedChanged: settings.dockMode = previewItem.pinned - - Binding { - previewItem.previewEnv: root.__previewEnv - previewItem.previewModel: root.__previewModel - delayed: true - } - - Connections { - target: root - - function onRefreshPreview() { - previewItem.refreshPreview() - } - } - } -} diff --git a/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorPreview.qml b/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorPreview.qml deleted file mode 100644 index c3c7ff5a973..00000000000 --- a/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorPreview.qml +++ /dev/null @@ -1,259 +0,0 @@ -// Copyright (C) 2024 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -import QtQuick -import HelperWidgets as HelperWidgets -import StudioControls as StudioControls -import StudioTheme as StudioTheme - -Rectangle { - id: root - - property string previewEnv - property string previewModel - property alias pinned: pinButton.checked - property alias showPinButton: pinButton.visible - - property StudioTheme.ControlStyle buttonStyle: StudioTheme.ViewBarButtonStyle { - // This is how you can override stuff from the control styles - baseIconFontSize: StudioTheme.Values.bigIconFontSize - } - - Connections { - target: HelperWidgets.Controller - - function onCloseContextMenu() { - root.closeContextMenu() - } - } - - implicitHeight: image.height - - clip: true - color: "#000000" - - // Called from C++ to close context menu on focus out - function closeContextMenu() - { - modelMenu.close() - envMenu.close() - } - - function refreshPreview() - { - image.source = "" - image.source = "image://materialEditor/preview" - } - - onPreviewEnvChanged: envMenu.updateEnvParams(root.previewEnv) - - Image { - id: image - - anchors.fill: parent - fillMode: Image.PreserveAspectFit - - source: "image://materialEditor/preview" - cache: false - smooth: true - - sourceSize.width: image.width - sourceSize.height: image.height - - Rectangle { - id: toolbarRect - - radius: 10 - color: StudioTheme.Values.themeToolbarBackground - width: optionsToolbar.width + 2 * toolbarRect.radius - height: optionsToolbar.height + toolbarRect.radius - anchors.left: parent.left - anchors.leftMargin: -toolbarRect.radius - anchors.verticalCenter: parent.verticalCenter - - Column { - id: optionsToolbar - - spacing: 5 - anchors.centerIn: parent - anchors.horizontalCenterOffset: optionsToolbar.spacing - - HelperWidgets.AbstractButton { - id: pinButton - - style: root.buttonStyle - buttonIcon: pinButton.checked ? StudioTheme.Constants.pin : StudioTheme.Constants.unpin - checkable: true - } - - HelperWidgets.AbstractButton { - id: previewEnvMenuButton - - style: root.buttonStyle - buttonIcon: StudioTheme.Constants.textures_medium - tooltip: qsTr("Select preview environment.") - onClicked: envMenu.popup() - } - - HelperWidgets.AbstractButton { - id: previewModelMenuButton - - style: root.buttonStyle - buttonIcon: StudioTheme.Constants.cube_medium - tooltip: qsTr("Select preview model.") - onClicked: modelMenu.popup() - } - } - } - } - - StudioControls.Menu { - id: modelMenu - - closePolicy: StudioControls.Menu.CloseOnEscape | StudioControls.Menu.CloseOnPressOutside - - ListModel { - id: modelMenuModel - ListElement { - modelName: qsTr("Cone") - modelStr: "#Cone" - } - ListElement { - modelName: qsTr("Cube") - modelStr: "#Cube" - } - ListElement { - modelName: qsTr("Cylinder") - modelStr: "#Cylinder" - } - ListElement { - modelName: qsTr("Sphere") - modelStr: "#Sphere" - } - } - - Repeater { - model: modelMenuModel - StudioControls.MenuItemWithIcon { - text: modelName - onClicked: { - // Force property change notifications to keep check mark when reselected - root.previewModel = "" - root.previewModel = modelStr - } - checkable: true - checked: root.previewModel === modelStr - } - } - } - - StudioControls.Menu { - id: envMenu - - property string previewEnvName - property string previewEnvValue - - signal envParametersChanged() - - closePolicy: StudioControls.Menu.CloseOnEscape | StudioControls.Menu.CloseOnPressOutside - - Component.onCompleted: envMenu.updateEnvParams(root.previewEnv) - - function updateEnvParams(str: string) { - let eqFound = str.lastIndexOf("=") - let newEnvName = (eqFound > 0) ? str.substr(0, eqFound) : str - let newEnvValue = (eqFound > 0) ? str.substr(eqFound + 1, str.length - eqFound) : "" - - if (envMenu.previewEnvName !== newEnvName - || envMenu.previewEnvValue !== newEnvValue) { - envMenu.previewEnvName = newEnvName - envMenu.previewEnvValue = newEnvValue - envMenu.envParametersChanged() - } - } - - EnvMenuItem { - envName: qsTr("Basic") - envStr: "Basic" - } - - EnvMenuItem { - id: colorItem - - property color color - property bool colorIsValid: false - - envName: qsTr("Color") - envStr: "Color" - checked: false - - Component.onCompleted: update() - onColorIsValidChanged: updatePopupOriginalColor() - - onClicked: { - colorItem.updatePopupOriginalColor() - colorPopup.open(colorItem) - } - - onColorChanged: { - colorItem.envStr = colorItem.checked - ? "Color=" + color.toString() - : "Color" - colorItem.commit() - } - - function updatePopupOriginalColor() { - if (colorItem.colorIsValid) - colorPopup.originalColor = colorItem.color - } - - function update() { - colorItem.checked = envMenu.previewEnvName === "Color" - if (colorItem.checked && envMenu.previewEnvValue) { - colorItem.color = envMenu.previewEnvValue - colorItem.colorIsValid = true - } else { - colorItem.colorIsValid = false - } - } - - Connections { - target: envMenu - function onEnvParametersChanged() { - colorItem.update(); - } - } - } - - EnvMenuItem { - envName: qsTr("Studio") - envStr: "SkyBox=preview_studio" - } - - EnvMenuItem { - envName: qsTr("Landscape") - envStr: "SkyBox=preview_landscape" - } - } - - ColorEditorPopup { - id: colorPopup - - currentColor: colorItem.color - onActivateColor: (color) => colorItem.color = color - } - - component EnvMenuItem: StudioControls.MenuItemWithIcon { - required property string envName - property string envStr - - function commit() { - root.previewEnv = envStr - } - - text: envName - onClicked: commit() - checkable: false - checked: root.previewEnv === envStr - } -} diff --git a/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorToolBar.qml b/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorToolBar.qml deleted file mode 100644 index 290c84317d0..00000000000 --- a/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorToolBar.qml +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (C) 2023 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -import QtQuick -import HelperWidgets as HelperWidgets -import StudioControls as StudioControls -import StudioTheme as StudioTheme -import MaterialToolBarAction - -Rectangle { - id: root - - color: StudioTheme.Values.themeToolbarBackground - height: StudioTheme.Values.toolbarHeight - - signal toolBarAction(int action) - - Row { - id: row - spacing: StudioTheme.Values.toolbarSpacing - anchors.verticalCenter: parent.verticalCenter - leftPadding: 6 - - HelperWidgets.AbstractButton { - style: StudioTheme.Values.viewBarButtonStyle - buttonIcon: StudioTheme.Constants.apply_medium - enabled: hasMaterial && hasModelSelection && hasQuick3DImport && hasMaterialLibrary - tooltip: qsTr("Apply material to selected model.") - onClicked: root.toolBarAction(ToolBarAction.ApplyToSelected) - } - - HelperWidgets.AbstractButton { - style: StudioTheme.Values.viewBarButtonStyle - buttonIcon: StudioTheme.Constants.create_medium - enabled: hasQuick3DImport && hasMaterialLibrary - tooltip: qsTr("Create new material.") - onClicked: root.toolBarAction(ToolBarAction.AddNewMaterial) - } - - HelperWidgets.AbstractButton { - style: StudioTheme.Values.viewBarButtonStyle - buttonIcon: StudioTheme.Constants.delete_medium - enabled: hasMaterial && hasQuick3DImport && hasMaterialLibrary - tooltip: qsTr("Delete current material.") - onClicked: root.toolBarAction(ToolBarAction.DeleteCurrentMaterial) - } - - HelperWidgets.AbstractButton { - style: StudioTheme.Values.viewBarButtonStyle - buttonIcon: StudioTheme.Constants.materialBrowser_medium - enabled: hasMaterial && hasQuick3DImport && hasMaterialLibrary - tooltip: qsTr("Open material browser.") - onClicked: root.toolBarAction(ToolBarAction.OpenMaterialBrowser) - } - } -} diff --git a/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorTopSection.qml b/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorTopSection.qml deleted file mode 100644 index 1860a498b38..00000000000 --- a/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorTopSection.qml +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (C) 2023 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import HelperWidgets as HelperWidgets -import StudioControls as StudioControls -import StudioTheme as StudioTheme - -StudioControls.SplitView { - id: root - - property alias showImage: previewLoader.active - property Component previewComponent: null - - width: parent.width - implicitHeight: showImage ? previewLoader.implicitHeight + nameSection.implicitHeight : nameSection.implicitHeight - - orientation: Qt.Vertical - - Loader { - id: previewLoader - - SplitView.fillWidth: true - SplitView.minimumWidth: 152 - SplitView.preferredHeight: previewLoader.visible ? Math.min(root.width * 0.75, 400) : 0 - SplitView.minimumHeight: previewLoader.visible ? 150 : 0 - SplitView.maximumHeight: previewLoader.visible ? 600 : 0 - - visible: previewLoader.active && previewLoader.item - - sourceComponent: root.previewComponent - } - - HelperWidgets.Section { - id: nameSection - - // Section with hidden header is used so properties are aligned with the other sections' properties - hideHeader: true - SplitView.fillWidth: true - SplitView.preferredHeight: implicitHeight - SplitView.maximumHeight: implicitHeight - bottomPadding: StudioTheme.Values.sectionPadding * 2 - collapsible: false - - HelperWidgets.SectionLayout { - HelperWidgets.PropertyLabel { text: qsTr("Name") } - - HelperWidgets.SecondColumnLayout { - HelperWidgets.Spacer { implicitWidth: StudioTheme.Values.actionIndicatorWidth } - - HelperWidgets.LineEdit { - id: matName - - implicitWidth: StudioTheme.Values.singleControlColumnWidth - width: StudioTheme.Values.singleControlColumnWidth - placeholderText: qsTr("Material name") - showTranslateCheckBox: false - showExtendedFunctionButton: false - - Timer { - running: true - interval: 0 - onTriggered: matName.backendValue = backendValues.objectName - // backendValues.objectName is not available yet without the Timer - } - - // allow only alphanumeric characters, underscores, no space at start, and 1 space between words - validator: RegularExpressionValidator { regularExpression: /^(\w+\s)*\w+$/ } - } - - HelperWidgets.ExpandingSpacer {} - } - - HelperWidgets.PropertyLabel { text: qsTr("Type") } - - HelperWidgets.SecondColumnLayout { - HelperWidgets.Spacer { implicitWidth: StudioTheme.Values.actionIndicatorWidth } - - HelperWidgets.ComboBox { - currentIndex: possibleTypeIndex - model: possibleTypes - showExtendedFunctionButton: false - implicitWidth: StudioTheme.Values.singleControlColumnWidth - enabled: possibleTypes.length > 1 - - onActivated: changeTypeName(currentValue) - } - } - } - } -} diff --git a/share/qtcreator/qmldesigner/workspacePresets/Advanced-3D.wrk b/share/qtcreator/qmldesigner/workspacePresets/Advanced-3D.wrk index 030ad35677c..b0373ba5787 100644 --- a/share/qtcreator/qmldesigner/workspacePresets/Advanced-3D.wrk +++ b/share/qtcreator/qmldesigner/workspacePresets/Advanced-3D.wrk @@ -52,7 +52,6 @@ - diff --git a/share/qtcreator/qmldesigner/workspacePresets/Basic-3D.wrk b/share/qtcreator/qmldesigner/workspacePresets/Basic-3D.wrk index 5402632f784..6cb8719530d 100644 --- a/share/qtcreator/qmldesigner/workspacePresets/Basic-3D.wrk +++ b/share/qtcreator/qmldesigner/workspacePresets/Basic-3D.wrk @@ -42,7 +42,6 @@ - diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt index 32d6ba212b8..5cff1676a83 100644 --- a/src/plugins/qmldesigner/CMakeLists.txt +++ b/src/plugins/qmldesigner/CMakeLists.txt @@ -82,7 +82,6 @@ add_qtc_plugin(QmlDesigner ${CMAKE_CURRENT_LIST_DIR}/components/integration ${CMAKE_CURRENT_LIST_DIR}/components/itemlibrary ${CMAKE_CURRENT_LIST_DIR}/components/materialbrowser - ${CMAKE_CURRENT_LIST_DIR}/components/materialeditor ${CMAKE_CURRENT_LIST_DIR}/components/textureeditor ${CMAKE_CURRENT_LIST_DIR}/components/navigator ${CMAKE_CURRENT_LIST_DIR}/components/propertyeditor @@ -438,6 +437,7 @@ extend_qtc_plugin(QmlDesigner qmltexturenodeproxy.cpp qmltexturenodeproxy.h quick2propertyeditorview.cpp quick2propertyeditorview.h propertyeditorutils.cpp propertyeditorutils.h + propertyeditor.qrc ) extend_qtc_plugin(QmlDesigner @@ -461,18 +461,6 @@ extend_qtc_plugin(QmlDesigner usertexturecategory.cpp usertexturecategory.h ) -extend_qtc_plugin(QmlDesigner - SOURCES_PREFIX components/materialeditor - SOURCES - materialeditorcontextobject.cpp materialeditorcontextobject.h - materialeditordynamicpropertiesproxymodel.cpp materialeditordynamicpropertiesproxymodel.h - materialeditorimageprovider.cpp materialeditorimageprovider.h - materialeditorqmlbackend.cpp materialeditorqmlbackend.h - materialeditortransaction.cpp materialeditortransaction.h - materialeditorview.cpp materialeditorview.h - materialeditor.qrc -) - extend_qtc_plugin(QmlDesigner SOURCES_PREFIX components/textureeditor SOURCES diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp index 48b3764fd81..b82f30e104b 100644 --- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp +++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp @@ -1001,10 +1001,8 @@ void editMaterial(const SelectionContext &selectionContext) } } - if (material.isValid()) { - QmlDesignerPlugin::instance()->mainWidget()->showDockWidget("MaterialEditor", true); - Utils3D::selectMaterial(material); - } + if (material.isValid()) + Utils3D::openNodeInPropertyEditor(material); } void addItemToStackedContainer(const SelectionContext &selectionContext) diff --git a/src/plugins/qmldesigner/components/componentcore/utils3d.cpp b/src/plugins/qmldesigner/components/componentcore/utils3d.cpp index 34fab1415c7..fe16c59bd77 100644 --- a/src/plugins/qmldesigner/components/componentcore/utils3d.cpp +++ b/src/plugins/qmldesigner/components/componentcore/utils3d.cpp @@ -3,6 +3,7 @@ #include "utils3d.h" +#include #include #include #include @@ -186,14 +187,6 @@ ModelNode getMaterialOfModel(const ModelNode &model, int idx) return mat; } -void selectMaterial(const ModelNode &material) -{ - if (material.metaInfo().isQtQuick3DMaterial()) { - material.model()->rootModelNode().setAuxiliaryData(Utils3D::matLibSelectedMaterialProperty, - material.id()); - } -} - void selectTexture(const ModelNode &texture) { if (texture.metaInfo().isQtQuick3DTexture()) { @@ -202,18 +195,6 @@ void selectTexture(const ModelNode &texture) } } -ModelNode selectedMaterial(AbstractView *view) -{ - if (!view) - return {}; - - ModelNode root = view->rootModelNode(); - - if (auto selectedProperty = root.auxiliaryData(Utils3D::matLibSelectedMaterialProperty)) - return view->modelNodeForId(selectedProperty->toString()); - return {}; -} - ModelNode selectedTexture(AbstractView *view) { if (!view) @@ -597,5 +578,12 @@ void duplicateMaterial(AbstractView *view, const ModelNode &material) } } +void openNodeInPropertyEditor(const ModelNode &node) +{ + QTC_ASSERT(node, return); + QmlDesignerPlugin::instance()->mainWidget()->showDockWidget("PropertyEditor", true); + node.view()->emitCustomNotification("force_editing_node", {node}); // To PropertyEditor +} + } // namespace Utils3D } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/componentcore/utils3d.h b/src/plugins/qmldesigner/components/componentcore/utils3d.h index 3f77326e53d..e6300131011 100644 --- a/src/plugins/qmldesigner/components/componentcore/utils3d.h +++ b/src/plugins/qmldesigner/components/componentcore/utils3d.h @@ -15,8 +15,6 @@ namespace Utils3D { inline constexpr AuxiliaryDataKeyView active3dSceneProperty{AuxiliaryDataType::Temporary, "active3dScene"}; -inline constexpr AuxiliaryDataKeyView matLibSelectedMaterialProperty{AuxiliaryDataType::Temporary, - "matLibSelMat"}; inline constexpr AuxiliaryDataKeyView matLibSelectedTextureProperty{AuxiliaryDataType::Temporary, "matLibSelTex"}; @@ -35,9 +33,7 @@ ModelNode getMaterialOfModel(const ModelNode &model, int idx = 0); // These methods handle selection of material library items for various material library views. // This is separate selection from the normal selection handling. -void selectMaterial(const ModelNode &material); void selectTexture(const ModelNode &texture); -ModelNode selectedMaterial(AbstractView *view); ModelNode selectedTexture(AbstractView *view); ModelNode resolveSceneEnv(AbstractView *view, int sceneId); @@ -50,6 +46,8 @@ void applyMaterialToModels(AbstractView *view, const ModelNode &material, void assignTextureAsLightProbe(AbstractView *view, const ModelNode &texture, int sceneId); +void openNodeInPropertyEditor(const ModelNode &node); + #ifdef QDS_USE_PROJECTSTORAGE ModelNode createMaterial(AbstractView *view, const TypeName &typeName); #else diff --git a/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp b/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp index 062aefde089..4b98b5bda4f 100644 --- a/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp +++ b/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -73,7 +72,6 @@ public: , navigatorView{externalDependencies} , propertyEditorView(imageCache, externalDependencies) #ifndef QTC_USE_QML_DESIGNER_LITE - , materialEditorView{externalDependencies} , materialBrowserView{imageCache, externalDependencies} , textureEditorView{imageCache, externalDependencies} #endif @@ -103,7 +101,6 @@ public: NavigatorView navigatorView; PropertyEditorView propertyEditorView; #ifndef QTC_USE_QML_DESIGNER_LITE - MaterialEditorView materialEditorView; MaterialBrowserView materialBrowserView; TextureEditorView textureEditorView; #endif @@ -233,7 +230,6 @@ QList ViewManager::standardViews() const &d->itemLibraryView, &d->navigatorView, &d->propertyEditorView, - &d->materialEditorView, &d->materialBrowserView, &d->textureEditorView, &d->statesEditorView, @@ -460,7 +456,6 @@ QList ViewManager::widgetInfos() const widgetInfoList.append(d->navigatorView.widgetInfo()); widgetInfoList.append(d->propertyEditorView.widgetInfo()); #ifndef QTC_USE_QML_DESIGNER_LITE - widgetInfoList.append(d->materialEditorView.widgetInfo()); widgetInfoList.append(d->materialBrowserView.widgetInfo()); widgetInfoList.append(d->textureEditorView.widgetInfo()); #endif diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dmaterialsaction.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dmaterialsaction.cpp index bc2dba44a3f..0e135b5c9aa 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dmaterialsaction.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dmaterialsaction.cpp @@ -181,8 +181,7 @@ QAction *Edit3DMaterialsAction::createMaterialAction(const ModelNode &material, QAction *editMaterialAction = new QAction(tr("Edit"), menu); connect(editMaterialAction, &QAction::triggered, menu, [material] { - QmlDesignerPlugin::instance()->mainWidget()->showDockWidget("MaterialEditor", true); - Utils3D::selectMaterial(material); + Utils3D::openNodeInPropertyEditor(material); }); menu->addAction(editMaterialAction); diff --git a/src/plugins/qmldesigner/components/integration/componentview.cpp b/src/plugins/qmldesigner/components/integration/componentview.cpp index 806bdb4ee31..19b9eaf3b3b 100644 --- a/src/plugins/qmldesigner/components/integration/componentview.cpp +++ b/src/plugins/qmldesigner/components/integration/componentview.cpp @@ -185,21 +185,12 @@ void ComponentView::ensureMatLibTriggered() return; bool texSelected = Utils3D::selectedTexture(this).isValid(); - bool matSelected = Utils3D::selectedMaterial(this).isValid(); - if (!texSelected || !matSelected) { + if (!texSelected) { const QList matLibNodes = matLib.directSubModelNodes(); for (const ModelNode &node : matLibNodes) { - if (!texSelected && node.metaInfo().isQtQuick3DTexture()) { + if (node.metaInfo().isQtQuick3DTexture()) { Utils3D::selectTexture(node); - if (matSelected) - break; - texSelected = true; - } - if (!matSelected && node.metaInfo().isQtQuick3DMaterial()) { - Utils3D::selectMaterial(node); - if (texSelected) - break; - matSelected = true; + break; } } } @@ -294,9 +285,7 @@ void ComponentView::nodeIdChanged(const ModelNode& node, const QString& newId, c }; auto metaInfo = node.metaInfo(); - if (metaInfo.isQtQuick3DMaterial()) - maybeSetAuxData(Utils3D::matLibSelectedMaterialProperty); - else if (metaInfo.isQtQuick3DTexture()) + if (metaInfo.isQtQuick3DTexture()) maybeSetAuxData(Utils3D::matLibSelectedTextureProperty); } diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp index f4b0e56d30f..5f092fa9d56 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp @@ -82,7 +82,6 @@ WidgetInfo MaterialBrowserView::widgetInfo() if (m_widget.isNull()) { m_widget = new MaterialBrowserWidget(m_imageCache, this); - // custom notifications below are sent to the MaterialEditor MaterialBrowserModel *matBrowserModel = m_widget->materialBrowserModel().data(); connect(matBrowserModel, &MaterialBrowserModel::applyToSelectedTriggered, this, diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp index aa5f0a50cc9..446e028d9ab 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp @@ -78,7 +78,8 @@ public: QSize *size, [[maybe_unused]] const QSize &requestedSize) override { - static QPixmap defaultPreview = QPixmap::fromImage(QImage(":/materialeditor/images/defaultmaterialpreview.png")); + static QPixmap defaultPreview = QPixmap::fromImage( + QImage(":/propertyeditor/images/defaultmaterialpreview.png")); QPixmap pixmap{150, 150}; diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.cpp b/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.cpp deleted file mode 100644 index a27924532dd..00000000000 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.cpp +++ /dev/null @@ -1,555 +0,0 @@ -// Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "materialeditorcontextobject.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace QmlDesigner { - -MaterialEditorContextObject::MaterialEditorContextObject(QQuickWidget *widget, QObject *parent) - : QObject(parent) - , m_quickWidget(widget) -{ - qmlRegisterUncreatableType("MaterialToolBarAction", 1, 0, "ToolBarAction", "Enum type"); -} - -QQmlComponent *MaterialEditorContextObject::specificQmlComponent() -{ - if (m_specificQmlComponent) - return m_specificQmlComponent; - - m_specificQmlComponent = new QQmlComponent(m_quickWidget->rootContext()->engine(), this); - m_specificQmlComponent->setData(m_specificQmlData.toUtf8(), QUrl::fromLocalFile("specifics.qml")); - - return m_specificQmlComponent; -} - -QString MaterialEditorContextObject::convertColorToString(const QVariant &color) -{ - QString colorString; - QColor theColor; - if (color.canConvert(QMetaType(QMetaType::QColor))) { - theColor = color.value(); - } else if (color.canConvert(QMetaType(QMetaType::QVector3D))) { - auto vec = color.value(); - theColor = QColor::fromRgbF(vec.x(), vec.y(), vec.z()); - } - - colorString = theColor.name(); - - if (theColor.alpha() != 255) { - QString hexAlpha = QString("%1").arg(theColor.alpha(), 2, 16, QLatin1Char('0')); - colorString.remove(0, 1); - colorString.prepend(hexAlpha); - colorString.prepend(QStringLiteral("#")); - } - return colorString; -} - -// TODO: this method is used by the ColorEditor helper widget, check if at all needed? -QColor MaterialEditorContextObject::colorFromString(const QString &colorString) -{ - return colorString; -} - -void MaterialEditorContextObject::changeTypeName(const QString &typeName) -{ - QTC_ASSERT(m_model && m_model->rewriterView(), return); - QTC_ASSERT(m_selectedMaterial.isValid(), return); - - if (m_selectedMaterial.simplifiedTypeName() == typeName) - return; - - // Ideally we should not misuse the rewriterView - // If we add more code here we have to forward the material editor view - RewriterView *rewriterView = m_model->rewriterView(); - - rewriterView->executeInTransaction("MaterialEditorContextObject::changeTypeName", [&] { - NodeMetaInfo metaInfo = m_model->metaInfo(typeName.toLatin1()); - - QTC_ASSERT(metaInfo.isValid(), return); - - // Create a list of properties available for the new type - PropertyNameList propertiesAndSignals = Utils::transform( - metaInfo.properties(), &PropertyMetaInfo::name); - // Add signals to the list - const PropertyNameList signalNames = metaInfo.signalNames(); - for (const PropertyName &signal : signalNames) { - if (signal.isEmpty()) - continue; - - PropertyName name = signal; - QChar firstChar = QChar(signal.at(0)).toUpper().toLatin1(); - name[0] = firstChar.toLatin1(); - name.prepend("on"); - propertiesAndSignals.append(name); - } - - // Add dynamic properties and respective change signals - const QList matProps = m_selectedMaterial.properties(); - for (const auto &property : matProps) { - if (!property.isDynamic()) - continue; - - // Add dynamic property - propertiesAndSignals.append(property.name().toByteArray()); - // Add its change signal - PropertyName name = property.name().toByteArray(); - QChar firstChar = QChar(property.name().at(0)).toUpper().toLatin1(); - name[0] = firstChar.toLatin1(); - name.prepend("on"); - name.append("Changed"); - propertiesAndSignals.append(name); - } - - // Compare current properties and signals with the ones available for change type - QList incompatibleProperties; - for (const auto &property : matProps) { - if (!propertiesAndSignals.contains(property.name())) - incompatibleProperties.append(property.name().toByteArray()); - } - - // When switching between material types, copy base (diffuse) color and map properties of - // source type into corresponding properties of the target type. - const QList baseColors = {"baseColor", "diffuseColor", "albedoColor"}; - const QList baseMaps = {"baseColorMap", "diffuseMap", "albedoMap"}; - int sourceIndex = -1; - int targetIndex = -1; - NodeMetaInfo oldMetaInfo = m_selectedMaterial.metaInfo(); - struct CopyData { - CopyData() {} - CopyData(PropertyName n) : name(n) {} - PropertyName name; - QVariant value; - bool isBinding = false; - }; - QHash copyMap; - - if (oldMetaInfo.isQtQuick3DPrincipledMaterial()) - sourceIndex = 0; - else if (oldMetaInfo.isQtQuick3DDefaultMaterial()) - sourceIndex = 1; - else if (oldMetaInfo.isQtQuick3DSpecularGlossyMaterial()) - sourceIndex = 2; - - if (metaInfo.isQtQuick3DPrincipledMaterial()) - targetIndex = 0; - else if (metaInfo.isQtQuick3DDefaultMaterial()) - targetIndex = 1; - else if (metaInfo.isQtQuick3DSpecularGlossyMaterial()) - targetIndex = 2; - - if (sourceIndex >= 0 && targetIndex >= 0) { - if (incompatibleProperties.contains(baseColors[sourceIndex])) { - copyMap.insert(baseColors[sourceIndex], baseColors[targetIndex]); - incompatibleProperties.removeOne(baseColors[sourceIndex]); - } - if (incompatibleProperties.contains(baseMaps[sourceIndex])) { - copyMap.insert(baseMaps[sourceIndex], baseMaps[targetIndex]); - incompatibleProperties.removeOne(baseMaps[sourceIndex]); - } - } - const auto ©Keys = copyMap.keys(); - - Utils::sort(incompatibleProperties); - - // Create a dialog showing incompatible properties and signals - if (!incompatibleProperties.empty()) { - QString detailedText = tr("Incompatible properties:
"); - - for (const auto &p : std::as_const(incompatibleProperties)) - detailedText.append("- " + QString::fromUtf8(p) + "
"); - - detailedText.chop(QString("
").size()); - - QMessageBox msgBox; - msgBox.setTextFormat(Qt::RichText); - msgBox.setIcon(QMessageBox::Question); - msgBox.setWindowTitle(tr("Change Type")); - msgBox.setText(tr("Changing the type from %1 to %2 can't be done without removing incompatible properties.

%3") - .arg(m_selectedMaterial.simplifiedTypeName(), typeName, detailedText)); - msgBox.setInformativeText(tr("Do you want to continue by removing incompatible properties?")); - msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); - msgBox.setDefaultButton(QMessageBox::Ok); - - if (msgBox.exec() == QMessageBox::Cancel) { - updatePossibleTypeIndex(); - return; - } - - for (const auto &p : std::as_const(incompatibleProperties)) - m_selectedMaterial.removeProperty(p); - } - - if (!copyKeys.isEmpty()) { - // Copy mapped properties to new name. Note that this will only copy the base - // property value and adjust the keyframe groups. Any other bindings related - // to the property will be ignored. - const QList timeLines = QmlObjectNode(m_selectedMaterial).allTimelines(); - for (const auto &key : std::as_const(copyKeys)) { - CopyData ©Data = copyMap[key]; - for (const auto &timeLineNode : timeLines) { - QmlTimeline timeLine(timeLineNode); - if (timeLine.hasKeyframeGroup(m_selectedMaterial, key)) { - QmlTimelineKeyframeGroup group = timeLine.keyframeGroup(m_selectedMaterial, - key); - group.setPropertyName(copyData.name); - } - } - // Property value itself cannot be copied until type has been changed, so store it - AbstractProperty prop = m_selectedMaterial.property(key); - if (prop.isValid()) { - if (prop.isBindingProperty()) { - copyData.isBinding = true; - copyData.value = prop.toBindingProperty().expression(); - } else { - copyData.value = prop.toVariantProperty().value(); - } - } - m_selectedMaterial.removeProperty(key); - } - } - -#ifdef QDS_USE_PROJECTSTORAGE - if (m_selectedMaterial.isRootNode()) - rewriterView->changeRootNodeType(typeName.toUtf8(), -1, -1); - else - m_selectedMaterial.changeType(typeName.toUtf8(), -1, -1); -#else - if (m_selectedMaterial.isRootNode()) - rewriterView->changeRootNodeType(metaInfo.typeName(), metaInfo.majorVersion(), metaInfo.minorVersion()); - else - m_selectedMaterial.changeType(metaInfo.typeName(), - metaInfo.majorVersion(), - metaInfo.minorVersion()); -#endif - for (const auto &key : copyKeys) { - const CopyData ©Data = copyMap[key]; - if (copyData.isBinding) - m_selectedMaterial.bindingProperty(copyData.name).setExpression(copyData.value.toString()); - else - m_selectedMaterial.variantProperty(copyData.name).setValue(copyData.value); - } - }); -} - -void MaterialEditorContextObject::insertKeyframe(const QString &propertyName) -{ - QTC_ASSERT(m_model && m_model->rewriterView(), return); - QTC_ASSERT(m_selectedMaterial.isValid(), return); - - // Ideally we should not missuse the rewriterView - // If we add more code here we have to forward the material editor view - RewriterView *rewriterView = m_model->rewriterView(); - - QmlTimeline timeline = rewriterView->currentTimelineNode(); - - QTC_ASSERT(timeline.isValid(), return); - - rewriterView->executeInTransaction("MaterialEditorContextObject::insertKeyframe", [&] { - timeline.insertKeyframe(m_selectedMaterial, propertyName.toUtf8()); - }); -} - -int MaterialEditorContextObject::majorVersion() const -{ - return m_majorVersion; -} - -void MaterialEditorContextObject::setMajorVersion(int majorVersion) -{ - if (m_majorVersion == majorVersion) - return; - - m_majorVersion = majorVersion; - - emit majorVersionChanged(); -} - -bool MaterialEditorContextObject::hasActiveTimeline() const -{ - return m_hasActiveTimeline; -} - -void MaterialEditorContextObject::setHasActiveTimeline(bool b) -{ - if (b == m_hasActiveTimeline) - return; - - m_hasActiveTimeline = b; - emit hasActiveTimelineChanged(); -} - -bool MaterialEditorContextObject::hasQuick3DImport() const -{ - return m_hasQuick3DImport; -} - -void MaterialEditorContextObject::setHasQuick3DImport(bool b) -{ - if (b == m_hasQuick3DImport) - return; - - m_hasQuick3DImport = b; - emit hasQuick3DImportChanged(); -} - -bool MaterialEditorContextObject::hasMaterialLibrary() const -{ - return m_hasMaterialLibrary; -} - -void MaterialEditorContextObject::setHasMaterialLibrary(bool b) -{ - if (b == m_hasMaterialLibrary) - return; - - m_hasMaterialLibrary = b; - emit hasMaterialLibraryChanged(); -} - -bool MaterialEditorContextObject::isQt6Project() const -{ - return m_isQt6Project; -} - -void MaterialEditorContextObject::setIsQt6Project(bool b) -{ - if (m_isQt6Project == b) - return; - - m_isQt6Project = b; - emit isQt6ProjectChanged(); -} - -bool MaterialEditorContextObject::hasModelSelection() const -{ - return m_hasModelSelection; -} - -void MaterialEditorContextObject::setHasModelSelection(bool b) -{ - if (b == m_hasModelSelection) - return; - - m_hasModelSelection = b; - emit hasModelSelectionChanged(); -} - -void MaterialEditorContextObject::setSelectedMaterial(const ModelNode &matNode) -{ - m_selectedMaterial = matNode; -} - -void MaterialEditorContextObject::setSpecificsUrl(const QUrl &newSpecificsUrl) -{ - if (newSpecificsUrl == m_specificsUrl) - return; - - m_specificsUrl = newSpecificsUrl; - emit specificsUrlChanged(); -} - -void MaterialEditorContextObject::setSpecificQmlData(const QString &newSpecificQmlData) -{ - if (newSpecificQmlData == m_specificQmlData) - return; - - m_specificQmlData = newSpecificQmlData; - - delete m_specificQmlComponent; - m_specificQmlComponent = nullptr; - - emit specificQmlComponentChanged(); - emit specificQmlDataChanged(); -} - -void MaterialEditorContextObject::setStateName(const QString &newStateName) -{ - if (newStateName == m_stateName) - return; - - m_stateName = newStateName; - emit stateNameChanged(); -} - -void MaterialEditorContextObject::setAllStateNames(const QStringList &allStates) -{ - if (allStates == m_allStateNames) - return; - - m_allStateNames = allStates; - emit allStateNamesChanged(); -} - -void MaterialEditorContextObject::setPossibleTypes(const QStringList &types) -{ - if (types == m_possibleTypes) - return; - - m_possibleTypes = types; - emit possibleTypesChanged(); - - updatePossibleTypeIndex(); -} - -void MaterialEditorContextObject::setCurrentType(const QString &type) -{ - m_currentType = type.split('.').last(); - updatePossibleTypeIndex(); -} - -void MaterialEditorContextObject::setIsBaseState(bool newIsBaseState) -{ - if (newIsBaseState == m_isBaseState) - return; - - m_isBaseState = newIsBaseState; - emit isBaseStateChanged(); -} - -void MaterialEditorContextObject::setSelectionChanged(bool newSelectionChanged) -{ - if (newSelectionChanged == m_selectionChanged) - return; - - m_selectionChanged = newSelectionChanged; - emit selectionChangedChanged(); -} - -void MaterialEditorContextObject::setBackendValues(QQmlPropertyMap *newBackendValues) -{ - if (newBackendValues == m_backendValues) - return; - - m_backendValues = newBackendValues; - emit backendValuesChanged(); -} - -void MaterialEditorContextObject::setModel(Model *model) -{ - m_model = model; -} - -void MaterialEditorContextObject::triggerSelectionChanged() -{ - setSelectionChanged(!m_selectionChanged); -} - -void MaterialEditorContextObject::setHasAliasExport(bool hasAliasExport) -{ - if (m_aliasExport == hasAliasExport) - return; - - m_aliasExport = hasAliasExport; - emit hasAliasExportChanged(); -} - -void MaterialEditorContextObject::updatePossibleTypeIndex() -{ - int newIndex = -1; - if (!m_currentType.isEmpty()) - newIndex = m_possibleTypes.indexOf(m_currentType); - - // Emit valid possible type index change even if the index doesn't change, as currentIndex on - // QML side will change to default internally if model is updated - if (m_possibleTypeIndex != -1 || m_possibleTypeIndex != newIndex) { - m_possibleTypeIndex = newIndex; - emit possibleTypeIndexChanged(); - } -} - -void MaterialEditorContextObject::hideCursor() -{ - if (QApplication::overrideCursor()) - return; - - QApplication::setOverrideCursor(QCursor(Qt::BlankCursor)); - - if (QWidget *w = QApplication::activeWindow()) - m_lastPos = QCursor::pos(w->screen()); -} - -void MaterialEditorContextObject::restoreCursor() -{ - if (!QApplication::overrideCursor()) - return; - - QApplication::restoreOverrideCursor(); - - if (QWidget *w = QApplication::activeWindow()) - QCursor::setPos(w->screen(), m_lastPos); -} - -void MaterialEditorContextObject::holdCursorInPlace() -{ - if (!QApplication::overrideCursor()) - return; - - if (QWidget *w = QApplication::activeWindow()) - QCursor::setPos(w->screen(), m_lastPos); -} - -int MaterialEditorContextObject::devicePixelRatio() -{ - if (QWidget *w = QApplication::activeWindow()) - return w->devicePixelRatio(); - - return 1; -} - -QStringList MaterialEditorContextObject::allStatesForId(const QString &id) -{ - if (m_model && m_model->rewriterView()) { - const QmlObjectNode node = m_model->rewriterView()->modelNodeForId(id); - if (node.isValid()) - return node.allStateNames(); - } - - return {}; -} - -bool MaterialEditorContextObject::isBlocked(const QString &) const -{ - return false; -} - -void MaterialEditorContextObject::goIntoComponent() -{ - QTC_ASSERT(m_model, return); - DocumentManager::goIntoComponent(m_selectedMaterial); -} - -QRect MaterialEditorContextObject::screenRect() const -{ - if (m_quickWidget && m_quickWidget->screen()) - return m_quickWidget->screen()->availableGeometry(); - return {}; -} - -QPoint MaterialEditorContextObject::globalPos(const QPoint &point) const -{ - if (m_quickWidget) - return m_quickWidget->mapToGlobal(point); - return point; -} - -} // QmlDesigner diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.h b/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.h deleted file mode 100644 index 0ae8e1016f1..00000000000 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.h +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#pragma once - -#include -#include - -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE -class QQmlComponent; -class QQmlPropertyMap; -class QQuickWidget; -QT_END_NAMESPACE - -namespace QmlDesigner { - -class MaterialEditorContextObject : public QObject -{ - Q_OBJECT - - Q_PROPERTY(QUrl specificsUrl READ specificsUrl WRITE setSpecificsUrl NOTIFY specificsUrlChanged) - Q_PROPERTY(QString specificQmlData READ specificQmlData WRITE setSpecificQmlData NOTIFY specificQmlDataChanged) - Q_PROPERTY(QQmlComponent *specificQmlComponent READ specificQmlComponent NOTIFY specificQmlComponentChanged) - - Q_PROPERTY(QString stateName READ stateName WRITE setStateName NOTIFY stateNameChanged) - Q_PROPERTY(QStringList allStateNames READ allStateNames WRITE setAllStateNames NOTIFY allStateNamesChanged) - Q_PROPERTY(QStringList possibleTypes READ possibleTypes WRITE setPossibleTypes NOTIFY possibleTypesChanged) - Q_PROPERTY(int possibleTypeIndex READ possibleTypeIndex NOTIFY possibleTypeIndexChanged) - - Q_PROPERTY(bool isBaseState READ isBaseState WRITE setIsBaseState NOTIFY isBaseStateChanged) - Q_PROPERTY(bool selectionChanged READ selectionChanged WRITE setSelectionChanged NOTIFY selectionChangedChanged) - - Q_PROPERTY(int majorVersion READ majorVersion WRITE setMajorVersion NOTIFY majorVersionChanged) - - Q_PROPERTY(bool hasAliasExport READ hasAliasExport NOTIFY hasAliasExportChanged) - Q_PROPERTY(bool hasActiveTimeline READ hasActiveTimeline NOTIFY hasActiveTimelineChanged) - Q_PROPERTY(bool hasQuick3DImport READ hasQuick3DImport WRITE setHasQuick3DImport NOTIFY hasQuick3DImportChanged) - Q_PROPERTY(bool hasModelSelection READ hasModelSelection WRITE setHasModelSelection NOTIFY hasModelSelectionChanged) - Q_PROPERTY(bool hasMaterialLibrary READ hasMaterialLibrary WRITE setHasMaterialLibrary NOTIFY hasMaterialLibraryChanged) - Q_PROPERTY(bool isQt6Project READ isQt6Project NOTIFY isQt6ProjectChanged) - - Q_PROPERTY(QQmlPropertyMap *backendValues READ backendValues WRITE setBackendValues NOTIFY backendValuesChanged) - -public: - MaterialEditorContextObject(QQuickWidget *widget, QObject *parent = nullptr); - - QUrl specificsUrl() const { return m_specificsUrl; } - QString specificQmlData() const {return m_specificQmlData; } - QQmlComponent *specificQmlComponent(); - QString stateName() const { return m_stateName; } - QStringList allStateNames() const { return m_allStateNames; } - QStringList possibleTypes() const { return m_possibleTypes; } - int possibleTypeIndex() const { return m_possibleTypeIndex; } - - bool isBaseState() const { return m_isBaseState; } - bool selectionChanged() const { return m_selectionChanged; } - - QQmlPropertyMap *backendValues() const { return m_backendValues; } - - Q_INVOKABLE QString convertColorToString(const QVariant &color); - Q_INVOKABLE QColor colorFromString(const QString &colorString); - - Q_INVOKABLE void changeTypeName(const QString &typeName); - Q_INVOKABLE void insertKeyframe(const QString &propertyName); - - Q_INVOKABLE void hideCursor(); - Q_INVOKABLE void restoreCursor(); - Q_INVOKABLE void holdCursorInPlace(); - - Q_INVOKABLE int devicePixelRatio(); - - Q_INVOKABLE QStringList allStatesForId(const QString &id); - - Q_INVOKABLE bool isBlocked(const QString &propName) const; - Q_INVOKABLE void goIntoComponent(); - - Q_INVOKABLE QRect screenRect() const; - Q_INVOKABLE QPoint globalPos(const QPoint &point) const; - - enum ToolBarAction { - ApplyToSelected = 0, - ApplyToSelectedAdd, - AddNewMaterial, - DeleteCurrentMaterial, - OpenMaterialBrowser - }; - Q_ENUM(ToolBarAction) - - int majorVersion() const; - void setMajorVersion(int majorVersion); - - bool hasActiveTimeline() const; - void setHasActiveTimeline(bool b); - - bool hasQuick3DImport() const; - void setHasQuick3DImport(bool b); - - bool hasMaterialLibrary() const; - void setHasMaterialLibrary(bool b); - - bool isQt6Project() const; - void setIsQt6Project(bool b); - - bool hasModelSelection() const; - void setHasModelSelection(bool b); - - bool hasAliasExport() const { return m_aliasExport; } - - void setSelectedMaterial(const ModelNode &matNode); - - void setSpecificsUrl(const QUrl &newSpecificsUrl); - void setSpecificQmlData(const QString &newSpecificQmlData); - void setStateName(const QString &newStateName); - void setAllStateNames(const QStringList &allStates); - void setPossibleTypes(const QStringList &types); - void setCurrentType(const QString &type); - void setIsBaseState(bool newIsBaseState); - void setSelectionChanged(bool newSelectionChanged); - void setBackendValues(QQmlPropertyMap *newBackendValues); - void setModel(QmlDesigner::Model *model); - - void triggerSelectionChanged(); - void setHasAliasExport(bool hasAliasExport); - -signals: - void specificsUrlChanged(); - void specificQmlDataChanged(); - void specificQmlComponentChanged(); - void stateNameChanged(); - void allStateNamesChanged(); - void possibleTypesChanged(); - void possibleTypeIndexChanged(); - void isBaseStateChanged(); - void selectionChangedChanged(); - void backendValuesChanged(); - void majorVersionChanged(); - void hasAliasExportChanged(); - void hasActiveTimelineChanged(); - void hasQuick3DImportChanged(); - void hasMaterialLibraryChanged(); - void hasModelSelectionChanged(); - void isQt6ProjectChanged(); - -private: - void updatePossibleTypeIndex(); - - QUrl m_specificsUrl; - QString m_specificQmlData; - QQmlComponent *m_specificQmlComponent = nullptr; - QQuickWidget *m_quickWidget = nullptr; - - QString m_stateName; - QStringList m_allStateNames; - QStringList m_possibleTypes; - int m_possibleTypeIndex = -1; - QString m_currentType; - - int m_majorVersion = 1; - - QQmlPropertyMap *m_backendValues = nullptr; - Model *m_model = nullptr; - - QPoint m_lastPos; - - bool m_isBaseState = false; - bool m_selectionChanged = false; - bool m_aliasExport = false; - bool m_hasActiveTimeline = false; - bool m_hasQuick3DImport = false; - bool m_hasMaterialLibrary = false; - bool m_hasModelSelection = false; - bool m_isQt6Project = false; - - ModelNode m_selectedMaterial; -}; - -} // QmlDesigner diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditordynamicpropertiesproxymodel.cpp b/src/plugins/qmldesigner/components/materialeditor/materialeditordynamicpropertiesproxymodel.cpp deleted file mode 100644 index c59ca61ff1e..00000000000 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditordynamicpropertiesproxymodel.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "materialeditordynamicpropertiesproxymodel.h" - -#include - -#include - -namespace QmlDesigner { - -MaterialEditorDynamicPropertiesProxyModel::MaterialEditorDynamicPropertiesProxyModel(QObject *parent) - : DynamicPropertiesProxyModel(parent) -{ - if (MaterialEditorView::instance()) - initModel(MaterialEditorView::instance()->dynamicPropertiesModel()); -} - -void MaterialEditorDynamicPropertiesProxyModel::registerDeclarativeType() -{ - DynamicPropertiesProxyModel::registerDeclarativeType(); - qmlRegisterType("HelperWidgets", 2, 0, "MaterialEditorDynamicPropertiesModel"); -} - -} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditordynamicpropertiesproxymodel.h b/src/plugins/qmldesigner/components/materialeditor/materialeditordynamicpropertiesproxymodel.h deleted file mode 100644 index d2add25c65c..00000000000 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditordynamicpropertiesproxymodel.h +++ /dev/null @@ -1,41 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include "dynamicpropertiesproxymodel.h" - -namespace QmlDesigner { - -class MaterialEditorDynamicPropertiesProxyModel : public DynamicPropertiesProxyModel -{ - Q_OBJECT -public: - explicit MaterialEditorDynamicPropertiesProxyModel(QObject *parent = nullptr); - - static void registerDeclarativeType(); -}; - -} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorimageprovider.cpp b/src/plugins/qmldesigner/components/materialeditor/materialeditorimageprovider.cpp deleted file mode 100644 index 24d7d583ab9..00000000000 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditorimageprovider.cpp +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (C) 2024 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -#include "materialeditorimageprovider.h" - -#include "materialeditorview.h" - -#include -#include - -namespace QmlDesigner { - -MaterialEditorImageProvider::MaterialEditorImageProvider(MaterialEditorView *materialEditorView) - : QQuickImageProvider(Pixmap) - , m_delayTimer(new QTimer(this)) -{ - m_delayTimer->setInterval(500); - m_delayTimer->setSingleShot(true); - m_delayTimer->callOnTimeout([this] { - if (m_previewPixmap.size() != m_requestedSize) - emit this->requestPreview(m_requestedSize); - }); - - connect(this, - &MaterialEditorImageProvider::requestPreview, - materialEditorView, - &MaterialEditorView::handlePreviewSizeChanged); -} - -void MaterialEditorImageProvider::setPixmap(const QPixmap &pixmap) -{ - m_previewPixmap = pixmap; -} - -QPixmap MaterialEditorImageProvider::requestPixmap(const QString &id, - QSize *size, - const QSize &requestedSize) -{ - static QPixmap defaultPreview = QPixmap::fromImage( - QImage(":/materialeditor/images/defaultmaterialpreview.png")); - - QPixmap pixmap{150, 150}; - - if (id == "preview") { - if (!m_previewPixmap.isNull()) { - pixmap = m_previewPixmap; - setRequestedSize(requestedSize); - } else { - if (requestedSize.isEmpty()) - pixmap = defaultPreview; - else - pixmap = defaultPreview.scaled(requestedSize, Qt::KeepAspectRatio); - } - } else { - qWarning() << __FUNCTION__ << "Unsupported image id:" << id; - pixmap.fill(Qt::red); - } - - if (size) - *size = pixmap.size(); - - return pixmap; -} - -/*! - * \internal - * \brief Sets the requested size. If the requested size is not the same as the - * size of the m_previewPixmap, it will ask \l {MaterialEditorView} to provide - * an image with the requested size - * The requests are delayed until the requested size is stable. - */ -void MaterialEditorImageProvider::setRequestedSize(const QSize &requestedSize) -{ - if (requestedSize.isEmpty()) - return; - - m_requestedSize = requestedSize; - - if (m_previewPixmap.size() != requestedSize) - m_delayTimer->start(); -} - -} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorimageprovider.h b/src/plugins/qmldesigner/components/materialeditor/materialeditorimageprovider.h deleted file mode 100644 index 6730f418a2c..00000000000 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditorimageprovider.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (C) 2024 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#pragma once - -#include - -QT_BEGIN_NAMESPACE -class QTimer; -QT_END_NAMESPACE - -namespace QmlDesigner { - -class MaterialEditorView; - -class MaterialEditorImageProvider : public QQuickImageProvider -{ - Q_OBJECT - -public: - explicit MaterialEditorImageProvider(MaterialEditorView *materialEditorView); - - void setPixmap(const QPixmap &pixmap); - QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) override; - -signals: - void requestPreview(QSize); - -private: - void setRequestedSize(const QSize &requestedSize); - - QPixmap m_previewPixmap; - QSize m_requestedSize; - QTimer *m_delayTimer = nullptr; // Delays the preview requests -}; - -} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.cpp deleted file mode 100644 index c71ac819ca7..00000000000 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.cpp +++ /dev/null @@ -1,299 +0,0 @@ -// Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "materialeditorqmlbackend.h" - -#include "materialeditorcontextobject.h" -#include "materialeditorimageprovider.h" -#include "materialeditortransaction.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -static QObject *variantToQObject(const QVariant &value) -{ - if (value.typeId() == QMetaType::QObjectStar || value.typeId() > QMetaType::User) - return *(QObject **)value.constData(); - - return nullptr; -} - -namespace QmlDesigner { - -MaterialEditorQmlBackend::MaterialEditorQmlBackend(MaterialEditorView *materialEditor) - : m_quickWidget(Utils::makeUniqueObjectPtr()) - , m_materialEditorTransaction(std::make_unique(materialEditor)) - , m_contextObject(std::make_unique(m_quickWidget.get())) - , m_materialEditorImageProvider(new MaterialEditorImageProvider(materialEditor)) -{ - m_quickWidget->setObjectName(Constants::OBJECT_NAME_MATERIAL_EDITOR); - m_quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView); - m_quickWidget->engine()->addImportPath(PropertyEditorQmlBackend::propertyEditorResourcesPath() + "/imports"); - m_quickWidget->engine()->addImageProvider("materialEditor", m_materialEditorImageProvider); - m_contextObject->setBackendValues(&m_backendValuesPropertyMap); - m_contextObject->setModel(materialEditor->model()); - context()->setContextObject(m_contextObject.get()); - context()->setContextProperty("hasMaterial", QVariant(false)); - context()->setContextProperty("modelNodeBackend", &m_backendModelNode); - - QObject::connect(&m_backendValuesPropertyMap, &DesignerPropertyMap::valueChanged, - materialEditor, &MaterialEditorView::changeValue); -} - -MaterialEditorQmlBackend::~MaterialEditorQmlBackend() -{ -} - -PropertyName MaterialEditorQmlBackend::auxNamePostFix(PropertyNameView propertyName) -{ - return propertyName + "__AUX"; -} - -void MaterialEditorQmlBackend::createPropertyEditorValue(const QmlObjectNode &qmlObjectNode, - PropertyNameView name, - const QVariant &value, - MaterialEditorView *materialEditor) -{ - PropertyName propertyName(name.toByteArray()); - propertyName.replace('.', '_'); - auto valueObject = qobject_cast(variantToQObject(backendValuesPropertyMap().value(QString::fromUtf8(propertyName)))); - if (!valueObject) { - valueObject = new PropertyEditorValue(&backendValuesPropertyMap()); - QObject::connect(valueObject, &PropertyEditorValue::valueChanged, &backendValuesPropertyMap(), &DesignerPropertyMap::valueChanged); - QObject::connect(valueObject, &PropertyEditorValue::expressionChanged, materialEditor, &MaterialEditorView::changeExpression); - QObject::connect(valueObject, &PropertyEditorValue::exportPropertyAsAliasRequested, materialEditor, &MaterialEditorView::exportPropertyAsAlias); - QObject::connect(valueObject, &PropertyEditorValue::removeAliasExportRequested, materialEditor, &MaterialEditorView::removeAliasExport); - backendValuesPropertyMap().insert(QString::fromUtf8(propertyName), QVariant::fromValue(valueObject)); - } - valueObject->setName(name); - valueObject->setModelNode(qmlObjectNode); - - if (qmlObjectNode.propertyAffectedByCurrentState(name) && !(qmlObjectNode.modelNode().property(name).isBindingProperty())) - valueObject->setValue(qmlObjectNode.modelValue(name)); - else - valueObject->setValue(value); - - if (propertyName != "id" && qmlObjectNode.currentState().isBaseState() - && qmlObjectNode.modelNode().property(propertyName).isBindingProperty()) { - valueObject->setExpression(qmlObjectNode.modelNode().bindingProperty(propertyName).expression()); - } else { - if (qmlObjectNode.hasBindingProperty(name)) - valueObject->setExpression(qmlObjectNode.expression(name)); - else - valueObject->setExpression(qmlObjectNode.instanceValue(name).toString()); - } -} - -void MaterialEditorQmlBackend::setValue(const QmlObjectNode &, - PropertyNameView name, - const QVariant &value) -{ - // Vector*D values need to be split into their subcomponents - if (value.typeId() == QMetaType::QVector2D) { - const char *suffix[2] = {"_x", "_y"}; - auto vecValue = value.value(); - for (int i = 0; i < 2; ++i) { - PropertyName subPropName(name.size() + 2, '\0'); - subPropName.replace(0, name.size(), name); - subPropName.replace(name.size(), 2, suffix[i]); - auto propertyValue = qobject_cast(variantToQObject(m_backendValuesPropertyMap.value(QString::fromUtf8(subPropName)))); - if (propertyValue) - propertyValue->setValue(QVariant(vecValue[i])); - } - } else if (value.typeId() == QMetaType::QVector3D) { - const char *suffix[3] = {"_x", "_y", "_z"}; - auto vecValue = value.value(); - for (int i = 0; i < 3; ++i) { - PropertyName subPropName(name.size() + 2, '\0'); - subPropName.replace(0, name.size(), name); - subPropName.replace(name.size(), 2, suffix[i]); - auto propertyValue = qobject_cast(variantToQObject(m_backendValuesPropertyMap.value(QString::fromUtf8(subPropName)))); - if (propertyValue) - propertyValue->setValue(QVariant(vecValue[i])); - } - } else if (value.typeId() == QMetaType::QVector4D) { - const char *suffix[4] = {"_x", "_y", "_z", "_w"}; - auto vecValue = value.value(); - for (int i = 0; i < 4; ++i) { - PropertyName subPropName(name.size() + 2, '\0'); - subPropName.replace(0, name.size(), name); - subPropName.replace(name.size(), 2, suffix[i]); - auto propertyValue = qobject_cast( - variantToQObject(m_backendValuesPropertyMap.value(QString::fromUtf8(subPropName)))); - if (propertyValue) - propertyValue->setValue(QVariant(vecValue[i])); - } - } else { - PropertyName propertyName = name.toByteArray(); - propertyName.replace('.', '_'); - auto propertyValue = qobject_cast(variantToQObject(m_backendValuesPropertyMap.value(QString::fromUtf8(propertyName)))); - if (propertyValue) - propertyValue->setValue(value); - } -} - -void MaterialEditorQmlBackend::setExpression(PropertyNameView propName, const QString &exp) -{ - PropertyEditorValue *propertyValue = propertyValueForName(QString::fromUtf8(propName)); - if (propertyValue) - propertyValue->setExpression(exp); -} - -QQmlContext *MaterialEditorQmlBackend::context() const -{ - return m_quickWidget->rootContext(); -} - -MaterialEditorContextObject *MaterialEditorQmlBackend::contextObject() const -{ - return m_contextObject.get(); -} - -QQuickWidget *MaterialEditorQmlBackend::widget() const -{ - return m_quickWidget.get(); -} - -void MaterialEditorQmlBackend::setSource(const QUrl &url) -{ - m_quickWidget->setSource(url); -} - -QmlAnchorBindingProxy &MaterialEditorQmlBackend::backendAnchorBinding() -{ - return m_backendAnchorBinding; -} - -void MaterialEditorQmlBackend::updateMaterialPreview(const QPixmap &pixmap) -{ - m_materialEditorImageProvider->setPixmap(pixmap); - QMetaObject::invokeMethod(m_quickWidget->rootObject(), "refreshPreview"); -} - -void MaterialEditorQmlBackend::refreshBackendModel() -{ - m_backendModelNode.refresh(); -} - -DesignerPropertyMap &MaterialEditorQmlBackend::backendValuesPropertyMap() -{ - return m_backendValuesPropertyMap; -} - -MaterialEditorTransaction *MaterialEditorQmlBackend::materialEditorTransaction() const -{ - return m_materialEditorTransaction.get(); -} - -PropertyEditorValue *MaterialEditorQmlBackend::propertyValueForName(const QString &propertyName) -{ - return qobject_cast(variantToQObject(backendValuesPropertyMap().value(propertyName))); -} - -void MaterialEditorQmlBackend::setup(const QmlObjectNode &selectedMaterialNode, const QString &stateName, - const QUrl &qmlSpecificsFile, MaterialEditorView *materialEditor) -{ - if (selectedMaterialNode.isValid()) { - m_contextObject->setModel(materialEditor->model()); - - for (const auto &property : selectedMaterialNode.modelNode().metaInfo().properties()) { - createPropertyEditorValue(selectedMaterialNode, - property.name(), - selectedMaterialNode.instanceValue(property.name()), - materialEditor); - } - - // model node - m_backendModelNode.setup(selectedMaterialNode); - context()->setContextProperty("modelNodeBackend", &m_backendModelNode); - context()->setContextProperty("hasMaterial", QVariant(true)); - - // className - auto valueObject = qobject_cast(variantToQObject( - m_backendValuesPropertyMap.value(Constants::PROPERTY_EDITOR_CLASSNAME_PROPERTY))); - if (!valueObject) - valueObject = new PropertyEditorValue(&m_backendValuesPropertyMap); - valueObject->setName(Constants::PROPERTY_EDITOR_CLASSNAME_PROPERTY); - valueObject->setModelNode(selectedMaterialNode.modelNode()); - valueObject->setValue(m_backendModelNode.simplifiedTypeName()); - QObject::connect(valueObject, - &PropertyEditorValue::valueChanged, - &backendValuesPropertyMap(), - &DesignerPropertyMap::valueChanged); - m_backendValuesPropertyMap.insert(Constants::PROPERTY_EDITOR_CLASSNAME_PROPERTY, - QVariant::fromValue(valueObject)); - - // anchors - m_backendAnchorBinding.setup(selectedMaterialNode.modelNode()); - context()->setContextProperties(QVector{ - {{"anchorBackend"}, QVariant::fromValue(&m_backendAnchorBinding)}, - {{"transaction"}, QVariant::fromValue(m_materialEditorTransaction.get())}}); - - contextObject()->setSpecificsUrl(qmlSpecificsFile); - contextObject()->setStateName(stateName); - - QStringList stateNames = selectedMaterialNode.allStateNames(); - stateNames.prepend("base state"); - contextObject()->setAllStateNames(stateNames); - contextObject()->setSelectedMaterial(selectedMaterialNode); - contextObject()->setIsBaseState(selectedMaterialNode.isInBaseState()); - contextObject()->setHasAliasExport(selectedMaterialNode.isAliasExported()); - contextObject()->setHasActiveTimeline(QmlTimeline::hasActiveTimeline(selectedMaterialNode.view())); - - contextObject()->setSelectionChanged(false); - -#ifndef QDS_USE_PROJECTSTORAGE - NodeMetaInfo metaInfo = selectedMaterialNode.modelNode().metaInfo(); - contextObject()->setMajorVersion(metaInfo.isValid() ? metaInfo.majorVersion() : -1); -#endif - } else { - context()->setContextProperty("hasMaterial", QVariant(false)); - } -} - -// static -QString MaterialEditorQmlBackend::materialEditorResourcesPath() -{ -#ifdef SHARE_QML_PATH - if (Utils::qtcEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE")) - return QLatin1String(SHARE_QML_PATH) + "/materialEditorQmlSources"; -#endif - return Core::ICore::resourcePath("qmldesigner/materialEditorQmlSources").toUrlishString(); -} - -void MaterialEditorQmlBackend::emitSelectionToBeChanged() -{ - m_backendModelNode.emitSelectionToBeChanged(); -} - -void MaterialEditorQmlBackend::emitSelectionChanged() -{ - m_backendModelNode.emitSelectionChanged(); -} - -void MaterialEditorQmlBackend::setValueforAuxiliaryProperties(const QmlObjectNode &qmlObjectNode, - AuxiliaryDataKeyView key) -{ - const PropertyName propertyName = auxNamePostFix(key.name.toByteArray()); - setValue(qmlObjectNode, propertyName, qmlObjectNode.modelNode().auxiliaryDataWithDefault(key)); -} - -} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.h b/src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.h deleted file mode 100644 index 9e95e11e32b..00000000000 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.h +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#pragma once - -#include "designerpropertymap.h" -#include "qmlanchorbindingproxy.h" -#include "qmlmodelnodeproxy.h" - -#include - -#include - -#include - -class PropertyEditorValue; - -QT_BEGIN_NAMESPACE -class QQuickWidget; -QT_END_NAMESPACE - -namespace QmlDesigner { - -class MaterialEditorContextObject; -class MaterialEditorImageProvider; -class MaterialEditorTransaction; -class MaterialEditorView; - -class MaterialEditorQmlBackend -{ - Q_DISABLE_COPY(MaterialEditorQmlBackend) - -public: - MaterialEditorQmlBackend(MaterialEditorView *materialEditor); - ~MaterialEditorQmlBackend(); - - void setup(const QmlObjectNode &selectedMaterialNode, const QString &stateName, const QUrl &qmlSpecificsFile, - MaterialEditorView *materialEditor); - void setValue(const QmlObjectNode &fxObjectNode, PropertyNameView name, const QVariant &value); - void setExpression(PropertyNameView propName, const QString &exp); - - QQmlContext *context() const; - MaterialEditorContextObject *contextObject() const; - QQuickWidget *widget() const; - void setSource(const QUrl &url); - QmlAnchorBindingProxy &backendAnchorBinding(); - void updateMaterialPreview(const QPixmap &pixmap); - void refreshBackendModel(); - DesignerPropertyMap &backendValuesPropertyMap(); - MaterialEditorTransaction *materialEditorTransaction() const; - - PropertyEditorValue *propertyValueForName(const QString &propertyName); - - static QString materialEditorResourcesPath(); - - void emitSelectionToBeChanged(); - void emitSelectionChanged(); - - void setValueforAuxiliaryProperties(const QmlObjectNode &qmlObjectNode, AuxiliaryDataKeyView key); - -private: - void createPropertyEditorValue(const QmlObjectNode &qmlObjectNode, - PropertyNameView name, - const QVariant &value, - MaterialEditorView *materialEditor); - PropertyName auxNamePostFix(PropertyNameView propertyName); - - // to avoid a crash while destructing DesignerPropertyMap in the QQmlData - // this needs be destructed after m_quickWidget->engine() is destructed - DesignerPropertyMap m_backendValuesPropertyMap; - - Utils::UniqueObjectPtr m_quickWidget = nullptr; - QmlAnchorBindingProxy m_backendAnchorBinding; - QmlModelNodeProxy m_backendModelNode; - std::unique_ptr m_materialEditorTransaction; - std::unique_ptr m_contextObject; - QPointer m_materialEditorImageProvider; -}; - -} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditortransaction.cpp b/src/plugins/qmldesigner/components/materialeditor/materialeditortransaction.cpp deleted file mode 100644 index 338b1b5de2c..00000000000 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditortransaction.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "materialeditortransaction.h" - -#include - -#include - -namespace QmlDesigner { - -MaterialEditorTransaction::MaterialEditorTransaction(QmlDesigner::MaterialEditorView *materialEditor) - : QObject(materialEditor), - m_materialEditor(materialEditor) -{ -} - -void MaterialEditorTransaction::start() -{ - if (!m_materialEditor->model()) - return; - if (m_rewriterTransaction.isValid()) - m_rewriterTransaction.commit(); - m_rewriterTransaction = m_materialEditor->beginRewriterTransaction(QByteArrayLiteral("MaterialEditorTransaction::start")); - m_timerId = startTimer(10000); -} - -void MaterialEditorTransaction::end() -{ - if (m_rewriterTransaction.isValid() && m_materialEditor->model()) { - killTimer(m_timerId); - m_rewriterTransaction.commit(); - } -} - -bool MaterialEditorTransaction::active() const -{ - return m_rewriterTransaction.isValid(); -} - -void MaterialEditorTransaction::timerEvent(QTimerEvent *timerEvent) -{ - if (timerEvent->timerId() != m_timerId) - return; - killTimer(timerEvent->timerId()); - if (m_rewriterTransaction.isValid()) - m_rewriterTransaction.commit(); -} - -} // namespace QmlDesigner - diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditortransaction.h b/src/plugins/qmldesigner/components/materialeditor/materialeditortransaction.h deleted file mode 100644 index aeda758809c..00000000000 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditortransaction.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#pragma once - -#include "materialeditorview.h" -#include "rewritertransaction.h" - -namespace QmlDesigner { - -class MaterialEditorTransaction : public QObject -{ - Q_OBJECT - -public: - MaterialEditorTransaction(MaterialEditorView *materialEditor); - - Q_INVOKABLE void start(); - Q_INVOKABLE void end(); - - Q_INVOKABLE bool active() const; - -protected: - void timerEvent(QTimerEvent *event) override; - -private: - MaterialEditorView *m_materialEditor = nullptr; - RewriterTransaction m_rewriterTransaction; - int m_timerId = -1; -}; - -} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp deleted file mode 100644 index fd2758cedfd..00000000000 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp +++ /dev/null @@ -1,1233 +0,0 @@ -// Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "materialeditorview.h" - -#include "asset.h" -#include "auxiliarydataproperties.h" -#include "bindingproperty.h" -#include "designdocument.h" -#include "designmodewidget.h" -#include "dynamicpropertiesmodel.h" -#include "externaldependenciesinterface.h" -#include "materialeditorcontextobject.h" -#include "materialeditordynamicpropertiesproxymodel.h" -#include "materialeditorqmlbackend.h" -#include "materialeditortransaction.h" -#include "metainfo.h" -#include "nodeinstanceview.h" -#include "nodelistproperty.h" -#include "nodemetainfo.h" -#include "propertyeditorqmlbackend.h" -#include "propertyeditorvalue.h" -#include "qmldesignerconstants.h" -#include "qmldesignerplugin.h" -#include "qmltimeline.h" -#include -#include "variantproperty.h" -#include -#include - -#include -#include - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace QmlDesigner { - -static const char MATERIAL_EDITOR_IMAGE_REQUEST_ID[] = "MaterialEditor"; - -static bool containsTexture(const ModelNode &node) -{ - if (node.metaInfo().isQtQuick3DTexture()) - return true; - - const ModelNodes children = node.allSubModelNodes(); - for (const ModelNode &child : children) { - if (child.metaInfo().isQtQuick3DTexture()) - return true; - } - return false; -}; - -static bool isPreviewAuxiliaryKey(AuxiliaryDataKeyView key) -{ - static const QVector previewKeys = [] { - QVector previewKeys{ - materialPreviewEnvDocProperty, - materialPreviewEnvValueDocProperty, - materialPreviewModelDocProperty, - materialPreviewEnvProperty, - materialPreviewEnvValueProperty, - materialPreviewModelProperty, - }; - std::sort(previewKeys.begin(), previewKeys.end()); - return previewKeys; - }(); - return Utils::containsInSorted(previewKeys, key); -} - -MaterialEditorView::MaterialEditorView(ExternalDependenciesInterface &externalDependencies) - : AbstractView{externalDependencies} - , m_stackedWidget(new QStackedWidget) - , m_propertyComponentGenerator{PropertyEditorQmlBackend::propertyEditorResourcesPath(), model()} - , m_dynamicPropertiesModel(new DynamicPropertiesModel(true, this)) -{ - m_updateShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_F7), m_stackedWidget); - connect(m_updateShortcut, &QShortcut::activated, this, &MaterialEditorView::reloadQml); - - QmlDesignerPlugin::trackWidgetFocusTime(m_stackedWidget, Constants::EVENT_MATERIALEDITOR_TIME); - - MaterialEditorDynamicPropertiesProxyModel::registerDeclarativeType(); -} - -MaterialEditorView::~MaterialEditorView() -{ - qDeleteAll(m_qmlBackendHash); -} - -QUrl MaterialEditorView::getPaneUrl() -{ - QString panePath = MaterialEditorQmlBackend::materialEditorResourcesPath(); - if (m_selectedMaterial.isValid() && m_hasQuick3DImport - && (Utils3D::materialLibraryNode(this).isValid() || m_hasMaterialRoot)) - panePath.append("/MaterialEditorPane.qml"); - else { - panePath.append("/EmptyMaterialEditorPane.qml"); - } - - return QUrl::fromLocalFile(panePath); -} - -namespace { - -#ifdef QDS_USE_PROJECTSTORAGE -QUrl getSpecificsUrl(const NodeMetaInfos &prototypes, const SourcePathCacheInterface &pathCache) -{ - Utils::PathString specificsPath; - - for (const NodeMetaInfo &prototype : prototypes) { - auto sourceId = prototype.propertyEditorPathId(); - if (sourceId) { - auto path = pathCache.sourcePath(sourceId); - if (path.endsWith("Specifics.qml")) { - specificsPath = path; - break; - } - } - } - - return QUrl::fromLocalFile(specificsPath.toQString()); -} -#endif - -} // namespace - -// from material editor to model -void MaterialEditorView::changeValue(const QString &name) -{ - PropertyName propertyName = name.toUtf8(); - - if (propertyName.isNull() || locked() || noValidSelection() || propertyName == "id" - || propertyName == Constants::PROPERTY_EDITOR_CLASSNAME_PROPERTY) { - return; - } - - if (propertyName == "objectName") { - renameMaterial(m_selectedMaterial, m_qmlBackEnd->propertyValueForName("objectName")->value().toString()); - return; - } - - PropertyName underscoreName(propertyName); - underscoreName.replace('.', '_'); - PropertyEditorValue *value = m_qmlBackEnd->propertyValueForName(QString::fromLatin1(underscoreName)); - - if (!value) - return; - - if (propertyName.endsWith("__AUX")) { - commitAuxValueToModel(propertyName, value->value()); - return; - } - - const NodeMetaInfo metaInfo = m_selectedMaterial.metaInfo(); - - QVariant castedValue; - - if (auto property = metaInfo.property(propertyName)) { - castedValue = property.castedValue(value->value()); - } else { - qWarning() << __FUNCTION__ << propertyName << "cannot be casted (metainfo)"; - return; - } - - if (value->value().isValid() && !castedValue.isValid()) { - qWarning() << __FUNCTION__ << propertyName << "not properly casted (metainfo)"; - return; - } - - bool propertyTypeUrl = false; - - if (auto property = metaInfo.property(propertyName)) { - if (property.propertyType().isUrl()) { - // turn absolute local file paths into relative paths - propertyTypeUrl = true; - QString filePath = castedValue.toUrl().toString(); - QFileInfo fi(filePath); - if (fi.exists() && fi.isAbsolute()) { - QDir fileDir(QFileInfo(model()->fileUrl().toLocalFile()).absolutePath()); - castedValue = QUrl(fileDir.relativeFilePath(filePath)); - } - } - } - - if (name == "state" && castedValue.toString() == "base state") - castedValue = ""; - - if (castedValue.typeId() == QMetaType::QColor) { - QColor color = castedValue.value(); - QColor newColor = QColor(color.name()); - newColor.setAlpha(color.alpha()); - castedValue = QVariant(newColor); - } - - if (!value->value().isValid() || (propertyTypeUrl && value->value().toString().isEmpty())) { // reset - removePropertyFromModel(propertyName); - } else { - // QVector*D(0, 0, 0) detects as null variant though it is valid value - if (castedValue.isValid() - && (!castedValue.isNull() || castedValue.typeId() == QMetaType::QVector2D - || castedValue.typeId() == QMetaType::QVector3D - || castedValue.typeId() == QMetaType::QVector4D)) { - commitVariantValueToModel(propertyName, castedValue); - } - } - - requestPreviewRender(); -} - -static bool isTrueFalseLiteral(const QString &expression) -{ - return (expression.compare("false", Qt::CaseInsensitive) == 0) - || (expression.compare("true", Qt::CaseInsensitive) == 0); -} - -void MaterialEditorView::setupCurrentQmlBackend(const ModelNode &selectedNode, - const QUrl &qmlSpecificsFile, - const QString &specificQmlData) -{ - - QmlModelState currState = currentStateNode(); - QString currentStateName = currState.isBaseState() ? QStringLiteral("invalid state") - : currState.name(); - - QmlObjectNode qmlObjectNode{selectedNode}; - if (specificQmlData.isEmpty()) - m_qmlBackEnd->contextObject()->setSpecificQmlData(specificQmlData); - m_qmlBackEnd->setup(qmlObjectNode, currentStateName, qmlSpecificsFile, this); - m_qmlBackEnd->contextObject()->setSpecificQmlData(specificQmlData); -} - -void MaterialEditorView::setupWidget() -{ - m_qmlBackEnd->widget()->installEventFilter(this); - m_stackedWidget->setCurrentWidget(m_qmlBackEnd->widget()); - m_stackedWidget->setMinimumSize({400, 300}); -} - -void MaterialEditorView::changeExpression(const QString &propertyName) -{ - PropertyName name = propertyName.toUtf8(); - - if (name.isNull() || locked() || noValidSelection()) - return; - - executeInTransaction(__FUNCTION__, [this, name] { - PropertyName underscoreName(name); - underscoreName.replace('.', '_'); - - QmlObjectNode qmlObjectNode(m_selectedMaterial); - PropertyEditorValue *value = m_qmlBackEnd->propertyValueForName(QString::fromLatin1(underscoreName)); - - if (!value) { - qWarning() << __FUNCTION__ << "no value for " << underscoreName; - return; - } - - if (auto property = m_selectedMaterial.metaInfo().property(name)) { - auto propertyType = property.propertyType(); - if (propertyType.isColor()) { - if (QColor(value->expression().remove('"')).isValid()) { - qmlObjectNode.setVariantProperty(name, QColor(value->expression().remove('"'))); - return; - } - } else if (propertyType.isBool()) { - if (isTrueFalseLiteral(value->expression())) { - if (value->expression().compare("true", Qt::CaseInsensitive) == 0) - qmlObjectNode.setVariantProperty(name, true); - else - qmlObjectNode.setVariantProperty(name, false); - return; - } - } else if (propertyType.isInteger()) { - bool ok; - int intValue = value->expression().toInt(&ok); - if (ok) { - qmlObjectNode.setVariantProperty(name, intValue); - return; - } - } else if (propertyType.isFloat()) { - bool ok; - qreal realValue = value->expression().toDouble(&ok); - if (ok) { - qmlObjectNode.setVariantProperty(name, realValue); - return; - } - } else if (propertyType.isVariant()) { - bool ok; - qreal realValue = value->expression().toDouble(&ok); - if (ok) { - qmlObjectNode.setVariantProperty(name, realValue); - return; - } else if (isTrueFalseLiteral(value->expression())) { - if (value->expression().compare("true", Qt::CaseInsensitive) == 0) - qmlObjectNode.setVariantProperty(name, true); - else - qmlObjectNode.setVariantProperty(name, false); - return; - } - } - } - - if (value->expression().isEmpty()) { - value->resetValue(); - return; - } - - if (qmlObjectNode.expression(name) != value->expression() || !qmlObjectNode.propertyAffectedByCurrentState(name)) - qmlObjectNode.setBindingProperty(name, value->expression()); - - requestPreviewRender(); - }); // end of transaction -} - -void MaterialEditorView::exportPropertyAsAlias(const QString &name) -{ - if (name.isNull() || locked() || noValidSelection()) - return; - - executeInTransaction(__FUNCTION__, [this, name] { - const QString id = m_selectedMaterial.validId(); - QString upperCasePropertyName = name; - upperCasePropertyName.replace(0, 1, upperCasePropertyName.at(0).toUpper()); - QString aliasName = id + upperCasePropertyName; - aliasName.replace(".", ""); //remove all dots - - PropertyName propertyName = aliasName.toUtf8(); - if (rootModelNode().hasProperty(propertyName)) { - Core::AsynchronousMessageBox::warning(tr("Cannot Export Property as Alias"), - tr("Property %1 does already exist for root component.").arg(aliasName)); - return; - } - rootModelNode().bindingProperty(propertyName).setDynamicTypeNameAndExpression("alias", id + "." + name); - }); -} - -void MaterialEditorView::removeAliasExport(const QString &name) -{ - if (name.isNull() || locked() || noValidSelection()) - return; - - executeInTransaction(__FUNCTION__, [this, name] { - const QString id = m_selectedMaterial.validId(); - - const QList bindingProps = rootModelNode().bindingProperties(); - for (const BindingProperty &property : bindingProps) { - if (property.expression() == (id + "." + name)) { - rootModelNode().removeProperty(property.name()); - break; - } - } - }); -} - -bool MaterialEditorView::locked() const -{ - return m_locked; -} - -void MaterialEditorView::currentTimelineChanged(const ModelNode &) -{ - if (m_qmlBackEnd) - m_qmlBackEnd->contextObject()->setHasActiveTimeline(QmlTimeline::hasActiveTimeline(this)); -} - -void MaterialEditorView::refreshMetaInfos(const TypeIds &deletedTypeIds) -{ - m_propertyComponentGenerator.refreshMetaInfos(deletedTypeIds); -} - -DynamicPropertiesModel *MaterialEditorView::dynamicPropertiesModel() const -{ - return m_dynamicPropertiesModel; -} - -MaterialEditorView *MaterialEditorView::instance() -{ - static MaterialEditorView *s_instance = nullptr; - - if (s_instance) - return s_instance; - - const auto views = QmlDesignerPlugin::instance()->viewManager().views(); - for (auto *view : views) { - MaterialEditorView *myView = qobject_cast(view); - if (myView) - s_instance = myView; - } - - QTC_ASSERT(s_instance, return nullptr); - return s_instance; -} - -void MaterialEditorView::timerEvent(QTimerEvent *timerEvent) -{ - if (m_timerId == timerEvent->timerId()) { - if (m_selectedMaterialChanged) { - m_selectedMaterialChanged = false; - Utils3D::selectMaterial(m_newSelectedMaterial); - m_newSelectedMaterial = {}; - } else { - resetView(); - } - } -} - -void MaterialEditorView::asyncResetView() -{ - if (m_timerId) - killTimer(m_timerId); - m_timerId = startTimer(0); -} - -void MaterialEditorView::resetView() -{ - if (!model()) - return; - - m_locked = true; - - if (m_timerId) - killTimer(m_timerId); - - setupQmlBackend(); - - if (m_qmlBackEnd) { - m_qmlBackEnd->emitSelectionChanged(); - updatePossibleTypes(); - } - - QTimer::singleShot(0, this, &MaterialEditorView::requestPreviewRender); - - m_locked = false; - - if (m_timerId) - m_timerId = 0; -} - -void MaterialEditorView::handleToolBarAction(int action) -{ - QTC_ASSERT(m_hasQuick3DImport, return); - - switch (action) { - case MaterialEditorContextObject::ApplyToSelected: { - Utils3D::applyMaterialToModels(this, m_selectedMaterial, Utils3D::getSelectedModels(this)); - break; - } - - case MaterialEditorContextObject::ApplyToSelectedAdd: { - Utils3D::applyMaterialToModels(this, m_selectedMaterial, Utils3D::getSelectedModels(this), true); - break; - } - - case MaterialEditorContextObject::AddNewMaterial: { - Utils3D::createMaterial(this); - break; - } - - case MaterialEditorContextObject::DeleteCurrentMaterial: { - if (m_selectedMaterial.isValid()) { - executeInTransaction(__FUNCTION__, [&] { - m_selectedMaterial.destroy(); - }); - } - break; - } - - case MaterialEditorContextObject::OpenMaterialBrowser: { - QmlDesignerPlugin::instance()->mainWidget()->showDockWidget("MaterialBrowser", true); - break; - } - } -} - -void MaterialEditorView::handlePreviewEnvChanged(const QString &envAndValue) -{ - if (envAndValue.isEmpty() || m_initializingPreviewData) - return; - - QTC_ASSERT(m_hasQuick3DImport, return); - QTC_ASSERT(model(), return); - QTC_ASSERT(model()->nodeInstanceView(), return); - - QStringList parts = envAndValue.split('='); - QString env = parts[0]; - QString value; - if (parts.size() > 1) - value = parts[1]; - - auto renderPreviews = [this](const QString &auxEnv, const QString &auxValue) { - rootModelNode().setAuxiliaryData(materialPreviewEnvDocProperty, auxEnv); - rootModelNode().setAuxiliaryData(materialPreviewEnvProperty, auxEnv); - rootModelNode().setAuxiliaryData(materialPreviewEnvValueDocProperty, auxValue); - rootModelNode().setAuxiliaryData(materialPreviewEnvValueProperty, auxValue); - QTimer::singleShot(0, this, &MaterialEditorView::requestPreviewRender); - emitCustomNotification("refresh_material_browser", {}); - }; - - if (env == "Color") { - auto oldColorPropVal = rootModelNode().auxiliaryData(materialPreviewColorDocProperty); - QString oldColor = oldColorPropVal ? oldColorPropVal->toString() : ""; - - if (value.isEmpty()) - value = oldColor; - else - rootModelNode().setAuxiliaryData(materialPreviewColorDocProperty, value); - } - - renderPreviews(env, value); -} - -void MaterialEditorView::handlePreviewModelChanged(const QString &modelStr) -{ - if (modelStr.isEmpty() || m_initializingPreviewData) - return; - - QTC_ASSERT(m_hasQuick3DImport, return); - QTC_ASSERT(model(), return); - QTC_ASSERT(model()->nodeInstanceView(), return); - - rootModelNode().setAuxiliaryData(materialPreviewModelDocProperty, modelStr); - rootModelNode().setAuxiliaryData(materialPreviewModelProperty, modelStr); - - QTimer::singleShot(0, this, &MaterialEditorView::requestPreviewRender); - emitCustomNotification("refresh_material_browser", {}); -} - -void MaterialEditorView::handlePreviewSizeChanged(const QSizeF &size) -{ - if (m_previewSize == size.toSize()) - return; - - m_previewSize = size.toSize(); - requestPreviewRender(); -} - -MaterialEditorQmlBackend *MaterialEditorView::getQmlBackend(const QUrl &qmlFileUrl) -{ - auto qmlFileName = qmlFileUrl.toString(); - MaterialEditorQmlBackend *currentQmlBackend = m_qmlBackendHash.value(qmlFileName); - - if (!currentQmlBackend) { - currentQmlBackend = new MaterialEditorQmlBackend(this); - - m_stackedWidget->addWidget(currentQmlBackend->widget()); - m_qmlBackendHash.insert(qmlFileName, currentQmlBackend); - - currentQmlBackend->setSource(qmlFileUrl); - - QObject *rootObj = currentQmlBackend->widget()->rootObject(); - connect(rootObj, SIGNAL(toolBarAction(int)), this, SLOT(handleToolBarAction(int))); - connect(rootObj, SIGNAL(previewEnvChanged(QString)), this, SLOT(handlePreviewEnvChanged(QString))); - connect(rootObj, SIGNAL(previewModelChanged(QString)), this, SLOT(handlePreviewModelChanged(QString))); - } - - return currentQmlBackend; -} - -void MaterialEditorView::setupQmlBackend() -{ - QUrl qmlPaneUrl = getPaneUrl(); - QUrl qmlSpecificsUrl; - QString specificQmlData; - -#ifdef QDS_USE_PROJECTSTORAGE - auto selfAndPrototypes = m_selectedMaterial.metaInfo().selfAndPrototypes(); - bool isEditableComponent = m_selectedMaterial.isComponent() - && !QmlItemNode(m_selectedMaterial).isEffectItem(); - specificQmlData = m_propertyEditorComponentGenerator.create(selfAndPrototypes, isEditableComponent); - qmlSpecificsUrl = getSpecificsUrl(selfAndPrototypes, model()->pathCache()); -#else - TypeName diffClassName; - if (NodeMetaInfo metaInfo = m_selectedMaterial.metaInfo()) { - diffClassName = metaInfo.typeName(); - for (const NodeMetaInfo &metaInfo : metaInfo.selfAndPrototypes()) { - if (PropertyEditorQmlBackend::checkIfUrlExists(qmlSpecificsUrl)) - break; - qmlSpecificsUrl = PropertyEditorQmlBackend::getQmlFileUrl(metaInfo.typeName() + "Specifics", metaInfo); - diffClassName = metaInfo.typeName(); - } - - if (diffClassName != m_selectedMaterial.type()) { - specificQmlData = PropertyEditorQmlBackend::templateGeneration( - metaInfo, model()->metaInfo(diffClassName), m_selectedMaterial); - } - } -#endif - - m_qmlBackEnd = getQmlBackend(qmlPaneUrl); - setupCurrentQmlBackend(m_selectedMaterial, qmlSpecificsUrl, specificQmlData); - - setupWidget(); - - m_qmlBackEnd->contextObject()->setHasQuick3DImport(m_hasQuick3DImport); - m_qmlBackEnd->contextObject()->setHasMaterialLibrary( - Utils3D::materialLibraryNode(this).isValid()); - m_qmlBackEnd->contextObject()->setIsQt6Project(externalDependencies().isQt6Project()); - - m_dynamicPropertiesModel->setSelectedNode(m_selectedMaterial); - - initPreviewData(); - QString matType = QString::fromLatin1(m_selectedMaterial.type()); - m_qmlBackEnd->contextObject()->setCurrentType(matType); -} - -void MaterialEditorView::commitVariantValueToModel(PropertyNameView propertyName, const QVariant &value) -{ - m_locked = true; - executeInTransaction(__FUNCTION__, [&] { - QmlObjectNode(m_selectedMaterial).setVariantProperty(propertyName, value); - }); - m_locked = false; -} - -void MaterialEditorView::commitAuxValueToModel(PropertyNameView propertyName, const QVariant &value) -{ - m_locked = true; - - PropertyNameView name = propertyName; - name.chop(5); - - try { - if (value.isValid()) - m_selectedMaterial.setAuxiliaryData(AuxiliaryDataType::Document, name, value); - else - m_selectedMaterial.removeAuxiliaryData(AuxiliaryDataType::Document, name); - } - catch (const Exception &e) { - e.showException(); - } - m_locked = false; -} - -void MaterialEditorView::removePropertyFromModel(PropertyNameView propertyName) -{ - m_locked = true; - executeInTransaction(__FUNCTION__, [&] { - QmlObjectNode(m_selectedMaterial).removeProperty(propertyName); - }); - m_locked = false; -} - -bool MaterialEditorView::noValidSelection() const -{ - QTC_ASSERT(m_qmlBackEnd, return true); - return !QmlObjectNode::isValidQmlObjectNode(m_selectedMaterial); -} - -void MaterialEditorView::initPreviewData() -{ - if (model() && m_qmlBackEnd) { - auto envPropVal = rootModelNode().auxiliaryData(materialPreviewEnvDocProperty); - auto envValuePropVal = rootModelNode().auxiliaryData(materialPreviewEnvValueDocProperty); - auto modelStrPropVal = rootModelNode().auxiliaryData(materialPreviewModelDocProperty); - QString env = envPropVal ? envPropVal->toString() : ""; - QString envValue = envValuePropVal ? envValuePropVal->toString() : ""; - QString modelStr = modelStrPropVal ? modelStrPropVal->toString() : ""; - // Initialize corresponding instance aux values used by puppet - QTimer::singleShot(0, this, [this, env, envValue, modelStr]() { - if (model()) { - rootModelNode().setAuxiliaryData(materialPreviewEnvProperty, env); - rootModelNode().setAuxiliaryData(materialPreviewEnvValueProperty, envValue); - rootModelNode().setAuxiliaryData(materialPreviewModelProperty, modelStr); - } - }); - - if (!envValue.isEmpty() && env != "Basic") { - env += '='; - env += envValue; - } - if (env.isEmpty()) - env = "SkyBox=preview_studio"; - if (modelStr.isEmpty()) - modelStr = "#Sphere"; - m_initializingPreviewData = true; - QMetaObject::invokeMethod(m_qmlBackEnd->widget()->rootObject(), - "initPreviewData", - Q_ARG(QVariant, env), Q_ARG(QVariant, modelStr)); - m_initializingPreviewData = false; - } -} - -void MaterialEditorView::updatePossibleTypes() -{ - QTC_ASSERT(model(), return); - - if (!m_qmlBackEnd) - return; - - static const QStringList basicTypes{ - "CustomMaterial", - "DefaultMaterial", - "PrincipledMaterial", - "SpecularGlossyMaterial", - }; - - const QString matType = m_selectedMaterial.simplifiedTypeName(); - - if (basicTypes.contains(matType)) { - m_qmlBackEnd->contextObject()->setPossibleTypes(basicTypes); - return; - } - - m_qmlBackEnd->contextObject()->setPossibleTypes({matType}); -} - -void MaterialEditorView::modelAttached(Model *model) -{ - AbstractView::modelAttached(model); - - if constexpr (useProjectStorage()) - m_propertyComponentGenerator.setModel(model); - - m_locked = true; - - m_hasQuick3DImport = model->hasImport("QtQuick3D"); - m_hasMaterialRoot = rootModelNode().metaInfo().isQtQuick3DMaterial(); - - if (m_hasMaterialRoot) - m_selectedMaterial = rootModelNode(); - else if (m_hasQuick3DImport) - m_selectedMaterial = Utils3D::selectedMaterial(this); - - if (!m_setupCompleted) { - reloadQml(); - m_setupCompleted = true; - } - resetView(); - - selectedNodesChanged(selectedModelNodes(), {}); - - m_locked = false; -} - -void MaterialEditorView::modelAboutToBeDetached(Model *model) -{ - AbstractView::modelAboutToBeDetached(model); - m_dynamicPropertiesModel->reset(); - if (m_qmlBackEnd) { - if (auto transaction = m_qmlBackEnd->materialEditorTransaction()) - transaction->end(); - m_qmlBackEnd->contextObject()->setHasMaterialLibrary(false); - } - m_selectedMaterial = {}; -} - -void MaterialEditorView::propertiesRemoved(const QList &propertyList) -{ - if (noValidSelection()) - return; - - bool changed = false; - for (const AbstractProperty &property : propertyList) { - ModelNode node(property.parentModelNode()); - - if (node.isRootNode()) - m_qmlBackEnd->contextObject()->setHasAliasExport(QmlObjectNode(m_selectedMaterial).isAliasExported()); - - if (node == m_selectedMaterial || QmlObjectNode(m_selectedMaterial).propertyChangeForCurrentState() == node) { - m_locked = true; - - const PropertyName propertyName = property.name().toByteArray(); - PropertyName convertedpropertyName = propertyName; - - convertedpropertyName.replace('.', '_'); - - PropertyEditorValue *value = m_qmlBackEnd->propertyValueForName( - QString::fromUtf8(convertedpropertyName)); - - if (value) { - value->resetValue(); - m_qmlBackEnd - ->setValue(m_selectedMaterial, - propertyName, - QmlObjectNode(m_selectedMaterial).instanceValue(propertyName)); - } - m_locked = false; - changed = true; - } - - dynamicPropertiesModel()->dispatchPropertyChanges(property); - } - if (changed) - requestPreviewRender(); -} - -void MaterialEditorView::variantPropertiesChanged(const QList &propertyList, PropertyChangeFlags /*propertyChange*/) -{ - if (noValidSelection()) - return; - - bool changed = false; - for (const VariantProperty &property : propertyList) { - ModelNode node(property.parentModelNode()); - if (node == m_selectedMaterial || QmlObjectNode(m_selectedMaterial).propertyChangeForCurrentState() == node) { - if (property.isDynamic()) - m_dynamicPropertiesModel->updateItem(property); - if (m_selectedMaterial.property(property.name()).isBindingProperty()) - setValue(m_selectedMaterial, property.name(), QmlObjectNode(m_selectedMaterial).instanceValue(property.name())); - else - setValue(m_selectedMaterial, property.name(), QmlObjectNode(m_selectedMaterial).modelValue(property.name())); - - changed = true; - } - - if (!changed && node.metaInfo().isQtQuick3DTexture() - && m_selectedMaterial.bindingProperties().size() > 0) { - // update preview when editing texture properties if the material has binding properties - changed = true; - } - - dynamicPropertiesModel()->dispatchPropertyChanges(property); - } - if (changed) - requestPreviewRender(); -} - -void MaterialEditorView::bindingPropertiesChanged(const QList &propertyList, PropertyChangeFlags /*propertyChange*/) -{ - if (noValidSelection()) - return; - - bool changed = false; - for (const BindingProperty &property : propertyList) { - ModelNode node(property.parentModelNode()); - - if (property.isAliasExport()) - m_qmlBackEnd->contextObject()->setHasAliasExport(QmlObjectNode(m_selectedMaterial).isAliasExported()); - - if (node == m_selectedMaterial || QmlObjectNode(m_selectedMaterial).propertyChangeForCurrentState() == node) { - if (property.isDynamic()) - m_dynamicPropertiesModel->updateItem(property); - m_locked = true; - QString exp = QmlObjectNode(m_selectedMaterial).bindingProperty(property.name()).expression(); - m_qmlBackEnd->setExpression(property.name(), exp); - m_locked = false; - changed = true; - } - - dynamicPropertiesModel()->dispatchPropertyChanges(property); - } - if (changed) - requestPreviewRender(); -} - -void MaterialEditorView::auxiliaryDataChanged(const ModelNode &node, - AuxiliaryDataKeyView key, - const QVariant &) -{ - if (!noValidSelection() && node.isSelected()) - m_qmlBackEnd->setValueforAuxiliaryProperties(m_selectedMaterial, key); - - if (!m_hasMaterialRoot) { - if (key == Utils3D::matLibSelectedMaterialProperty) { - if (ModelNode selNode = Utils3D::selectedMaterial(this)) { - m_selectedMaterial = selNode; - m_dynamicPropertiesModel->setSelectedNode(m_selectedMaterial); - asyncResetView(); - } - } else if (isPreviewAuxiliaryKey(key)) { - QTimer::singleShot(0, this, &MaterialEditorView::initPreviewData); - } - } -} - -void MaterialEditorView::propertiesAboutToBeRemoved(const QList &propertyList) -{ - for (const auto &property : propertyList) - m_dynamicPropertiesModel->removeItem(property); -} - -// request render image for the selected material node -void MaterialEditorView::requestPreviewRender() -{ - if (model() && model()->nodeInstanceView() && m_selectedMaterial.isValid()) { - static int requestId = 0; - m_previewRequestId = QByteArray(MATERIAL_EDITOR_IMAGE_REQUEST_ID) - + QByteArray::number(++requestId); - - model()->sendCustomNotificationToNodeInstanceView( - NodePreviewImage{m_selectedMaterial, {}, m_previewSize, m_previewRequestId}); - } -} - -bool MaterialEditorView::hasWidget() const -{ - return true; -} - -WidgetInfo MaterialEditorView::widgetInfo() -{ - return createWidgetInfo(m_stackedWidget, - "MaterialEditor", - WidgetInfo::RightPane, - tr("Material Editor"), - tr("Material Editor view")); -} - -void MaterialEditorView::selectedNodesChanged([[maybe_unused]] const QList &selectedNodeList, - [[maybe_unused]] const QList &lastSelectedNodeList) -{ - if (m_qmlBackEnd) - m_qmlBackEnd->contextObject()->setHasModelSelection(!Utils3D::getSelectedModels(this).isEmpty()); -} - -void MaterialEditorView::currentStateChanged(const ModelNode &node) -{ - QmlModelState newQmlModelState(node); - Q_ASSERT(newQmlModelState.isValid()); - - resetView(); -} - -void MaterialEditorView::instancePropertyChanged(const QList > &propertyList) -{ - if (!m_selectedMaterial.isValid() || !m_qmlBackEnd) - return; - - m_locked = true; - - bool changed = false; - for (const QPair &propertyPair : propertyList) { - const ModelNode modelNode = propertyPair.first; - const QmlObjectNode qmlObjectNode(modelNode); - const PropertyName propertyName = propertyPair.second; - - if (qmlObjectNode.isValid() && modelNode == m_selectedMaterial && qmlObjectNode.currentState().isValid()) { - const AbstractProperty property = modelNode.property(propertyName); - if (!modelNode.hasProperty(propertyName) || modelNode.property(property.name()).isBindingProperty()) - setValue(modelNode, property.name(), qmlObjectNode.instanceValue(property.name())); - else - setValue(modelNode, property.name(), qmlObjectNode.modelValue(property.name())); - changed = true; - } - } - if (changed) - requestPreviewRender(); - - m_locked = false; -} - -void MaterialEditorView::nodeTypeChanged(const ModelNode &node, const TypeName &typeName, int, int) -{ - if (node == m_selectedMaterial) { - m_qmlBackEnd->contextObject()->setCurrentType(QString::fromLatin1(typeName)); - resetView(); - } -} - -void MaterialEditorView::rootNodeTypeChanged(const QString &type, int, int) -{ - if (rootModelNode() == m_selectedMaterial) { - m_qmlBackEnd->contextObject()->setCurrentType(type); - resetView(); - } -} - -void MaterialEditorView::modelNodePreviewPixmapChanged(const ModelNode &node, - const QPixmap &pixmap, - const QByteArray &requestId) -{ - if (!m_qmlBackEnd || node != m_selectedMaterial || requestId != m_previewRequestId) - return; - - m_qmlBackEnd->updateMaterialPreview(pixmap); -} - -void MaterialEditorView::importsChanged([[maybe_unused]] const Imports &addedImports, - [[maybe_unused]] const Imports &removedImports) -{ - m_hasQuick3DImport = model()->hasImport("QtQuick3D"); - if (m_qmlBackEnd) - m_qmlBackEnd->contextObject()->setHasQuick3DImport(m_hasQuick3DImport); - - resetView(); -} - -void MaterialEditorView::renameMaterial(ModelNode &material, const QString &newName) -{ - QTC_ASSERT(material.isValid(), return); - QmlObjectNode(material).setNameAndId(newName, "material"); -} - -void MaterialEditorView::duplicateMaterial(const ModelNode &material) -{ - QTC_ASSERT(material.isValid() && model(), return); - - TypeName matType = material.type(); - QmlObjectNode sourceMat(material); - ModelNode duplicateMatNode; - QList dynamicProps; - - executeInTransaction(__FUNCTION__, [&] { - ModelNode matLib = Utils3D::materialLibraryNode(this); - QTC_ASSERT(matLib.isValid(), return); - - // create the duplicate material -#ifdef QDS_USE_PROJECTSTORAGE - QmlObjectNode duplicateMat = createModelNode(matType); -#else - NodeMetaInfo metaInfo = model()->metaInfo(matType); - QmlObjectNode duplicateMat = createModelNode(matType, metaInfo.majorVersion(), metaInfo.minorVersion()); -#endif - duplicateMatNode = duplicateMat.modelNode(); - - // generate and set a unique name - QString newName = sourceMat.modelNode().variantProperty("objectName").value().toString(); - if (!newName.contains("copy", Qt::CaseInsensitive)) - newName.append(" copy"); - - const QList mats = matLib.directSubModelNodesOfType(model()->qtQuick3DMaterialMetaInfo()); - QStringList matNames; - for (const ModelNode &mat : mats) - matNames.append(mat.variantProperty("objectName").value().toString()); - - newName = UniqueName::generate(newName, [&] (const QString &name) { - return matNames.contains(name); - }); - - VariantProperty objNameProp = duplicateMatNode.variantProperty("objectName"); - objNameProp.setValue(newName); - - // generate and set an id - duplicateMatNode.setIdWithoutRefactoring(model()->generateNewId(newName, "material")); - - // sync properties. Only the base state is duplicated. - const QList props = material.properties(); - for (const AbstractProperty &prop : props) { - if (prop.name() == "objectName" || prop.name() == "data") - continue; - - if (prop.isVariantProperty()) { - if (prop.isDynamic()) { - dynamicProps.append(prop); - } else { - VariantProperty variantProp = duplicateMatNode.variantProperty(prop.name()); - variantProp.setValue(prop.toVariantProperty().value()); - } - } else if (prop.isBindingProperty()) { - if (prop.isDynamic()) { - dynamicProps.append(prop); - } else { - BindingProperty bindingProp = duplicateMatNode.bindingProperty(prop.name()); - bindingProp.setExpression(prop.toBindingProperty().expression()); - } - } - } - - matLib.defaultNodeListProperty().reparentHere(duplicateMat); - }); - - // For some reason, creating dynamic properties in the same transaction doesn't work, so - // let's do it in separate transaction. - // TODO: Fix the issue and merge transactions (QDS-8094) - if (!dynamicProps.isEmpty()) { - executeInTransaction(__FUNCTION__, [&] { - for (const AbstractProperty &prop : std::as_const(dynamicProps)) { - if (prop.isVariantProperty()) { - VariantProperty variantProp = duplicateMatNode.variantProperty(prop.name()); - variantProp.setDynamicTypeNameAndValue(prop.dynamicTypeName(), - prop.toVariantProperty().value()); - } else if (prop.isBindingProperty()) { - BindingProperty bindingProp = duplicateMatNode.bindingProperty(prop.name()); - bindingProp.setDynamicTypeNameAndExpression(prop.dynamicTypeName(), - prop.toBindingProperty().expression()); - } - } - }); - } -} - -void MaterialEditorView::nodeReparented(const ModelNode &node, - [[maybe_unused]] const NodeAbstractProperty &newPropertyParent, - [[maybe_unused]] const NodeAbstractProperty &oldPropertyParent, - [[maybe_unused]] PropertyChangeFlags propertyChange) -{ - if (node.id() == Constants::MATERIAL_LIB_ID && m_qmlBackEnd && m_qmlBackEnd->contextObject()) { - m_qmlBackEnd->contextObject()->setHasMaterialLibrary(true); - asyncResetView(); - } else { - if (!m_selectedMaterial && node.metaInfo().isQtQuick3DMaterial() - && node.parentProperty().parentModelNode() == Utils3D::materialLibraryNode(this)) { - ModelNode currentSelection = Utils3D::selectedMaterial(this); - if (currentSelection) { - m_selectedMaterial = currentSelection; - asyncResetView(); - } else { - QTimer::singleShot(0, this, [node]() { - Utils3D::selectMaterial(node); - }); - } - } - - if (m_qmlBackEnd && containsTexture(node)) - m_qmlBackEnd->refreshBackendModel(); - } -} - -void MaterialEditorView::nodeIdChanged(const ModelNode &node, - [[maybe_unused]] const QString &newId, - [[maybe_unused]] const QString &oldId) -{ - if (m_qmlBackEnd && node.metaInfo().isQtQuick3DTexture()) - m_qmlBackEnd->refreshBackendModel(); -} - -void MaterialEditorView::nodeAboutToBeRemoved(const ModelNode &removedNode) -{ - if (removedNode.id() == Constants::MATERIAL_LIB_ID && m_qmlBackEnd && m_qmlBackEnd->contextObject()) { - m_selectedMaterial = {}; - m_qmlBackEnd->contextObject()->setHasMaterialLibrary(false); - asyncResetView(); - } else { - if (removedNode == m_selectedMaterial) { - ModelNode matLib = Utils3D::materialLibraryNode(this); - QTC_ASSERT(matLib.isValid(), return); - - const QList mats = matLib.directSubModelNodesOfType( - model()->qtQuick3DMaterialMetaInfo()); - bool selectedNodeFound = false; - m_newSelectedMaterial = {}; - for (const ModelNode &mat : mats) { - if (selectedNodeFound) { - m_newSelectedMaterial = mat; - break; - } - if (m_selectedMaterial == mat) - selectedNodeFound = true; - else - m_newSelectedMaterial = mat; - } - m_selectedMaterialChanged = true; - } - - if (containsTexture(removedNode)) - m_textureAboutToBeRemoved = true; - } -} - -void MaterialEditorView::nodeRemoved([[maybe_unused]] const ModelNode &removedNode, - [[maybe_unused]] const NodeAbstractProperty &parentProperty, - [[maybe_unused]] PropertyChangeFlags propertyChange) -{ - if (m_qmlBackEnd && m_textureAboutToBeRemoved) - m_qmlBackEnd->refreshBackendModel(); - - m_textureAboutToBeRemoved = false; - - if (m_selectedMaterialChanged) - asyncResetView(); -} - -void MaterialEditorView::highlightSupportedProperties(bool highlight) -{ - if (!m_selectedMaterial.isValid()) - return; - - DesignerPropertyMap &propMap = m_qmlBackEnd->backendValuesPropertyMap(); - const QStringList propNames = propMap.keys(); - NodeMetaInfo metaInfo = m_selectedMaterial.metaInfo(); - QTC_ASSERT(metaInfo.isValid(), return); - - for (const QString &propName : propNames) { - if (metaInfo.property(propName.toUtf8()).propertyType().isQtQuick3DTexture()) { - QObject *propEditorValObj = propMap.value(propName).value(); - PropertyEditorValue *propEditorVal = qobject_cast(propEditorValObj); - propEditorVal->setHasActiveDrag(highlight); - } - } -} - -void MaterialEditorView::dragStarted(QMimeData *mimeData) -{ - if (mimeData->hasFormat(Constants::MIME_TYPE_ASSETS)) { - const QString assetPath = QString::fromUtf8(mimeData->data(Constants::MIME_TYPE_ASSETS)).split(',')[0]; - Asset asset(assetPath); - - if (!asset.isValidTextureSource()) // currently only image assets have dnd-supported properties - return; - - highlightSupportedProperties(); - } else if (mimeData->hasFormat(Constants::MIME_TYPE_TEXTURE) - || mimeData->hasFormat(Constants::MIME_TYPE_BUNDLE_TEXTURE)) { - highlightSupportedProperties(); - } -} - -void MaterialEditorView::dragEnded() -{ - highlightSupportedProperties(false); -} - -// from model to material editor -void MaterialEditorView::setValue(const QmlObjectNode &qmlObjectNode, - PropertyNameView name, - const QVariant &value) -{ - m_locked = true; - m_qmlBackEnd->setValue(qmlObjectNode, name, value); - m_locked = false; -} - -bool MaterialEditorView::eventFilter(QObject *obj, QEvent *event) -{ - if (event->type() == QEvent::FocusOut) { - if (m_qmlBackEnd && m_qmlBackEnd->widget() == obj) - QMetaObject::invokeMethod(m_qmlBackEnd->widget()->rootObject(), "closeContextMenu"); - } - return AbstractView::eventFilter(obj, event); -} - -void MaterialEditorView::reloadQml() -{ - m_qmlBackendHash.clear(); - while (QWidget *widget = m_stackedWidget->widget(0)) { - m_stackedWidget->removeWidget(widget); - delete widget; - } - m_qmlBackEnd = nullptr; - - resetView(); -} - -} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.h b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.h deleted file mode 100644 index b51eeede3bd..00000000000 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.h +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#pragma once - -#include - -#include - -#include -#include -#include - -QT_BEGIN_NAMESPACE -class QShortcut; -class QStackedWidget; -class QUrl; -QT_END_NAMESPACE - -namespace QmlDesigner { - -class DynamicPropertiesModel; -class ItemLibraryInfo; -class MaterialEditorQmlBackend; -class QmlObjectNode; -class SourcePathCacheInterface; - -class MaterialEditorView : public AbstractView -{ - Q_OBJECT - -public: - MaterialEditorView(ExternalDependenciesInterface &externalDependencies); - ~MaterialEditorView() override; - - bool hasWidget() const override; - WidgetInfo widgetInfo() override; - - void selectedNodesChanged(const QList &selectedNodeList, - const QList &lastSelectedNodeList) override; - - void propertiesRemoved(const QList &propertyList) override; - - void modelAttached(Model *model) override; - void modelAboutToBeDetached(Model *model) override; - - void variantPropertiesChanged(const QList &propertyList, PropertyChangeFlags propertyChange) override; - void bindingPropertiesChanged(const QList &propertyList, PropertyChangeFlags propertyChange) override; - void auxiliaryDataChanged(const ModelNode &node, - AuxiliaryDataKeyView key, - const QVariant &data) override; - void propertiesAboutToBeRemoved(const QList &propertyList) override; - - void resetView(); - void currentStateChanged(const ModelNode &node) override; - void instancePropertyChanged(const QList > &propertyList) override; - - void nodeTypeChanged(const ModelNode& node, const TypeName &type, int majorVersion, int minorVersion) override; - void rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion) override; - void modelNodePreviewPixmapChanged(const ModelNode &node, - const QPixmap &pixmap, - const QByteArray &requestId) override; - void importsChanged(const Imports &addedImports, const Imports &removedImports) override; - - void nodeReparented(const ModelNode &node, - const NodeAbstractProperty &newPropertyParent, - const NodeAbstractProperty &oldPropertyParent, - AbstractView::PropertyChangeFlags propertyChange) override; - - void nodeIdChanged(const ModelNode &node, const QString &newId, const QString &oldId) override; - void nodeAboutToBeRemoved(const ModelNode &removedNode) override; - void nodeRemoved(const ModelNode &removedNode, - const NodeAbstractProperty &parentProperty, - PropertyChangeFlags propertyChange) override; - - void dragStarted(QMimeData *mimeData) override; - void dragEnded() override; - - void changeValue(const QString &name); - void changeExpression(const QString &name); - void exportPropertyAsAlias(const QString &name); - void removeAliasExport(const QString &name); - - bool locked() const; - - void currentTimelineChanged(const ModelNode &node) override; - - void refreshMetaInfos(const TypeIds &deletedTypeIds) override; - - DynamicPropertiesModel *dynamicPropertiesModel() const; - - static MaterialEditorView *instance(); - -public slots: - void handleToolBarAction(int action); - void handlePreviewEnvChanged(const QString &envAndValue); - void handlePreviewModelChanged(const QString &modelStr); - void handlePreviewSizeChanged(const QSizeF &size); - -protected: - void timerEvent(QTimerEvent *event) override; - void setValue(const QmlObjectNode &fxObjectNode, PropertyNameView name, const QVariant &value); - bool eventFilter(QObject *obj, QEvent *event) override; - -private: - void reloadQml(); - void highlightSupportedProperties(bool highlight = true); - - void requestPreviewRender(); - - void setupQmlBackend(); - MaterialEditorQmlBackend *getQmlBackend(const QUrl &qmlFileUrl); - QUrl getPaneUrl(); - void setupCurrentQmlBackend(const ModelNode &selectedNode, - const QUrl &qmlSpecificsFile, - const QString &specificQmlData); - void setupWidget(); - - void commitVariantValueToModel(PropertyNameView propertyName, const QVariant &value); - void commitAuxValueToModel(PropertyNameView propertyName, const QVariant &value); - void removePropertyFromModel(PropertyNameView propertyName); - void renameMaterial(ModelNode &material, const QString &newName); - void duplicateMaterial(const ModelNode &material); - - bool noValidSelection() const; - - void initPreviewData(); - void updatePossibleTypes(); - void asyncResetView(); - - ModelNode m_selectedMaterial; - QShortcut *m_updateShortcut = nullptr; - int m_timerId = 0; - QStackedWidget *m_stackedWidget = nullptr; - QHash m_qmlBackendHash; - MaterialEditorQmlBackend *m_qmlBackEnd = nullptr; - PropertyComponentGenerator m_propertyComponentGenerator; - PropertyEditorComponentGenerator m_propertyEditorComponentGenerator{m_propertyComponentGenerator}; - bool m_locked = false; - bool m_setupCompleted = false; - bool m_hasQuick3DImport = false; - bool m_hasMaterialRoot = false; - bool m_initializingPreviewData = false; - bool m_textureAboutToBeRemoved = false; - ModelNode m_newSelectedMaterial; - bool m_selectedMaterialChanged = false; - QSize m_previewSize; - QByteArray m_previewRequestId; - - QPointer m_itemLibraryInfo; - DynamicPropertiesModel *m_dynamicPropertiesModel = nullptr; -}; - -} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/materialeditor/images/defaultmaterialpreview.png b/src/plugins/qmldesigner/components/propertyeditor/images/defaultmaterialpreview.png similarity index 100% rename from src/plugins/qmldesigner/components/materialeditor/images/defaultmaterialpreview.png rename to src/plugins/qmldesigner/components/propertyeditor/images/defaultmaterialpreview.png diff --git a/src/plugins/qmldesigner/components/propertyeditor/instanceimageprovider.cpp b/src/plugins/qmldesigner/components/propertyeditor/instanceimageprovider.cpp index eba1d90b0d1..6b7cc4084ec 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/instanceimageprovider.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/instanceimageprovider.cpp @@ -32,7 +32,7 @@ QPixmap InstanceImageProvider::requestPixmap(const QString &id, QSize *size, con { using namespace Qt::StringLiterals; static const QPixmap defaultImage = QPixmap::fromImage( - QImage(":/materialeditor/images/defaultmaterialpreview.png")); + QImage(":/propertyeditor/images/defaultmaterialpreview.png")); if (id != "preview") return defaultImage; diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditor.qrc b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.qrc similarity index 67% rename from src/plugins/qmldesigner/components/materialeditor/materialeditor.qrc rename to src/plugins/qmldesigner/components/propertyeditor/propertyeditor.qrc index 4ed3c769175..cd74e356c6d 100644 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditor.qrc +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.qrc @@ -1,5 +1,5 @@ - + images/defaultmaterialpreview.png diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp index db6921b35b5..cec544b7f72 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp @@ -1160,6 +1160,18 @@ void PropertyEditorView::setActiveNodeToSelection() setActiveNode(node); } +void PropertyEditorView::forceSelection(const ModelNode &node) +{ + if (node == activeNode()) + return; + + if (m_isSelectionLocked) + setActiveNode(node); + ModelNode(node).selectNode(); + + resetView(); +} + bool PropertyEditorView::hasWidget() const { return true; @@ -1260,6 +1272,17 @@ void PropertyEditorView::importsChanged(const Imports &addedImports, const Impor m_qmlBackEndForCurrentType->contextObject()->setHasQuick3DImport(true); } +void PropertyEditorView::customNotification([[maybe_unused]] const AbstractView *view, + const QString &identifier, + const QList &nodeList, + [[maybe_unused]] const QList &data) +{ + if (identifier == "force_editing_node") { + if (!nodeList.isEmpty()) + forceSelection(nodeList.first()); + } +} + void PropertyEditorView::modelNodePreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap, const QByteArray &requestId) diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h index 65773ec6f87..7ee189ce23d 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h @@ -83,6 +83,10 @@ public: const QByteArray &requestId) override; void importsChanged(const Imports &addedImports, const Imports &removedImports) override; + void customNotification(const AbstractView *view, + const QString &identifier, + const QList &nodeList, + const QList &data) override; void dragStarted(QMimeData *mimeData) override; void dragEnded() override; @@ -123,6 +127,7 @@ private: //functions void select(); void setActiveNodeToSelection(); + void forceSelection(const ModelNode &node); void delayedResetView(); void setupQmlBackend(); diff --git a/src/plugins/qmldesigner/components/textureeditor/textureeditortransaction.cpp b/src/plugins/qmldesigner/components/textureeditor/textureeditortransaction.cpp index 391d22536e7..bd50f8dec97 100644 --- a/src/plugins/qmldesigner/components/textureeditor/textureeditortransaction.cpp +++ b/src/plugins/qmldesigner/components/textureeditor/textureeditortransaction.cpp @@ -19,7 +19,8 @@ void TextureEditorTransaction::start() return; if (m_rewriterTransaction.isValid()) m_rewriterTransaction.commit(); - m_rewriterTransaction = m_textureEditor->beginRewriterTransaction(QByteArrayLiteral("MaterialEditorTransaction::start")); + m_rewriterTransaction = m_textureEditor->beginRewriterTransaction( + QByteArrayLiteral("TextureEditorTransaction::start")); m_timerId = startTimer(10000); } diff --git a/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp b/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp index a3d4bf75500..c3125b3e0d5 100644 --- a/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp +++ b/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp @@ -559,9 +559,8 @@ void TextureEditorView::commitAuxValueToModel(PropertyNameView propertyName, con void TextureEditorView::removePropertyFromModel(PropertyNameView propertyName) { m_locked = true; - executeInTransaction("MaterialEditorView:removePropertyFromModel", [&] { - QmlObjectNode(m_selectedTexture).removeProperty(propertyName); - }); + executeInTransaction(__FUNCTION__, + [&] { QmlObjectNode(m_selectedTexture).removeProperty(propertyName); }); m_locked = false; } diff --git a/src/plugins/qmldesigner/designmodewidget.cpp b/src/plugins/qmldesigner/designmodewidget.cpp index 34183af8b26..c88dde8e473 100644 --- a/src/plugins/qmldesigner/designmodewidget.cpp +++ b/src/plugins/qmldesigner/designmodewidget.cpp @@ -512,8 +512,12 @@ void DesignModeWidget::setup() static bool isMcuDisabledView(const QString viewId) { - static const QStringList mcuDisabledViews = {"Editor3D", "MaterialEditor", "MaterialBrowser", - "TextureEditor", "EffectComposer"}; + static const QStringList mcuDisabledViews = { + "Editor3D", + "MaterialBrowser", + "TextureEditor", + "EffectComposer", + }; return mcuDisabledViews.contains(viewId); } diff --git a/src/plugins/qmldesigner/qmldesignerconstants.h b/src/plugins/qmldesigner/qmldesignerconstants.h index 24ae14ce3c5..3ee201675a1 100644 --- a/src/plugins/qmldesigner/qmldesignerconstants.h +++ b/src/plugins/qmldesigner/qmldesignerconstants.h @@ -124,7 +124,6 @@ inline constexpr char EVENT_EFFECTCOMPOSER_TIME[] = "effectComposerTime"; inline constexpr char EVENT_ITEMLIBRARY_TIME[] = "itemLibrary"; inline constexpr char EVENT_TRANSLATIONVIEW_TIME[] = "translationView"; inline constexpr char EVENT_NAVIGATORVIEW_TIME[] = "navigatorView"; -inline constexpr char EVENT_MATERIALEDITOR_TIME[] = "materialEditor"; inline constexpr char EVENT_MATERIALBROWSER_TIME[] = "materialBrowser"; inline constexpr char EVENT_CONTENTLIBRARY_TIME[] = "contentLibrary"; inline constexpr char EVENT_INSIGHT_TIME[] = "insight"; @@ -177,7 +176,6 @@ inline constexpr char OBJECT_NAME_COMPONENT_LIBRARY[] = "QQuickWidgetComponentLi inline constexpr char OBJECT_NAME_DESIGN_SYSTEM[] = "QQuickWidgetDesignSystem"; inline constexpr char OBJECT_NAME_EFFECT_COMPOSER[] = "QQuickWidgetEffectComposer"; inline constexpr char OBJECT_NAME_MATERIAL_BROWSER[] = "QQuickWidgetMaterialBrowser"; -inline constexpr char OBJECT_NAME_MATERIAL_EDITOR[] = "QQuickWidgetMaterialEditor"; inline constexpr char OBJECT_NAME_PROPERTY_EDITOR[] = "QQuickWidgetPropertyEditor"; inline constexpr char OBJECT_NAME_STATES_EDITOR[] = "QQuickWidgetStatesEditor"; inline constexpr char OBJECT_NAME_TEXTURE_EDITOR[] = "QQuickWidgetTextureEditor";