QmlDesigner: Refactor Effect maker nodes view

Also add node click handler

Change-Id: I4b4e327f5c69f27d64ef2f2c3d13628aea46f0af
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
Mahmoud Badri
2023-08-15 15:40:46 +03:00
parent 8812c1816b
commit bf6ea8496a
5 changed files with 144 additions and 174 deletions

View File

@@ -2,8 +2,6 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import HelperWidgets as HelperWidgets import HelperWidgets as HelperWidgets
import StudioControls as StudioControls import StudioControls as StudioControls
import StudioTheme as StudioTheme import StudioTheme as StudioTheme
@@ -36,136 +34,8 @@ Item {
height: StudioTheme.Values.toolbarHeight height: StudioTheme.Values.toolbarHeight
color: StudioTheme.Values.themeToolbarBackground color: StudioTheme.Values.themeToolbarBackground
StudioControls.ComboBox { EffectNodesComboBox {
id: effectNodesComboBox mainRoot: root
actionIndicatorVisible: false
x: 5
width: parent.width - 50
anchors.verticalCenter: parent.verticalCenter
model: [qsTr("+ Add Effect")]
// hide default popup
popup.width: 0
popup.height: 0
Connections {
target: effectNodesComboBox.popup
function onAboutToShow() {
var a = root.mapToGlobal(0, 0)
var b = effectNodesComboBox.mapToItem(root, 0, 0)
effectNodesWindow.x = a.x + b.x + effectNodesComboBox.width - effectNodesWindow.width
effectNodesWindow.y = a.y + b.y + effectNodesComboBox.height - 1
effectNodesWindow.show()
effectNodesWindow.requestActivate()
}
function onAboutToHide() {
effectNodesWindow.hide()
}
}
Window {
id: effectNodesWindow
width: row.width + 2 // 2: scrollView left and right 1px margins
height: Math.min(800, Math.min(row.height + 2, Screen.height - y - 40)) // 40: some bottom margin to cover OS bottom toolbar
flags: Qt.Popup | Qt.FramelessWindowHint
onActiveChanged: {
if (!active)
effectNodesComboBox.popup.close()
}
Rectangle {
anchors.fill: parent
color: StudioTheme.Values.themePanelBackground
border.color: StudioTheme.Values.themeInteraction
border.width: 1
HelperWidgets.ScrollView {
anchors.fill: parent
anchors.margins: 1
Row {
id: row
onWidthChanged: {
// Needed to update on first window showing, as row.width only gets
// correct value after the window is shown, so first showing is off
var a = root.mapToGlobal(0, 0)
var b = effectNodesComboBox.mapToItem(root, 0, 0)
effectNodesWindow.x = a.x + b.x + effectNodesComboBox.width - row.width
}
padding: 10
spacing: 10
Repeater {
model: EffectMakerBackend.effectMakerNodesModel
Column {
spacing: 10
Text {
text: categoryName
color: StudioTheme.Values.themeTextColor
font.pointSize: StudioTheme.Values.baseFontSize
}
Item { width: 1; height: 5 } // spacer
Repeater {
model: categoryNodes
Rectangle {
width: 140
height: 22
color: mouseArea.containsMouse ? StudioTheme.Values.themeControlBackgroundInteraction
: "transparent"
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
}
Row {
spacing: 5
IconImage {
id: nodeIcon
width: 22
height: 22
color: StudioTheme.Values.themeTextColor
source: modelData.nodeIcon
}
Text {
text: modelData.nodeName
color: StudioTheme.Values.themeTextColor
font.pointSize: StudioTheme.Values.smallFontSize
anchors.verticalCenter: nodeIcon.verticalCenter
}
}
}
}
}
}
}
}
}
}
} }
} }

View File

