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