1 /***************************************************************************
2 testqgsmaptoolscalefeature.cpp
3 --------------------------------
4 Date : December 2020
5 Copyright : (C) 2020 by roya0045
6 Contact : ping me on github
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 "qgsmapcanvassnappingutils.h"
22 #include "qgssnappingconfig.h"
23 #include "qgssnappingutils.h"
24 #include "qgsmaptoolscalefeature.h"
25 #include "qgsproject.h"
26 #include "qgssettings.h"
27 #include "qgsvectorlayer.h"
28 #include "qgsmapmouseevent.h"
29 #include "testqgsmaptoolutils.h"
30
31
32 /**
33 * \ingroup UnitTests
34 * This is a unit test for the vertex tool
35 */
36 class TestQgsMapToolScaleFeature: public QObject
37 {
38 Q_OBJECT
39 public:
40 TestQgsMapToolScaleFeature();
41
42 private slots:
43 void initTestCase();// will be called before the first testfunction is executed.
44 void cleanupTestCase();// will be called after the last testfunction was executed.
45
46 void testScaleFeature();
47 void testScaleFeatureWithAnchor();
48 void testCancelManualAnchor();
49 void testScaleFeatureWithAnchorSetAfterStart();
50 void testScaleSelectedFeatures();
51 void testScaleFeatureManualAnchorSnapping();
52 void testScaleFeatureDifferentCrs();
53
54 private:
55 QgisApp *mQgisApp = nullptr;
56 QgsMapCanvas *mCanvas = nullptr;
57 QgsMapToolScaleFeature *mScaleTool = nullptr;
58 QgsVectorLayer *mLayerBase = nullptr;
59 };
60
61 TestQgsMapToolScaleFeature::TestQgsMapToolScaleFeature() = default;
62
63
64 //runs before all tests
initTestCase()65 void TestQgsMapToolScaleFeature::initTestCase()
66 {
67 qDebug() << "TestMapToolCapture::initTestCase()";
68 // init QGIS's paths - true means that all path will be inited from prefix
69 QgsApplication::init();
70 QgsApplication::initQgis();
71
72 // Set up the QSettings environment
73 QCoreApplication::setOrganizationName( QStringLiteral( "QGIS" ) );
74 QCoreApplication::setOrganizationDomain( QStringLiteral( "qgis.org" ) );
75 QCoreApplication::setApplicationName( QStringLiteral( "QGIS-TEST" ) );
76
77 mQgisApp = new QgisApp();
78
79 mCanvas = new QgsMapCanvas();
80
81 mCanvas->setDestinationCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:3946" ) ) );
82
83 mCanvas->setFrameStyle( QFrame::NoFrame );
84 mCanvas->resize( 512, 512 );
85 mCanvas->setExtent( QgsRectangle( -4, -4, 4, 4 ) );
86 mCanvas->show(); // to make the canvas resize
87 mCanvas->hide();
88
89 // make testing layers
90 mLayerBase = new QgsVectorLayer( QStringLiteral( "Polygon?crs=EPSG:3946" ), QStringLiteral( "baselayer" ), QStringLiteral( "memory" ) );
91 QVERIFY( mLayerBase->isValid() );
92 QgsProject::instance()->addMapLayers( QList<QgsMapLayer *>() << mLayerBase );
93
94 mLayerBase->startEditing();
95 const QString wkt1 = QStringLiteral( "Polygon ((-2 -2, -2 -1, -1 -1, -1 -2, -2 -2))" );
96 QgsFeature f1;
97 f1.setGeometry( QgsGeometry::fromWkt( wkt1 ) );
98 const QString wkt2 = QStringLiteral( "Polygon ((1.1 0.8, 1.1 5, 2.1 5, 2.1 0.8, 1.1 0.8))" );
99 QgsFeature f2;
100 f2.setGeometry( QgsGeometry::fromWkt( wkt2 ) );
101
102 QgsFeatureList flist;
103 flist << f1 << f2;
104 mLayerBase->dataProvider()->addFeatures( flist );
105 QCOMPARE( mLayerBase->featureCount(), 2L );
106 QCOMPARE( mLayerBase->getFeature( 1 ).geometry().asWkt(), wkt1 );
107 QCOMPARE( mLayerBase->getFeature( 2 ).geometry().asWkt( 1 ), wkt2 );
108
109 QgsSnappingConfig cfg = mCanvas->snappingUtils()->config();
110 cfg.setMode( QgsSnappingConfig::AllLayers );
111 cfg.setTolerance( 1 );
112 cfg.setTypeFlag( static_cast<QgsSnappingConfig::SnappingTypeFlag>( QgsSnappingConfig::VertexFlag | QgsSnappingConfig::SegmentFlag ) );
113 cfg.setEnabled( true );
114 mCanvas->snappingUtils()->setConfig( cfg );
115
116 mCanvas->setLayers( QList<QgsMapLayer *>() << mLayerBase );
117 mCanvas->setCurrentLayer( mLayerBase );
118 mCanvas->snappingUtils()->locatorForLayer( mLayerBase )->init();
119
120 // create the tool
121 mScaleTool = new QgsMapToolScaleFeature( mCanvas );
122 mCanvas->setMapTool( mScaleTool );
123
124 QCOMPARE( mCanvas->mapSettings().outputSize(), QSize( 512, 512 ) );
125 QCOMPARE( mCanvas->mapSettings().visibleExtent(), QgsRectangle( -4, -4, 4, 4 ) );
126 }
127
128 //runs after all tests
cleanupTestCase()129 void TestQgsMapToolScaleFeature::cleanupTestCase()
130 {
131 delete mScaleTool;
132 delete mCanvas;
133 QgsApplication::exitQgis();
134 }
135
testScaleFeature()136 void TestQgsMapToolScaleFeature::testScaleFeature()
137 {
138 TestQgsMapToolUtils utils( mScaleTool );
139
140 //scale up
141 utils.mouseClick( -2, -1, Qt::LeftButton, Qt::KeyboardModifiers(), true );
142 utils.mouseMove( -2.5, -0.5 );
143 utils.mouseClick( -2.5, -0.5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
144
145 QCOMPARE( mLayerBase->getFeature( 1 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((-2.5 -2.5, -2.5 -0.5, -0.5 -0.5, -0.5 -2.5, -2.5 -2.5))" ) );
146 QCOMPARE( mLayerBase->getFeature( 2 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((1.1 0.8, 1.1 5, 2.1 5, 2.1 0.8, 1.1 0.8))" ) );
147
148 //scale down
149 utils.mouseClick( 1.1, 0.8, Qt::LeftButton, Qt::KeyboardModifiers(), true );
150 utils.mouseMove( 1.35, 1.85 );
151 utils.mouseClick( 1.35, 1.85, Qt::LeftButton, Qt::KeyboardModifiers(), true );
152
153 QCOMPARE( mLayerBase->getFeature( 1 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((-2.5 -2.5, -2.5 -0.5, -0.5 -0.5, -0.5 -2.5, -2.5 -2.5))" ) );
154 QCOMPARE( mLayerBase->getFeature( 2 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((1.35 1.84, 1.35 3.96, 1.85 3.96, 1.85 1.84, 1.35 1.84))" ) );
155
156 mLayerBase->undoStack()->undo();
157 mLayerBase->undoStack()->undo();
158 }
159
testScaleFeatureWithAnchor()160 void TestQgsMapToolScaleFeature::testScaleFeatureWithAnchor()
161 {
162 TestQgsMapToolUtils utils( mScaleTool );
163
164 //set manual anchor point
165 utils.mouseClick( 1, -1, Qt::LeftButton, Qt::ControlModifier, true );
166
167 // resize
168 utils.mouseClick( -2, -1, Qt::LeftButton, Qt::KeyboardModifiers(), true );
169 utils.mouseMove( -2.5, -0.5 );
170 utils.mouseClick( -2.5, -0.5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
171
172 QCOMPARE( mLayerBase->getFeature( 1 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((-2.54 -2.18, -2.54 -1, -1.36 -1, -1.36 -2.18, -2.54 -2.18))" ) );
173 QCOMPARE( mLayerBase->getFeature( 2 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((1.1 0.8, 1.1 5, 2.1 5, 2.1 0.8, 1.1 0.8))" ) );
174
175 mLayerBase->undoStack()->undo();
176 }
177
testCancelManualAnchor()178 void TestQgsMapToolScaleFeature::testCancelManualAnchor()
179 {
180 TestQgsMapToolUtils utils( mScaleTool );
181
182 //set manual anchor point
183 utils.mouseClick( 1, -1, Qt::LeftButton, Qt::ControlModifier, true );
184
185 // remove manual anchor point via right click
186 utils.mouseClick( 10, 25, Qt::RightButton, Qt::KeyboardModifiers(), true );
187
188 // resize
189 utils.mouseClick( -2, -1, Qt::LeftButton, Qt::KeyboardModifiers(), true );
190 utils.mouseMove( -2.5, -0.5 );
191 utils.mouseClick( -2.5, -0.5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
192
193 QCOMPARE( mLayerBase->getFeature( 1 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((-2.5 -2.5, -2.5 -0.5, -0.5 -0.5, -0.5 -2.5, -2.5 -2.5))" ) );
194 QCOMPARE( mLayerBase->getFeature( 2 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((1.1 0.8, 1.1 5, 2.1 5, 2.1 0.8, 1.1 0.8))" ) );
195
196 mLayerBase->undoStack()->undo();
197 }
198
testScaleFeatureWithAnchorSetAfterStart()199 void TestQgsMapToolScaleFeature::testScaleFeatureWithAnchorSetAfterStart()
200 {
201 TestQgsMapToolUtils utils( mScaleTool );
202
203 // resize
204 utils.mouseClick( -2, -1, Qt::LeftButton, Qt::KeyboardModifiers(), true );
205
206 //set manual anchor point
207 utils.mouseClick( 1, -1, Qt::LeftButton, Qt::ControlModifier, true );
208
209 utils.mouseMove( -2.5, -0.5 );
210 utils.mouseClick( -2.5, -0.5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
211
212 QCOMPARE( mLayerBase->getFeature( 1 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((-14 -6, -14 -1, -9 -1, -9 -6, -14 -6))" ) );
213 QCOMPARE( mLayerBase->getFeature( 2 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((1.1 0.8, 1.1 5, 2.1 5, 2.1 0.8, 1.1 0.8))" ) );
214
215 mLayerBase->undoStack()->undo();
216 }
217
testScaleSelectedFeatures()218 void TestQgsMapToolScaleFeature::testScaleSelectedFeatures()
219 {
220 TestQgsMapToolUtils utils( mScaleTool );
221 mLayerBase->selectAll();
222
223 // resize
224 utils.mouseClick( -2, -1, Qt::LeftButton, Qt::KeyboardModifiers(), true );
225 utils.mouseMove( -2.5, -0.5 );
226 utils.mouseClick( -2.5, -0.5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
227
228 QCOMPARE( mLayerBase->getFeature( 1 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((-2.54 -2.18, -2.54 -1, -1.36 -1, -1.36 -2.18, -2.54 -2.18))" ) );
229 QCOMPARE( mLayerBase->getFeature( 2 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((1.12 1.12, 1.12 6.07, 2.3 6.07, 2.3 1.12, 1.12 1.12))" ) );
230
231 mLayerBase->removeSelection();
232 mLayerBase->undoStack()->undo();
233 }
234
testScaleFeatureManualAnchorSnapping()235 void TestQgsMapToolScaleFeature::testScaleFeatureManualAnchorSnapping()
236 {
237 TestQgsMapToolUtils utils( mScaleTool );
238
239 QgsSnappingConfig cfg = mCanvas->snappingUtils()->config();
240 const double tolerance = cfg.tolerance();
241 const QgsTolerance::UnitType units = cfg.units();
242 cfg.setTolerance( 0.5 );
243 cfg.setUnits( QgsTolerance::LayerUnits );
244 mCanvas->snappingUtils()->setConfig( cfg );
245
246 //set manual anchor point, should snap to (-2, -2)
247 utils.mouseClick( -1.9, -1.9, Qt::LeftButton, Qt::ControlModifier, true );
248
249 // resize, source point should snap to (-1, -1)
250 utils.mouseMove( -0.9, -0.9 );
251 utils.mouseClick( -0.9, -0.9, Qt::LeftButton, Qt::KeyboardModifiers(), true );
252 // target point should snap to (1.1, 0.8)
253 utils.mouseMove( 1.2, 0.9 );
254 utils.mouseClick( 1.2, 0.9, Qt::LeftButton, Qt::KeyboardModifiers(), true );
255
256 QCOMPARE( mLayerBase->getFeature( 1 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((-2 -2, -2 0.95, 0.95 0.95, 0.95 -2, -2 -2))" ) );
257 QCOMPARE( mLayerBase->getFeature( 2 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((1.1 0.8, 1.1 5, 2.1 5, 2.1 0.8, 1.1 0.8))" ) );
258
259 mLayerBase->undoStack()->undo();
260
261 // restore tolerance setting
262 cfg.setTolerance( tolerance );
263 cfg.setUnits( units );
264 mCanvas->snappingUtils()->setConfig( cfg );
265
266 // remove manual anchor point via right click
267 utils.mouseClick( 10, 25, Qt::RightButton, Qt::KeyboardModifiers(), true );
268 }
269
testScaleFeatureDifferentCrs()270 void TestQgsMapToolScaleFeature::testScaleFeatureDifferentCrs()
271 {
272 mCanvas->setDestinationCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) );
273 TestQgsMapToolUtils utils( mScaleTool );
274
275 //scale up
276 utils.mouseClick( -8.82187821744550682, 2.0909475540607434, Qt::LeftButton, Qt::KeyboardModifiers(), true );
277 utils.mouseMove( -8.82188215592444536, 2.09095048559432861 );
278 utils.mouseClick( -8.82188215592444536, 2.09095048559432861, Qt::LeftButton, Qt::KeyboardModifiers(), true );
279
280 QCOMPARE( mLayerBase->getFeature( 1 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((-2.5 -2.5, -2.5 -0.5, -0.5 -0.5, -0.5 -2.5, -2.5 -2.5))" ) );
281 QCOMPARE( mLayerBase->getFeature( 2 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((1.1 0.8, 1.1 5, 2.1 5, 2.1 0.8, 1.1 0.8))" ) );
282
283 //scale down
284 utils.mouseClick( -8.82185881943214234, 2.09096315856551129, Qt::LeftButton, Qt::KeyboardModifiers(), true );
285 utils.mouseMove( -8.82185818217576667, 2.09097065484482636 );
286 utils.mouseClick( -8.82185818217576667, 2.09097065484482636, Qt::LeftButton, Qt::KeyboardModifiers(), true );
287
288 QCOMPARE( mLayerBase->getFeature( 1 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((-2.5 -2.5, -2.5 -0.5, -0.5 -0.5, -0.5 -2.5, -2.5 -2.5))" ) );
289 QCOMPARE( mLayerBase->getFeature( 2 ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((1.35 1.84, 1.35 3.96, 1.85 3.96, 1.85 1.84, 1.35 1.84))" ) );
290
291 mLayerBase->undoStack()->undo();
292 mLayerBase->undoStack()->undo();
293 mCanvas->setDestinationCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:3946" ) ) );
294 }
295
296 QGSTEST_MAIN( TestQgsMapToolScaleFeature )
297 #include "testqgsmaptoolscalefeature.moc"
298