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