From 3a43033731c5e40e5e7c804dd4cd5289ddcc42e0 Mon Sep 17 00:00:00 2001 From: Matej Bagar Date: Fri, 22 May 2026 13:39:40 +0200 Subject: [PATCH 01/11] Create MMGeometry as QML integration for QgsGeometry --- app/CMakeLists.txt | 2 ++ app/externalTypes/mmgeometry.h | 40 +++++++++++++++++++++++++++++++++ app/guidelinecontroller.cpp | 4 ++-- app/guidelinecontroller.h | 8 +++---- app/inpututils.cpp | 10 ++++----- app/inpututils.h | 5 +++-- app/qml/map/MMHighlight.qml | 5 +++-- app/qml/map/MMMapController.qml | 8 +++---- 8 files changed, 63 insertions(+), 19 deletions(-) create mode 100644 app/externalTypes/mmgeometry.h diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index aab84959c..f1898c0b5 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -190,6 +190,7 @@ set(MM_HDRS workspacesmodel.h workspacesproxymodel.h mmstyle.h + externalTypes/mmgeometry.h ) if (NOT WIN32) @@ -331,6 +332,7 @@ target_include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/layer ${CMAKE_CURRENT_SOURCE_DIR}/maptools ${CMAKE_CURRENT_SOURCE_DIR}/position + ${CMAKE_CURRENT_SOURCE_DIR}/externalTypes ) qt_policy(SET QTP0002 NEW) diff --git a/app/externalTypes/mmgeometry.h b/app/externalTypes/mmgeometry.h new file mode 100644 index 000000000..899ac4fc9 --- /dev/null +++ b/app/externalTypes/mmgeometry.h @@ -0,0 +1,40 @@ +/*************************************************************************** +* * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef MMGEOMETRY_H +#define MMGEOMETRY_H + +#include + +#include + +/** + * MMGeometry is just a wrapper around QgsGeometry, which adds equals operator that is missing. + * We expose this type to QML instead of QgsGeometry. The reason is that QML in Qt 6.9+ also checks equality, when firing + * onChanged signal. The missing operator is breaking property bindings. + */ +class MMGeometry: public QgsGeometry +{ + Q_GADGET + QML_VALUE_TYPE( mmGeometry ); + + public: + using QgsGeometry::QgsGeometry; + + MMGeometry() = default; + MMGeometry( const QgsGeometry &geom ) : QgsGeometry( geom ) {} + MMGeometry( QgsGeometry &geom ) : QgsGeometry( geom ) {} + + bool operator==( const MMGeometry &rhs ) const + { + return equals( rhs ); + } +}; + +#endif //MMGEOMETRY_H diff --git a/app/guidelinecontroller.cpp b/app/guidelinecontroller.cpp index ce9151ebe..a6fdb26df 100644 --- a/app/guidelinecontroller.cpp +++ b/app/guidelinecontroller.cpp @@ -187,12 +187,12 @@ void GuidelineController::buildGuideline() } } -const QgsGeometry &GuidelineController::guidelineGeometry() const +const MMGeometry &GuidelineController::guidelineGeometry() const { return mGuidelineGeometry; } -void GuidelineController::setGuidelineGeometry( const QgsGeometry &newGuidelineGeometry ) +void GuidelineController::setGuidelineGeometry( const MMGeometry &newGuidelineGeometry ) { if ( mGuidelineGeometry.equals( newGuidelineGeometry ) ) return; diff --git a/app/guidelinecontroller.h b/app/guidelinecontroller.h index 76166fcc6..4cf9bd25c 100644 --- a/app/guidelinecontroller.h +++ b/app/guidelinecontroller.h @@ -37,13 +37,13 @@ class GuidelineController : public QObject Q_PROPERTY( bool allowed READ allowed WRITE setAllowed NOTIFY allowedChanged ) // output properties (real geometry + crosshair position ) in map CRS - Q_PROPERTY( QgsGeometry guidelineGeometry READ guidelineGeometry WRITE setGuidelineGeometry NOTIFY guidelineGeometryChanged ) + Q_PROPERTY( MMGeometry guidelineGeometry READ guidelineGeometry WRITE setGuidelineGeometry NOTIFY guidelineGeometryChanged ) public: explicit GuidelineController( QObject *parent = nullptr ); - const QgsGeometry &guidelineGeometry() const; - void setGuidelineGeometry( const QgsGeometry &newGuidelineGeometry ); + const MMGeometry &guidelineGeometry() const; + void setGuidelineGeometry( const MMGeometry &newGuidelineGeometry ); QPointF crosshairPosition() const; void setCrosshairPosition( QPointF newCrosshairPosition ); @@ -93,7 +93,7 @@ class GuidelineController : public QObject private: - QgsGeometry mGuidelineGeometry; + MMGeometry mGuidelineGeometry; QPointF mCrosshairPosition; QgsGeometry mRealGeometry; InputMapSettings *mMapSettings = nullptr; // not owned diff --git a/app/inpututils.cpp b/app/inpututils.cpp index 855e5b2c2..5d6006e4e 100644 --- a/app/inpututils.cpp +++ b/app/inpututils.cpp @@ -446,14 +446,14 @@ QgsGeometry InputUtils::transformGeometry( const QgsGeometry &geometry, const Qg return transformGeometry( geometry, sourceCRS, targetLayer->crs(), targetLayer->transformContext() ); } -QgsGeometry InputUtils::transformGeometryToMapWithLayer( const QgsGeometry &geometry, QgsVectorLayer *sourceLayer, InputMapSettings *targetSettings ) +MMGeometry InputUtils::transformGeometryToMapWithLayer( const QgsGeometry &geometry, QgsVectorLayer *sourceLayer, InputMapSettings *targetSettings ) { if ( !sourceLayer || !sourceLayer->isValid() || !targetSettings ) { - return QgsGeometry(); + return {}; } - return transformGeometry( geometry, sourceLayer->crs(), targetSettings->destinationCrs(), targetSettings->transformContext() ); + return MMGeometry( transformGeometry( geometry, sourceLayer->crs(), targetSettings->destinationCrs(), targetSettings->transformContext() ) ); } QgsGeometry InputUtils::transformGeometryToMapWithCRS( const QgsGeometry &geometry, const QgsCoordinateReferenceSystem &sourceCRS, InputMapSettings *targetSettings ) @@ -816,9 +816,9 @@ QgsPoint InputUtils::point( double x, double y, double z, double m ) return QgsPoint( x, y, z, m ); } -QgsGeometry InputUtils::emptyGeometry() +MMGeometry InputUtils::emptyGeometry() { - return QgsGeometry(); + return {}; } QgsFeature InputUtils::emptyFeature() diff --git a/app/inpututils.h b/app/inpututils.h index d94e1803e..e9d2e2c0d 100644 --- a/app/inpututils.h +++ b/app/inpututils.h @@ -38,6 +38,7 @@ #include "inputmapsettings.h" #include "featurelayerpair.h" #include "qgscoordinateformatter.h" +#include "externalTypes/mmgeometry.h" #include "position/mapposition.h" class QgsFeature; @@ -114,7 +115,7 @@ class InputUtils: public QObject static QgsGeometry transformGeometry( const QgsGeometry &geometry, const QgsCoordinateReferenceSystem &sourceCRS, const QgsCoordinateReferenceSystem &destinationCRS, const QgsCoordinateTransformContext &context ); //! Helper methods to use for transforming geometry from QML as overriding does not work properly there - Q_INVOKABLE static QgsGeometry transformGeometryToMapWithLayer( const QgsGeometry &geometry, QgsVectorLayer *sourceLayer, InputMapSettings *targetSettings ); + Q_INVOKABLE static MMGeometry transformGeometryToMapWithLayer( const QgsGeometry &geometry, QgsVectorLayer *sourceLayer, InputMapSettings *targetSettings ); Q_INVOKABLE static QgsGeometry transformGeometryToMapWithCRS( const QgsGeometry &geometry, const QgsCoordinateReferenceSystem &sourceCRS, InputMapSettings *targetSettings ); /** @@ -270,7 +271,7 @@ class InputUtils: public QObject /** * Creates empty geometry */ - Q_INVOKABLE static QgsGeometry emptyGeometry(); + Q_INVOKABLE static MMGeometry emptyGeometry(); /** * Creates empty feature diff --git a/app/qml/map/MMHighlight.qml b/app/qml/map/MMHighlight.qml index 7c813c1cc..d28f5c45a 100644 --- a/app/qml/map/MMHighlight.qml +++ b/app/qml/map/MMHighlight.qml @@ -11,6 +11,7 @@ import QtQuick import QtQuick.Shapes import mm 1.0 as MM +import MMInput import ".." @@ -19,7 +20,7 @@ Item { // geometry to highlight // geometry must be in map canvas CRS! - property var geometry + property mmGeometry geometry // for transformation of the highlight to the correct location on the map property MM.MapSettings mapSettings @@ -108,7 +109,7 @@ Item { { if ( !mapSettings ) return - if ( !geometry ) + if ( __inputUtils.isEmptyGeometry( geometry ) ) { // trigger repaint for empty geometries markerItems = markerItems.map( function (marker) { return marker.destroy() } ) diff --git a/app/qml/map/MMMapController.qml b/app/qml/map/MMMapController.qml index f3b3601ee..02afcbf78 100644 --- a/app/qml/map/MMMapController.qml +++ b/app/qml/map/MMMapController.qml @@ -1380,7 +1380,7 @@ Item { } function jumpToHighlighted( mapOffset ) { - if ( identifyHighlight.geometry === null ) + if ( identifyHighlight.geometry.isNull ) return let screenPt = __inputUtils.relevantGeometryCenterToScreenCoordinates( identifyHighlight.geometry, mapCanvas.mapSettings ) @@ -1394,7 +1394,7 @@ Item { } function hideHighlight() { - identifyHighlight.geometry = null + identifyHighlight.geometry = __inputUtils.emptyGeometry() updatePosition() } @@ -1441,7 +1441,7 @@ Item { case "view": { // While a feature is highlighted we want to keep it visible in the map extent // so in that case we skip centering to position - if ( identifyHighlight.geometry !== null ) + if ( !__inputUtils.isEmptyGeometry( identifyHighlight.geometry ) ) { break } @@ -1476,7 +1476,7 @@ Item { // clear all previous references to old project (if we don't clear references to the previous project, // highlights may end up with dangling pointers to map layers and cause crashes) - identifyHighlight.geometry = null + identifyHighlight.geometry = __inputUtils.emptyGeometry() } function setTracking( shouldTrack ) { From fe0db666bb132d782411a8b5cdb49452751eb6a0 Mon Sep 17 00:00:00 2001 From: Matej Bagar Date: Fri, 22 May 2026 16:34:42 +0200 Subject: [PATCH 02/11] Add missing imports --- app/qml/map/MMHighlight.qml | 1 + app/qml/map/MMRecordingTools.qml | 2 ++ 2 files changed, 3 insertions(+) diff --git a/app/qml/map/MMHighlight.qml b/app/qml/map/MMHighlight.qml index d28f5c45a..affa6da97 100644 --- a/app/qml/map/MMHighlight.qml +++ b/app/qml/map/MMHighlight.qml @@ -9,6 +9,7 @@ import QtQuick import QtQuick.Shapes +import QtQml import mm 1.0 as MM import MMInput diff --git a/app/qml/map/MMRecordingTools.qml b/app/qml/map/MMRecordingTools.qml index da976654c..22ffd1012 100644 --- a/app/qml/map/MMRecordingTools.qml +++ b/app/qml/map/MMRecordingTools.qml @@ -10,6 +10,8 @@ import QtQuick import QtQuick.Shapes import QtMultimedia +import QtQml +import QtQml.Models import mm 1.0 as MM import MMInput From 5963d318dde453d41e5667aabb006406cc0e317a Mon Sep 17 00:00:00 2001 From: Matej Bagar Date: Fri, 22 May 2026 16:49:09 +0200 Subject: [PATCH 03/11] Fix guideline geometry signal --- app/guidelinecontroller.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/guidelinecontroller.h b/app/guidelinecontroller.h index 4cf9bd25c..aea3f5cdc 100644 --- a/app/guidelinecontroller.h +++ b/app/guidelinecontroller.h @@ -71,7 +71,7 @@ class GuidelineController : public QObject signals: - void guidelineGeometryChanged( const QgsGeometry &guidelineGeometry ); + void guidelineGeometryChanged( const MMGeometry &guidelineGeometry ); void crosshairPositionChanged( QPointF crosshairPosition ); void realGeometryChanged( const QgsGeometry &realGeometry ); From b2a15b4ab2a33c3d42378f9cac263110c00cf26c Mon Sep 17 00:00:00 2001 From: Matej Bagar Date: Fri, 22 May 2026 18:29:24 +0200 Subject: [PATCH 04/11] Fix highlight for position tracking --- app/position/tracking/positiontrackinghighlight.cpp | 12 +++++++----- app/position/tracking/positiontrackinghighlight.h | 11 ++++++----- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/app/position/tracking/positiontrackinghighlight.cpp b/app/position/tracking/positiontrackinghighlight.cpp index 4ad84b270..1cd3fef7c 100644 --- a/app/position/tracking/positiontrackinghighlight.cpp +++ b/app/position/tracking/positiontrackinghighlight.cpp @@ -9,6 +9,8 @@ #include "positiontrackinghighlight.h" +#include "inpututils.h" + PositionTrackingHighlight::PositionTrackingHighlight( QObject *parent ) : QObject( parent ) { @@ -20,20 +22,20 @@ void PositionTrackingHighlight::recalculate() { if ( mMapPosition.isEmpty() ) { - setHighlightGeometry( QgsGeometry() ); + setHighlightGeometry( InputUtils::emptyGeometry() ); return; } if ( mTrackedGeometry.isEmpty() ) { - setHighlightGeometry( QgsGeometry() ); + setHighlightGeometry( InputUtils::emptyGeometry() ); return; } // add map position to the end of the tracked geometry // note - map position must be in the same CRS as the tracked geometry - QgsGeometry highlightGeometry( mTrackedGeometry ); + MMGeometry highlightGeometry( mTrackedGeometry ); QgsVertexId lastVertex( 0, 0, highlightGeometry.constGet()->vertexCount() ); highlightGeometry.get()->insertVertex( lastVertex, mMapPosition ); @@ -55,12 +57,12 @@ void PositionTrackingHighlight::setTrackedGeometry( const QgsGeometry &newTracke emit trackedGeometryChanged( mTrackedGeometry ); } -QgsGeometry PositionTrackingHighlight::highlightGeometry() const +MMGeometry PositionTrackingHighlight::highlightGeometry() const { return mHighlightGeometry; } -void PositionTrackingHighlight::setHighlightGeometry( const QgsGeometry &newHighlightGeometry ) +void PositionTrackingHighlight::setHighlightGeometry( const MMGeometry &newHighlightGeometry ) { if ( mHighlightGeometry.equals( newHighlightGeometry ) ) return; diff --git a/app/position/tracking/positiontrackinghighlight.h b/app/position/tracking/positiontrackinghighlight.h index 396f1a7ed..db4dc99da 100644 --- a/app/position/tracking/positiontrackinghighlight.h +++ b/app/position/tracking/positiontrackinghighlight.h @@ -14,6 +14,7 @@ #include #include "qgsgeometry.h" +#include "externalTypes/mmgeometry.h" class PositionTrackingHighlight : public QObject { @@ -25,7 +26,7 @@ class PositionTrackingHighlight : public QObject Q_PROPERTY( QgsGeometry trackedGeometry READ trackedGeometry WRITE setTrackedGeometry NOTIFY trackedGeometryChanged ) // Geometry out - Q_PROPERTY( QgsGeometry highlightGeometry READ highlightGeometry NOTIFY highlightGeometryChanged ) + Q_PROPERTY( MMGeometry highlightGeometry READ highlightGeometry NOTIFY highlightGeometryChanged ) public: explicit PositionTrackingHighlight( QObject *parent = nullptr ); @@ -33,7 +34,7 @@ class PositionTrackingHighlight : public QObject QgsGeometry trackedGeometry() const; void setTrackedGeometry( const QgsGeometry &newTrackedGeometry ); - QgsGeometry highlightGeometry() const; + MMGeometry highlightGeometry() const; QgsPoint mapPosition() const; void setMapPosition( QgsPoint newMapPosition ); @@ -43,15 +44,15 @@ class PositionTrackingHighlight : public QObject signals: void trackedGeometryChanged( QgsGeometry trackedGeometry ); - void highlightGeometryChanged( QgsGeometry highlightGeometry ); + void highlightGeometryChanged( MMGeometry highlightGeometry ); void mapPositionChanged( QgsPoint mapPosition ); private: - void setHighlightGeometry( const QgsGeometry &newHighlightGeometry ); + void setHighlightGeometry( const MMGeometry &newHighlightGeometry ); QgsGeometry mTrackedGeometry; - QgsGeometry mHighlightGeometry; + MMGeometry mHighlightGeometry; QgsPoint mMapPosition; }; From c44417cf0220787fb271b14c0f34d25eb4d55c16 Mon Sep 17 00:00:00 2001 From: Matej Bagar Date: Fri, 22 May 2026 18:57:25 +0200 Subject: [PATCH 05/11] Fix multieditmanager highlight --- app/multieditmanager.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/multieditmanager.h b/app/multieditmanager.h index 134d4ef37..ff811eebb 100644 --- a/app/multieditmanager.h +++ b/app/multieditmanager.h @@ -14,6 +14,7 @@ #include "featurelayerpair.h" #include "staticfeaturesmodel.h" +#include "externalTypes/mmgeometry.h" class QgsVectorLayer; @@ -30,7 +31,7 @@ class MultiEditManager : public QObject Q_PROPERTY( QgsVectorLayer *layer MEMBER mLayer NOTIFY layerChanged ) Q_PROPERTY( StaticFeaturesModel *model READ model CONSTANT ) - Q_PROPERTY( QgsGeometry geometry READ collectGeometry NOTIFY geometryChanged ) + Q_PROPERTY( MMGeometry geometry READ collectGeometry NOTIFY geometryChanged ) Q_PROPERTY( InputMapSettings *mapSettings MEMBER mMapSettings ) public: @@ -49,7 +50,7 @@ class MultiEditManager : public QObject Q_INVOKABLE void deleteSelectedFeatures(); //! Returns multipart geometry of all geometries in the model, in map crs - QgsGeometry collectGeometry() const { return mModel->collectGeometries( mMapSettings ); } + MMGeometry collectGeometry() const { return mModel->collectGeometries( mMapSettings ); } StaticFeaturesModel *model() const { return mModel.get(); } From ca9f03f57faaaed41289a3a2bdb2d6d1e250778b Mon Sep 17 00:00:00 2001 From: Matej Bagar Date: Fri, 22 May 2026 19:10:39 +0200 Subject: [PATCH 06/11] Fix map sketching highlight --- app/mapsketchingcontroller.cpp | 6 +++--- app/mapsketchingcontroller.h | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/app/mapsketchingcontroller.cpp b/app/mapsketchingcontroller.cpp index af5cf5010..a8c39799e 100644 --- a/app/mapsketchingcontroller.cpp +++ b/app/mapsketchingcontroller.cpp @@ -44,7 +44,7 @@ void MapSketchingController::updateHighlight( const QPointF &oldPoint, const QPo ls->addZValue(); ls->addMValue(); QgsMultiLineString *mls = new QgsMultiLineString( QList() << ls ); - mHighlight = QgsGeometry( mls ); + mHighlight = MMGeometry( mls ); mScreenPoints = QgsGeometry( new QgsLineString( { QgsPointXY( oldPoint.x(), oldPoint.y() ) } ) ); } @@ -139,7 +139,7 @@ void MapSketchingController::undo() const mLayer->undoStack()->undo(); } -QgsGeometry MapSketchingController::highlightGeometry() const +MMGeometry MapSketchingController::highlightGeometry() const { return mHighlight; } @@ -152,7 +152,7 @@ QStringList MapSketchingController::availableColors() const void MapSketchingController::clearHighlight() { - mHighlight = QgsGeometry( new QgsMultiLineString() ); + mHighlight = MMGeometry( new QgsMultiLineString() ); emit highlightGeometryChanged(); } diff --git a/app/mapsketchingcontroller.h b/app/mapsketchingcontroller.h index ab0488571..73923d631 100644 --- a/app/mapsketchingcontroller.h +++ b/app/mapsketchingcontroller.h @@ -13,6 +13,7 @@ #include #include "qgsgeometry.h" +#include "externalTypes/mmgeometry.h" class QgsVectorLayer; class InputMapSettings; @@ -22,7 +23,7 @@ class MapSketchingController : public QObject Q_OBJECT Q_PROPERTY( InputMapSettings *mapSettings READ mapSettings WRITE setMapSettings NOTIFY mapSettingsChanged ) - Q_PROPERTY( QgsGeometry highlightGeometry READ highlightGeometry NOTIFY highlightGeometryChanged ) + Q_PROPERTY( MMGeometry highlightGeometry READ highlightGeometry NOTIFY highlightGeometryChanged ) Q_PROPERTY( QColor activeColor READ activeColor WRITE setActiveColor NOTIFY activeColorChanged ) Q_PROPERTY( bool canRedo READ canRedo NOTIFY canRedoChanged ) Q_PROPERTY( bool canUndo READ canUndo NOTIFY canUndoChanged ) @@ -51,7 +52,7 @@ class MapSketchingController : public QObject void eraserActiveChanged(); private: - QgsGeometry highlightGeometry() const; + MMGeometry highlightGeometry() const; void clearHighlight(); void setMapSettings( InputMapSettings *settings ); InputMapSettings *mapSettings() const; @@ -65,7 +66,7 @@ class MapSketchingController : public QObject InputMapSettings *mMapSettings = nullptr; QgsVectorLayer *mLayer = nullptr; - QgsGeometry mHighlight; + MMGeometry mHighlight; QgsGeometry mScreenPoints; QColor mColor; From 35c27cf649c81d6fb6bf600c929457ee7f46b32c Mon Sep 17 00:00:00 2001 From: Matej Bagar Date: Fri, 22 May 2026 19:41:32 +0200 Subject: [PATCH 07/11] Fix measurement highlight --- app/maptools/measurementmaptool.cpp | 8 ++++---- app/maptools/measurementmaptool.h | 21 +++++++++++---------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/app/maptools/measurementmaptool.cpp b/app/maptools/measurementmaptool.cpp index d9ce8680e..d30f80514 100644 --- a/app/maptools/measurementmaptool.cpp +++ b/app/maptools/measurementmaptool.cpp @@ -178,17 +178,17 @@ void MeasurementMapTool::updateMapSettings( InputMapSettings *newMapSettings ) } } -const QgsGeometry &MeasurementMapTool::recordedGeometry() const +const MMGeometry &MeasurementMapTool::recordedGeometry() const { return mRecordedGeometry; } -QgsGeometry MeasurementMapTool::existingVertices() const +MMGeometry MeasurementMapTool::existingVertices() const { return mExistingVertices; } -void MeasurementMapTool::setExistingVertices( const QgsGeometry &vertices ) +void MeasurementMapTool::setExistingVertices( const MMGeometry &vertices ) { if ( mExistingVertices.equals( vertices ) ) return; @@ -273,7 +273,7 @@ void MeasurementMapTool::setMeasurementFinalized( bool newMeasurementFinalized ) emit measurementFinalizedChanged( mMeasurementFinalized ); } -void MeasurementMapTool::setRecordedGeometry( const QgsGeometry &newRecordedGeometry ) +void MeasurementMapTool::setRecordedGeometry( const MMGeometry &newRecordedGeometry ) { if ( mRecordedGeometry.equals( newRecordedGeometry ) ) return; diff --git a/app/maptools/measurementmaptool.h b/app/maptools/measurementmaptool.h index 1d041b203..f7c5fe31b 100644 --- a/app/maptools/measurementmaptool.h +++ b/app/maptools/measurementmaptool.h @@ -19,6 +19,7 @@ #include "qgsgeometry.h" #include "qgsvectorlayer.h" #include "qgsmultipoint.h" +#include "externalTypes/mmgeometry.h" const double CLOSE_THRESHOLD = 10.0; // in pixels @@ -26,8 +27,8 @@ class MeasurementMapTool : public AbstractMapTool { Q_OBJECT - Q_PROPERTY( QgsGeometry recordedGeometry READ recordedGeometry WRITE setRecordedGeometry NOTIFY recordedGeometryChanged ) - Q_PROPERTY( QgsGeometry existingVertices READ existingVertices WRITE setExistingVertices NOTIFY existingVerticesChanged ) + Q_PROPERTY( MMGeometry recordedGeometry READ recordedGeometry WRITE setRecordedGeometry NOTIFY recordedGeometryChanged ) + Q_PROPERTY( MMGeometry existingVertices READ existingVertices WRITE setExistingVertices NOTIFY existingVerticesChanged ) Q_PROPERTY( QPointF crosshairPoint READ crosshairPoint WRITE setCrosshairPoint NOTIFY crosshairPointChanged ) Q_PROPERTY( double lengthWithGuideline READ lengthWithGuideline WRITE setLengthWithGuideline NOTIFY lengthWithGuidelineChanged ) @@ -93,11 +94,11 @@ class MeasurementMapTool : public AbstractMapTool bool measurementFinalized() const; void setMeasurementFinalized( bool newMeasurementFinalized ); - const QgsGeometry &recordedGeometry() const; - void setRecordedGeometry( const QgsGeometry &newRecordedGeometry ); + const MMGeometry &recordedGeometry() const; + void setRecordedGeometry( const MMGeometry &newRecordedGeometry ); - QgsGeometry existingVertices() const; - void setExistingVertices( const QgsGeometry &vertices ); + MMGeometry existingVertices() const; + void setExistingVertices( const MMGeometry &vertices ); void resetMapSettings(); void updateMapSettings( InputMapSettings *newMapSettings ); @@ -109,8 +110,8 @@ class MeasurementMapTool : public AbstractMapTool void canUndoChanged( bool canUndo ); void canCloseShapeChanged( bool canUndo ); void measurementFinalizedChanged( bool measurementFinalized ); - void recordedGeometryChanged( const QgsGeometry &recordedGeometry ); - void existingVerticesChanged( const QgsGeometry &vertices ); + void recordedGeometryChanged( const MMGeometry &recordedGeometry ); + void existingVerticesChanged( const MMGeometry &vertices ); void crosshairPointChanged( const QPointF &crosshairPoint ); void isValidGeometryChanged( bool canFinalize ); @@ -123,8 +124,8 @@ class MeasurementMapTool : public AbstractMapTool private: QVector mPoints; - QgsGeometry mRecordedGeometry; - QgsGeometry mExistingVertices; + MMGeometry mRecordedGeometry; + MMGeometry mExistingVertices; QgsDistanceArea mDistanceArea; QPointF mCrosshairPoint; double mLengthWithGuideline = 0; From 5e9a4aad1ec7c7f38f85278aea59302ca75fc76c Mon Sep 17 00:00:00 2001 From: Matej Bagar Date: Fri, 22 May 2026 20:18:57 +0200 Subject: [PATCH 08/11] Fix stake out highlight --- app/inpututils.cpp | 10 +++++----- app/inpututils.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/inpututils.cpp b/app/inpututils.cpp index 5d6006e4e..e13253971 100644 --- a/app/inpututils.cpp +++ b/app/inpututils.cpp @@ -1667,15 +1667,15 @@ QgsRectangle InputUtils::stakeoutPathExtent( return extent; } -QgsGeometry InputUtils::stakeoutGeometry( const QgsPoint &mapPosition, const FeatureLayerPair &target, InputMapSettings *mapSettings ) +MMGeometry InputUtils::stakeoutGeometry( const QgsPoint &mapPosition, const FeatureLayerPair &target, InputMapSettings *mapSettings ) { if ( !mapSettings || !target.isValid() ) - return QgsGeometry(); + return {}; - QgsPointXY targetInLayerCoordinates = target.feature().geometry().asPoint(); - QgsPointXY t = transformPointXY( target.layer()->crs(), mapSettings->destinationCrs(), mapSettings->transformContext(), targetInLayerCoordinates ); + const QgsPointXY targetInLayerCoordinates = target.feature().geometry().asPoint(); + const QgsPointXY t = transformPointXY( target.layer()->crs(), mapSettings->destinationCrs(), mapSettings->transformContext(), targetInLayerCoordinates ); - QVector points { mapPosition, QgsPoint( t ) }; + const QVector points { mapPosition, QgsPoint( t ) }; return QgsGeometry::fromPolyline( points ); } diff --git a/app/inpututils.h b/app/inpututils.h index e9d2e2c0d..87a0a2f57 100644 --- a/app/inpututils.h +++ b/app/inpututils.h @@ -523,7 +523,7 @@ class InputUtils: public QObject Q_INVOKABLE QgsRectangle stakeoutPathExtent( MapPosition *mapPosition, const FeatureLayerPair &targetFeature, InputMapSettings *mapSettings, double mapExtentOffset ); //! Returns geometry created out of the two points and converts it to map canvas screen pixels. - Q_INVOKABLE static QgsGeometry stakeoutGeometry( const QgsPoint &mapPosition, const FeatureLayerPair &target, InputMapSettings *mapSettings ); + Q_INVOKABLE static MMGeometry stakeoutGeometry( const QgsPoint &mapPosition, const FeatureLayerPair &target, InputMapSettings *mapSettings ); // Translates distance to target point into scale factor that should be used for map canvas during stakeout qreal distanceToScale( qreal distance ); From 0d4e0114f31d0496bdc7de551fd7ad0a637980b9 Mon Sep 17 00:00:00 2001 From: Matej Bagar Date: Mon, 1 Jun 2026 13:27:03 +0200 Subject: [PATCH 09/11] Refactor MMGeometry class into QGIS patch --- app/CMakeLists.txt | 2 +- app/externalTypes/mmgeometry.h | 40 ------------------- app/guidelinecontroller.cpp | 4 +- app/guidelinecontroller.h | 10 ++--- app/inpututils.cpp | 8 ++-- app/inpututils.h | 7 ++-- app/mapsketchingcontroller.cpp | 6 +-- app/mapsketchingcontroller.h | 7 ++-- app/maptools/measurementmaptool.cpp | 8 ++-- app/maptools/measurementmaptool.h | 21 +++++----- app/mmtypeutils.h | 27 +++++++++++++ app/multieditmanager.h | 6 +-- .../tracking/positiontrackinghighlight.cpp | 6 +-- .../tracking/positiontrackinghighlight.h | 11 +++-- app/qml/map/MMHighlight.qml | 2 +- .../ports/qgis/geometry-equals-operator.patch | 21 ++++++++++ vcpkg/ports/qgis/portfile.cmake | 3 ++ 17 files changed, 98 insertions(+), 91 deletions(-) delete mode 100644 app/externalTypes/mmgeometry.h create mode 100644 app/mmtypeutils.h create mode 100644 vcpkg/ports/qgis/geometry-equals-operator.patch diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index f1898c0b5..74ca2e171 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -190,7 +190,7 @@ set(MM_HDRS workspacesmodel.h workspacesproxymodel.h mmstyle.h - externalTypes/mmgeometry.h + mmtypeutils.h ) if (NOT WIN32) diff --git a/app/externalTypes/mmgeometry.h b/app/externalTypes/mmgeometry.h deleted file mode 100644 index 899ac4fc9..000000000 --- a/app/externalTypes/mmgeometry.h +++ /dev/null @@ -1,40 +0,0 @@ -/*************************************************************************** -* * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ - -#ifndef MMGEOMETRY_H -#define MMGEOMETRY_H - -#include - -#include - -/** - * MMGeometry is just a wrapper around QgsGeometry, which adds equals operator that is missing. - * We expose this type to QML instead of QgsGeometry. The reason is that QML in Qt 6.9+ also checks equality, when firing - * onChanged signal. The missing operator is breaking property bindings. - */ -class MMGeometry: public QgsGeometry -{ - Q_GADGET - QML_VALUE_TYPE( mmGeometry ); - - public: - using QgsGeometry::QgsGeometry; - - MMGeometry() = default; - MMGeometry( const QgsGeometry &geom ) : QgsGeometry( geom ) {} - MMGeometry( QgsGeometry &geom ) : QgsGeometry( geom ) {} - - bool operator==( const MMGeometry &rhs ) const - { - return equals( rhs ); - } -}; - -#endif //MMGEOMETRY_H diff --git a/app/guidelinecontroller.cpp b/app/guidelinecontroller.cpp index a6fdb26df..ce9151ebe 100644 --- a/app/guidelinecontroller.cpp +++ b/app/guidelinecontroller.cpp @@ -187,12 +187,12 @@ void GuidelineController::buildGuideline() } } -const MMGeometry &GuidelineController::guidelineGeometry() const +const QgsGeometry &GuidelineController::guidelineGeometry() const { return mGuidelineGeometry; } -void GuidelineController::setGuidelineGeometry( const MMGeometry &newGuidelineGeometry ) +void GuidelineController::setGuidelineGeometry( const QgsGeometry &newGuidelineGeometry ) { if ( mGuidelineGeometry.equals( newGuidelineGeometry ) ) return; diff --git a/app/guidelinecontroller.h b/app/guidelinecontroller.h index aea3f5cdc..76166fcc6 100644 --- a/app/guidelinecontroller.h +++ b/app/guidelinecontroller.h @@ -37,13 +37,13 @@ class GuidelineController : public QObject Q_PROPERTY( bool allowed READ allowed WRITE setAllowed NOTIFY allowedChanged ) // output properties (real geometry + crosshair position ) in map CRS - Q_PROPERTY( MMGeometry guidelineGeometry READ guidelineGeometry WRITE setGuidelineGeometry NOTIFY guidelineGeometryChanged ) + Q_PROPERTY( QgsGeometry guidelineGeometry READ guidelineGeometry WRITE setGuidelineGeometry NOTIFY guidelineGeometryChanged ) public: explicit GuidelineController( QObject *parent = nullptr ); - const MMGeometry &guidelineGeometry() const; - void setGuidelineGeometry( const MMGeometry &newGuidelineGeometry ); + const QgsGeometry &guidelineGeometry() const; + void setGuidelineGeometry( const QgsGeometry &newGuidelineGeometry ); QPointF crosshairPosition() const; void setCrosshairPosition( QPointF newCrosshairPosition ); @@ -71,7 +71,7 @@ class GuidelineController : public QObject signals: - void guidelineGeometryChanged( const MMGeometry &guidelineGeometry ); + void guidelineGeometryChanged( const QgsGeometry &guidelineGeometry ); void crosshairPositionChanged( QPointF crosshairPosition ); void realGeometryChanged( const QgsGeometry &realGeometry ); @@ -93,7 +93,7 @@ class GuidelineController : public QObject private: - MMGeometry mGuidelineGeometry; + QgsGeometry mGuidelineGeometry; QPointF mCrosshairPosition; QgsGeometry mRealGeometry; InputMapSettings *mMapSettings = nullptr; // not owned diff --git a/app/inpututils.cpp b/app/inpututils.cpp index e13253971..2b6595cd3 100644 --- a/app/inpututils.cpp +++ b/app/inpututils.cpp @@ -446,14 +446,14 @@ QgsGeometry InputUtils::transformGeometry( const QgsGeometry &geometry, const Qg return transformGeometry( geometry, sourceCRS, targetLayer->crs(), targetLayer->transformContext() ); } -MMGeometry InputUtils::transformGeometryToMapWithLayer( const QgsGeometry &geometry, QgsVectorLayer *sourceLayer, InputMapSettings *targetSettings ) +QgsGeometry InputUtils::transformGeometryToMapWithLayer( const QgsGeometry &geometry, QgsVectorLayer *sourceLayer, InputMapSettings *targetSettings ) { if ( !sourceLayer || !sourceLayer->isValid() || !targetSettings ) { return {}; } - return MMGeometry( transformGeometry( geometry, sourceLayer->crs(), targetSettings->destinationCrs(), targetSettings->transformContext() ) ); + return QgsGeometry( transformGeometry( geometry, sourceLayer->crs(), targetSettings->destinationCrs(), targetSettings->transformContext() ) ); } QgsGeometry InputUtils::transformGeometryToMapWithCRS( const QgsGeometry &geometry, const QgsCoordinateReferenceSystem &sourceCRS, InputMapSettings *targetSettings ) @@ -816,7 +816,7 @@ QgsPoint InputUtils::point( double x, double y, double z, double m ) return QgsPoint( x, y, z, m ); } -MMGeometry InputUtils::emptyGeometry() +QgsGeometry InputUtils::emptyGeometry() { return {}; } @@ -1667,7 +1667,7 @@ QgsRectangle InputUtils::stakeoutPathExtent( return extent; } -MMGeometry InputUtils::stakeoutGeometry( const QgsPoint &mapPosition, const FeatureLayerPair &target, InputMapSettings *mapSettings ) +QgsGeometry InputUtils::stakeoutGeometry( const QgsPoint &mapPosition, const FeatureLayerPair &target, InputMapSettings *mapSettings ) { if ( !mapSettings || !target.isValid() ) return {}; diff --git a/app/inpututils.h b/app/inpututils.h index 87a0a2f57..d94e1803e 100644 --- a/app/inpututils.h +++ b/app/inpututils.h @@ -38,7 +38,6 @@ #include "inputmapsettings.h" #include "featurelayerpair.h" #include "qgscoordinateformatter.h" -#include "externalTypes/mmgeometry.h" #include "position/mapposition.h" class QgsFeature; @@ -115,7 +114,7 @@ class InputUtils: public QObject static QgsGeometry transformGeometry( const QgsGeometry &geometry, const QgsCoordinateReferenceSystem &sourceCRS, const QgsCoordinateReferenceSystem &destinationCRS, const QgsCoordinateTransformContext &context ); //! Helper methods to use for transforming geometry from QML as overriding does not work properly there - Q_INVOKABLE static MMGeometry transformGeometryToMapWithLayer( const QgsGeometry &geometry, QgsVectorLayer *sourceLayer, InputMapSettings *targetSettings ); + Q_INVOKABLE static QgsGeometry transformGeometryToMapWithLayer( const QgsGeometry &geometry, QgsVectorLayer *sourceLayer, InputMapSettings *targetSettings ); Q_INVOKABLE static QgsGeometry transformGeometryToMapWithCRS( const QgsGeometry &geometry, const QgsCoordinateReferenceSystem &sourceCRS, InputMapSettings *targetSettings ); /** @@ -271,7 +270,7 @@ class InputUtils: public QObject /** * Creates empty geometry */ - Q_INVOKABLE static MMGeometry emptyGeometry(); + Q_INVOKABLE static QgsGeometry emptyGeometry(); /** * Creates empty feature @@ -523,7 +522,7 @@ class InputUtils: public QObject Q_INVOKABLE QgsRectangle stakeoutPathExtent( MapPosition *mapPosition, const FeatureLayerPair &targetFeature, InputMapSettings *mapSettings, double mapExtentOffset ); //! Returns geometry created out of the two points and converts it to map canvas screen pixels. - Q_INVOKABLE static MMGeometry stakeoutGeometry( const QgsPoint &mapPosition, const FeatureLayerPair &target, InputMapSettings *mapSettings ); + Q_INVOKABLE static QgsGeometry stakeoutGeometry( const QgsPoint &mapPosition, const FeatureLayerPair &target, InputMapSettings *mapSettings ); // Translates distance to target point into scale factor that should be used for map canvas during stakeout qreal distanceToScale( qreal distance ); diff --git a/app/mapsketchingcontroller.cpp b/app/mapsketchingcontroller.cpp index a8c39799e..af5cf5010 100644 --- a/app/mapsketchingcontroller.cpp +++ b/app/mapsketchingcontroller.cpp @@ -44,7 +44,7 @@ void MapSketchingController::updateHighlight( const QPointF &oldPoint, const QPo ls->addZValue(); ls->addMValue(); QgsMultiLineString *mls = new QgsMultiLineString( QList() << ls ); - mHighlight = MMGeometry( mls ); + mHighlight = QgsGeometry( mls ); mScreenPoints = QgsGeometry( new QgsLineString( { QgsPointXY( oldPoint.x(), oldPoint.y() ) } ) ); } @@ -139,7 +139,7 @@ void MapSketchingController::undo() const mLayer->undoStack()->undo(); } -MMGeometry MapSketchingController::highlightGeometry() const +QgsGeometry MapSketchingController::highlightGeometry() const { return mHighlight; } @@ -152,7 +152,7 @@ QStringList MapSketchingController::availableColors() const void MapSketchingController::clearHighlight() { - mHighlight = MMGeometry( new QgsMultiLineString() ); + mHighlight = QgsGeometry( new QgsMultiLineString() ); emit highlightGeometryChanged(); } diff --git a/app/mapsketchingcontroller.h b/app/mapsketchingcontroller.h index 73923d631..ab0488571 100644 --- a/app/mapsketchingcontroller.h +++ b/app/mapsketchingcontroller.h @@ -13,7 +13,6 @@ #include #include "qgsgeometry.h" -#include "externalTypes/mmgeometry.h" class QgsVectorLayer; class InputMapSettings; @@ -23,7 +22,7 @@ class MapSketchingController : public QObject Q_OBJECT Q_PROPERTY( InputMapSettings *mapSettings READ mapSettings WRITE setMapSettings NOTIFY mapSettingsChanged ) - Q_PROPERTY( MMGeometry highlightGeometry READ highlightGeometry NOTIFY highlightGeometryChanged ) + Q_PROPERTY( QgsGeometry highlightGeometry READ highlightGeometry NOTIFY highlightGeometryChanged ) Q_PROPERTY( QColor activeColor READ activeColor WRITE setActiveColor NOTIFY activeColorChanged ) Q_PROPERTY( bool canRedo READ canRedo NOTIFY canRedoChanged ) Q_PROPERTY( bool canUndo READ canUndo NOTIFY canUndoChanged ) @@ -52,7 +51,7 @@ class MapSketchingController : public QObject void eraserActiveChanged(); private: - MMGeometry highlightGeometry() const; + QgsGeometry highlightGeometry() const; void clearHighlight(); void setMapSettings( InputMapSettings *settings ); InputMapSettings *mapSettings() const; @@ -66,7 +65,7 @@ class MapSketchingController : public QObject InputMapSettings *mMapSettings = nullptr; QgsVectorLayer *mLayer = nullptr; - MMGeometry mHighlight; + QgsGeometry mHighlight; QgsGeometry mScreenPoints; QColor mColor; diff --git a/app/maptools/measurementmaptool.cpp b/app/maptools/measurementmaptool.cpp index d30f80514..d9ce8680e 100644 --- a/app/maptools/measurementmaptool.cpp +++ b/app/maptools/measurementmaptool.cpp @@ -178,17 +178,17 @@ void MeasurementMapTool::updateMapSettings( InputMapSettings *newMapSettings ) } } -const MMGeometry &MeasurementMapTool::recordedGeometry() const +const QgsGeometry &MeasurementMapTool::recordedGeometry() const { return mRecordedGeometry; } -MMGeometry MeasurementMapTool::existingVertices() const +QgsGeometry MeasurementMapTool::existingVertices() const { return mExistingVertices; } -void MeasurementMapTool::setExistingVertices( const MMGeometry &vertices ) +void MeasurementMapTool::setExistingVertices( const QgsGeometry &vertices ) { if ( mExistingVertices.equals( vertices ) ) return; @@ -273,7 +273,7 @@ void MeasurementMapTool::setMeasurementFinalized( bool newMeasurementFinalized ) emit measurementFinalizedChanged( mMeasurementFinalized ); } -void MeasurementMapTool::setRecordedGeometry( const MMGeometry &newRecordedGeometry ) +void MeasurementMapTool::setRecordedGeometry( const QgsGeometry &newRecordedGeometry ) { if ( mRecordedGeometry.equals( newRecordedGeometry ) ) return; diff --git a/app/maptools/measurementmaptool.h b/app/maptools/measurementmaptool.h index f7c5fe31b..1d041b203 100644 --- a/app/maptools/measurementmaptool.h +++ b/app/maptools/measurementmaptool.h @@ -19,7 +19,6 @@ #include "qgsgeometry.h" #include "qgsvectorlayer.h" #include "qgsmultipoint.h" -#include "externalTypes/mmgeometry.h" const double CLOSE_THRESHOLD = 10.0; // in pixels @@ -27,8 +26,8 @@ class MeasurementMapTool : public AbstractMapTool { Q_OBJECT - Q_PROPERTY( MMGeometry recordedGeometry READ recordedGeometry WRITE setRecordedGeometry NOTIFY recordedGeometryChanged ) - Q_PROPERTY( MMGeometry existingVertices READ existingVertices WRITE setExistingVertices NOTIFY existingVerticesChanged ) + Q_PROPERTY( QgsGeometry recordedGeometry READ recordedGeometry WRITE setRecordedGeometry NOTIFY recordedGeometryChanged ) + Q_PROPERTY( QgsGeometry existingVertices READ existingVertices WRITE setExistingVertices NOTIFY existingVerticesChanged ) Q_PROPERTY( QPointF crosshairPoint READ crosshairPoint WRITE setCrosshairPoint NOTIFY crosshairPointChanged ) Q_PROPERTY( double lengthWithGuideline READ lengthWithGuideline WRITE setLengthWithGuideline NOTIFY lengthWithGuidelineChanged ) @@ -94,11 +93,11 @@ class MeasurementMapTool : public AbstractMapTool bool measurementFinalized() const; void setMeasurementFinalized( bool newMeasurementFinalized ); - const MMGeometry &recordedGeometry() const; - void setRecordedGeometry( const MMGeometry &newRecordedGeometry ); + const QgsGeometry &recordedGeometry() const; + void setRecordedGeometry( const QgsGeometry &newRecordedGeometry ); - MMGeometry existingVertices() const; - void setExistingVertices( const MMGeometry &vertices ); + QgsGeometry existingVertices() const; + void setExistingVertices( const QgsGeometry &vertices ); void resetMapSettings(); void updateMapSettings( InputMapSettings *newMapSettings ); @@ -110,8 +109,8 @@ class MeasurementMapTool : public AbstractMapTool void canUndoChanged( bool canUndo ); void canCloseShapeChanged( bool canUndo ); void measurementFinalizedChanged( bool measurementFinalized ); - void recordedGeometryChanged( const MMGeometry &recordedGeometry ); - void existingVerticesChanged( const MMGeometry &vertices ); + void recordedGeometryChanged( const QgsGeometry &recordedGeometry ); + void existingVerticesChanged( const QgsGeometry &vertices ); void crosshairPointChanged( const QPointF &crosshairPoint ); void isValidGeometryChanged( bool canFinalize ); @@ -124,8 +123,8 @@ class MeasurementMapTool : public AbstractMapTool private: QVector mPoints; - MMGeometry mRecordedGeometry; - MMGeometry mExistingVertices; + QgsGeometry mRecordedGeometry; + QgsGeometry mExistingVertices; QgsDistanceArea mDistanceArea; QPointF mCrosshairPoint; double mLengthWithGuideline = 0; diff --git a/app/mmtypeutils.h b/app/mmtypeutils.h new file mode 100644 index 000000000..76f4da156 --- /dev/null +++ b/app/mmtypeutils.h @@ -0,0 +1,27 @@ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +/** + * This file should be used for explicit declaration of 3rd party types into QML. + */ + +#ifndef MMTYPEUTILS_H +#define MMTYPEUTILS_H + +#include +#include + +struct ForeignGeometry +{ + Q_GADGET + QML_FOREIGN( QgsGeometry ) + QML_VALUE_TYPE( qgsGeometry ); +}; + +#endif //MMTYPEUTILS_H diff --git a/app/multieditmanager.h b/app/multieditmanager.h index ff811eebb..c39ff31ef 100644 --- a/app/multieditmanager.h +++ b/app/multieditmanager.h @@ -10,11 +10,11 @@ #ifndef MULTIEDITMANAGER_H #define MULTIEDITMANAGER_H +#include #include #include "featurelayerpair.h" #include "staticfeaturesmodel.h" -#include "externalTypes/mmgeometry.h" class QgsVectorLayer; @@ -31,7 +31,7 @@ class MultiEditManager : public QObject Q_PROPERTY( QgsVectorLayer *layer MEMBER mLayer NOTIFY layerChanged ) Q_PROPERTY( StaticFeaturesModel *model READ model CONSTANT ) - Q_PROPERTY( MMGeometry geometry READ collectGeometry NOTIFY geometryChanged ) + Q_PROPERTY( QgsGeometry geometry READ collectGeometry NOTIFY geometryChanged ) Q_PROPERTY( InputMapSettings *mapSettings MEMBER mMapSettings ) public: @@ -50,7 +50,7 @@ class MultiEditManager : public QObject Q_INVOKABLE void deleteSelectedFeatures(); //! Returns multipart geometry of all geometries in the model, in map crs - MMGeometry collectGeometry() const { return mModel->collectGeometries( mMapSettings ); } + QgsGeometry collectGeometry() const { return mModel->collectGeometries( mMapSettings ); } StaticFeaturesModel *model() const { return mModel.get(); } diff --git a/app/position/tracking/positiontrackinghighlight.cpp b/app/position/tracking/positiontrackinghighlight.cpp index 1cd3fef7c..adbe0b3db 100644 --- a/app/position/tracking/positiontrackinghighlight.cpp +++ b/app/position/tracking/positiontrackinghighlight.cpp @@ -35,7 +35,7 @@ void PositionTrackingHighlight::recalculate() // add map position to the end of the tracked geometry // note - map position must be in the same CRS as the tracked geometry - MMGeometry highlightGeometry( mTrackedGeometry ); + QgsGeometry highlightGeometry( mTrackedGeometry ); QgsVertexId lastVertex( 0, 0, highlightGeometry.constGet()->vertexCount() ); highlightGeometry.get()->insertVertex( lastVertex, mMapPosition ); @@ -57,12 +57,12 @@ void PositionTrackingHighlight::setTrackedGeometry( const QgsGeometry &newTracke emit trackedGeometryChanged( mTrackedGeometry ); } -MMGeometry PositionTrackingHighlight::highlightGeometry() const +QgsGeometry PositionTrackingHighlight::highlightGeometry() const { return mHighlightGeometry; } -void PositionTrackingHighlight::setHighlightGeometry( const MMGeometry &newHighlightGeometry ) +void PositionTrackingHighlight::setHighlightGeometry( const QgsGeometry &newHighlightGeometry ) { if ( mHighlightGeometry.equals( newHighlightGeometry ) ) return; diff --git a/app/position/tracking/positiontrackinghighlight.h b/app/position/tracking/positiontrackinghighlight.h index db4dc99da..396f1a7ed 100644 --- a/app/position/tracking/positiontrackinghighlight.h +++ b/app/position/tracking/positiontrackinghighlight.h @@ -14,7 +14,6 @@ #include #include "qgsgeometry.h" -#include "externalTypes/mmgeometry.h" class PositionTrackingHighlight : public QObject { @@ -26,7 +25,7 @@ class PositionTrackingHighlight : public QObject Q_PROPERTY( QgsGeometry trackedGeometry READ trackedGeometry WRITE setTrackedGeometry NOTIFY trackedGeometryChanged ) // Geometry out - Q_PROPERTY( MMGeometry highlightGeometry READ highlightGeometry NOTIFY highlightGeometryChanged ) + Q_PROPERTY( QgsGeometry highlightGeometry READ highlightGeometry NOTIFY highlightGeometryChanged ) public: explicit PositionTrackingHighlight( QObject *parent = nullptr ); @@ -34,7 +33,7 @@ class PositionTrackingHighlight : public QObject QgsGeometry trackedGeometry() const; void setTrackedGeometry( const QgsGeometry &newTrackedGeometry ); - MMGeometry highlightGeometry() const; + QgsGeometry highlightGeometry() const; QgsPoint mapPosition() const; void setMapPosition( QgsPoint newMapPosition ); @@ -44,15 +43,15 @@ class PositionTrackingHighlight : public QObject signals: void trackedGeometryChanged( QgsGeometry trackedGeometry ); - void highlightGeometryChanged( MMGeometry highlightGeometry ); + void highlightGeometryChanged( QgsGeometry highlightGeometry ); void mapPositionChanged( QgsPoint mapPosition ); private: - void setHighlightGeometry( const MMGeometry &newHighlightGeometry ); + void setHighlightGeometry( const QgsGeometry &newHighlightGeometry ); QgsGeometry mTrackedGeometry; - MMGeometry mHighlightGeometry; + QgsGeometry mHighlightGeometry; QgsPoint mMapPosition; }; diff --git a/app/qml/map/MMHighlight.qml b/app/qml/map/MMHighlight.qml index affa6da97..fb16f35a4 100644 --- a/app/qml/map/MMHighlight.qml +++ b/app/qml/map/MMHighlight.qml @@ -21,7 +21,7 @@ Item { // geometry to highlight // geometry must be in map canvas CRS! - property mmGeometry geometry + property qgsGeometry geometry // for transformation of the highlight to the correct location on the map property MM.MapSettings mapSettings diff --git a/vcpkg/ports/qgis/geometry-equals-operator.patch b/vcpkg/ports/qgis/geometry-equals-operator.patch new file mode 100644 index 000000000..8d7207dbb --- /dev/null +++ b/vcpkg/ports/qgis/geometry-equals-operator.patch @@ -0,0 +1,21 @@ +diff --git a/src/core/geometry/qgsgeometry.h b/src/core/geometry/qgsgeometry.h +index 98e40e74e14..06fa2a78ddd 100644 +--- a/src/core/geometry/qgsgeometry.h ++++ b/src/core/geometry/qgsgeometry.h +@@ -177,6 +177,16 @@ class CORE_EXPORT QgsGeometry + */ + QgsGeometry &operator=( QgsGeometry const &rhs ) SIP_SKIP; + ++ /** ++ * Upstream QgsGeometry is missing equals operator overload and uses equals() to correctly check for equality. ++ * However QML in Qt 6.9+ also checks equality, before firing onChanged signal. The incorrect equality evaluation ++ * is breaking property bindings. ++ */ ++ bool operator==( const QgsGeometry &rhs ) const ++ { ++ return equals( rhs ); ++ } ++ + /** + * Creates a geometry from an abstract geometry object. Ownership of + * geom is transferred. diff --git a/vcpkg/ports/qgis/portfile.cmake b/vcpkg/ports/qgis/portfile.cmake index d98e62100..0cd68add3 100644 --- a/vcpkg/ports/qgis/portfile.cmake +++ b/vcpkg/ports/qgis/portfile.cmake @@ -21,6 +21,9 @@ vcpkg_from_github( snapping-casting.patch qflags-qstring-arg.patch point-cloud-guard.patch + # TODO: when updating to QGIS 4, this has to be reworked to support new QgsGeometry + # comparison in QGIS 4 + geometry-equals-operator.patch ) file(REMOVE ${SOURCE_PATH}/cmake/FindQtKeychain.cmake) From 556587fe9313c9eaa6c2d6942d5e67e2e3d21bd9 Mon Sep 17 00:00:00 2001 From: Matej Bagar Date: Mon, 1 Jun 2026 13:28:33 +0200 Subject: [PATCH 10/11] Remove forgotten directory include --- app/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 74ca2e171..b75d1b8e1 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -332,7 +332,6 @@ target_include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/layer ${CMAKE_CURRENT_SOURCE_DIR}/maptools ${CMAKE_CURRENT_SOURCE_DIR}/position - ${CMAKE_CURRENT_SOURCE_DIR}/externalTypes ) qt_policy(SET QTP0002 NEW) From 7d18cc5efa8b1b4378eada4d212f7683010c7f11 Mon Sep 17 00:00:00 2001 From: Matej Bagar Date: Mon, 1 Jun 2026 13:30:48 +0200 Subject: [PATCH 11/11] Minimize git diff --- app/inpututils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/inpututils.cpp b/app/inpututils.cpp index 2b6595cd3..3fb7a2564 100644 --- a/app/inpututils.cpp +++ b/app/inpututils.cpp @@ -453,7 +453,7 @@ QgsGeometry InputUtils::transformGeometryToMapWithLayer( const QgsGeometry &geom return {}; } - return QgsGeometry( transformGeometry( geometry, sourceLayer->crs(), targetSettings->destinationCrs(), targetSettings->transformContext() ) ); + return transformGeometry( geometry, sourceLayer->crs(), targetSettings->destinationCrs(), targetSettings->transformContext() ); } QgsGeometry InputUtils::transformGeometryToMapWithCRS( const QgsGeometry &geometry, const QgsCoordinateReferenceSystem &sourceCRS, InputMapSettings *targetSettings )