@@ -3,70 +3,51 @@
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Layouts
import QtQuickDesignerTheme import QtQuickDesignerTheme
import HelperWidgets import HelperWidgets
import StudioControls as StudioControls import StudioControls as StudioControls
import StudioTheme 1.0 as StudioTheme import StudioTheme 1.0 as StudioTheme
import EffectMakerBackend import EffectMakerBackend
// TODO: this will be redone based on new specs
Rectangle { Rectangle {
property real margin: StudioTheme.Values.marginTopBottom
id: root id: root
height: col.height + margin * 2
signal showContextMenu() width: 140
height: 22
border.width: EffectMakerBackend.effectMakerModel.selectedIndex === index ? 3 : 0 color: mouseArea.containsMouse ? StudioTheme.Values.themeControlBackgroundInteraction
border.color: EffectMakerBackend.effectMakerModel.selectedIndex === index
? StudioTheme.Values.themeControlOutlineInteraction
: "transparent" : "transparent"
color: "transparent"
visible: true // TODO: from rolename -> effectVisible
MouseArea { MouseArea {
id: mouseArea id: mouseArea
anchors.fill: parent anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton hoverEnabled: true
acceptedButtons: Qt.LeftButton
onPressed: (mouse) => { onClicked: {
EffectMakerBackend.effectMakerModel.selectEffect(index) EffectMakerBackend.rootView.addEffectNode(modelData.nodeName)
EffectMakerBackend.rootView.focusSection(0) // TODO: Set the correct section based on current effect
if (mouse.button === Qt.LeftButton)
// TODO: Start dragging here
;
else if (mouse.button === Qt.RightButton)
root.showContextMenu()
} }
} }
ColumnLayout {
id: col
Layout.topMargin: margin
Layout.bottomMargin: margin
Row { Row {
spacing: 5
width: parent.width IconImage {
id: nodeIcon
width: 22
height: 22
color: StudioTheme.Values.themeTextColor
source: modelData.nodeIcon
}
Text { Text {
anchors.verticalCenter: parent.verticalCenter text: modelData.nodeName
rightPadding: margin * 3 color: StudioTheme.Values.themeTextColor
text: '⋮⋮' font.pointSize: StudioTheme.Values.smallFontSize
color: StudioTheme.Values.themeTextColorDisabled anchors.verticalCenter: nodeIcon.verticalCenter
font.letterSpacing: -10
font.bold: true
font.pointSize: StudioTheme.Values.mediumIconFontSize
}
StudioControls.CheckBox {
text: modelData
actionIndicatorVisible: false
}
} }
} }
} }

View File

@@ -0,0 +1,109 @@
// 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 QtQuickDesignerTheme
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
import StudioTheme 1.0 as StudioTheme
import EffectMakerBackend
StudioControls.ComboBox {
id: root
actionIndicatorVisible: false
x: 5
width: parent.width - 50
anchors.verticalCenter: parent.verticalCenter
model: [qsTr("+ Add Effect")]
// hide default popup
popup.width: 0
popup.height: 0
required property Item mainRoot
Connections {
target: root.popup
function onAboutToShow() {
var a = mainRoot.mapToGlobal(0, 0)
var b = root.mapToItem(mainRoot, 0, 0)
effectNodesWindow.x = a.x + b.x + root.width - effectNodesWindow.width
effectNodesWindow.y = a.y + b.y + root.height - 1
effectNodesWindow.show()
effectNodesWindow.requestActivate()
}
function onAboutToHide() {
effectNodesWindow.hide()
}
}
Window {
id: effectNodesWindow
width: row.width + 2 // 2: scrollView left and right 1px margins
height: Math.min(800, Math.min(row.height + 2, Screen.height - y - 40)) // 40: some bottom margin to cover OS bottom toolbar
flags: Qt.Popup | Qt.FramelessWindowHint
onActiveChanged: {
if (!active)
root.popup.close()
}
Rectangle {
anchors.fill: parent
color: StudioTheme.Values.themePanelBackground
border.color: StudioTheme.Values.themeInteraction
border.width: 1
HelperWidgets.ScrollView {
anchors.fill: parent
anchors.margins: 1
Row {
id: row
onWidthChanged: {
// Needed to update on first window showing, as row.width only gets
// correct value after the window is shown, so first showing is off
var a = mainRoot.mapToGlobal(0, 0)
var b = root.mapToItem(mainRoot, 0, 0)
effectNodesWindow.x = a.x + b.x + root.width - row.width
}
padding: 10
spacing: 10
Repeater {
model: EffectMakerBackend.effectMakerNodesModel
Column {
spacing: 10
Text {
text: categoryName
color: StudioTheme.Values.themeTextColor
font.pointSize: StudioTheme.Values.baseFontSize
}
Item { width: 1; height: 5 } // spacer
Repeater {
model: categoryNodes
EffectNode {}
}
}
}
}
}
}
}
}

View File

@@ -99,6 +99,15 @@ QPointer<EffectMakerNodesModel> EffectMakerWidget::effectMakerNodesModel() const
return m_effectMakerNodesModel; return m_effectMakerNodesModel;
} }
void EffectMakerWidget::addEffectNode(const QString &nodeName)
{
Q_UNUSED(nodeName)
// TODO: implement adding a node to the composition
// TODO: nodeName might be changed to nodeId?
// m_effectMakerModel.addNode(nodeName);
}
void EffectMakerWidget::focusSection(int section) void EffectMakerWidget::focusSection(int section)
{ {
Q_UNUSED(section) Q_UNUSED(section)

View File

@@ -35,6 +35,7 @@ public:
QPointer<EffectMakerModel> effectMakerModel() const; QPointer<EffectMakerModel> effectMakerModel() const;
QPointer<EffectMakerNodesModel> effectMakerNodesModel() const; QPointer<EffectMakerNodesModel> effectMakerNodesModel() const;
Q_INVOKABLE void addEffectNode(const QString &nodeName);
Q_INVOKABLE void focusSection(int section); Q_INVOKABLE void focusSection(int section);
protected: protected: