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