Skip to content

Commit 3d494ac

Browse files
committed
Fix feature's value action not working (fix #14536)
Replace broken/missing $currfield with new @current_field expression variable. Update other default actions to use expression variables instead of deprecated special columns.
1 parent 0a8df07 commit 3d494ac

File tree

5 files changed

+74
-15
lines changed

5 files changed

+74
-15
lines changed

python/core/qgsattributeaction.sip

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,30 @@ class QgsAttributeAction
6262
const QgsFeature &feat,
6363
int defaultValueIndex = 0 ) /PyName=doActionFeature/;
6464

65+
/** Does the action using the expression engine to replace any embedded expressions
66+
* in the action definition.
67+
* @param index action index
68+
* @param feature feature to run action for
69+
* @param context expression context to evalute expressions under
70+
* @param substitutionMap deprecated - kept for compatibilty with projects, will be removed for 3.0
71+
*/
72+
// TODO QGIS 3.0 remove substition map - force use of expression variables
73+
void doAction( int index,
74+
const QgsFeature& feature,
75+
const QgsExpressionContext& context,
76+
const QMap<QString, QVariant> *substitutionMap = nullptr );
77+
78+
6579
/** Does the action using the expression builder to expand it
6680
* and getting values from the passed feature attribute map.
6781
* substitutionMap is used to pass custom substitutions, to replace
6882
* each key in the map with the associated value
6983
* @note available in python bindings as doActionFeatureWithSubstitution
84+
* @deprecated use QgsExpressionContext variant instead
7085
*/
7186
void doAction( int index,
7287
const QgsFeature &feat,
73-
const QMap<QString, QVariant> *substitutionMap ) /PyName=doActionFeatureWithSubstitution/;
88+
const QMap<QString, QVariant> *substitutionMap ) /Deprecated,PyName=doActionFeatureWithSubstitution/;
7489

7590
//! Removes all actions
7691
void clearActions();

src/app/qgsattributeactiondialog.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,8 +298,8 @@ void QgsAttributeActionDialog::addDefaultActions()
298298
insertRow( pos++, QgsAction::Generic, tr( "Echo attribute's value" ), "echo \"[% \"MY_FIELD\" %]\"", "", true );
299299
insertRow( pos++, QgsAction::Generic, tr( "Run an application" ), "ogr2ogr -f \"ESRI Shapefile\" \"[% \"OUTPUT_PATH\" %]\" \"[% \"INPUT_FILE\" %]\"", "", true );
300300
insertRow( pos++, QgsAction::GenericPython, tr( "Get feature id" ), "QtGui.QMessageBox.information(None, \"Feature id\", \"feature id is [% $id %]\")", "", false );
301-
insertRow( pos++, QgsAction::GenericPython, tr( "Selected field's value (Identify features tool)" ), "QtGui.QMessageBox.information(None, \"Current field's value\", \"[% $currentfield %]\")", "", false );
302-
insertRow( pos++, QgsAction::GenericPython, tr( "Clicked coordinates (Run feature actions tool)" ), "QtGui.QMessageBox.information(None, \"Clicked coords\", \"layer: [% $layerid %]\\ncoords: ([% $clickx %],[% $clicky %])\")", "", false );
301+
insertRow( pos++, QgsAction::GenericPython, tr( "Selected field's value (Identify features tool)" ), "QtGui.QMessageBox.information(None, \"Current field's value\", \"[% @current_field %]\")", "", false );
302+
insertRow( pos++, QgsAction::GenericPython, tr( "Clicked coordinates (Run feature actions tool)" ), "QtGui.QMessageBox.information(None, \"Clicked coords\", \"layer: [% @layer_id %]\\ncoords: ([% @click_x %],[% @click_y %])\")", "", false );
303303
insertRow( pos++, QgsAction::OpenUrl, tr( "Open file" ), "[% \"PATH\" %]", "", false );
304304
insertRow( pos++, QgsAction::OpenUrl, tr( "Search on web based on attribute's value" ), "http://www.google.com/search?q=[% \"ATTRIBUTE\" %]", "", false );
305305
}

