1 /***************************************************************************
2                              qgscreateannotationitemmaptool_impl.cpp
3                              ------------------------
4     Date                 : September 2021
5     Copyright            : (C) 2021 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 
16 #include "qgscreateannotationitemmaptool_impl.h"
17 #include "qgsmapmouseevent.h"
18 #include "qgsannotationpointtextitem.h"
19 #include "qgsannotationmarkeritem.h"
20 #include "qgsannotationlineitem.h"
21 #include "qgsannotationpolygonitem.h"
22 #include "qgsannotationlayer.h"
23 #include "qgsstyle.h"
24 #include "qgsmapcanvas.h"
25 #include "qgsmarkersymbol.h"
26 #include "qgslinesymbol.h"
27 #include "qgsfillsymbol.h"
28 #include "qgsadvanceddigitizingdockwidget.h"
29 #include "qgsapplication.h"
30 #include "qgsrecentstylehandler.h"
31 
32 ///@cond PRIVATE
33 
34 //
35 // QgsMapToolCaptureAnnotationItem
36 //
37 
QgsMapToolCaptureAnnotationItem(QgsMapCanvas * canvas,QgsAdvancedDigitizingDockWidget * cadDockWidget,CaptureMode mode)38 QgsMapToolCaptureAnnotationItem::QgsMapToolCaptureAnnotationItem( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget, CaptureMode mode )
39   : QgsMapToolCapture( canvas, cadDockWidget, mode )
40 {
41 
42 }
43 
handler()44 QgsCreateAnnotationItemMapToolHandler *QgsMapToolCaptureAnnotationItem::handler()
45 {
46   return mHandler;
47 }
48 
mapTool()49 QgsMapTool *QgsMapToolCaptureAnnotationItem::mapTool()
50 {
51   return this;
52 }
53 
layer() const54 QgsMapLayer *QgsMapToolCaptureAnnotationItem::layer() const
55 {
56   return mHandler->targetLayer();
57 }
58 
59 
capabilities() const60 QgsMapToolCapture::Capabilities QgsMapToolCaptureAnnotationItem::capabilities() const
61 {
62   // no geometry validation!
63   return SupportsCurves;
64 }
65 
supportsTechnique(CaptureTechnique) const66 bool QgsMapToolCaptureAnnotationItem::supportsTechnique( CaptureTechnique ) const
67 {
68   return true;
69 }
70 
71 
72 
73 
74 //
75 // QgsCreatePointTextItemMapTool
76 //
77 
QgsCreatePointTextItemMapTool(QgsMapCanvas * canvas,QgsAdvancedDigitizingDockWidget * cadDockWidget)78 QgsCreatePointTextItemMapTool::QgsCreatePointTextItemMapTool( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget )
79   : QgsMapToolAdvancedDigitizing( canvas, cadDockWidget )
80   , mHandler( new QgsCreateAnnotationItemMapToolHandler( canvas, cadDockWidget ) )
81 {
82 
83 }
84 
85 QgsCreatePointTextItemMapTool::~QgsCreatePointTextItemMapTool() = default;
86 
cadCanvasPressEvent(QgsMapMouseEvent * event)87 void QgsCreatePointTextItemMapTool::cadCanvasPressEvent( QgsMapMouseEvent *event )
88 {
89   if ( event->button() != Qt::LeftButton )
90     return;
91 
92   const QgsPointXY layerPoint = toLayerCoordinates( mHandler->targetLayer(), event->mapPoint() );
93 
94   std::unique_ptr< QgsAnnotationPointTextItem > createdItem = std::make_unique< QgsAnnotationPointTextItem >( tr( "Text" ), layerPoint );
95   createdItem->setAlignment( Qt::AlignLeft );
96   createdItem->setFormat( QgsStyle::defaultStyle()->defaultTextFormat( QgsStyle::TextFormatContext::Labeling ) );
97   // newly created point text items default to using symbology reference scale at the current map scale
98   createdItem->setUseSymbologyReferenceScale( true );
99   createdItem->setSymbologyReferenceScale( canvas()->scale() );
100   mHandler->pushCreatedItem( createdItem.release() );
101 }
102 
handler()103 QgsCreateAnnotationItemMapToolHandler *QgsCreatePointTextItemMapTool::handler()
104 {
105   return mHandler;
106 }
107 
mapTool()108 QgsMapTool *QgsCreatePointTextItemMapTool::mapTool()
109 {
110   return this;
111 }
112 
113 
114 
115 //
116 // QgsCreateMarkerMapTool
117 //
118 
QgsCreateMarkerItemMapTool(QgsMapCanvas * canvas,QgsAdvancedDigitizingDockWidget * cadDockWidget)119 QgsCreateMarkerItemMapTool::QgsCreateMarkerItemMapTool( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget )
120   : QgsMapToolCaptureAnnotationItem( canvas, cadDockWidget, CapturePoint )
121 {
122   mHandler = new QgsCreateAnnotationItemMapToolHandler( canvas, cadDockWidget, this );
123 }
124 
cadCanvasReleaseEvent(QgsMapMouseEvent * event)125 void QgsCreateMarkerItemMapTool::cadCanvasReleaseEvent( QgsMapMouseEvent *event )
126 {
127   if ( event->button() != Qt::LeftButton )
128     return;
129 
130   const QgsPointXY layerPoint = toLayerCoordinates( mHandler->targetLayer(), event->mapPoint() );
131   std::unique_ptr< QgsAnnotationMarkerItem > createdItem = std::make_unique< QgsAnnotationMarkerItem >( QgsPoint( layerPoint ) );
132 
133   std::unique_ptr< QgsMarkerSymbol > markerSymbol = QgsApplication::recentStyleHandler()->recentSymbol< QgsMarkerSymbol >( QStringLiteral( "marker_annotation_item" ) );
134   if ( !markerSymbol )
135     markerSymbol.reset( qgis::down_cast< QgsMarkerSymbol * >( QgsSymbol::defaultSymbol( QgsWkbTypes::PointGeometry ) ) );
136   createdItem->setSymbol( markerSymbol.release() );
137 
138   // set reference scale to match canvas scale, but don't enable it by default for marker items
139   createdItem->setSymbologyReferenceScale( canvas()->scale() );
140 
141   mHandler->pushCreatedItem( createdItem.release() );
142 
143   stopCapturing();
144 
145   cadDockWidget()->clearPoints();
146 }
147 
148 //
149 // QgsCreateLineMapTool
150 //
151 
QgsCreateLineItemMapTool(QgsMapCanvas * canvas,QgsAdvancedDigitizingDockWidget * cadDockWidget)152 QgsCreateLineItemMapTool::QgsCreateLineItemMapTool( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget )
153   : QgsMapToolCaptureAnnotationItem( canvas, cadDockWidget, CaptureLine )
154 {
155   mHandler = new QgsCreateAnnotationItemMapToolHandler( canvas, cadDockWidget, this );
156 }
157 
cadCanvasReleaseEvent(QgsMapMouseEvent * e)158 void QgsCreateLineItemMapTool::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
159 {
160   //add point to list and to rubber band
161   if ( e->button() == Qt::LeftButton )
162   {
163     const int error = addVertex( e->mapPoint(), e->mapPointMatch() );
164     if ( error == 2 )
165     {
166       //problem with coordinate transformation
167       emit messageEmitted( tr( "Cannot transform the point to the layers coordinate system" ), Qgis::MessageLevel::Warning );
168       return;
169     }
170 
171     startCapturing();
172   }
173   else if ( e->button() == Qt::RightButton )
174   {
175     deleteTempRubberBand();
176 
177     //find out bounding box of mCaptureList
178     if ( size() < 1 )
179     {
180       stopCapturing();
181       return;
182     }
183 
184     // do it!
185     std::unique_ptr< QgsAbstractGeometry > geometry( captureCurve()->simplifiedTypeRef()->clone() );
186     if ( qgsgeometry_cast< QgsCurve * >( geometry.get() ) )
187     {
188       std::unique_ptr< QgsAnnotationLineItem > createdItem = std::make_unique< QgsAnnotationLineItem >( qgsgeometry_cast< QgsCurve * >( geometry.release() ) );
189 
190       std::unique_ptr< QgsLineSymbol > lineSymbol = QgsApplication::recentStyleHandler()->recentSymbol< QgsLineSymbol >( QStringLiteral( "line_annotation_item" ) );
191       if ( !lineSymbol )
192         lineSymbol.reset( qgis::down_cast< QgsLineSymbol * >( QgsSymbol::defaultSymbol( QgsWkbTypes::LineGeometry ) ) );
193       createdItem->setSymbol( lineSymbol.release() );
194 
195       // set reference scale to match canvas scale, but don't enable it by default for marker items
196       createdItem->setSymbologyReferenceScale( canvas()->scale() );
197 
198       mHandler->pushCreatedItem( createdItem.release() );
199     }
200     stopCapturing();
201   }
202 }
203 
204 //
205 // QgsCreatePolygonItemMapTool
206 //
207 
QgsCreatePolygonItemMapTool(QgsMapCanvas * canvas,QgsAdvancedDigitizingDockWidget * cadDockWidget)208 QgsCreatePolygonItemMapTool::QgsCreatePolygonItemMapTool( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget )
209   : QgsMapToolCaptureAnnotationItem( canvas, cadDockWidget, CapturePolygon )
210 {
211   mHandler = new QgsCreateAnnotationItemMapToolHandler( canvas, cadDockWidget, this );
212 }
213 
cadCanvasReleaseEvent(QgsMapMouseEvent * e)214 void QgsCreatePolygonItemMapTool::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
215 {
216   //add point to list and to rubber band
217   if ( e->button() == Qt::LeftButton )
218   {
219     const int error = addVertex( e->mapPoint(), e->mapPointMatch() );
220     if ( error == 2 )
221     {
222       //problem with coordinate transformation
223       emit messageEmitted( tr( "Cannot transform the point to the layers coordinate system" ), Qgis::MessageLevel::Warning );
224       return;
225     }
226 
227     startCapturing();
228   }
229   else if ( e->button() == Qt::RightButton )
230   {
231     deleteTempRubberBand();
232 
233     //find out bounding box of mCaptureList
234     if ( size() < 1 )
235     {
236       stopCapturing();
237       return;
238     }
239 
240     closePolygon();
241 
242     std::unique_ptr< QgsAbstractGeometry > geometry( captureCurve()->simplifiedTypeRef()->clone() );
243     if ( qgsgeometry_cast< QgsCurve * >( geometry.get() ) )
244     {
245       std::unique_ptr< QgsCurvePolygon > newPolygon = std::make_unique< QgsCurvePolygon >();
246       newPolygon->setExteriorRing( qgsgeometry_cast< QgsCurve * >( geometry.release() ) );
247       std::unique_ptr< QgsAnnotationPolygonItem > createdItem = std::make_unique< QgsAnnotationPolygonItem >( newPolygon.release() );
248 
249       std::unique_ptr< QgsFillSymbol > fillSymbol = QgsApplication::recentStyleHandler()->recentSymbol< QgsFillSymbol >( QStringLiteral( "polygon_annotation_item" ) );
250       if ( !fillSymbol )
251         fillSymbol.reset( qgis::down_cast< QgsFillSymbol * >( QgsSymbol::defaultSymbol( QgsWkbTypes::PolygonGeometry ) ) );
252       createdItem->setSymbol( fillSymbol.release() );
253 
254       // set reference scale to match canvas scale, but don't enable it by default for marker items
255       createdItem->setSymbologyReferenceScale( canvas()->scale() );
256 
257       mHandler->pushCreatedItem( createdItem.release() );
258     }
259     stopCapturing();
260   }
261 }
262 
263 ///@endcond PRIVATE
264 
265