QGIS API Documentation 4.1.0-Master (31622b25bb0)
Loading...
Searching...
No Matches
qgsmaptool.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmaptool.cpp - base class for map canvas tools
3 ----------------------
4 begin : January 2006
5 copyright : (C) 2006 by Martin Dobias
6 email : wonder.sk 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 "qgsmaptool.h"
17
19#include "qgslogger.h"
20#include "qgsmapcanvas.h"
21#include "qgsmapmouseevent.h"
22#include "qgsmaptopixel.h"
23#include "qgsrendercontext.h"
24#include "qgssettings.h"
26#include "qgssettingstree.h"
27
28#include <QAbstractButton>
29#include <QAction>
30#include <QString>
31
32#include "moc_qgsmaptool.cpp"
33
34using namespace Qt::StringLiterals;
35
37 = new QgsSettingsEntryDouble( u"search-radius-mm"_s, QgsSettingsTree::sTreeMap, Qgis::DEFAULT_SEARCH_RADIUS_MM, u"Search/identify radius in millimeters"_s );
38
40 : QObject( canvas )
41 , mCanvas( canvas )
42 , mCursor( Qt::CrossCursor )
43{}
44
45
47{
48 if ( mCanvas )
49 mCanvas->unsetMapTool( this );
50}
51
53{
54 return mCanvas->getCoordinateTransform()->toMapCoordinates( point );
55}
56
58{
59 return mCanvas->mapSettings().layerToMapCoordinates( layer, point );
60}
61
63{
64 const QgsPointXY pt = toMapCoordinates( point );
65 return toLayerCoordinates( layer, pt );
66}
67
69{
70 return mCanvas->mapSettings().mapToLayerCoordinates( layer, point );
71}
72
74{
75 return mCanvas->mapSettings().mapToLayerCoordinates( layer, point );
76}
77
79{
80 return mCanvas->mapSettings().layerToMapCoordinates( layer, point );
81}
82
84{
85 return mCanvas->mapSettings().mapToLayerCoordinates( layer, rect );
86}
87
88QPoint QgsMapTool::toCanvasCoordinates( const QgsPointXY &point ) const
89{
90 qreal x = point.x(), y = point.y();
91 mCanvas->getCoordinateTransform()->transformInPlace( x, y );
92 return QPoint( std::round( x ), std::round( y ) );
93}
94
95QgsMapLayer *QgsMapTool::layer( const QString &id )
96{
97 return mCanvas->layer( id );
98}
99
100void QgsMapTool::setToolName( const QString &name )
101{
102 mToolName = name;
103}
104
106{
107 // make action and/or button active
108 if ( mAction )
109 mAction->setChecked( true );
110 if ( mButton )
111 mButton->setChecked( true );
112
113 // set cursor (map tools usually set it in constructor)
114 mCanvas->setCursor( mCursor );
115 QgsDebugMsgLevel( u"Cursor has been set"_s, 4 );
116
117 emit activated();
118}
119
120
122{
123 if ( mAction )
124 mAction->setChecked( false );
125 if ( mButton )
126 mButton->setChecked( false );
127
128 emit deactivated();
129}
130
131
133{
134 emit reactivated();
135}
136
138{}
139
141{
142 if ( mAction )
143 disconnect( mAction, &QObject::destroyed, this, &QgsMapTool::actionDestroyed );
144 mAction = action;
145 if ( mAction )
146 connect( mAction, &QObject::destroyed, this, &QgsMapTool::actionDestroyed );
147}
148
149void QgsMapTool::actionDestroyed()
150{
151 if ( mAction == sender() )
152 mAction = nullptr;
153}
154
156{
157 return mAction;
158}
159
161{
162 return mCanvas && mCanvas->mapTool() == this;
163}
164
165void QgsMapTool::setButton( QAbstractButton *button )
166{
167 mButton = button;
168}
169
170QAbstractButton *QgsMapTool::button()
171{
172 return mButton;
173}
174
175void QgsMapTool::setCursor( const QCursor &cursor )
176{
177 mCursor = cursor;
178 if ( isActive() )
179 mCanvas->setCursor( mCursor );
180}
181
182
184{
185 Q_UNUSED( e )
186}
187
189{
190 Q_UNUSED( e )
191}
192
194{
195 Q_UNUSED( e )
196}
197
199{
200 Q_UNUSED( e )
201}
202
203void QgsMapTool::wheelEvent( QWheelEvent *e )
204{
205 e->ignore();
206}
207
208void QgsMapTool::keyPressEvent( QKeyEvent *e )
209{
210 Q_UNUSED( e )
211}
212
213void QgsMapTool::keyReleaseEvent( QKeyEvent *e )
214{
215 Q_UNUSED( e )
216}
217
218bool QgsMapTool::gestureEvent( QGestureEvent *e )
219{
220 Q_UNUSED( e )
221 return true;
222}
223
225{
226 Q_UNUSED( e )
227 return false;
228}
229
230bool QgsMapTool::shortcutEvent( QKeyEvent *e )
231{
232 Q_UNUSED( e )
233 return false;
234}
235
237{
238 return mCanvas;
239}
240
242{
243 const double radius = settingSearchRadiusMM->value();
244
245 if ( radius > 0 )
246 {
247 return radius;
248 }
250}
251
256
258{
259 if ( !canvas )
260 {
261 return 0;
262 }
263 const QgsMapSettings mapSettings = canvas->mapSettings();
264 const QgsRenderContext context = QgsRenderContext::fromMapSettings( mapSettings );
265 return searchRadiusMU( context ) / mapSettings.magnificationFactor();
266}
267
268
271
272
274{
275 return false;
276}
277
278QString QgsMapTool::dataDefinedColumnName( int propertyKey, const QgsPropertyCollection &properties, const QgsVectorLayer *layer, PropertyStatus &status ) const
279{
281 if ( !properties.isActive( propertyKey ) )
282 return QString();
283
284 const QgsProperty property = properties.property( propertyKey );
285
286 switch ( property.propertyType() )
287 {
289 break;
290
292 status = PropertyStatus::Valid;
293 break;
294
296 status = PropertyStatus::Valid;
297 return property.field();
298
300 {
301 status = PropertyStatus::Valid;
302
303 // an expression based property may still be a effectively a single field reference in the map canvas context.
304 // e.g. if it is a expression like '"some_field"', or 'case when @some_project_var = 'a' then "field_a" else "field_b" end'
305
306 QgsExpressionContext context = mCanvas->createExpressionContext();
307 context.appendScope( layer->createExpressionContextScope() );
308
309 QgsExpression expression( property.expressionString() );
310 if ( expression.prepare( &context ) )
311 {
312 // maybe the expression is effectively a single node in this context...
313 const QgsExpressionNode *node = expression.rootNode()->effectiveNode();
315 {
316 const QgsExpressionNodeColumnRef *columnRef = qgis::down_cast<const QgsExpressionNodeColumnRef *>( node );
317 return columnRef->name();
318 }
319
320 // ok, it's not. But let's be super smart and helpful for users!
321 // maybe it's a COALESCE("some field", 'some' || 'fallback' || 'expression') type expression, where the user wants to override
322 // some labels with a value stored in a field but all others use some expression
324 {
325 const QgsExpressionNodeFunction *functionNode = qgis::down_cast<const QgsExpressionNodeFunction *>( node );
326 if ( const QgsExpressionFunction *function = QgsExpression::QgsExpression::Functions()[functionNode->fnIndex()] )
327 {
328 if ( function->name() == "coalesce"_L1 )
329 {
330 if ( const QgsExpressionNode *firstArg = functionNode->args()->list().value( 0 ) )
331 {
332 const QgsExpressionNode *firstArgNode = firstArg->effectiveNode();
333 if ( firstArgNode->nodeType() == QgsExpressionNode::ntColumnRef )
334 {
335 const QgsExpressionNodeColumnRef *columnRef = qgis::down_cast<const QgsExpressionNodeColumnRef *>( firstArgNode );
336 return columnRef->name();
337 }
338 }
339 }
340 }
341 }
342 }
343 else
344 {
346 }
347 break;
348 }
349 }
350
351 return QString();
352}
353
354int QgsMapTool::dataDefinedColumnIndex( int propertyKey, const QgsPropertyCollection &properties, const QgsVectorLayer *vlayer ) const
355{
357 QString fieldname = dataDefinedColumnName( propertyKey, properties, vlayer, status );
358 if ( !fieldname.isEmpty() )
359 return vlayer->fields().lookupField( fieldname );
360 return -1;
361}
@ Invalid
Invalid (not set) property.
Definition qgis.h:710
@ Field
Field based property.
Definition qgis.h:712
@ Static
Static property.
Definition qgis.h:711
@ Expression
Expression based property.
Definition qgis.h:713
@ Millimeters
Millimeters.
Definition qgis.h:5553
static const double DEFAULT_SEARCH_RADIUS_MM
Identify search radius in mm.
Definition qgis.h:6786
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
An abstract base class for defining QgsExpression functions.
An expression node which takes its value from a feature's field.
QString name() const
The name of the column.
An expression node for expression functions.
int fnIndex() const
Returns the index of the node's function.
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
QList< QgsExpressionNode * > list()
Gets a list of all the nodes.
Abstract base class for all nodes that can appear in an expression.
virtual QgsExpressionNode::NodeType nodeType() const =0
Gets the type of this node.
const QgsExpressionNode * effectiveNode() const
Returns a reference to the simplest node which represents this node, after any compilation optimizati...
Handles parsing and evaluation of expressions (formerly called "search strings").
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
const QgsExpressionNode * rootNode() const
Returns the root node of the expression.
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Base class for all map layer types.
Definition qgsmaplayer.h:83
A mouse event which is the result of a user interaction with a QgsMapCanvas.
Contains configuration for rendering maps.
double magnificationFactor() const
Returns the magnification factor.
QgsPoint toLayerCoordinates(const QgsMapLayer *layer, const QgsPoint &point)
Transforms a point from map coordinates to layer coordinates.
void deactivated()
Emitted when the map tool is deactivated.
static double searchRadiusMM()
Gets search radius in mm.
QgsMapLayer * layer(const QString &id)
Returns the map layer with the matching ID, or nullptr if no layers could be found.
QgsMapCanvas * canvas() const
returns pointer to the tool's map canvas
QgsMapTool(QgsMapCanvas *canvas)
Constructor takes a map canvas as a parameter.
QAbstractButton * mButton
Optional pointer to a button that will be checked on map tool activation and unchecked on map tool de...
Definition qgsmaptool.h:418
virtual void populateContextMenu(QMenu *menu)
Allows the tool to populate and customize the given menu, prior to showing it in response to a right-...
virtual bool canvasToolTipEvent(QHelpEvent *e)
Tooltip event for overriding.
void setToolName(const QString &name)
Sets the tool's name.
virtual void canvasDoubleClickEvent(QgsMapMouseEvent *e)
Mouse double-click event for overriding. Default implementation does nothing.
QgsPointXY toMapCoordinates(QPoint point)
Transforms a point from screen coordinates to map coordinates.
virtual void setCursor(const QCursor &cursor)
Sets a user defined cursor.
QPointer< QgsMapCanvas > mCanvas
The pointer to the map canvas.
Definition qgsmaptool.h:403
QString mToolName
The translated name of the map tool.
Definition qgsmaptool.h:421
friend class QgsMapCanvas
Definition qgsmaptool.h:423
QAbstractButton * button()
Returns associated button with map tool or nullptr if no button is associated.
void setButton(QAbstractButton *button)
Use this to associate a button to this maptool.
virtual bool populateContextMenuWithEvent(QMenu *menu, QgsMapMouseEvent *event)
Allows the tool to populate and customize the given menu, prior to showing it in response to a right-...
PropertyStatus
Property status used in method dealing with property.
Definition qgsmaptool.h:293
@ Valid
Property is valid.
Definition qgsmaptool.h:294
@ CurrentExpressionInvalid
Property is an invalid expression.
Definition qgsmaptool.h:296
@ DoesNotExist
Property does not exist.
Definition qgsmaptool.h:295
virtual void canvasPressEvent(QgsMapMouseEvent *e)
Mouse press event for overriding. Default implementation does nothing.
void activated()
Emitted when the map tool is activated.
void setAction(QAction *action)
Use this to associate a QAction to this maptool.
virtual void canvasMoveEvent(QgsMapMouseEvent *e)
Mouse move event for overriding. Default implementation does nothing.
QAction * mAction
Optional pointer to an action that will be checked on map tool activation and unchecked on map tool d...
Definition qgsmaptool.h:412
virtual void keyPressEvent(QKeyEvent *e)
Key event for overriding. Default implementation does nothing.
virtual bool shortcutEvent(QKeyEvent *e)
Shortcut events coming from the application for overriding.
static double searchRadiusMU(const QgsRenderContext &context)
Gets search radius in map units for given context.
QAction * action()
Returns associated action with map tool or nullptr if no action is associated.
virtual void keyReleaseEvent(QKeyEvent *e)
Key event for overriding. Default implementation does nothing.
~QgsMapTool() override
virtual void canvasReleaseEvent(QgsMapMouseEvent *e)
Mouse release event for overriding. Default implementation does nothing.
QPoint toCanvasCoordinates(const QgsPointXY &point) const
Transforms a point from map coordinates to screen coordinates.
void reactivated()
Emitted when the map tool is activated, while it is already active.
static const QgsSettingsEntryDouble * settingSearchRadiusMM
Settings entry for the search/identify radius in mm.
Definition qgsmaptool.h:234
virtual void wheelEvent(QWheelEvent *e)
Mouse wheel event for overriding. Default implementation does nothing.
bool isActive() const
Returns if the current map tool active on the map canvas.
virtual void reactivate()
Called when the map tool is being activated while it is already active.
virtual void clean()
convenient method to clean members
QString dataDefinedColumnName(int propertyKey, const QgsPropertyCollection &properties, const QgsVectorLayer *layer, PropertyStatus &status) const
Returns data defined property column name for the propertyKey from properties associated to the layer...
virtual void activate()
called when set as currently active map tool
virtual bool gestureEvent(QGestureEvent *e)
gesture event for overriding. Default implementation does nothing.
int dataDefinedColumnIndex(int propertyKey, const QgsPropertyCollection &properties, const QgsVectorLayer *vlayer) const
Returns data defined property column index for the propertyKey from properties associated to the laye...
QCursor mCursor
The cursor used in the map tool.
Definition qgsmaptool.h:406
virtual void deactivate()
called when map tool is being deactivated
Represents a 2D point.
Definition qgspointxy.h:62
double y
Definition qgspointxy.h:66
double x
Definition qgspointxy.h:65
Point geometry type, with support for z-dimension and m-values.
Definition qgspoint.h:53
A grouped map of multiple QgsProperty objects, each referenced by an integer key value.
bool isActive(int key) const final
Returns true if the collection contains an active property with the specified key.
QgsProperty property(int key) const final
Returns a matching property from the collection, if one exists.
A store for object properties.
A rectangle specified with double values.
Contains information about the context of a rendering operation.
double convertToMapUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to map units.
static QgsRenderContext fromMapSettings(const QgsMapSettings &mapSettings)
create initialized QgsRenderContext instance from given QgsMapSettings
A double settings entry.
static QgsSettingsTreeNode * sTreeMap
Represents a vector layer which manages a vector based dataset.
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63