Skip to content

Commit

Permalink
Merge pull request #5945 from opengisch/snapping-angle-configure
Browse files Browse the repository at this point in the history
Angle snapping tolerance functionality
  • Loading branch information
nirvn authored Feb 7, 2025
2 parents d58cdbf + d0f8a2a commit 4807c29
Show file tree
Hide file tree
Showing 2 changed files with 167 additions and 21 deletions.
21 changes: 20 additions & 1 deletion src/qml/CoordinateLocator.qml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Item {
property bool snapToCommonAngles: false
property bool snappingIsRelative: false
property real snappingAngleDegrees: 45.0
property real snappingTolerance: 1

/**
* Overrides any possibility for the user to modify the coordinate.
Expand Down Expand Up @@ -390,6 +391,24 @@ Item {
flashAnimation.start();
}

/** Function to get the multiplier based on the selected tolerance
*
* - Narrow tolerance (index 0) divides by 2.
* - Normal tolerance (index 1) keeps unchanged.
* - Large tolerance (index 2) multiplies by 4.
*/
function getToleranceMultiplier() {
switch (snappingTolerance) {
case 0:
return 0.5;
case 2:
return 4;
case 1:
default:
return 1;
}
}

/**
* Computes the possible common angle
*
Expand All @@ -405,7 +424,7 @@ Item {
return;
}
const MINIMAL_PIXEL_DISTANCE_TRESHOLD = 20;
const SOFT_CONSTRAINT_TOLERANCE_DEGREES = 20;
const SOFT_CONSTRAINT_TOLERANCE_DEGREES = 20 * getToleranceMultiplier();
const SOFT_CONSTRAINT_TOLERANCE_PIXEL = 40;
const rubberbandPointsCount = rubberbandModel.vertexCount;
const targetPoint = mapCanvas.mapSettings.coordinateToScreen(forwardMode ? rubberbandModel.firstCoordinate : rubberbandModel.lastCoordinate);
Expand Down
167 changes: 147 additions & 20 deletions src/qml/qgismobileapp.qml
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ ApplicationWindow {
id: mapCanvasMap

property bool isEnabled: !dashBoard.opened && !aboutDialog.visible && !welcomeScreen.visible && !qfieldSettings.visible && !qfieldLocalDataPickerScreen.visible && !qfieldCloudScreen.visible && !qfieldCloudPopup.visible && !codeReader.visible && !sketcher.visible && !overlayFeatureFormDrawer.visible && !rotateFeaturesToolbar.rotateFeaturesRequested
interactive: isEnabled && !screenLocker.enabled
interactive: isEnabled && !screenLocker.enabled && !snapToCommonAngleMenu.visible
isMapRotationEnabled: qfieldSettings.enableMapRotation
incrementalRendering: true
quality: qfieldSettings.quality
Expand Down Expand Up @@ -1713,10 +1713,12 @@ ApplicationWindow {
coordinateLocator.snapToCommonAngles = settings.valueBool("/QField/Digitizing/SnapToCommonAngleIsEnabled", false);
coordinateLocator.snappingIsRelative = settings.valueBool("/QField/Digitizing/SnapToCommonAngleIsRelative", true);
coordinateLocator.snappingAngleDegrees = settings.valueInt("/QField/Digitizing/SnapToCommonAngleDegrees", 45);
coordinateLocator.snappingTolerance = settings.valueInt("/QField/Digitizing/SnappingTolerance", 1);
}

Menu {
id: snapToCommonAngleMenu
width: Theme.menuItemIconlessLeftPadding + Math.max(angles.count * 35, tolorences.count * 55) + 24

MenuItem {
text: qsTr("Relative angle")
Expand All @@ -1737,31 +1739,156 @@ ApplicationWindow {
width: parent.width
}

Repeater {
// list of common angles to snap to
Text {
text: qsTr("Snapping to every")
color: Theme.mainTextColor
font: Theme.defaultFont
leftPadding: Theme.menuItemIconlessLeftPadding
}

Item {
width: 1
height: 8
}

ListView {
id: angles
height: 35
anchors {
left: parent.left
leftMargin: Theme.menuItemIconlessLeftPadding
rightMargin: 4
}
spacing: 3
orientation: ListView.Horizontal
model: [10, 15, 30, 45, 90]
delegate: MenuItem {
required property int modelData
currentIndex: Math.max(model.findIndex(q => q === coordinateLocator.snappingAngleDegrees), 0)
highlightFollowsCurrentItem: true

highlight: Rectangle {
width: 35
height: parent.height
color: Theme.mainColor
radius: width / 2
}

delegate: Item {
width: 35
height: width
enabled: !selected

property bool selected: modelData === coordinateLocator.snappingAngleDegrees

Text {
text: qsTr("%1°").arg(modelData)
font: parent.selected ? Theme.strongTipFont : Theme.tipFont
anchors.centerIn: parent
color: Theme.mainTextColor
}

Ripple {
clip: true
anchors.fill: parent
clipRadius: width / 2
pressed: angleMouseArea.pressed
anchor: parent
active: angleMouseArea.pressed
color: "#22aaaaaa"
}

MouseArea {
id: angleMouseArea
anchors.fill: parent
onClicked: {
if (parent.selected) {
return;
}
coordinateLocator.snapToCommonAngles = true;
coordinateLocator.snappingAngleDegrees = modelData;
settings.setValue("/QField/Digitizing/SnapToCommonAngleDegrees", coordinateLocator.snappingAngleDegrees);
displayToast(qsTr("Snap to %1° angle turned on").arg(modelData));
}
}
}
}

Item {
width: 1
height: 8
}

Text {
text: qsTr("Snapping tolerance")
color: Theme.mainTextColor
font: Theme.defaultFont
leftPadding: Theme.menuItemIconlessLeftPadding
}

text: qsTr("Snap every %1°").arg(modelData)
Item {
width: 1
height: 8
}

font: Theme.defaultFont
height: 48
leftPadding: Theme.menuItemCheckLeftPadding
ListView {
id: tolorences
height: 35
anchors {
left: parent.left
leftMargin: Theme.menuItemIconlessLeftPadding
rightMargin: 4
}
spacing: 3
orientation: ListView.Horizontal
model: [qsTr("Narrow"), qsTr("Normal"), qsTr("Large")]
highlight: Rectangle {
width: 35
height: parent.height
color: Theme.mainColor
radius: 4
}
currentIndex: coordinateLocator.snappingTolerance
highlightFollowsCurrentItem: true
delegate: Item {
id: tolorenceDelegate
width: (angles.contentWidth) / 3
height: 35
enabled: !selected

property bool selected: index === coordinateLocator.snappingTolerance

Text {
id: tolorenceText
text: modelData
font: parent.selected ? Theme.strongTipFont : Theme.tipFont
anchors.centerIn: parent
color: Theme.mainTextColor
elide: Text.ElideRight
width: parent.width
horizontalAlignment: Text.AlignHCenter
}

checkable: true
checked: modelData === coordinateLocator.snappingAngleDegrees
enabled: modelData !== coordinateLocator.snappingAngleDegrees
Ripple {
clip: true
anchors.fill: parent
clipRadius: 4
pressed: tolerancesMouseArea.pressed
anchor: parent
active: tolerancesMouseArea.pressed
color: "#22aaaaaa"
}

onTriggered: {
if (!checked) {
return;
MouseArea {
id: tolerancesMouseArea
anchors.fill: parent
onClicked: {
if (parent.selected) {
return;
}
coordinateLocator.snapToCommonAngles = true;
coordinateLocator.snappingTolerance = index;
settings.setValue("/QField/Digitizing/SnappingTolerance", coordinateLocator.snappingTolerance);
displayToast(qsTr("Snapping tolerance setted to %1").arg(modelData));
}
coordinateLocator.snapToCommonAngles = true;
coordinateLocator.snappingAngleDegrees = modelData;
settings.setValue("/QField/Digitizing/SnapToCommonAngleDegrees", coordinateLocator.snappingAngleDegrees);
displayToast(qsTr("Snap to %1° angle turned on").arg(modelData));
snapToCommonAngleMenu.close();
}
}
}
Expand Down

1 comment on commit 4807c29

@qfield-fairy
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.