QGIS API Documentation  3.4.15-Madeira (e83d02e274)
qgsidentifymenu.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsidentifymenu.cpp - menu to be used in identify map tool
3  ---------------------
4  begin : August 2014
5  copyright : (C) 2014 by Denis Rouzaud
6  email : [email protected]
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 <QMouseEvent>
17 
18 #include "qgsidentifymenu.h"
19 #include "qgsapplication.h"
20 #include "qgsactionmanager.h"
21 #include "qgshighlight.h"
22 #include "qgsmapcanvas.h"
23 #include "qgsactionmenu.h"
24 #include "qgsvectorlayer.h"
25 #include "qgslogger.h"
26 #include "qgssettings.h"
27 #include "qgsgui.h"
28 
29 //TODO 4.0 add explicitly qobject parent to constructor
31  : QMenu( canvas )
32  , mCanvas( canvas )
33  , mAllowMultipleReturn( true )
34  , mExecWithSingleResult( false )
35  , mShowFeatureActions( false )
36  , mResultsIfExternalAction( false )
37  , mMaxLayerDisplay( 10 )
38  , mMaxFeatureDisplay( 10 )
39  , mDefaultActionName( tr( "Identify" ) )
40 {
41 }
42 
44 {
45  deleteRubberBands();
46 }
47 
48 
50 {
51  if ( maxLayerDisplay < 0 )
52  {
53  QgsDebugMsg( QStringLiteral( "invalid value for number of layers displayed." ) );
54  }
55  mMaxLayerDisplay = maxLayerDisplay;
56 }
57 
58 
60 {
61  if ( maxFeatureDisplay < 0 )
62  {
63  QgsDebugMsg( QStringLiteral( "invalid value for number of layers displayed." ) );
64  }
65  mMaxFeatureDisplay = maxFeatureDisplay;
66 }
67 
68 
69 QList<QgsMapToolIdentify::IdentifyResult> QgsIdentifyMenu::exec( const QList<QgsMapToolIdentify::IdentifyResult> &idResults, QPoint pos )
70 {
71  clear();
72  mLayerIdResults.clear();
73 
74  QList<QgsMapToolIdentify::IdentifyResult> returnResults = QList<QgsMapToolIdentify::IdentifyResult>();
75 
76  if ( idResults.isEmpty() )
77  {
78  return returnResults;
79  }
80  if ( idResults.count() == 1 && !mExecWithSingleResult )
81  {
82  returnResults << idResults[0];
83  return returnResults;
84  }
85 
86  // sort results by layer
87  Q_FOREACH ( const QgsMapToolIdentify::IdentifyResult &result, idResults )
88  {
89  QgsMapLayer *layer = result.mLayer;
90  if ( mLayerIdResults.contains( layer ) )
91  {
92  mLayerIdResults[layer].append( result );
93  }
94  else
95  {
96  mLayerIdResults.insert( layer, QList<QgsMapToolIdentify::IdentifyResult>() << result );
97  }
98  }
99 
100  // add results to the menu
101  bool singleLayer = mLayerIdResults.count() == 1;
102  int count = 0;
103  QMapIterator< QgsMapLayer *, QList<QgsMapToolIdentify::IdentifyResult> > it( mLayerIdResults );
104  while ( it.hasNext() )
105  {
106  if ( mMaxLayerDisplay != 0 && count > mMaxLayerDisplay )
107  break;
108  ++count;
109  it.next();
110  QgsMapLayer *layer = it.key();
111  if ( layer->type() == QgsMapLayer::RasterLayer )
112  {
113  addRasterLayer( layer );
114  }
115  else if ( layer->type() == QgsMapLayer::VectorLayer )
116  {
117  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer );
118  if ( !vl )
119  continue;
120  addVectorLayer( vl, it.value(), singleLayer );
121  }
122  }
123 
124  // add an "identify all" action on the top level
125  if ( !singleLayer && mAllowMultipleReturn && idResults.count() > 1 )
126  {
127  addSeparator();
128  QAction *allAction = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionIdentify.svg" ) ), tr( "%1 All (%2)" ).arg( mDefaultActionName ).arg( idResults.count() ), this );
129  allAction->setData( QVariant::fromValue<ActionData>( ActionData( nullptr ) ) );
130  connect( allAction, &QAction::hovered, this, &QgsIdentifyMenu::handleMenuHover );
131  addAction( allAction );
132  }
133 
134  // exec
135  QAction *selectedAction = QMenu::exec( pos );
136  bool externalAction;
137  returnResults = results( selectedAction, externalAction );
138 
139  // delete actions
140  clear();
141  // also remove the QgsActionMenu
142  qDeleteAll( findChildren<QgsActionMenu *>() );
143 
144  if ( externalAction && !mResultsIfExternalAction )
145  {
146  return QList<QgsMapToolIdentify::IdentifyResult>();
147  }
148  else
149  {
150  return returnResults;
151  }
152 }
153 
154 void QgsIdentifyMenu::closeEvent( QCloseEvent *e )
155 {
156  deleteRubberBands();
157  QMenu::closeEvent( e );
158 }
159 
160 void QgsIdentifyMenu::addRasterLayer( QgsMapLayer *layer )
161 {
162  QAction *layerAction = nullptr;
163  QMenu *layerMenu = nullptr;
164 
165  QList<QgsMapLayerAction *> separators = QList<QgsMapLayerAction *>();
166  QList<QgsMapLayerAction *> layerActions = mCustomActionRegistry.mapLayerActions( layer, QgsMapLayerAction::Layer );
167  int nCustomActions = layerActions.count();
168  if ( nCustomActions )
169  {
170  separators.append( layerActions[0] );
171  }
172  if ( mShowFeatureActions )
173  {
174  layerActions.append( QgsGui::mapLayerActionRegistry()->mapLayerActions( layer, QgsMapLayerAction::Layer ) );
175  if ( layerActions.count() > nCustomActions )
176  {
177  separators.append( layerActions[nCustomActions] );
178  }
179  }
180 
181  // use a menu only if actions will be listed
182  if ( layerActions.isEmpty() )
183  {
184  layerAction = new QAction( layer->name(), this );
185  }
186  else
187  {
188  layerMenu = new QMenu( layer->name(), this );
189  layerAction = layerMenu->menuAction();
190  }
191 
192  // add layer action to the top menu
193  layerAction->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mIconRasterLayer.svg" ) ) );
194  layerAction->setData( QVariant::fromValue<ActionData>( ActionData( layer ) ) );
195  connect( layerAction, &QAction::hovered, this, &QgsIdentifyMenu::handleMenuHover );
196  addAction( layerAction );
197 
198  // no need to go further if there is no menu
199  if ( !layerMenu )
200  return;
201 
202  // add default identify action
203  QAction *identifyFeatureAction = new QAction( mDefaultActionName, layerMenu );
204  connect( identifyFeatureAction, &QAction::hovered, this, &QgsIdentifyMenu::handleMenuHover );
205  identifyFeatureAction->setData( QVariant::fromValue<ActionData>( ActionData( layer ) ) );
206  layerMenu->addAction( identifyFeatureAction );
207 
208  // add custom/layer actions
209  Q_FOREACH ( QgsMapLayerAction *mapLayerAction, layerActions )
210  {
211  QAction *action = new QAction( mapLayerAction->icon(), mapLayerAction->text(), layerMenu );
212  action->setData( QVariant::fromValue<ActionData>( ActionData( layer, true ) ) );
213  connect( action, &QAction::hovered, this, &QgsIdentifyMenu::handleMenuHover );
214  connect( action, &QAction::triggered, this, &QgsIdentifyMenu::triggerMapLayerAction );
215  layerMenu->addAction( action );
216  if ( separators.contains( mapLayerAction ) )
217  {
218  layerMenu->insertSeparator( action );
219  }
220  }
221 }
222 
223 void QgsIdentifyMenu::addVectorLayer( QgsVectorLayer *layer, const QList<QgsMapToolIdentify::IdentifyResult> &results, bool singleLayer )
224 {
225  QAction *layerAction = nullptr;
226  QMenu *layerMenu = nullptr;
227 
228  // do not add actions with MultipleFeatures as target if only 1 feature is found for this layer
229  // targets defines which actions will be shown
230  QgsMapLayerAction::Targets targets = results.count() > 1 ? QgsMapLayerAction::Layer | QgsMapLayerAction::MultipleFeatures : QgsMapLayerAction::Layer;
231 
232  QList<QgsMapLayerAction *> separators = QList<QgsMapLayerAction *>();
233  QList<QgsMapLayerAction *> layerActions = mCustomActionRegistry.mapLayerActions( layer, targets );
234  int nCustomActions = layerActions.count();
235  if ( nCustomActions )
236  {
237  separators << layerActions[0];
238  }
239  if ( mShowFeatureActions )
240  {
241  layerActions << QgsGui::mapLayerActionRegistry()->mapLayerActions( layer, targets );
242 
243  if ( layerActions.count() > nCustomActions )
244  {
245  separators << layerActions[nCustomActions];
246  }
247  }
248 
249  // determines if a menu should be created or not. Following cases:
250  // 1. only one result and no feature action to be shown => just create an action
251  // 2. several features (2a) or display feature actions (2b) => create a menu
252  // 3. case 2 but only one layer (singeLayer) => do not create a menu, but give the top menu instead
253 
254  bool createMenu = results.count() > 1 || !layerActions.isEmpty();
255 
256  // case 2b: still create a menu for layer, if there is a sub-level for features
257  // i.e custom actions or map layer actions at feature level
258  if ( !createMenu )
259  {
260  createMenu = !mCustomActionRegistry.mapLayerActions( layer, QgsMapLayerAction::SingleFeature ).isEmpty();
261  if ( !createMenu && mShowFeatureActions )
262  {
263  QgsActionMenu *featureActionMenu = new QgsActionMenu( layer, results[0].mFeature, QStringLiteral( "Feature" ), this );
264  featureActionMenu->setMode( QgsAttributeEditorContext::IdentifyMode );
265  createMenu = !featureActionMenu->actions().isEmpty();
266  delete featureActionMenu;
267  }
268  }
269 
270  // use a menu only if actions will be listed
271  if ( !createMenu )
272  {
273  // case 1
274  QString featureTitle = results[0].mFeature.attribute( layer->displayField() ).toString();
275  if ( featureTitle.isEmpty() )
276  featureTitle = QStringLiteral( "%1" ).arg( results[0].mFeature.id() );
277  layerAction = new QAction( QStringLiteral( "%1 (%2)" ).arg( layer->name(), featureTitle ), this );
278  }
279  else
280  {
281  if ( singleLayer )
282  {
283  // case 3
284  layerMenu = this;
285  }
286  else
287  {
288  // case 2a
289  if ( results.count() > 1 )
290  {
291  layerMenu = new QMenu( layer->name(), this );
292  }
293  // case 2b
294  else
295  {
296  QString featureTitle = results[0].mFeature.attribute( layer->displayField() ).toString();
297  if ( featureTitle.isEmpty() )
298  featureTitle = QStringLiteral( "%1" ).arg( results[0].mFeature.id() );
299  layerMenu = new QMenu( QStringLiteral( "%1 (%2)" ).arg( layer->name(), featureTitle ), this );
300  }
301  layerAction = layerMenu->menuAction();
302  }
303  }
304 
305  // case 1 or 2
306  if ( layerAction )
307  {
308  // icons
309  switch ( layer->geometryType() )
310  {
312  layerAction->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPointLayer.svg" ) ) );
313  break;
315  layerAction->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mIconLineLayer.svg" ) ) );
316  break;
318  layerAction->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPolygonLayer.svg" ) ) );
319  break;
320  default:
321  break;
322  }
323 
324  // add layer action to the top menu
325  layerAction->setData( QVariant::fromValue<ActionData>( ActionData( layer ) ) );
326  connect( layerAction, &QAction::hovered, this, &QgsIdentifyMenu::handleMenuHover );
327  addAction( layerAction );
328  }
329 
330  // case 1. no need to go further
331  if ( !layerMenu )
332  return;
333 
334  // add results to the menu
335  int count = 0;
336  Q_FOREACH ( const QgsMapToolIdentify::IdentifyResult &result, results )
337  {
338  if ( mMaxFeatureDisplay != 0 && count > mMaxFeatureDisplay )
339  break;
340  ++count;
341 
342  QAction *featureAction = nullptr;
343  QMenu *featureMenu = nullptr;
344  QgsActionMenu *featureActionMenu = nullptr;
345 
346  QList<QgsMapLayerAction *> customFeatureActions = mCustomActionRegistry.mapLayerActions( layer, QgsMapLayerAction::SingleFeature );
347  if ( mShowFeatureActions )
348  {
349  featureActionMenu = new QgsActionMenu( layer, result.mFeature, QStringLiteral( "Feature" ), layerMenu );
350  featureActionMenu->setMode( QgsAttributeEditorContext::IdentifyMode );
351  featureActionMenu->setExpressionContextScope( mExpressionContextScope );
352  }
353 
354  // feature title
355  QString featureTitle = result.mFeature.attribute( layer->displayField() ).toString();
356  if ( featureTitle.isEmpty() )
357  featureTitle = QStringLiteral( "%1" ).arg( result.mFeature.id() );
358 
359  if ( customFeatureActions.isEmpty() && ( !featureActionMenu || featureActionMenu->actions().isEmpty() ) )
360  {
361  featureAction = new QAction( featureTitle, layerMenu );
362  // add the feature action (or menu) to the layer menu
363  featureAction->setData( QVariant::fromValue<ActionData>( ActionData( layer, result.mFeature.id() ) ) );
364  connect( featureAction, &QAction::hovered, this, &QgsIdentifyMenu::handleMenuHover );
365  layerMenu->addAction( featureAction );
366  }
367  else if ( results.count() == 1 )
368  {
369  // if we are here with only one results, this means there is a sub-feature level (for actions)
370  // => skip the feature level since there would be only a single entry
371  // => give the layer menu as pointer instead of a new feature menu
372  featureMenu = layerMenu;
373  }
374  else
375  {
376  featureMenu = new QMenu( featureTitle, layerMenu );
377 
378  // get the action from the menu
379  featureAction = featureMenu->menuAction();
380  // add the feature action (or menu) to the layer menu
381  featureAction->setData( QVariant::fromValue<ActionData>( ActionData( layer, result.mFeature.id() ) ) );
382  connect( featureAction, &QAction::hovered, this, &QgsIdentifyMenu::handleMenuHover );
383  layerMenu->addAction( featureAction );
384  }
385 
386  // if no feature menu, no need to go further
387  if ( !featureMenu )
388  continue;
389 
390  // add default identify action
391  QAction *identifyFeatureAction = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionIdentify.svg" ) ), mDefaultActionName, featureMenu );
392  connect( identifyFeatureAction, &QAction::hovered, this, &QgsIdentifyMenu::handleMenuHover );
393  identifyFeatureAction->setData( QVariant::fromValue<ActionData>( ActionData( layer, result.mFeature.id() ) ) );
394  featureMenu->addAction( identifyFeatureAction );
395  featureMenu->addSeparator();
396 
397  // custom action at feature level
398  Q_FOREACH ( QgsMapLayerAction *mapLayerAction, customFeatureActions )
399  {
400  QAction *action = new QAction( mapLayerAction->icon(), mapLayerAction->text(), featureMenu );
401  action->setData( QVariant::fromValue<ActionData>( ActionData( layer, result.mFeature.id(), mapLayerAction ) ) );
402  connect( action, &QAction::hovered, this, &QgsIdentifyMenu::handleMenuHover );
403  connect( action, &QAction::triggered, this, &QgsIdentifyMenu::triggerMapLayerAction );
404  featureMenu->addAction( action );
405  }
406  // use QgsActionMenu for feature actions
407  if ( featureActionMenu )
408  {
409  Q_FOREACH ( QAction *action, featureActionMenu->actions() )
410  {
411  connect( action, &QAction::hovered, this, &QgsIdentifyMenu::handleMenuHover );
412  featureMenu->addAction( action );
413  }
414  }
415  }
416 
417  // back to layer level
418 
419  // identify all action
420  if ( mAllowMultipleReturn && results.count() > 1 )
421  {
422  layerMenu->addSeparator();
423  QAction *allAction = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionIdentify.svg" ) ), tr( "%1 All (%2)" ).arg( mDefaultActionName ).arg( results.count() ), layerMenu );
424  allAction->setData( QVariant::fromValue<ActionData>( ActionData( layer ) ) );
425  connect( allAction, &QAction::hovered, this, &QgsIdentifyMenu::handleMenuHover );
426  layerMenu->addAction( allAction );
427  }
428 
429  // add custom/layer actions
430  Q_FOREACH ( QgsMapLayerAction *mapLayerAction, layerActions )
431  {
432  QString title = mapLayerAction->text();
433  if ( mapLayerAction->targets().testFlag( QgsMapLayerAction::MultipleFeatures ) )
434  title.append( QStringLiteral( " (%1)" ).arg( results.count() ) );
435  QAction *action = new QAction( mapLayerAction->icon(), title, layerMenu );
436  action->setData( QVariant::fromValue<ActionData>( ActionData( layer, mapLayerAction ) ) );
437  connect( action, &QAction::hovered, this, &QgsIdentifyMenu::handleMenuHover );
438  connect( action, &QAction::triggered, this, &QgsIdentifyMenu::triggerMapLayerAction );
439  layerMenu->addAction( action );
440  if ( separators.contains( mapLayerAction ) )
441  {
442  layerMenu->insertSeparator( action );
443  }
444  }
445 }
446 
447 void QgsIdentifyMenu::triggerMapLayerAction()
448 {
449  QAction *action = qobject_cast<QAction *>( sender() );
450  if ( !action )
451  return;
452  QVariant varData = action->data();
453  if ( !varData.isValid() || !varData.canConvert<ActionData>() )
454  return;
455 
456  ActionData actData = action->data().value<ActionData>();
457 
458  if ( actData.mIsValid && actData.mMapLayerAction )
459  {
460  // layer
461  if ( actData.mMapLayerAction->targets().testFlag( QgsMapLayerAction::Layer ) )
462  {
463  actData.mMapLayerAction->triggerForLayer( actData.mLayer );
464  }
465 
466  // multiples features
467  if ( actData.mMapLayerAction->targets().testFlag( QgsMapLayerAction::MultipleFeatures ) )
468  {
469  QList<QgsFeature> featureList;
470  Q_FOREACH ( const QgsMapToolIdentify::IdentifyResult &result, mLayerIdResults[actData.mLayer] )
471  {
472  featureList << result.mFeature;
473  }
474  actData.mMapLayerAction->triggerForFeatures( actData.mLayer, featureList );
475  }
476 
477  // single feature
478  if ( actData.mMapLayerAction->targets().testFlag( QgsMapLayerAction::SingleFeature ) )
479  {
480  Q_FOREACH ( const QgsMapToolIdentify::IdentifyResult &result, mLayerIdResults[actData.mLayer] )
481  {
482  if ( result.mFeature.id() == actData.mFeatureId )
483  {
484  actData.mMapLayerAction->triggerForFeature( actData.mLayer, new QgsFeature( result.mFeature ) );
485  return;
486  }
487  }
488  QgsDebugMsg( QStringLiteral( "Identify menu: could not retrieve feature for action %1" ).arg( action->text() ) );
489  }
490  }
491 }
492 
493 
494 QList<QgsMapToolIdentify::IdentifyResult> QgsIdentifyMenu::results( QAction *action, bool &externalAction )
495 {
496  QList<QgsMapToolIdentify::IdentifyResult> idResults = QList<QgsMapToolIdentify::IdentifyResult>();
497 
498  externalAction = false;
499 
500  ActionData actData;
501  bool hasData = false;
502 
503  if ( !action )
504  return idResults;
505 
506  QVariant varData = action->data();
507  if ( !varData.isValid() )
508  {
509  QgsDebugMsg( QStringLiteral( "Identify menu: could not retrieve results from menu entry (invalid data)" ) );
510  return idResults;
511  }
512 
513  if ( varData.canConvert<ActionData>() )
514  {
515  actData = action->data().value<ActionData>();
516  if ( actData.mIsValid )
517  {
518  externalAction = actData.mIsExternalAction;
519  hasData = true;
520  }
521  }
522 
523  if ( !hasData && varData.canConvert<QgsActionMenu::ActionData>() )
524  {
525  QgsActionMenu::ActionData dataSrc = action->data().value<QgsActionMenu::ActionData>();
526  if ( dataSrc.actionType != QgsActionMenu::Invalid )
527  {
528  externalAction = true;
529  actData = ActionData( dataSrc.mapLayer, dataSrc.featureId );
530  hasData = true;
531  }
532  }
533 
534  if ( !hasData )
535  {
536  QgsDebugMsg( QStringLiteral( "Identify menu: could not retrieve results from menu entry (no data found)" ) );
537  return idResults;
538  }
539 
540  // return all results
541  if ( actData.mAllResults )
542  {
543  // this means "All" action was triggered
544  QMapIterator< QgsMapLayer *, QList<QgsMapToolIdentify::IdentifyResult> > it( mLayerIdResults );
545  while ( it.hasNext() )
546  {
547  it.next();
548  idResults << it.value();
549  }
550  return idResults;
551  }
552 
553  if ( !mLayerIdResults.contains( actData.mLayer ) )
554  {
555  QgsDebugMsg( QStringLiteral( "Identify menu: could not retrieve results from menu entry (layer not found)" ) );
556  return idResults;
557  }
558 
559  if ( actData.mLevel == LayerLevel )
560  {
561  return mLayerIdResults[actData.mLayer];
562  }
563 
564  if ( actData.mLevel == FeatureLevel )
565  {
566  Q_FOREACH ( const QgsMapToolIdentify::IdentifyResult &res, mLayerIdResults[actData.mLayer] )
567  {
568  if ( res.mFeature.id() == actData.mFeatureId )
569  {
570  idResults << res;
571  return idResults;
572  }
573  }
574  }
575 
576  QgsDebugMsg( QStringLiteral( "Identify menu: could not retrieve results from menu entry (don't know what happened')" ) );
577  return idResults;
578 }
579 
580 void QgsIdentifyMenu::handleMenuHover()
581 {
582  if ( !mCanvas )
583  return;
584 
585  deleteRubberBands();
586 
587  QAction *senderAction = qobject_cast<QAction *>( sender() );
588  if ( !senderAction )
589  return;
590 
591  bool externalAction;
592  QList<QgsMapToolIdentify::IdentifyResult> idResults = results( senderAction, externalAction );
593 
594  Q_FOREACH ( const QgsMapToolIdentify::IdentifyResult &result, idResults )
595  {
596  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( result.mLayer );
597  if ( !vl )
598  continue;
599 
600  QgsHighlight *hl = new QgsHighlight( mCanvas, result.mFeature.geometry(), vl );
601  QgsSettings settings;
602  QColor color = QColor( settings.value( QStringLiteral( "Map/highlight/color" ), Qgis::DEFAULT_HIGHLIGHT_COLOR.name() ).toString() );
603  int alpha = settings.value( QStringLiteral( "Map/highlight/colorAlpha" ), Qgis::DEFAULT_HIGHLIGHT_COLOR.alpha() ).toInt();
604  double buffer = settings.value( QStringLiteral( "Map/highlight/buffer" ), Qgis::DEFAULT_HIGHLIGHT_BUFFER_MM ).toDouble();
605  double minWidth = settings.value( QStringLiteral( "Map/highlight/minWidth" ), Qgis::DEFAULT_HIGHLIGHT_MIN_WIDTH_MM ).toDouble();
606  hl->setColor( color ); // sets also fill with default alpha
607  color.setAlpha( alpha );
608  hl->setFillColor( color ); // sets fill with alpha
609  hl->setBuffer( buffer );
610  hl->setMinWidth( minWidth );
611  mRubberBands.append( hl );
612  connect( vl, &QObject::destroyed, this, &QgsIdentifyMenu::layerDestroyed );
613  }
614 }
615 
616 void QgsIdentifyMenu::deleteRubberBands()
617 {
618  QList<QgsHighlight *>::const_iterator it = mRubberBands.constBegin();
619  for ( ; it != mRubberBands.constEnd(); ++it )
620  delete *it;
621  mRubberBands.clear();
622 }
623 
624 void QgsIdentifyMenu::layerDestroyed()
625 {
626  QList<QgsHighlight *>::iterator it = mRubberBands.begin();
627  while ( it != mRubberBands.end() )
628  {
629  if ( ( *it )->layer() == sender() )
630  {
631  delete *it;
632  it = mRubberBands.erase( it );
633  }
634  else
635  {
636  ++it;
637  }
638  }
639 }
640 
642 {
643  mCustomActionRegistry.clear();
644 
645 }
646 
648 {
649  mExpressionContextScope = scope;
650 }
651 
653 {
654  return mExpressionContextScope;
655 }
QgsFeatureId id
Definition: qgsfeature.h:64
QgsIdentifyMenu::MenuLevel mLevel
Base class for all map layer types.
Definition: qgsmaplayer.h:63
QgsMapLayer::LayerType type() const
Returns the type of the layer.
QgsExpressionContextScope expressionContextScope() const
Returns an expression context scope used to resolve underlying actions.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:58
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
void setFillColor(const QColor &fillColor)
Fill color for the highlight.
static const QColor DEFAULT_HIGHLIGHT_COLOR
Default highlight color.
Definition: qgis.h:122
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
QString displayField() const
This is a shorthand for accessing the displayExpression if it is a simple field.
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:74
void setMode(QgsAttributeEditorContext::Mode mode)
Change the mode of the actions.
void setBuffer(double buffer)
Set line / stroke buffer in millimeters.
Definition: qgshighlight.h:142
QList< QgsMapLayerAction * > mapLayerActions(QgsMapLayer *layer, QgsMapLayerAction::Targets targets=QgsMapLayerAction::AllActions)
Returns the map layer actions which can run on the specified layer.
QList< QgsMapToolIdentify::IdentifyResult > exec(const QList< QgsMapToolIdentify::IdentifyResult > &idResults, QPoint pos)
exec
QgsMapLayerAction * mMapLayerAction
This class is a menu that is populated automatically with the actions defined for a given layer...
Definition: qgsactionmenu.h:38
QgsIdentifyMenu(QgsMapCanvas *canvas)
QgsIdentifyMenu is a menu to be used to choose within a list of QgsMapTool::IdentifyReults.
A class for highlight features on the map.
Definition: qgshighlight.h:56
Single scope for storing variables and functions for use within a QgsExpressionContext.
const Targets & targets() const
Returns availibity of action.
void setMaxFeatureDisplay(int maxFeatureDisplay)
Defines the maximum number of features displayed in the menu for vector layers (default is 10)...
void triggerForFeatures(QgsMapLayer *layer, const QList< QgsFeature > &featureList)
Triggers the action with the specified layer and list of feature.
void closeEvent(QCloseEvent *e) override
void setExpressionContextScope(const QgsExpressionContextScope &scope)
Sets an expression context scope used to resolve underlying actions.
~QgsIdentifyMenu() override
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:262
void setColor(const QColor &color)
Set line/stroke to color, polygon fill to color with alpha = 63.
static const double DEFAULT_HIGHLIGHT_MIN_WIDTH_MM
Default highlight line/stroke minimum width in mm.
Definition: qgis.h:132
QString name
Definition: qgsmaplayer.h:67
QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
QgsGeometry geometry
Definition: qgsfeature.h:67
QgsActionMenu::ActionType actionType
Definition: qgsactionmenu.h:60
void setExpressionContextScope(const QgsExpressionContextScope &scope)
Sets an expression context scope used to resolve underlying actions.
static const double DEFAULT_HIGHLIGHT_BUFFER_MM
Default highlight buffer in mm.
Definition: qgis.h:127
void removeCustomActions()
remove all custom actions from the menu to be built
Represents a vector layer which manages a vector based data sets.
void setMaxLayerDisplay(int maxLayerDisplay)
Defines the maximum number of layers displayed in the menu (default is 10).
static QgsMapLayerActionRegistry * mapLayerActionRegistry()
Returns the global map layer action registry, used for registering map layer actions.
Definition: qgsgui.cpp:78
void triggerForLayer(QgsMapLayer *layer)
Triggers the action with the specified layer.
void triggerForFeature(QgsMapLayer *layer, const QgsFeature *feature)
Triggers the action with the specified layer and feature.
An action which can run on map layers.
void setMinWidth(double width)
Set minimum line / stroke width in millimeters.
Definition: qgshighlight.h:149