mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-06-02 19:02:29 +02:00
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.
151 lines
4.9 KiB
QML
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
|
|
}
|
|
}
|
|
}
|