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