Meshroom/meshroom/ui/qml/GraphEditor/Edge.qml
Candice Bentéjac 52444ef0ad [GraphEditor] Edge: Set curve scale after initializing EdgeMouseArea
The curve scale of the mouse area for an edge used to be defined when
initializing the `EdgeMouseArea` for that edge. Setting it triggers a
chain of event that allow the mouse area to be active, thus correctly
detecting when it is being hovered or clicked on.

With Qt6, these events unfolded before the `EdgeMouseArea` had finished
initializing, which then caused it to not be active until the edge's
shape was modified (and the chain of events triggered again). It is now
set once the component has been created, so all the events can happen
in an environment where they are taken into account.
2024-11-07 18:13:33 +01:00

151 lines
4.9 KiB
QML

import QtQuick
import QtQuick.Controls
import QtQuick.Shapes 1.6
import GraphEditor 1.0
import MaterialIcons 2.2
/**
A cubic spline representing an edge, going from point1 to point2, providing mouse interaction.
*/
Item {
id: root
property var edge
property real point1x
property real point1y
property real point2x
property real point2y
property alias thickness: path.strokeWidth
property alias color: path.strokeColor
property bool isForLoop: false
property int loopSize: 0
property int iteration: 0
// BUG: edgeArea is destroyed before path, need to test if not null to avoid warnings
readonly property bool containsMouse: (loopArea && loopArea.containsMouse) || (edgeArea && edgeArea.containsMouse)
signal pressed(var event)
signal released(var event)
x: point1x
y: point1y
width: point2x - point1x
height: point2y - point1y
property real startX: 0
property real startY: 0
property real endX: width
property real endY: height
Shape {
anchors.fill: parent
// Cause rendering artifacts when enabled (and don't support hot reload really well)
vendorExtensionsEnabled: false
opacity: 0.7
ShapePath {
id: path
startX: root.startX
startY: root.startY
fillColor: "transparent"
strokeColor: "#3E3E3E"
strokeStyle: edge !== undefined && ((edge.src !== undefined && edge.src.isOutput) || edge.dst === undefined) ? ShapePath.SolidLine : ShapePath.DashLine
strokeWidth: 1
// Final visual width of this path (never below 1)
readonly property real visualWidth: Math.max(strokeWidth, 1)
dashPattern: [6 / visualWidth, 4 / visualWidth]
capStyle: ShapePath.RoundCap
PathCubic {
id: cubic
property real ctrlPtDist: 30
x: root.isForLoop ? (root.startX + root.endX) / 2 - loopArea.width / 2 : root.endX
y: root.isForLoop ? (root.startY + root.endY) / 2 : root.endY
relativeControl1X: ctrlPtDist
relativeControl1Y: 0
control2X: x - ctrlPtDist
control2Y: y
}
}
ShapePath {
id: pathSecondary
startX: (root.startX + root.endX) / 2 + loopArea.width / 2
startY: (root.startY + root.endY) / 2
fillColor: "transparent"
strokeColor: root.isForLoop ? root.color : "transparent"
strokeStyle: edge !== undefined && ((edge.src !== undefined && edge.src.isOutput) || edge.dst === undefined) ? ShapePath.SolidLine : ShapePath.DashLine
strokeWidth: root.thickness
// Final visual width of this path (never below 1)
readonly property real visualWidth: Math.max(strokeWidth, 1)
dashPattern: [6 / visualWidth, 4 / visualWidth]
capStyle: ShapePath.RoundCap
PathCubic {
id: cubicSecondary
property real ctrlPtDist: 30
x: root.endX
y: root.endY
relativeControl1X: ctrlPtDist
relativeControl1Y: 0
control2X: x - ctrlPtDist
control2Y: y
}
}
}
Item {
// Place the label at the middle of the edge
x: (root.startX + root.endX) / 2
y: (root.startY + root.endY) / 2
visible: root.isForLoop
Rectangle {
anchors.centerIn: parent
property int margin: 2
width: icon.width + 2 * margin
height: icon.height + 2 * margin
radius: width
color: path.strokeColor
MaterialToolLabel {
id: icon
anchors.centerIn: parent
iconText: MaterialIcons.loop
label: (root.iteration + 1) + "/" + root.loopSize + " "
color: palette.base
ToolTip.text: "Foreach Loop"
}
MouseArea {
id: loopArea
anchors.fill: parent
hoverEnabled: true
onClicked: root.pressed(arguments[0])
}
}
}
EdgeMouseArea {
id: edgeArea
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
thickness: root.thickness + 4
onPressed: function(event) {
root.pressed(event)
}
onReleased: function(event) {
root.released(event)
}
Component.onCompleted: {
/* The curve scale must be set only once the component has been fully created, so
* that all the events following the update of the curve scale can be taken into
* account */
curveScale = cubic.ctrlPtDist / root.width // Normalize by width
}
}
}