1 /***************************************************************************
2 testqgsmaptoolsplitfeatures.cpp
3 ------------------------
4 Date : August 2020
5 Copyright : (C) 2020 by Stefanos Natsis
6 Email : uclaros@gmail.com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16 #include "qgstest.h"
17
18 #include "qgisapp.h"
19 #include "qgsgeometry.h"
20 #include "qgsmapcanvas.h"
21 #include "qgssettings.h"
22 #include "qgsvectorlayer.h"
23 #include "qgsmaptoolsplitfeatures.h"
24 #include "qgsgeometryutils.h"
25
26 #include "testqgsmaptoolutils.h"
27
28 class TestQgsMapToolSplitFeatures : public QObject
29 {
30 Q_OBJECT
31
32 public:
33 TestQgsMapToolSplitFeatures();
34
35 private slots:
36 void initTestCase();
37 void cleanupTestCase();
38
39 void testNoFeaturesSplit();
40 void testSplitPolygon();
41 void testSplitPolygonTopologicalEditing();
42
43 private:
44 QPoint mapToPoint( double x, double y );
45 QgisApp *mQgisApp = nullptr;
46 QgsMapCanvas *mCanvas = nullptr;
47 QgsVectorLayer *mMultiLineStringLayer = nullptr;
48 QgsVectorLayer *mPolygonLayer = nullptr;
49 QgsVectorLayer *mMultiPolygonLayer = nullptr;
50 QgsFeature lineF1, lineF2, polygonF1, polygonF2, multipolygonF1;
51 };
52
53 TestQgsMapToolSplitFeatures::TestQgsMapToolSplitFeatures() = default;
54
55
56 //runs before all tests
initTestCase()57 void TestQgsMapToolSplitFeatures::initTestCase()
58 {
59 QgsApplication::init();
60 QgsApplication::initQgis();
61
62 mQgisApp = new QgisApp();
63
64 mCanvas = new QgsMapCanvas();
65 mCanvas->setDestinationCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:3946" ) ) );
66
67 // make testing layers
68 mMultiLineStringLayer = new QgsVectorLayer( QStringLiteral( "MultiLineString?crs=EPSG:3946" ), QStringLiteral( "layer multiline" ), QStringLiteral( "memory" ) );
69 QVERIFY( mMultiLineStringLayer->isValid() );
70 mMultiLineStringLayer->startEditing();
71 lineF1.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "MultiLineString ((0 0, 10 0))" ) ) );
72 lineF2.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "MultiLineString ((0 5, 10 5),(10 5, 15 5))" ) ) );
73 mMultiLineStringLayer->addFeature( lineF1 );
74 mMultiLineStringLayer->addFeature( lineF2 );
75
76 mPolygonLayer = new QgsVectorLayer( QStringLiteral( "Polygon?crs=EPSG:3946" ), QStringLiteral( "layer polygon" ), QStringLiteral( "memory" ) );
77 QVERIFY( mPolygonLayer->isValid() );
78 mPolygonLayer->startEditing();
79 polygonF1.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "Polygon ((0 5, 0 10, 10 10, 10 5, 0 5))" ) ) );
80 polygonF2.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "Polygon ((0 0, 0 5, 10 5, 10 0, 0 0))" ) ) );
81 mPolygonLayer->addFeature( polygonF1 );
82 mPolygonLayer->addFeature( polygonF2 );
83
84 mMultiPolygonLayer = new QgsVectorLayer( QStringLiteral( "MultiPolygon?crs=EPSG:3946" ), QStringLiteral( "layer multipolygon" ), QStringLiteral( "memory" ) );
85 QVERIFY( mMultiPolygonLayer->isValid() );
86 mMultiPolygonLayer->startEditing();
87 multipolygonF1.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "MultiPolygon (((0 5, 0 10, 10 10, 10 5, 0 5)),((0 0, 0 4, 10 4, 10 0, 0 0)))" ) ) );
88 mMultiPolygonLayer->addFeature( multipolygonF1 );
89
90 mCanvas->setFrameStyle( QFrame::NoFrame );
91 mCanvas->resize( 50, 50 );
92 mCanvas->setExtent( QgsRectangle( 0, 0, 10, 10 ) );
93 mCanvas->show(); // to make the canvas resize
94 mCanvas->hide();
95 // Disable flaky tests on windows...
96 // QCOMPARE( mCanvas->mapSettings().outputSize(), QSize( 50, 50 ) );
97 // QCOMPARE( mCanvas->mapSettings().visibleExtent(), QgsRectangle( 0, 0, 10, 10 ) );
98
99 QgsProject::instance()->addMapLayers( QList<QgsMapLayer *>() << mMultiLineStringLayer
100 << mPolygonLayer
101 << mMultiPolygonLayer );
102
103 // set layers in canvas
104 mCanvas->setLayers( QList<QgsMapLayer *>() << mMultiLineStringLayer
105 << mPolygonLayer
106 << mMultiPolygonLayer );
107
108 }
109
cleanupTestCase()110 void TestQgsMapToolSplitFeatures::cleanupTestCase()
111 {
112 QgsApplication::exitQgis();
113 }
114
mapToPoint(double x,double y)115 QPoint TestQgsMapToolSplitFeatures::mapToPoint( double x, double y )
116 {
117
118 QgsPointXY mapPoint = mCanvas->mapSettings().mapToPixel().transform( x, y );
119
120 return QPoint( std::round( mapPoint.x() ), std::round( mapPoint.y() ) );
121 }
122
testNoFeaturesSplit()123 void TestQgsMapToolSplitFeatures::testNoFeaturesSplit()
124 {
125 mCanvas->setCurrentLayer( mMultiLineStringLayer );
126 QgsMapToolSplitFeatures *mapTool = new QgsMapToolSplitFeatures( mCanvas ) ;
127 mCanvas->setMapTool( mapTool );
128
129 std::unique_ptr< QgsMapMouseEvent > event( new QgsMapMouseEvent(
130 mCanvas,
131 QEvent::MouseButtonRelease,
132 mapToPoint( 4, 7 ),
133 Qt::LeftButton
134 ) );
135 mapTool->cadCanvasReleaseEvent( event.get() );
136 event.reset( new QgsMapMouseEvent(
137 mCanvas,
138 QEvent::MouseButtonRelease,
139 mapToPoint( 4, 8 ),
140 Qt::LeftButton
141 ) );
142 mapTool->cadCanvasReleaseEvent( event.get() );
143
144 event.reset( new QgsMapMouseEvent(
145 mCanvas,
146 QEvent::MouseButtonRelease,
147 mapToPoint( 4, 8 ),
148 Qt::RightButton
149 ) );
150 mapTool->cadCanvasReleaseEvent( event.get() );
151
152
153 QVERIFY( mMultiLineStringLayer->featureCount() == 2 );
154 QVERIFY( mMultiLineStringLayer->undoStack()->index() == 2 );
155 }
156
testSplitPolygon()157 void TestQgsMapToolSplitFeatures::testSplitPolygon()
158 {
159 QgsProject::instance()->setTopologicalEditing( false );
160 mCanvas->setCurrentLayer( mPolygonLayer );
161 QgsMapToolSplitFeatures *mapTool = new QgsMapToolSplitFeatures( mCanvas ) ;
162 mCanvas->setMapTool( mapTool );
163
164 std::unique_ptr< QgsMapMouseEvent > event( new QgsMapMouseEvent(
165 mCanvas,
166 QEvent::MouseButtonRelease,
167 mapToPoint( 4, 11 ),
168 Qt::LeftButton
169 ) );
170 mapTool->cadCanvasReleaseEvent( event.get() );
171 event.reset( new QgsMapMouseEvent(
172 mCanvas,
173 QEvent::MouseButtonRelease,
174 mapToPoint( 4, 3 ),
175 Qt::LeftButton
176 ) );
177 mapTool->cadCanvasReleaseEvent( event.get() );
178
179 event.reset( new QgsMapMouseEvent(
180 mCanvas,
181 QEvent::MouseButtonRelease,
182 mapToPoint( 4, 3 ),
183 Qt::RightButton
184 ) );
185 mapTool->cadCanvasReleaseEvent( event.get() );
186
187 QVERIFY( mPolygonLayer->undoStack()->index() == 3 );
188 QVERIFY( mPolygonLayer->featureCount() == 3 );
189 QCOMPARE( mPolygonLayer->getFeature( polygonF1.id() ).geometry().asWkt(), QStringLiteral( "Polygon ((4 10, 4 5, 0 5, 0 10, 4 10))" ) );
190 QCOMPARE( mPolygonLayer->getFeature( polygonF2.id() ).geometry().asWkt(), QStringLiteral( "Polygon ((0 0, 0 5, 10 5, 10 0, 0 0))" ) );
191
192 // no change to other layers
193 QVERIFY( mMultiLineStringLayer->undoStack()->index() == 2 );
194 QVERIFY( mMultiPolygonLayer->undoStack()->index() == 1 );
195
196 // undo changes
197 mPolygonLayer->undoStack()->undo();
198 QVERIFY( mPolygonLayer->undoStack()->index() == 2 );
199 }
200
testSplitPolygonTopologicalEditing()201 void TestQgsMapToolSplitFeatures::testSplitPolygonTopologicalEditing()
202 {
203 QgsProject::instance()->setTopologicalEditing( true );
204 mCanvas->setCurrentLayer( mPolygonLayer );
205 QgsMapToolSplitFeatures *mapTool = new QgsMapToolSplitFeatures( mCanvas ) ;
206 mCanvas->setMapTool( mapTool );
207
208 std::unique_ptr< QgsMapMouseEvent > event( new QgsMapMouseEvent(
209 mCanvas,
210 QEvent::MouseButtonRelease,
211 mapToPoint( 4, 11 ),
212 Qt::LeftButton
213 ) );
214 mapTool->cadCanvasReleaseEvent( event.get() );
215 event.reset( new QgsMapMouseEvent(
216 mCanvas,
217 QEvent::MouseButtonRelease,
218 mapToPoint( 4, 3 ),
219 Qt::LeftButton
220 ) );
221 mapTool->cadCanvasReleaseEvent( event.get() );
222
223 event.reset( new QgsMapMouseEvent(
224 mCanvas,
225 QEvent::MouseButtonRelease,
226 mapToPoint( 4, 3 ),
227 Qt::RightButton
228 ) );
229 mapTool->cadCanvasReleaseEvent( event.get() );
230
231 QVERIFY( mPolygonLayer->undoStack()->index() == 3 );
232 QVERIFY( mPolygonLayer->featureCount() == 3 );
233 QCOMPARE( mPolygonLayer->getFeature( polygonF1.id() ).geometry().asWkt(), QStringLiteral( "Polygon ((4 10, 4 5, 0 5, 0 10, 4 10))" ) );
234 QCOMPARE( mPolygonLayer->getFeature( polygonF2.id() ).geometry().asWkt(), QStringLiteral( "Polygon ((0 0, 0 5, 4 5, 10 5, 10 0, 0 0))" ) );
235
236 QVERIFY( mMultiLineStringLayer->undoStack()->index() == 3 );
237 QCOMPARE( mMultiLineStringLayer->getFeature( lineF2.id() ).geometry().asWkt(), QStringLiteral( "MultiLineString ((0 5, 4 5, 10 5),(10 5, 15 5))" ) );
238 QVERIFY( mMultiPolygonLayer->undoStack()->index() == 2 );
239 QCOMPARE( mMultiPolygonLayer->getFeature( multipolygonF1.id() ).geometry().asWkt(), QStringLiteral( "MultiPolygon (((0 5, 0 10, 4 10, 10 10, 10 5, 4 5, 0 5)),((0 0, 0 4, 10 4, 10 0, 0 0)))" ) );
240
241 // undo changes
242 mPolygonLayer->undoStack()->undo();
243 QVERIFY( mPolygonLayer->undoStack()->index() == 2 );
244 mMultiLineStringLayer->undoStack()->undo();
245 QVERIFY( mMultiLineStringLayer->undoStack()->index() == 2 );
246 mMultiPolygonLayer->undoStack()->undo();
247 QVERIFY( mMultiPolygonLayer->undoStack()->index() == 1 );
248 }
249
250 QGSTEST_MAIN( TestQgsMapToolSplitFeatures )
251 #include "testqgsmaptoolsplitfeatures.moc"
252