Skip to content

Commit e797f7e

Browse files
authored
Merge pull request #8229 from signedav/duplication-context-fix
Select feature menu on action with multiple features
2 parents bbdbfa1 + fa625ff commit e797f7e

File tree

2 files changed

+55
-22
lines changed

2 files changed

+55
-22
lines changed

src/app/qgsmaptoolfeatureaction.cpp

+53-22
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
#include "qgsmaptoolfeatureaction.h"
1717

18-
#include "qgsfeature.h"
1918
#include "qgsfeatureiterator.h"
2019
#include "qgsfields.h"
2120
#include "qgsgeometry.h"
@@ -96,6 +95,7 @@ bool QgsMapToolFeatureAction::doAction( QgsVectorLayer *layer, int x, int y )
9695
return false;
9796

9897
QgsPointXY point = mCanvas->getCoordinateTransform()->toMapCoordinates( x, y );
98+
QPoint position = mCanvas->mapToGlobal( QPoint( x + 5, y + 5 ) );
9999

100100
QgsRectangle r;
101101

@@ -121,36 +121,67 @@ bool QgsMapToolFeatureAction::doAction( QgsVectorLayer *layer, int x, int y )
121121
QgsDebugMsg( QStringLiteral( "Caught CRS exception %1" ).arg( cse.what() ) );
122122
}
123123

124-
QgsAction defaultAction = layer->actions()->defaultAction( QStringLiteral( "Canvas" ) );
125-
124+
QgsFeature f;
125+
QgsFeatureList features;
126126
QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest().setFilterRect( r ).setFlags( QgsFeatureRequest::ExactIntersect ) );
127-
QgsFeature feat;
128-
while ( fit.nextFeature( feat ) )
127+
while ( fit.nextFeature( f ) )
128+
{
129+
features.append( f );
130+
}
131+
132+
if ( !features.isEmpty() )
129133
{
130-
if ( defaultAction.isValid() )
134+
if ( features.count() == 1 )
131135
{
132-
// define custom substitutions: layer id and clicked coords
133-
QgsExpressionContext context;
134-
context << QgsExpressionContextUtils::globalScope()
135-
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() )
136-
<< QgsExpressionContextUtils::mapSettingsScope( mCanvas->mapSettings() );
137-
QgsExpressionContextScope *actionScope = new QgsExpressionContextScope();
138-
actionScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "click_x" ), point.x(), true ) );
139-
actionScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "click_y" ), point.y(), true ) );
140-
actionScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "action_scope" ), QStringLiteral( "Canvas" ), true ) );
141-
context << actionScope;
142-
143-
defaultAction.run( layer, feat, context );
136+
doActionForFeature( layer, features.first(), point );
144137
}
145138
else
146139
{
147-
QgsMapLayerAction *mapLayerAction = QgsGui::mapLayerActionRegistry()->defaultActionForLayer( layer );
148-
if ( mapLayerAction )
140+
QMenu *featureMenu = new QMenu();
141+
for ( const QgsFeature &feature : qgis::as_const( features ) )
149142
{
150-
mapLayerAction->triggerForFeature( layer, &feat );
143+
QAction *featureAction = featureMenu->addAction( FID_TO_STRING( feature.id() ) );
144+
connect( featureAction, &QAction::triggered, this, [ = ] { doActionForFeature( layer, feature, point );} );
151145
}
146+
QAction *allFeatureAction = featureMenu->addAction( tr( "All Features" ) );
147+
connect( allFeatureAction, &QAction::triggered, this, [ = ]
148+
{
149+
for ( const QgsFeature &feature : qgis::as_const( features ) )
150+
{
151+
doActionForFeature( layer, feature, point );
152+
}
153+
} );
154+
featureMenu->exec( position );
152155
}
156+
return true;
153157
}
158+
return false;
159+
}
154160

155-
return true;
161+
void QgsMapToolFeatureAction::doActionForFeature( QgsVectorLayer *layer, const QgsFeature &feature, const QgsPointXY &point )
162+
{
163+
QgsAction defaultAction = layer->actions()->defaultAction( QStringLiteral( "Canvas" ) );
164+
if ( defaultAction.isValid() )
165+
{
166+
// define custom substitutions: layer id and clicked coords
167+
QgsExpressionContext context;
168+
context << QgsExpressionContextUtils::globalScope()
169+
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() )
170+
<< QgsExpressionContextUtils::mapSettingsScope( mCanvas->mapSettings() );
171+
QgsExpressionContextScope *actionScope = new QgsExpressionContextScope();
172+
actionScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "click_x" ), point.x(), true ) );
173+
actionScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "click_y" ), point.y(), true ) );
174+
actionScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "action_scope" ), QStringLiteral( "Canvas" ), true ) );
175+
context << actionScope;
176+
177+
defaultAction.run( layer, feature, context );
178+
}
179+
else
180+
{
181+
QgsMapLayerAction *mapLayerAction = QgsGui::mapLayerActionRegistry()->defaultActionForLayer( layer );
182+
if ( mapLayerAction )
183+
{
184+
mapLayerAction->triggerForFeature( layer, &feature );
185+
}
186+
}
156187
}

src/app/qgsmaptoolfeatureaction.h

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "qgis_app.h"
2525

2626
class QgsVectorLayer;
27+
class QgsFeature;
2728

2829
/**
2930
\brief Map tool for running feature actions on the current layer
@@ -52,6 +53,7 @@ class APP_EXPORT QgsMapToolFeatureAction : public QgsMapTool
5253

5354
private:
5455
bool doAction( QgsVectorLayer *layer, int x, int y );
56+
void doActionForFeature( QgsVectorLayer *layer, const QgsFeature &feature, const QgsPointXY &point );
5557
};
5658

5759
#endif

0 commit comments

Comments
 (0)