1 /***************************************************************************
2 testqgsmaptooleditannotation.cpp
3 --------------------------------------
4 Date : September 2021
5 Copyright : (C) 2021 by Nyall Dawson
6 Email : nyall dot dawson at gmail dot 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 #include <QCoreApplication>
16
17 #include "qgstest.h"
18 #include "qgsguiutils.h"
19 #include "qgsmaptooledit.h"
20 #include "qgsapplication.h"
21 #include "qgsmapcanvas.h"
22 #include "qgslogger.h"
23 #include "qgsannotationlayer.h"
24 #include "qgsannotationpolygonitem.h"
25 #include "qgsproject.h"
26 #include "testqgsmaptoolutils.h"
27 #include "qgsmapmouseevent.h"
28 #include "qgspolygon.h"
29 #include "qgslinestring.h"
30 #include "qgsmaptoolmodifyannotation.h"
31 #include "qgsadvanceddigitizingdockwidget.h"
32 #include "qgsrendereditemresults.h"
33
34 #include <QSignalSpy>
35
36 class TestQgsMapToolEditAnnotation : public QObject
37 {
38 Q_OBJECT
39 public:
40 TestQgsMapToolEditAnnotation() = default;
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 void init(); // will be called before each testfunction is executed.
46 void cleanup(); // will be called after every testfunction.
47
48 void testSelectItem();
49 void testDeleteItem();
50 void testMoveItem();
51 void testMoveNode();
52 void testDeleteNode();
53 void testAddNode();
54
55 };
56
initTestCase()57 void TestQgsMapToolEditAnnotation::initTestCase()
58 {
59 QgsApplication::init();
60 QgsApplication::initQgis();
61 QgsApplication::showSettings();
62 }
63
cleanupTestCase()64 void TestQgsMapToolEditAnnotation::cleanupTestCase()
65 {
66 QgsApplication::exitQgis();
67 }
68
init()69 void TestQgsMapToolEditAnnotation::init()
70 {
71 }
72
cleanup()73 void TestQgsMapToolEditAnnotation::cleanup()
74 {
75 }
76
testSelectItem()77 void TestQgsMapToolEditAnnotation::testSelectItem()
78 {
79 QgsProject::instance()->clear();
80 QgsMapCanvas canvas;
81 canvas.setDestinationCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) );
82 canvas.setFrameStyle( QFrame::NoFrame );
83 canvas.resize( 600, 600 );
84 canvas.setExtent( QgsRectangle( 0, 0, 10, 10 ) );
85 canvas.show(); // to make the canvas resize
86
87 QgsAnnotationLayer *layer = new QgsAnnotationLayer( QStringLiteral( "test" ), QgsAnnotationLayer::LayerOptions( QgsProject::instance()->transformContext() ) );
88 QVERIFY( layer->isValid() );
89 QgsAnnotationLayer *layer2 = new QgsAnnotationLayer( QStringLiteral( "test" ), QgsAnnotationLayer::LayerOptions( QgsProject::instance()->transformContext() ) );
90 QVERIFY( layer2->isValid() );
91 QgsProject::instance()->addMapLayers( { layer, layer2 } );
92
93 QgsAnnotationPolygonItem *item1 = new QgsAnnotationPolygonItem( new QgsPolygon( new QgsLineString( QVector<QgsPoint> { QgsPoint( 1, 1 ), QgsPoint( 5, 1 ), QgsPoint( 5, 5 ), QgsPoint( 1, 5 ), QgsPoint( 1, 1 ) } ) ) );
94 item1->setZIndex( 1 );
95 const QString i1id = layer->addItem( item1 );
96
97 QgsAnnotationPolygonItem *item2 = new QgsAnnotationPolygonItem( new QgsPolygon( new QgsLineString( QVector<QgsPoint> { QgsPoint( 1, 4 ), QgsPoint( 5, 4 ), QgsPoint( 5, 9 ), QgsPoint( 1, 9 ), QgsPoint( 1, 4 ) } ) ) );
98 item2->setZIndex( 2 );
99 const QString i2id = layer->addItem( item2 );
100
101 QgsAnnotationPolygonItem *item3 = new QgsAnnotationPolygonItem( new QgsPolygon( new QgsLineString( QVector<QgsPoint> { QgsPoint( 7, 1 ), QgsPoint( 8, 1 ), QgsPoint( 8, 2 ), QgsPoint( 7, 2 ), QgsPoint( 7, 1 ) } ) ) );
102 item3->setZIndex( 3 );
103 const QString i3id = layer2->addItem( item3 );
104
105 layer->setCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) );
106 layer2->setCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) );
107
108 canvas.setLayers( { layer, layer2 } );
109 while ( !canvas.isDrawing() )
110 {
111 QgsApplication::processEvents();
112 }
113 canvas.waitWhileRendering();
114 QCOMPARE( canvas.renderedItemResults()->renderedItems().size(), 3 );
115
116 QgsAdvancedDigitizingDockWidget cadDock( &canvas );
117 QgsMapToolModifyAnnotation tool( &canvas, &cadDock );
118 canvas.setMapTool( &tool );
119
120 QSignalSpy spy( &tool, &QgsMapToolModifyAnnotation::itemSelected );
121 TestQgsMapToolUtils utils( &tool );
122
123 // click outside of items
124 utils.mouseMove( 9, 9 );
125 utils.mouseClick( 9, 9, Qt::LeftButton, Qt::KeyboardModifiers(), true );
126 QCOMPARE( spy.count(), 0 );
127
128 // click on items
129 utils.mouseMove( 1.5, 1.5 );
130 utils.mouseClick( 1.5, 1.5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
131 QCOMPARE( spy.count(), 1 );
132 QCOMPARE( spy.at( 0 ).at( 1 ).toString(), i1id );
133
134 // overlapping items, highest z order should be selected
135 utils.mouseMove( 1.5, 4.5 );
136 utils.mouseClick( 1.5, 4.5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
137 QCOMPARE( spy.count(), 2 );
138 QCOMPARE( spy.at( 1 ).at( 1 ).toString(), i2id );
139
140 utils.mouseMove( 7.5, 1.5 );
141 utils.mouseClick( 7.5, 1.5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
142 QCOMPARE( spy.count(), 3 );
143 QCOMPARE( spy.at( 2 ).at( 1 ).toString(), i3id );
144
145 // click on no item - should clear selection
146 QSignalSpy selectionClearedSpy( &tool, &QgsMapToolModifyAnnotation::selectionCleared );
147 utils.mouseMove( 9.5, 9.5 );
148 utils.mouseClick( 9.5, 9.5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
149 QCOMPARE( spy.count(), 3 );
150 QCOMPARE( selectionClearedSpy.count(), 1 );
151 }
152
testDeleteItem()153 void TestQgsMapToolEditAnnotation::testDeleteItem()
154 {
155 QgsProject::instance()->clear();
156 QgsMapCanvas canvas;
157 canvas.setDestinationCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) );
158 canvas.setFrameStyle( QFrame::NoFrame );
159 canvas.resize( 600, 600 );
160 canvas.setExtent( QgsRectangle( 0, 0, 10, 10 ) );
161 canvas.show(); // to make the canvas resize
162
163 QgsAnnotationLayer *layer = new QgsAnnotationLayer( QStringLiteral( "test" ), QgsAnnotationLayer::LayerOptions( QgsProject::instance()->transformContext() ) );
164 QVERIFY( layer->isValid() );
165 QgsProject::instance()->addMapLayers( { layer } );
166
167 QgsAnnotationPolygonItem *item1 = new QgsAnnotationPolygonItem( new QgsPolygon( new QgsLineString( QVector<QgsPoint> { QgsPoint( 1, 1 ), QgsPoint( 5, 1 ), QgsPoint( 5, 5 ), QgsPoint( 1, 5 ), QgsPoint( 1, 1 ) } ) ) );
168 item1->setZIndex( 1 );
169 const QString i1id = layer->addItem( item1 );
170
171 QgsAnnotationPolygonItem *item2 = new QgsAnnotationPolygonItem( new QgsPolygon( new QgsLineString( QVector<QgsPoint> { QgsPoint( 1, 4 ), QgsPoint( 5, 4 ), QgsPoint( 5, 9 ), QgsPoint( 1, 9 ), QgsPoint( 1, 4 ) } ) ) );
172 item2->setZIndex( 2 );
173 const QString i2id = layer->addItem( item2 );
174
175 QgsAnnotationPolygonItem *item3 = new QgsAnnotationPolygonItem( new QgsPolygon( new QgsLineString( QVector<QgsPoint> { QgsPoint( 7, 1 ), QgsPoint( 8, 1 ), QgsPoint( 8, 2 ), QgsPoint( 7, 2 ), QgsPoint( 7, 1 ) } ) ) );
176 item3->setZIndex( 3 );
177 const QString i3id = layer->addItem( item3 );
178
179 layer->setCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) );
180
181 canvas.setLayers( { layer } );
182 while ( !canvas.isDrawing() )
183 {
184 QgsApplication::processEvents();
185 }
186 canvas.waitWhileRendering();
187 QCOMPARE( canvas.renderedItemResults()->renderedItems().size(), 3 );
188
189 QgsAdvancedDigitizingDockWidget cadDock( &canvas );
190 QgsMapToolModifyAnnotation tool( &canvas, &cadDock );
191 canvas.setMapTool( &tool );
192
193 TestQgsMapToolUtils utils( &tool );
194
195 // no selected item
196 utils.mouseMove( 9, 9 );
197 utils.mouseClick( 9, 9, Qt::LeftButton, Qt::KeyboardModifiers(), true );
198 utils.keyClick( Qt::Key_Delete );
199 QCOMPARE( qgis::listToSet( layer->items().keys() ), QSet< QString >( { i1id, i2id, i3id } ) );
200
201 // with selected item
202 utils.mouseMove( 1.5, 1.5 );
203 utils.mouseClick( 1.5, 1.5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
204 utils.keyClick( Qt::Key_Delete );
205 QCOMPARE( qgis::listToSet( layer->items().keys() ), QSet< QString >( { i2id, i3id } ) );
206 while ( !canvas.isDrawing() )
207 {
208 QgsApplication::processEvents();
209 }
210 canvas.waitWhileRendering();
211
212 utils.mouseMove( 1.5, 4.5 );
213 utils.mouseClick( 1.5, 4.5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
214 utils.keyClick( Qt::Key_Delete );
215 QCOMPARE( qgis::listToSet( layer->items().keys() ), QSet< QString >( { i3id } ) );
216 }
217
testMoveItem()218 void TestQgsMapToolEditAnnotation::testMoveItem()
219 {
220 QgsProject::instance()->clear();
221 QgsMapCanvas canvas;
222 canvas.setDestinationCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) );
223 canvas.setFrameStyle( QFrame::NoFrame );
224 canvas.resize( 600, 600 );
225 canvas.setExtent( QgsRectangle( 0, 0, 10, 10 ) );
226 canvas.show(); // to make the canvas resize
227
228 QgsAnnotationLayer *layer = new QgsAnnotationLayer( QStringLiteral( "test" ), QgsAnnotationLayer::LayerOptions( QgsProject::instance()->transformContext() ) );
229 QVERIFY( layer->isValid() );
230 QgsProject::instance()->addMapLayers( { layer } );
231
232 QgsAnnotationPolygonItem *item1 = new QgsAnnotationPolygonItem( new QgsPolygon( new QgsLineString( QVector<QgsPoint> { QgsPoint( 1, 1 ), QgsPoint( 5, 1 ), QgsPoint( 5, 5 ), QgsPoint( 1, 5 ), QgsPoint( 1, 1 ) } ) ) );
233 item1->setZIndex( 1 );
234 const QString i1id = layer->addItem( item1 );
235 QCOMPARE( qgis::down_cast< QgsAnnotationPolygonItem * >( layer->item( i1id ) )->geometry()->asWkt(), QStringLiteral( "Polygon ((1 1, 5 1, 5 5, 1 5, 1 1))" ) );
236
237 layer->setCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) );
238
239 canvas.setLayers( { layer } );
240 while ( !canvas.isDrawing() )
241 {
242 QgsApplication::processEvents();
243 }
244 canvas.waitWhileRendering();
245 QCOMPARE( canvas.renderedItemResults()->renderedItems().size(), 1 );
246
247 QgsAdvancedDigitizingDockWidget cadDock( &canvas );
248 QgsMapToolModifyAnnotation tool( &canvas, &cadDock );
249 canvas.setMapTool( &tool );
250
251 QSignalSpy spy( &tool, &QgsMapToolModifyAnnotation::itemSelected );
252 TestQgsMapToolUtils utils( &tool );
253
254 // click on item
255 utils.mouseMove( 1.5, 1.5 );
256 utils.mouseClick( 1.5, 1.5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
257 QCOMPARE( spy.count(), 1 );
258 QCOMPARE( spy.at( 0 ).at( 1 ).toString(), i1id );
259
260 // a second left click on the item will start moving the item
261 utils.mouseClick( 1.5, 1.5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
262 // second click isn't selecting an item, so no new signals should be emitted
263 QCOMPARE( spy.count(), 1 );
264
265 // move mouse and click to end item move
266 utils.mouseMove( 4.5, 4.5 );
267 utils.mouseClick( 4.5, 4.5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
268 while ( !canvas.isDrawing() )
269 {
270 QgsApplication::processEvents();
271 }
272 canvas.waitWhileRendering();
273 QCOMPARE( canvas.renderedItemResults()->renderedItems().size(), 1 );
274
275 // check that item was moved
276 QCOMPARE( qgis::down_cast< QgsAnnotationPolygonItem * >( layer->item( i1id ) )->geometry()->asWkt(), QStringLiteral( "Polygon ((4 4, 8 4, 8 8, 4 8, 4 4))" ) );
277
278 // start a new move
279 // click on item -- it should already be selected, so this will start a new move, not emit the itemSelected signal
280 utils.mouseMove( 4.6, 4.5 );
281 utils.mouseClick( 4.6, 4.5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
282 QCOMPARE( spy.count(), 1 );
283
284 utils.mouseMove( 1.5, 1.5 );
285 utils.mouseClick( 1.5, 1.5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
286 while ( !canvas.isDrawing() )
287 {
288 QgsApplication::processEvents();
289 }
290 canvas.waitWhileRendering();
291 QCOMPARE( canvas.renderedItemResults()->renderedItems().size(), 1 );
292
293 // check that item was moved
294 QCOMPARE( qgis::down_cast< QgsAnnotationPolygonItem * >( layer->item( i1id ) )->geometry()->asWkt( 1 ), QStringLiteral( "Polygon ((0.9 1, 4.9 1, 4.9 5, 0.9 5, 0.9 1))" ) );
295
296 // start a move then cancel it via right click
297 utils.mouseMove( 1.6, 1.6 );
298 utils.mouseClick( 1.6, 1.6, Qt::LeftButton, Qt::KeyboardModifiers(), true );
299 QCOMPARE( spy.count(), 1 );
300
301 utils.mouseMove( 4.5, 4.5 );
302 utils.mouseClick( 4.5, 4.5, Qt::RightButton, Qt::KeyboardModifiers(), true );
303 // check that item was NOT moved
304 QCOMPARE( qgis::down_cast< QgsAnnotationPolygonItem * >( layer->item( i1id ) )->geometry()->asWkt( 1 ), QStringLiteral( "Polygon ((0.9 1, 4.9 1, 4.9 5, 0.9 5, 0.9 1))" ) );
305
306 // cancel a move via escape key
307 utils.mouseMove( 1.6, 1.6 );
308 utils.mouseClick( 1.6, 1.6, Qt::LeftButton, Qt::KeyboardModifiers(), true );
309 QCOMPARE( spy.count(), 1 );
310
311 utils.mouseMove( 4.5, 4.5 );
312 // escape should cancel
313 utils.keyClick( Qt::Key_Escape );
314 //... so next click is not "finish move", but "clear selection"
315 utils.mouseClick( 4.5, 4.5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
316 // check that item was NOT moved
317 QCOMPARE( qgis::down_cast< QgsAnnotationPolygonItem * >( layer->item( i1id ) )->geometry()->asWkt( 1 ), QStringLiteral( "Polygon ((0.9 1, 4.9 1, 4.9 5, 0.9 5, 0.9 1))" ) );
318 }
319
testMoveNode()320 void TestQgsMapToolEditAnnotation::testMoveNode()
321 {
322 QgsProject::instance()->clear();
323 QgsMapCanvas canvas;
324 canvas.setDestinationCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) );
325 canvas.setFrameStyle( QFrame::NoFrame );
326 canvas.resize( 600, 600 );
327 canvas.setExtent( QgsRectangle( 0, 0, 10, 10 ) );
328 canvas.show(); // to make the canvas resize
329
330 QgsAnnotationLayer *layer = new QgsAnnotationLayer( QStringLiteral( "test" ), QgsAnnotationLayer::LayerOptions( QgsProject::instance()->transformContext() ) );
331 QVERIFY( layer->isValid() );
332 QgsProject::instance()->addMapLayers( { layer } );
333
334 QgsAnnotationPolygonItem *item1 = new QgsAnnotationPolygonItem( new QgsPolygon( new QgsLineString( QVector<QgsPoint> { QgsPoint( 1, 1 ), QgsPoint( 5, 1 ), QgsPoint( 5, 5 ), QgsPoint( 1, 5 ), QgsPoint( 1, 1 ) } ) ) );
335 item1->setZIndex( 1 );
336 const QString i1id = layer->addItem( item1 );
337 QCOMPARE( qgis::down_cast< QgsAnnotationPolygonItem * >( layer->item( i1id ) )->geometry()->asWkt(), QStringLiteral( "Polygon ((1 1, 5 1, 5 5, 1 5, 1 1))" ) );
338
339 layer->setCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) );
340
341 canvas.setLayers( { layer } );
342 while ( !canvas.isDrawing() )
343 {
344 QgsApplication::processEvents();
345 }
346 canvas.waitWhileRendering();
347 QCOMPARE( canvas.renderedItemResults()->renderedItems().size(), 1 );
348
349 QgsAdvancedDigitizingDockWidget cadDock( &canvas );
350 QgsMapToolModifyAnnotation tool( &canvas, &cadDock );
351 canvas.setMapTool( &tool );
352
353 QSignalSpy spy( &tool, &QgsMapToolModifyAnnotation::itemSelected );
354 TestQgsMapToolUtils utils( &tool );
355
356 // click on item
357 utils.mouseMove( 1.5, 1.5 );
358 utils.mouseClick( 1.5, 1.5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
359 QCOMPARE( spy.count(), 1 );
360 QCOMPARE( spy.at( 0 ).at( 1 ).toString(), i1id );
361
362 // click on a node
363 utils.mouseMove( 5, 5 );
364 utils.mouseClick( 5, 5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
365 // second click isn't selecting an item, so no new signals should be emitted
366 QCOMPARE( spy.count(), 1 );
367
368 // move mouse and click to end node move
369 utils.mouseMove( 4.5, 4.5 );
370 utils.mouseClick( 4.5, 4.5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
371 while ( !canvas.isDrawing() )
372 {
373 QgsApplication::processEvents();
374 }
375 canvas.waitWhileRendering();
376 QCOMPARE( canvas.renderedItemResults()->renderedItems().size(), 1 );
377
378 // check that item was moved
379 QCOMPARE( qgis::down_cast< QgsAnnotationPolygonItem * >( layer->item( i1id ) )->geometry()->asWkt(), QStringLiteral( "Polygon ((1 1, 5 1, 4.5 4.5, 1 5, 1 1))" ) );
380
381 // start a new move node
382 // click on item -- it should already be selected, so this will start a new move, not emit the itemSelected signal
383 utils.mouseMove( 5, 1 );
384 utils.mouseClick( 5, 1, Qt::LeftButton, Qt::KeyboardModifiers(), true );
385 QCOMPARE( spy.count(), 1 );
386
387 utils.mouseMove( 5.5, 1.5 );
388 utils.mouseClick( 5.5, 1.5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
389 while ( !canvas.isDrawing() )
390 {
391 QgsApplication::processEvents();
392 }
393 canvas.waitWhileRendering();
394 QCOMPARE( canvas.renderedItemResults()->renderedItems().size(), 1 );
395
396 // check that item was moved
397 QCOMPARE( qgis::down_cast< QgsAnnotationPolygonItem * >( layer->item( i1id ) )->geometry()->asWkt( 1 ), QStringLiteral( "Polygon ((1 1, 5.5 1.5, 4.5 4.5, 1 5, 1 1))" ) );
398
399 // start a move then cancel it via right click
400 utils.mouseMove( 4.5, 4.5 );
401 utils.mouseClick( 4.5, 4.5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
402 QCOMPARE( spy.count(), 1 );
403
404 utils.mouseMove( 4.9, 4.9 );
405 utils.mouseClick( 4.9, 4.9, Qt::RightButton, Qt::KeyboardModifiers(), true );
406 // check that node was NOT moved
407 QCOMPARE( qgis::down_cast< QgsAnnotationPolygonItem * >( layer->item( i1id ) )->geometry()->asWkt( 1 ), QStringLiteral( "Polygon ((1 1, 5.5 1.5, 4.5 4.5, 1 5, 1 1))" ) );
408
409 // cancel a move via escape key
410 utils.mouseMove( 4.5, 4.5 );
411 utils.mouseClick( 4.5, 4.5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
412 QCOMPARE( spy.count(), 1 );
413
414 utils.mouseMove( 4.9, 4.9 );
415 // escape should cancel
416 utils.keyClick( Qt::Key_Escape );
417 //... so next click is not "finish move", but "clear selection"
418 utils.mouseClick( 6.5, 6.5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
419 // check that node was NOT moved
420 QCOMPARE( qgis::down_cast< QgsAnnotationPolygonItem * >( layer->item( i1id ) )->geometry()->asWkt( 1 ), QStringLiteral( "Polygon ((1 1, 5.5 1.5, 4.5 4.5, 1 5, 1 1))" ) );
421 }
422
testDeleteNode()423 void TestQgsMapToolEditAnnotation::testDeleteNode()
424 {
425 QgsProject::instance()->clear();
426 QgsMapCanvas canvas;
427 canvas.setDestinationCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) );
428 canvas.setFrameStyle( QFrame::NoFrame );
429 canvas.resize( 600, 600 );
430 canvas.setExtent( QgsRectangle( 0, 0, 10, 10 ) );
431 canvas.show(); // to make the canvas resize
432
433 QgsAnnotationLayer *layer = new QgsAnnotationLayer( QStringLiteral( "test" ), QgsAnnotationLayer::LayerOptions( QgsProject::instance()->transformContext() ) );
434 QVERIFY( layer->isValid() );
435 QgsProject::instance()->addMapLayers( { layer } );
436
437 QgsAnnotationPolygonItem *item1 = new QgsAnnotationPolygonItem( new QgsPolygon( new QgsLineString( QVector<QgsPoint> { QgsPoint( 1, 1 ), QgsPoint( 5, 1 ), QgsPoint( 5, 5 ), QgsPoint( 1, 5 ), QgsPoint( 1, 1 ) } ) ) );
438 item1->setZIndex( 1 );
439 const QString i1id = layer->addItem( item1 );
440 QCOMPARE( qgis::down_cast< QgsAnnotationPolygonItem * >( layer->item( i1id ) )->geometry()->asWkt(), QStringLiteral( "Polygon ((1 1, 5 1, 5 5, 1 5, 1 1))" ) );
441
442 layer->setCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) );
443
444 canvas.setLayers( { layer } );
445 while ( !canvas.isDrawing() )
446 {
447 QgsApplication::processEvents();
448 }
449 canvas.waitWhileRendering();
450 QCOMPARE( canvas.renderedItemResults()->renderedItems().size(), 1 );
451
452 QgsAdvancedDigitizingDockWidget cadDock( &canvas );
453 QgsMapToolModifyAnnotation tool( &canvas, &cadDock );
454 canvas.setMapTool( &tool );
455
456 QSignalSpy spy( &tool, &QgsMapToolModifyAnnotation::itemSelected );
457 TestQgsMapToolUtils utils( &tool );
458
459 // click on item
460 utils.mouseMove( 1.5, 1.5 );
461 utils.mouseClick( 1.5, 1.5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
462 QCOMPARE( spy.count(), 1 );
463 QCOMPARE( spy.at( 0 ).at( 1 ).toString(), i1id );
464
465 // click on a node
466 utils.mouseMove( 5, 5 );
467 utils.mouseClick( 5, 5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
468 // second click isn't selecting an item, so no new signals should be emitted
469 QCOMPARE( spy.count(), 1 );
470
471 // delete node
472 utils.keyClick( Qt::Key_Delete );
473 while ( !canvas.isDrawing() )
474 {
475 QgsApplication::processEvents();
476 }
477 canvas.waitWhileRendering();
478 QCOMPARE( canvas.renderedItemResults()->renderedItems().size(), 1 );
479
480 // check that node was deleted
481 QCOMPARE( qgis::down_cast< QgsAnnotationPolygonItem * >( layer->item( i1id ) )->geometry()->asWkt(), QStringLiteral( "Polygon ((1 1, 5 1, 1 5, 1 1))" ) );
482
483 // start a new delete node
484 // click on item -- it should already be selected, so this will start a new move, not emit the itemSelected signal
485 utils.mouseMove( 5, 1 );
486 utils.mouseClick( 5, 1, Qt::LeftButton, Qt::KeyboardModifiers(), true );
487 QCOMPARE( spy.count(), 1 );
488
489 utils.keyClick( Qt::Key_Delete );
490 while ( !canvas.isDrawing() )
491 {
492 QgsApplication::processEvents();
493 }
494 canvas.waitWhileRendering();
495
496 // check that node was deleted -- this should delete the whole item, as its geometry was cleared
497 QCOMPARE( canvas.renderedItemResults()->renderedItems().size(), 0 );
498 QVERIFY( !layer->item( i1id ) );
499 }
500
testAddNode()501 void TestQgsMapToolEditAnnotation::testAddNode()
502 {
503 QgsProject::instance()->clear();
504 QgsMapCanvas canvas;
505 canvas.setDestinationCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) );
506 canvas.setFrameStyle( QFrame::NoFrame );
507 canvas.resize( 600, 600 );
508 canvas.setExtent( QgsRectangle( 0, 0, 10, 10 ) );
509 canvas.show(); // to make the canvas resize
510
511 QgsAnnotationLayer *layer = new QgsAnnotationLayer( QStringLiteral( "test" ), QgsAnnotationLayer::LayerOptions( QgsProject::instance()->transformContext() ) );
512 QVERIFY( layer->isValid() );
513 QgsProject::instance()->addMapLayers( { layer } );
514
515 QgsAnnotationPolygonItem *item1 = new QgsAnnotationPolygonItem( new QgsPolygon( new QgsLineString( QVector<QgsPoint> { QgsPoint( 1, 1 ), QgsPoint( 5, 1 ), QgsPoint( 5, 5 ), QgsPoint( 1, 5 ), QgsPoint( 1, 1 ) } ) ) );
516 item1->setZIndex( 1 );
517 const QString i1id = layer->addItem( item1 );
518 QCOMPARE( qgis::down_cast< QgsAnnotationPolygonItem * >( layer->item( i1id ) )->geometry()->asWkt(), QStringLiteral( "Polygon ((1 1, 5 1, 5 5, 1 5, 1 1))" ) );
519
520 layer->setCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) );
521
522 canvas.setLayers( { layer } );
523 while ( !canvas.isDrawing() )
524 {
525 QgsApplication::processEvents();
526 }
527 canvas.waitWhileRendering();
528 QCOMPARE( canvas.renderedItemResults()->renderedItems().size(), 1 );
529
530 QgsAdvancedDigitizingDockWidget cadDock( &canvas );
531 QgsMapToolModifyAnnotation tool( &canvas, &cadDock );
532 canvas.setMapTool( &tool );
533
534 QSignalSpy spy( &tool, &QgsMapToolModifyAnnotation::itemSelected );
535 TestQgsMapToolUtils utils( &tool );
536
537 // click on item
538 utils.mouseMove( 1.5, 1.5 );
539 utils.mouseClick( 1.5, 1.5, Qt::LeftButton, Qt::KeyboardModifiers(), true );
540 QCOMPARE( spy.count(), 1 );
541 QCOMPARE( spy.at( 0 ).at( 1 ).toString(), i1id );
542
543 // double-click a segment
544 utils.mouseMove( 5, 3 );
545 utils.mouseDoubleClick( 5, 3, Qt::LeftButton, Qt::KeyboardModifiers(), true );
546 // second click isn't selecting an item, so no new signals should be emitted
547 QCOMPARE( spy.count(), 1 );
548 while ( !canvas.isDrawing() )
549 {
550 QgsApplication::processEvents();
551 }
552 canvas.waitWhileRendering();
553 QCOMPARE( canvas.renderedItemResults()->renderedItems().size(), 1 );
554
555 // check that node was added
556 QCOMPARE( qgis::down_cast< QgsAnnotationPolygonItem * >( layer->item( i1id ) )->geometry()->asWkt(), QStringLiteral( "Polygon ((1 1, 5 1, 5 3, 5 5, 1 5, 1 1))" ) );
557 }
558
559
560 QGSTEST_MAIN( TestQgsMapToolEditAnnotation )
561 #include "testqgsmaptooleditannotation.moc"
562