diff --git a/images/images.qrc b/images/images.qrc
index 2a2bbfe8bb4..aa79f2e192d 100755
--- a/images/images.qrc
+++ b/images/images.qrc
@@ -704,6 +704,7 @@
themes/default/mIconGPU.svg
themes/default/mAddToProject.svg
themes/default/mDockify.svg
+ themes/default/mActionReverseLine.svg
themes/default/mActionAdd3DMap.svg
diff --git a/images/themes/default/mActionReverseLine.svg b/images/themes/default/mActionReverseLine.svg
new file mode 100644
index 00000000000..e40cab70bf6
--- /dev/null
+++ b/images/themes/default/mActionReverseLine.svg
@@ -0,0 +1,142 @@
+
+
diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt
index 7d273efcd48..c2a5a59dd1c 100755
--- a/src/app/CMakeLists.txt
+++ b/src/app/CMakeLists.txt
@@ -98,6 +98,7 @@ SET(QGIS_APP_SRCS
qgsmaptooloffsetpointsymbol.cpp
qgsmaptoolpointsymbol.cpp
qgsmaptoolreshape.cpp
+ qgsmaptoolreverseline.cpp
qgsmaptoolrotatefeature.cpp
qgsmaptoolrotatelabel.cpp
qgsmaptoolrotatepointsymbols.cpp
@@ -320,6 +321,7 @@ SET (QGIS_APP_MOC_HDRS
qgsmaptooloffsetpointsymbol.h
qgsmaptoolpointsymbol.h
qgsmaptoolreshape.h
+ qgsmaptoolreverseline.h
qgsmaptoolrotatefeature.h
qgsmaptoolrotatelabel.h
qgsmaptoolrotatepointsymbols.h
diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp
index aa2d010c7cf..4245e25261e 100644
--- a/src/app/qgisapp.cpp
+++ b/src/app/qgisapp.cpp
@@ -403,6 +403,7 @@ Q_GUI_EXPORT extern int qt_defaultDpiX();
#include "qgsmaptoolmovelabel.h"
#include "qgsmaptoolrotatelabel.h"
#include "qgsmaptoolchangelabelproperties.h"
+#include "qgsmaptoolreverseline.h"
#include "vertextool/qgsvertextool.h"
@@ -1466,6 +1467,7 @@ QgisApp::~QgisApp()
delete mMapTools.mOffsetCurve;
delete mMapTools.mPinLabels;
delete mMapTools.mReshapeFeatures;
+ delete mMapTools.mReverseLine;
delete mMapTools.mRotateFeature;
delete mMapTools.mRotateLabel;
delete mMapTools.mRotatePointSymbolsTool;
@@ -2063,6 +2065,7 @@ void QgisApp::createActions()
connect( mActionOffsetPointSymbol, &QAction::triggered, this, &QgisApp::offsetPointSymbol );
connect( mActionSnappingOptions, &QAction::triggered, this, &QgisApp::snappingOptions );
connect( mActionOffsetCurve, &QAction::triggered, this, &QgisApp::offsetCurve );
+ connect( mActionReverseLine, &QAction::triggered, this, &QgisApp::reverseLine );
// View Menu Items
connect( mActionPan, &QAction::triggered, this, &QgisApp::pan );
@@ -2354,6 +2357,7 @@ void QgisApp::createActionGroups()
mMapToolGroup->addAction( mActionMoveLabel );
mMapToolGroup->addAction( mActionRotateLabel );
mMapToolGroup->addAction( mActionChangeLabelProperties );
+ mMapToolGroup->addAction( mActionReverseLine );
//
// Preview Modes Group
@@ -3307,6 +3311,7 @@ void QgisApp::setTheme( const QString &themeName )
mActionDecorationNorthArrow->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/north_arrow.png" ) ) );
mActionDecorationScaleBar->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionScaleBar.svg" ) ) );
mActionDecorationGrid->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/transformed.svg" ) ) );
+ mActionReverseLine->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionReverseLine.svg" ) ) );
emit currentThemeChanged( themeName );
}
@@ -3518,6 +3523,8 @@ void QgisApp::createCanvasTools()
mMapTools.mOffsetCurve->setAction( mActionOffsetCurve );
mMapTools.mReshapeFeatures = new QgsMapToolReshape( mMapCanvas );
mMapTools.mReshapeFeatures->setAction( mActionReshapeFeatures );
+ mMapTools.mReverseLine = new QgsMapToolReverseLine( mMapCanvas );
+ mMapTools.mReverseLine->setAction( mActionReverseLine );
mMapTools.mSplitFeatures = new QgsMapToolSplitFeatures( mMapCanvas );
mMapTools.mSplitFeatures->setAction( mActionSplitFeatures );
mMapTools.mSplitParts = new QgsMapToolSplitParts( mMapCanvas );
@@ -7605,6 +7612,11 @@ void QgisApp::deletePart()
mMapCanvas->setMapTool( mMapTools.mDeletePart );
}
+void QgisApp::reverseLine()
+{
+ mMapCanvas->setMapTool( mMapTools.mReverseLine );
+}
+
QgsGeometry QgisApp::unionGeometries( const QgsVectorLayer *vl, QgsFeatureList &featureList, bool &canceled )
{
canceled = false;
@@ -12140,6 +12152,7 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer *layer )
mActionPasteStyle->setEnabled( false );
mActionCopyLayer->setEnabled( false );
mActionPasteLayer->setEnabled( false );
+ mActionReverseLine->setEnabled( false );
mUndoDock->widget()->setEnabled( false );
mActionUndo->setEnabled( false );
@@ -12214,6 +12227,7 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer *layer )
mActionZoomToSelected->setEnabled( isSpatial );
mActionLabeling->setEnabled( isSpatial );
mActionDiagramProperties->setEnabled( isSpatial );
+ mActionReverseLine->setEnabled( false );
mActionSelectFeatures->setEnabled( isSpatial );
mActionSelectPolygon->setEnabled( isSpatial );
@@ -12357,6 +12371,7 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer *layer )
mActionSplitParts->setEnabled( isEditable && canChangeGeometry && isMultiPart );
mActionSimplifyFeature->setEnabled( isEditable && canChangeGeometry );
mActionOffsetCurve->setEnabled( isEditable && canAddFeatures && canChangeAttributes );
+ mActionReverseLine->setEnabled( isEditable && canChangeGeometry );
mActionAddRing->setEnabled( false );
mActionFillRing->setEnabled( false );
diff --git a/src/app/qgisapp.h b/src/app/qgisapp.h
index 17a729165e7..44d2d5823e2 100644
--- a/src/app/qgisapp.h
+++ b/src/app/qgisapp.h
@@ -1399,6 +1399,8 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
void rotatePointSymbols();
//! activates the offset point symbol tool
void offsetPointSymbol();
+ //! activates the reverse line tool
+ void reverseLine();
//! activates the tool
void setMapTool( QgsMapTool *tool, bool clean = false );
@@ -2056,6 +2058,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
QgsMapTool *mRotateFeature = nullptr;
QgsMapTool *mRotateLabel = nullptr;
QgsMapTool *mChangeLabelProperties = nullptr;
+ QgsMapTool *mReverseLine = nullptr ;
} mMapTools;
QgsMapTool *mNonEditMapTool = nullptr;
diff --git a/src/app/qgsmaptoolreverseline.cpp b/src/app/qgsmaptoolreverseline.cpp
new file mode 100644
index 00000000000..2b5d2ec2dd4
--- /dev/null
+++ b/src/app/qgsmaptoolreverseline.cpp
@@ -0,0 +1,182 @@
+/***************************************************************************
+ qgsmaptoolreverseline.cpp - reverse a line geometry
+ ---------------------
+ begin : April 2018
+ copyright : (C) 2018 by Loïc Bartoletti
+ email : loic dot bartoletti at oslandia dot com
+ ***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include "qgsmaptoolreverseline.h"
+
+#include "qgsfeatureiterator.h"
+#include "qgsmapcanvas.h"
+#include "qgsvertexmarker.h"
+#include "qgsvectorlayer.h"
+#include "qgsgeometry.h"
+#include "qgsrubberband.h"
+#include "qgssnappingutils.h"
+#include "qgstolerance.h"
+#include "qgisapp.h"
+#include "qgslinestring.h"
+#include "qgsmultilinestring.h"
+
+#include
+
+QgsMapToolReverseLine::QgsMapToolReverseLine( QgsMapCanvas *canvas )
+ : QgsMapToolEdit( canvas )
+{
+ mToolName = tr( "Reverse line geometry" );
+}
+
+QgsMapToolReverseLine::~QgsMapToolReverseLine()
+{
+}
+
+void QgsMapToolReverseLine::canvasMoveEvent( QgsMapMouseEvent *e )
+{
+ Q_UNUSED( e );
+ //nothing to do
+}
+
+void QgsMapToolReverseLine::canvasPressEvent( QgsMapMouseEvent *e )
+{
+ mPressedFid = -1;
+ mPressedPartNum = -1;
+
+ QgsMapLayer *currentLayer = mCanvas->currentLayer();
+ if ( !currentLayer )
+ return;
+
+ vlayer = qobject_cast( currentLayer );
+ if ( !vlayer )
+ {
+ notifyNotVectorLayer();
+ return;
+ }
+
+ if ( !vlayer->isEditable() )
+ {
+ notifyNotEditableLayer();
+ return;
+ }
+
+ QgsGeometry geomPart = partUnderPoint( e->pos(), mPressedFid, mPressedPartNum );
+
+ if ( mPressedFid != -1 )
+ {
+ mRubberBand.reset( createRubberBand( vlayer->geometryType() ) );
+
+ mRubberBand->setToGeometry( geomPart, vlayer );
+ mRubberBand->show();
+ }
+
+}
+
+void QgsMapToolReverseLine::canvasReleaseEvent( QgsMapMouseEvent *e )
+{
+ Q_UNUSED( e );
+
+ if ( !vlayer || !vlayer->isEditable() )
+ {
+ return;
+ }
+
+ if ( mPressedFid == -1 )
+ return;
+
+ QgsFeature f;
+ vlayer->getFeatures( QgsFeatureRequest().setFilterFid( mPressedFid ) ).nextFeature( f );
+ QgsGeometry geom;
+
+ if ( f.hasGeometry() )
+ {
+ if ( f.geometry().isMultipart() )
+ {
+ std::unique_ptr line_reversed( static_cast( f.geometry().constGet()->clone() ) );
+ std::unique_ptr line_part( static_cast( line_reversed->geometryN( mPressedPartNum )->clone() ) );
+ std::unique_ptr line_part_reversed( line_part->reversed() );
+ line_reversed->removeGeometry( mPressedPartNum );
+ line_reversed->insertGeometry( line_part_reversed.release(), mPressedPartNum );
+
+ geom = QgsGeometry( line_reversed.release() );
+
+ }
+ else
+ {
+
+ geom = QgsGeometry( static_cast< const QgsCurve * >( f.geometry().constGet() )->reversed() );
+
+ }
+
+ if ( geom )
+ {
+ vlayer->beginEditCommand( tr( "Reverse line" ) );
+ vlayer->changeGeometry( f.id(), geom );
+ vlayer->endEditCommand();
+ vlayer->triggerRepaint();
+ emit messageEmitted( tr( "Line reversed." ) );
+ }
+ else
+ {
+ emit messageEmitted( tr( "Couldn't reverse the selected part." ) );
+ }
+ }
+}
+
+QgsGeometry QgsMapToolReverseLine::partUnderPoint( QPoint point, QgsFeatureId &fid, int &partNum )
+{
+ QgsFeature f;
+ QgsGeometry geomPart;
+
+ switch ( vlayer->geometryType() )
+ {
+ case QgsWkbTypes::LineGeometry:
+ {
+ QgsPointLocator::Match match = mCanvas->snappingUtils()->snapToCurrentLayer( point, QgsPointLocator::Types( QgsPointLocator::Vertex | QgsPointLocator::Edge ) );
+ if ( !match.isValid() )
+ return geomPart;
+
+ int snapVertex = match.vertexIndex();
+ vlayer->getFeatures( QgsFeatureRequest().setFilterFid( match.featureId() ) ).nextFeature( f );
+ QgsGeometry g = f.geometry();
+ if ( !g.isMultipart() )
+ {
+ fid = match.featureId();
+ return g;
+ }
+ else if ( QgsWkbTypes::geometryType( g.wkbType() ) == QgsWkbTypes::LineGeometry )
+ {
+ QgsMultiPolylineXY mline = g.asMultiPolyline();
+ for ( int part = 0; part < mline.count(); part++ )
+ {
+ if ( snapVertex < mline[part].count() )
+ {
+ fid = match.featureId();
+ partNum = part;
+ return QgsGeometry::fromPolylineXY( mline[part] );
+ }
+ snapVertex -= mline[part].count();
+ }
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ return geomPart;
+}
+
+void QgsMapToolReverseLine::deactivate()
+{
+ QgsMapTool::deactivate();
+}
+
diff --git a/src/app/qgsmaptoolreverseline.h b/src/app/qgsmaptoolreverseline.h
new file mode 100644
index 00000000000..2e034ac6c51
--- /dev/null
+++ b/src/app/qgsmaptoolreverseline.h
@@ -0,0 +1,56 @@
+/***************************************************************************
+ qgsmaptoolreverseline.h - reverse a line geometry
+ ---------------------
+ begin : April 2018
+ copyright : (C) 2018 by Loïc Bartoletti
+ email : loic dot bartoletti at oslandia dot com
+ ***************************************************************************
+ * *
+ * 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 QGSMAPTOOLREVERSELINE_H
+#define QGSMAPTOOLREVERSELINE_H
+
+#include "qgsmaptooledit.h"
+#include "qgis_app.h"
+
+class QgsVertexMarker;
+
+//! Map tool to delete vertices from line/polygon features
+class APP_EXPORT QgsMapToolReverseLine: public QgsMapToolEdit
+{
+ Q_OBJECT
+
+ public:
+ QgsMapToolReverseLine( QgsMapCanvas *canvas );
+ ~QgsMapToolReverseLine() override;
+
+ void canvasMoveEvent( QgsMapMouseEvent *e ) override;
+
+ void canvasPressEvent( QgsMapMouseEvent *e ) override;
+
+ void canvasReleaseEvent( QgsMapMouseEvent *e ) override;
+
+ //! called when map tool is being deactivated
+ void deactivate() override;
+
+ private:
+ QgsVectorLayer *vlayer = nullptr;
+
+ QgsGeometry partUnderPoint( QPoint p, QgsFeatureId &fid, int &partNum );
+
+ /* Rubberband that shows the part being reversed*/
+ std::unique_ptrmRubberBand;
+
+ //The feature and part where the mouse cursor was pressed
+ //This is used to check whether we are still in the same part at cursor release
+ QgsFeatureId mPressedFid = 0;
+ int mPressedPartNum = 0;
+};
+
+#endif // QGSMAPTOOLREVERSELINE_H
diff --git a/src/ui/qgisapp.ui b/src/ui/qgisapp.ui
index aea900f5df4..68bd085446f 100755
--- a/src/ui/qgisapp.ui
+++ b/src/ui/qgisapp.ui
@@ -362,6 +362,7 @@
+
@@ -468,6 +469,7 @@
+
@@ -1047,6 +1049,18 @@
Offset Point Symbol
+
+
+ true
+
+
+
+ :/images/themes/default/mActionReverseLine.svg:/images/themes/default/mActionReverseLine.svg
+
+
+ Reverse line
+
+
&Snapping Options…
diff --git a/tests/src/app/CMakeLists.txt b/tests/src/app/CMakeLists.txt
index 7a5bf565beb..fa74a667b8a 100644
--- a/tests/src/app/CMakeLists.txt
+++ b/tests/src/app/CMakeLists.txt
@@ -108,3 +108,5 @@ ADD_QGIS_TEST(maptoolregularpolygontest testqgsmaptoolregularpolygon.cpp)
ADD_QGIS_TEST(measuretool testqgsmeasuretool.cpp)
ADD_QGIS_TEST(vertextool testqgsvertextool.cpp)
ADD_QGIS_TEST(vectorlayersaveasdialogtest testqgsvectorlayersaveasdialog.cpp)
+ADD_QGIS_TEST(maptoolreverselinetest testqgsmaptoolreverseline.cpp)
+
diff --git a/tests/src/app/testqgsmaptoolreverseline.cpp b/tests/src/app/testqgsmaptoolreverseline.cpp
new file mode 100644
index 00000000000..a893c127cb2
--- /dev/null
+++ b/tests/src/app/testqgsmaptoolreverseline.cpp
@@ -0,0 +1,190 @@
+/***************************************************************************
+ TestQgsMapToolReverseLine.cpp
+ --------------------------------
+ Date : May 2018
+ Copyright : (C) 2018 by Loïc Bartoletti
+ Email : loic dot bartoletti at oslandia dot com
+ ***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include "qgstest.h"
+
+#include "qgisapp.h"
+#include "qgsgeometry.h"
+#include "qgsmapcanvas.h"
+#include "qgssettings.h"
+#include "qgsvectorlayer.h"
+#include "qgsmaptooladdfeature.h"
+
+#include "testqgsmaptoolutils.h"
+#include "qgsmaptoolreverseline.h"
+
+
+class TestQgsMapToolReverseLine : public QObject
+{
+ Q_OBJECT
+
+ public:
+ TestQgsMapToolReverseLine();
+
+ private slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+ void testReverseCurve();
+ void testReverseLineString();
+ void testReverseMultiLineString();
+
+ private:
+ QgisApp *mQgisApp = nullptr;
+ QgsMapCanvas *mCanvas = nullptr;
+};
+
+TestQgsMapToolReverseLine::TestQgsMapToolReverseLine() = default;
+
+
+//runs before all tests
+void TestQgsMapToolReverseLine::initTestCase()
+{
+ QgsApplication::init();
+ QgsApplication::initQgis();
+
+ mQgisApp = new QgisApp();
+
+ mCanvas = new QgsMapCanvas();
+ mCanvas->setDestinationCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:3946" ) ) );
+
+}
+
+void TestQgsMapToolReverseLine::cleanupTestCase()
+{
+ QgsApplication::exitQgis();
+}
+
+void TestQgsMapToolReverseLine::testReverseCurve()
+{
+ //create a temporary layer
+ std::unique_ptr< QgsVectorLayer > memoryLayer( new QgsVectorLayer( QStringLiteral( "LineString?crs=EPSG:3946&field=pk:int" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) ) );
+ QVERIFY( memoryLayer->isValid() );
+ QgsFeature curve( memoryLayer->dataProvider()->fields(), 1 );
+
+ curve.setAttribute( QStringLiteral( "pk" ), 1 );
+ curve.setGeometry( QgsGeometry::fromWkt( QStringLiteral(
+ "CircularString(10 10, 5 5)" ) ) );
+
+ memoryLayer->dataProvider()->addFeatures( QgsFeatureList() << curve );
+
+ mCanvas->setLayers( QList() << memoryLayer.get() );
+ mCanvas->setCurrentLayer( memoryLayer.get() );
+
+ std::unique_ptr< QgsMapToolReverseLine > tool( new QgsMapToolReverseLine( mCanvas ) );
+
+ memoryLayer->startEditing();
+ QgsPointXY mapPoint = mCanvas->getCoordinateTransform()->transform( 5, 5 );
+ std::unique_ptr< QgsMapMouseEvent > event( new QgsMapMouseEvent(
+ mCanvas,
+ QEvent::MouseButtonRelease,
+ QPoint( mapPoint.x(), mapPoint.y() )
+ ) );
+ // trigger mouseRelease handler
+ tool->canvasPressEvent( event.get() );
+ tool->canvasReleaseEvent( event.get() );
+ QgsFeature f = memoryLayer->getFeature( 1 );
+
+ QString wkt = "CircularString (5 5, 10 10)";
+ QCOMPARE( f.geometry().asWkt(), wkt );
+ memoryLayer->rollBack();
+
+}
+
+void TestQgsMapToolReverseLine::testReverseLineString()
+{
+ //create a temporary layer
+ std::unique_ptr< QgsVectorLayer > memoryLayer( new QgsVectorLayer( QStringLiteral( "LineStringZ?crs=EPSG:3946&field=pk:int" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) ) );
+ QVERIFY( memoryLayer->isValid() );
+ QgsFeature line( memoryLayer->dataProvider()->fields(), 1 );
+
+ line.setAttribute( QStringLiteral( "pk" ), 1 );
+ line.setGeometry( QgsGeometry::fromWkt( QStringLiteral(
+ "LineStringZ(0 0 0, 10 10 10, 5 5 5)" ) ) );
+
+ memoryLayer->dataProvider()->addFeatures( QgsFeatureList() << line );
+ mCanvas->setLayers( QList() << memoryLayer.get() );
+ mCanvas->setCurrentLayer( memoryLayer.get() );
+
+
+ std::unique_ptr< QgsMapToolReverseLine > tool( new QgsMapToolReverseLine( mCanvas ) );
+ memoryLayer->startEditing();
+ QgsPointXY mapPoint = mCanvas->getCoordinateTransform()->transform( 6, 6 );
+ std::unique_ptr< QgsMapMouseEvent > event( new QgsMapMouseEvent(
+ mCanvas,
+ QEvent::MouseButtonRelease,
+ QPoint( mapPoint.x(), mapPoint.y() )
+ ) );
+ // trigger mouseRelease handler
+ tool->canvasPressEvent( event.get() );
+ tool->canvasReleaseEvent( event.get() );
+
+ QgsFeature f = memoryLayer->getFeature( 1 );
+
+ QString wkt = "LineStringZ (5 5 5, 10 10 10, 0 0 0)";
+ QCOMPARE( f.geometry().asWkt(), wkt );
+
+ memoryLayer->rollBack();
+}
+
+void TestQgsMapToolReverseLine::testReverseMultiLineString()
+{
+ //create a temporary layer
+ std::unique_ptr< QgsVectorLayer > memoryLayer( new QgsVectorLayer( QStringLiteral( "MultiLineStringZ?crs=EPSG:3946&field=pk:int" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) ) );
+ QVERIFY( memoryLayer->isValid() );
+ QgsFeature multi( memoryLayer->dataProvider()->fields(), 1 );
+
+ multi.setAttribute( QStringLiteral( "pk" ), 1 );
+ multi.setGeometry( QgsGeometry::fromWkt( QStringLiteral(
+ "MultiLineStringZ((0 0 0, 10 10 10, 5 5 5), (100 100 100, 120 120 120))" ) ) );
+
+ memoryLayer->dataProvider()->addFeatures( QgsFeatureList() << multi );
+ mCanvas->setLayers( QList() << memoryLayer.get() );
+ mCanvas->setCurrentLayer( memoryLayer.get() );
+
+ std::unique_ptr< QgsMapToolReverseLine > tool( new QgsMapToolReverseLine( mCanvas ) );
+
+ memoryLayer->startEditing();
+ QgsPointXY mapPoint = mCanvas->getCoordinateTransform()->transform( 6, 6 );
+ std::unique_ptr< QgsMapMouseEvent > event( new QgsMapMouseEvent(
+ mCanvas,
+ QEvent::MouseButtonRelease,
+ QPoint( mapPoint.x(), mapPoint.y() )
+ ) );
+ // trigger mouseRelease handler
+ tool->canvasPressEvent( event.get() );
+ tool->canvasReleaseEvent( event.get() );
+ QgsFeature f = memoryLayer->getFeature( 1 );
+
+ QString wkt = "MultiLineStringZ ((5 5 5, 10 10 10, 0 0 0),(100 100 100, 120 120 120))";
+ QCOMPARE( f.geometry().asWkt(), wkt );
+
+ mapPoint = mCanvas->getCoordinateTransform()->transform( 110, 110 );
+ event.reset( new QgsMapMouseEvent(
+ mCanvas,
+ QEvent::MouseButtonRelease,
+ QPoint( mapPoint.x(), mapPoint.y() )
+ ) );
+ // trigger mouseRelease handler
+ tool->canvasPressEvent( event.get() );
+ tool->canvasReleaseEvent( event.get() );
+ f = memoryLayer->getFeature( 1 );
+
+ wkt = "MultiLineStringZ ((5 5 5, 10 10 10, 0 0 0),(120 120 120, 100 100 100))";
+ QCOMPARE( f.geometry().asWkt(), wkt );
+ memoryLayer->rollBack();
+}
+QGSTEST_MAIN( TestQgsMapToolReverseLine )
+#include "testqgsmaptoolreverseline.moc"