16 #include <QMouseEvent> 32 , mAllowMultipleReturn( true )
33 , mExecWithSingleResult( false )
34 , mShowFeatureActions( false )
35 , mResultsIfExternalAction( false )
36 , mMaxLayerDisplay( 10 )
37 , mMaxFeatureDisplay( 10 )
38 , mDefaultActionName( tr(
"Identify" ) )
50 if ( maxLayerDisplay < 0 )
52 QgsDebugMsg(
"invalid value for number of layers displayed." );
60 if ( maxFeatureDisplay < 0 )
62 QgsDebugMsg(
"invalid value for number of layers displayed." );
68 QList<QgsMapToolIdentify::IdentifyResult>
QgsIdentifyMenu::exec(
const QList<QgsMapToolIdentify::IdentifyResult> &idResults, QPoint pos )
71 mLayerIdResults.clear();
73 QList<QgsMapToolIdentify::IdentifyResult> returnResults = QList<QgsMapToolIdentify::IdentifyResult>();
75 if ( idResults.isEmpty() )
79 if ( idResults.count() == 1 && !mExecWithSingleResult )
81 returnResults << idResults[0];
89 if ( mLayerIdResults.contains( layer ) )
91 mLayerIdResults[layer].append( result );
95 mLayerIdResults.insert( layer, QList<QgsMapToolIdentify::IdentifyResult>() << result );
100 bool singleLayer = mLayerIdResults.count() == 1;
102 QMapIterator< QgsMapLayer *, QList<QgsMapToolIdentify::IdentifyResult> > it( mLayerIdResults );
103 while ( it.hasNext() )
105 if ( mMaxLayerDisplay != 0 && count > mMaxLayerDisplay )
112 addRasterLayer( layer );
119 addVectorLayer( vl, it.value(), singleLayer );
124 if ( !singleLayer && mAllowMultipleReturn && idResults.count() > 1 )
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 );
134 QAction *selectedAction = QMenu::exec( pos );
136 returnResults = results( selectedAction, externalAction );
141 qDeleteAll( findChildren<QgsActionMenu *>() );
143 if ( externalAction && !mResultsIfExternalAction )
145 return QList<QgsMapToolIdentify::IdentifyResult>();
149 return returnResults;
156 QMenu::closeEvent( e );
159 void QgsIdentifyMenu::addRasterLayer(
QgsMapLayer *layer )
161 QAction *layerAction =
nullptr;
162 QMenu *layerMenu =
nullptr;
164 QList<QgsMapLayerAction *> separators = QList<QgsMapLayerAction *>();
166 int nCustomActions = layerActions.count();
167 if ( nCustomActions )
169 separators.append( layerActions[0] );
171 if ( mShowFeatureActions )
174 if ( layerActions.count() > nCustomActions )
176 separators.append( layerActions[nCustomActions] );
181 if ( layerActions.isEmpty() )
183 layerAction =
new QAction( layer->
name(), this );
187 layerMenu =
new QMenu( layer->
name(), this );
188 layerAction = layerMenu->menuAction();
193 layerAction->setData( QVariant::fromValue<ActionData>(
ActionData( layer ) ) );
194 connect( layerAction, &QAction::hovered,
this, &QgsIdentifyMenu::handleMenuHover );
195 addAction( layerAction );
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 );
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 ) )
217 layerMenu->insertSeparator( action );
222 void QgsIdentifyMenu::addVectorLayer(
QgsVectorLayer *layer,
const QList<QgsMapToolIdentify::IdentifyResult> &results,
bool singleLayer )
224 QAction *layerAction =
nullptr;
225 QMenu *layerMenu =
nullptr;
231 QList<QgsMapLayerAction *> separators = QList<QgsMapLayerAction *>();
232 QList<QgsMapLayerAction *> layerActions = mCustomActionRegistry.mapLayerActions( layer, targets );
233 int nCustomActions = layerActions.count();
234 if ( nCustomActions )
236 separators << layerActions[0];
238 if ( mShowFeatureActions )
242 if ( layerActions.count() > nCustomActions )
244 separators << layerActions[nCustomActions];
253 bool createMenu = results.count() > 1 || !layerActions.isEmpty();
260 if ( !createMenu && mShowFeatureActions )
264 createMenu = !featureActionMenu->actions().isEmpty();
265 delete featureActionMenu;
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 );
288 if ( results.count() > 1 )
290 layerMenu =
new QMenu( layer->
name(), this );
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 );
300 layerAction = layerMenu->menuAction();
324 layerAction->setData( QVariant::fromValue<ActionData>(
ActionData( layer ) ) );
325 connect( layerAction, &QAction::hovered,
this, &QgsIdentifyMenu::handleMenuHover );
326 addAction( layerAction );
337 if ( mMaxFeatureDisplay != 0 && count > mMaxFeatureDisplay )
341 QAction *featureAction =
nullptr;
342 QMenu *featureMenu =
nullptr;
346 if ( mShowFeatureActions )
348 featureActionMenu =
new QgsActionMenu( layer, result.
mFeature, QStringLiteral(
"Feature" ), layerMenu );
355 if ( featureTitle.isEmpty() )
356 featureTitle = QStringLiteral(
"%1" ).arg( result.
mFeature.
id() );
358 if ( customFeatureActions.isEmpty() && ( !featureActionMenu || featureActionMenu->actions().isEmpty() ) )
360 featureAction =
new QAction( featureTitle, layerMenu );
362 featureAction->setData( QVariant::fromValue<ActionData>(
ActionData( layer, result.
mFeature.
id() ) ) );
363 connect( featureAction, &QAction::hovered,
this, &QgsIdentifyMenu::handleMenuHover );
364 layerMenu->addAction( featureAction );
366 else if ( results.count() == 1 )
371 featureMenu = layerMenu;
375 featureMenu =
new QMenu( featureTitle, layerMenu );
378 featureAction = featureMenu->menuAction();
380 featureAction->setData( QVariant::fromValue<ActionData>(
ActionData( layer, result.
mFeature.
id() ) ) );
381 connect( featureAction, &QAction::hovered,
this, &QgsIdentifyMenu::handleMenuHover );
382 layerMenu->addAction( featureAction );
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();
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 );
406 if ( featureActionMenu )
408 Q_FOREACH ( QAction *action, featureActionMenu->actions() )
410 connect( action, &QAction::hovered,
this, &QgsIdentifyMenu::handleMenuHover );
411 featureMenu->addAction( action );
419 if ( mAllowMultipleReturn && results.count() > 1 )
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 );
431 QString title = mapLayerAction->text();
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 ) )
441 layerMenu->insertSeparator( action );
446 void QgsIdentifyMenu::triggerMapLayerAction()
448 QAction *action = qobject_cast<QAction *>( sender() );
451 QVariant varData = action->data();
452 if ( !varData.isValid() || !varData.canConvert<
ActionData>() )
468 QList<QgsFeature> featureList;
487 QgsDebugMsg( QString(
"Identify menu: could not retrieve feature for action %1" ).arg( action->text() ) );
493 QList<QgsMapToolIdentify::IdentifyResult> QgsIdentifyMenu::results( QAction *action,
bool &externalAction )
495 QList<QgsMapToolIdentify::IdentifyResult> idResults = QList<QgsMapToolIdentify::IdentifyResult>();
497 externalAction =
false;
500 bool hasData =
false;
505 QVariant varData = action->data();
506 if ( !varData.isValid() )
508 QgsDebugMsg(
"Identify menu: could not retrieve results from menu entry (invalid data)" );
527 externalAction =
true;
535 QgsDebugMsg(
"Identify menu: could not retrieve results from menu entry (no data found)" );
543 QMapIterator< QgsMapLayer *, QList<QgsMapToolIdentify::IdentifyResult> > it( mLayerIdResults );
544 while ( it.hasNext() )
547 idResults << it.value();
552 if ( !mLayerIdResults.contains( actData.
mLayer ) )
554 QgsDebugMsg(
"Identify menu: could not retrieve results from menu entry (layer not found)" );
560 return mLayerIdResults[actData.
mLayer];
575 QgsDebugMsg(
"Identify menu: could not retrieve results from menu entry (don't know what happened')" );
579 void QgsIdentifyMenu::handleMenuHover()
586 QAction *senderAction = qobject_cast<QAction *>( sender() );
591 QList<QgsMapToolIdentify::IdentifyResult> idResults = results( senderAction, externalAction );
606 color.setAlpha( alpha );
610 mRubberBands.append( hl );
611 connect( vl, &QObject::destroyed,
this, &QgsIdentifyMenu::layerDestroyed );
615 void QgsIdentifyMenu::deleteRubberBands()
617 QList<QgsHighlight *>::const_iterator it = mRubberBands.constBegin();
618 for ( ; it != mRubberBands.constEnd(); ++it )
620 mRubberBands.clear();
623 void QgsIdentifyMenu::layerDestroyed()
625 QList<QgsHighlight *>::iterator it = mRubberBands.begin();
626 while ( it != mRubberBands.end() )
628 if ( ( *it )->layer() == sender() )
631 it = mRubberBands.erase( it );
642 mCustomActionRegistry.clear();
648 mExpressionContextScope = scope;
653 return mExpressionContextScope;
Base class for all map layer types.
This class is a composition of two QSettings instances:
void setFillColor(const QColor &fillColor)
Fill color for the highlight.
static const QColor DEFAULT_HIGHLIGHT_COLOR
Default highlight color.
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...
QgsMapLayer::LayerType type() const
Returns the type of the layer.
Map canvas is a class for displaying all GIS data types on a canvas.
void setBuffer(double buffer)
Set line / stroke buffer in millimeters.
A class for highlight features on the map.
Single scope for storing variables and functions for use within a QgsExpressionContext.
QgsGeometry geometry() const
Returns the geometry associated with this feature.
const Targets & targets() const
Return availibity of action.
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 setColor(const QColor &color)
Set line/stroke to color, polygon fill to color with alpha = 63.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), const Section section=NoSection) const
Returns the value for setting key.
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.
static const double DEFAULT_HIGHLIGHT_BUFFER_MM
Default highlight buffer in mm.
Represents a vector layer which manages a vector based data sets.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
static QgsMapLayerActionRegistry * mapLayerActionRegistry()
Returns the global map layer action registry, used for registering map layer actions.
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.