diff --git a/meshroom/ui/qml/Controls/DelegateSelectionLine.qml b/meshroom/ui/qml/Controls/DelegateSelectionLine.qml new file mode 100644 index 00000000..779ec5fd --- /dev/null +++ b/meshroom/ui/qml/Controls/DelegateSelectionLine.qml @@ -0,0 +1,31 @@ +import QtQuick +import Meshroom.Helpers + +/* +A SelectionLine that can be used to select delegates in a model instantiator (Repeater, ListView...). +Interesection test is done in the coordinate system of the container Item, using delegate's bounding boxes. +The list of selected indices is emitted when the selection ends. +*/ + +SelectionLine { + id: root + + // The Item instantiating the delegates. + property Item modelInstantiator + // The Item containing the delegates (used for coordinate mapping). + property Item container + // Emitted when the selection has ended, with the list of selected indices and modifiers. + signal delegateSelectionEnded(list indices, int modifiers) + + onSelectionEnded: function(selectionRect, modifiers) { + let selectedIndices = []; + const mappedSelectionRect = mapToItem(container, selectionRect); + for (var i = 0; i < modelInstantiator.count; ++i) { + const delegate = modelInstantiator.itemAt(i); + if (delegate.intersects(mappedSelectionRect)) { + selectedIndices.push(i); + } + } + delegateSelectionEnded(selectedIndices, modifiers); + } +} diff --git a/meshroom/ui/qml/Controls/SelectionLine.qml b/meshroom/ui/qml/Controls/SelectionLine.qml new file mode 100644 index 00000000..80cf8545 --- /dev/null +++ b/meshroom/ui/qml/Controls/SelectionLine.qml @@ -0,0 +1,77 @@ +import QtQuick +import QtQuick.Shapes + +/* +Simple selection line that can be used by a MouseArea. + +Usage: +1. Create a MouseArea and a selectionShape. +2. Bind the selectionShape to the MouseArea by setting the `mouseArea` property. +3. Call startSelection() with coordinates when the selection starts. +4. Call endSelection() when the selection ends. +5. Listen to the selectionEnded signal to get the rectangle whose Diagonal is the selection line. +*/ + +Item { + id: root + + property MouseArea mouseArea + + readonly property bool active: mouseArea.drag.target == dragTarget + + signal selectionEnded(rect selectionRect, int modifiers) + + function startSelection(mouse) { + dragTarget.startPos.x = dragTarget.x = mouse.x; + dragTarget.startPos.y = dragTarget.y = mouse.y; + dragTarget.modifiers = mouse.modifiers; + mouseArea.drag.target = dragTarget; + } + + function endSelection() { + if (!active) { + return; + } + mouseArea.drag.target = null; + const rect = Qt.rect(selectionShape.x, selectionShape.y, selectionShape.width, selectionShape.height) + selectionEnded(rect, dragTarget.modifiers); + } + + visible: active + + Item { + id: selectionShape + x: dragTarget.startPos.x + y: dragTarget.startPos.y + width: dragTarget.x - dragTarget.startPos.x + height: dragTarget.y - dragTarget.startPos.y + + Shape { + id: dynamicLine; + width: selectionShape.width; + height: selectionShape.height; + anchors.fill: parent; + + ShapePath { + strokeWidth: 2; + strokeStyle: ShapePath.DashLine; + strokeColor: "#FF0000"; + dashPattern: [3, 2]; + + startX: 0; + startY: 0; + + PathLine { + x: selectionShape.width; + y: selectionShape.height; + } + } + } + } + + Item { + id: dragTarget + property point startPos + property var modifiers + } +} diff --git a/meshroom/ui/qml/Controls/qmldir b/meshroom/ui/qml/Controls/qmldir index 9d3e23cb..c11085ac 100644 --- a/meshroom/ui/qml/Controls/qmldir +++ b/meshroom/ui/qml/Controls/qmldir @@ -18,4 +18,6 @@ MScrollBar 1.0 MScrollBar.qml MSplitView 1.0 MSplitView.qml DirectionalLightPane 1.0 DirectionalLightPane.qml SelectionBox 1.0 SelectionBox.qml -DelegateSelectionBox 1.0 DelegateSelectionBox.qml \ No newline at end of file +SelectionLine 1.0 SelectionLine.qml +DelegateSelectionBox 1.0 DelegateSelectionBox.qml +DelegateSelectionLine 1.0 DelegateSelectionLine.qml