src/app/qgsmaptoolfeatureaction.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,14 +136,25 @@ bool QgsMapToolFeatureAction::doAction( QgsVectorLayer *layer, int x, int y )
136136
if ( layer->actions()->defaultAction() >= 0 )
137137
{
138138
// define custom substitutions: layer id and clicked coords
139+
140+
// TODO QGIS 3.0 - remove these deprecated global expression variables!
139141
QMap<QString, QVariant> substitutionMap;
140142
substitutionMap.insert( "$layerid", layer->id() );
141143
point = toLayerCoordinates( layer, point );
142144
substitutionMap.insert( "$clickx", point.x() );
143145
substitutionMap.insert( "$clicky", point.y() );
144146

147+
QgsExpressionContext context;
148+
context << QgsExpressionContextUtils::globalScope()
149+
<< QgsExpressionContextUtils::projectScope()
150+
<< QgsExpressionContextUtils::mapSettingsScope( mCanvas->mapSettings() );
151+
QgsExpressionContextScope* actionScope = new QgsExpressionContextScope();
152+
actionScope->setVariable( "click_x", point.x() );
153+
actionScope->setVariable( "click_y", point.y() );
154+
context << actionScope;
155+
145156
int actionIdx = layer->actions()->defaultAction();
146-
layer->actions()->doAction( actionIdx, feat, &substitutionMap );
157+
layer->actions()->doAction( actionIdx, feat, context, &substitutionMap );
147158
}
148159
else
149160
{

src/core/qgsactionmanager.cpp

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,34 @@ void QgsActionManager::removeAction( int index )
6565

6666
void QgsActionManager::doAction( int index, const QgsFeature& feat, int defaultValueIndex )
6767
{
68-
QMap<QString, QVariant> substitutionMap;
69-
if ( defaultValueIndex >= 0 )
70-
{
71-
QVariant defaultValue = feat.attribute( defaultValueIndex );
72-
if ( defaultValue.isValid() )
73-
substitutionMap.insert( "$currfield", defaultValue );
74-
}
68+
QgsExpressionContext context = createExpressionContext();
69+
QgsExpressionContextScope* actionScope = new QgsExpressionContextScope();
70+
actionScope->setVariable( "current_field", feat.attribute( defaultValueIndex ) );
71+
context << actionScope;
72+
doAction( index, feat, context );
73+
}
74+
75+
void QgsActionManager::doAction( int index, const QgsFeature& feat, const QgsExpressionContext& context, const QMap<QString, QVariant> *substitutionMap )
76+
{
77+
if ( index < 0 || index >= size() )
78+
return;
79+
80+
const QgsAction &action = at( index );
81+
if ( !action.runable() )
82+
return;
83+
84+
QgsExpressionContext actionContext( context );
85+
86+
if ( mLayer )
87+
actionContext << QgsExpressionContextUtils::layerScope( mLayer );
88+
actionContext.setFeature( feat );
7589

76-
doAction( index, feat, &substitutionMap );
90+
QString expandedAction = QgsExpression::replaceExpressionText( action.action(), &actionContext, substitutionMap );
91+
if ( expandedAction.isEmpty() )
92+
return;
93+
94+
QgsAction newAction( action.type(), action.name(), expandedAction, action.capture() );
95+
runAction( newAction );
7796
}
7897

7998
void QgsActionManager::doAction( int index, const QgsFeature &feat, const QMap<QString, QVariant> *substitutionMap )

src/core/qgsactionmanager.h

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,15 +85,29 @@ class CORE_EXPORT QgsActionManager
8585
const QgsFeature &feat,
8686
int defaultValueIndex = 0 );
8787

88+
/** Does the action using the expression engine to replace any embedded expressions
89+
* in the action definition.
90+
* @param index action index
91+
* @param feature feature to run action for
92+
* @param context expression context to evalute expressions under
93+
* @param substitutionMap deprecated - kept for compatibilty with projects, will be removed for 3.0
94+
*/
95+
// TODO QGIS 3.0 remove substition map - force use of expression variables
96+
void doAction( int index,
97+
const QgsFeature& feature,
98+
const QgsExpressionContext& context,
99+
const QMap<QString, QVariant> *substitutionMap = nullptr );
100+
88101
/** Does the action using the expression builder to expand it
89102
* and getting values from the passed feature attribute map.
90103
* substitutionMap is used to pass custom substitutions, to replace
91104
* each key in the map with the associated value
92105
* @note available in python bindings as doActionFeatureWithSubstitution
106+
* @deprecated use QgsExpressionContext variant instead
93107
*/
94-
void doAction( int index,
95-
const QgsFeature &feat,
96-
const QMap<QString, QVariant> *substitutionMap );
108+
Q_DECL_DEPRECATED void doAction( int index,
109+
const QgsFeature &feat,
110+
const QMap<QString, QVariant> *substitutionMap );
97111

98112
//! Removes all actions
99113
void clearActions();

0 commit comments

Comments
 (0)