Skip to content

Commit

Permalink
Fix feature's value action not working (fix #14536)
Browse files Browse the repository at this point in the history
Replace broken/missing $currfield with new @current_field
expression variable. Update other default actions to use
expression variables instead of deprecated special columns.
  • Loading branch information
nyalldawson committed May 28, 2016
1 parent 0a8df07 commit 3d494ac
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 15 deletions.
17 changes: 16 additions & 1 deletion python/core/qgsattributeaction.sip
Expand Up @@ -62,15 +62,30 @@ class QgsAttributeAction
const QgsFeature &feat,
int defaultValueIndex = 0 ) /PyName=doActionFeature/;

/** Does the action using the expression engine to replace any embedded expressions
* in the action definition.
* @param index action index
* @param feature feature to run action for
* @param context expression context to evalute expressions under
* @param substitutionMap deprecated - kept for compatibilty with projects, will be removed for 3.0
*/
// TODO QGIS 3.0 remove substition map - force use of expression variables
void doAction( int index,
const QgsFeature& feature,
const QgsExpressionContext& context,
const QMap<QString, QVariant> *substitutionMap = nullptr );


/** Does the action using the expression builder to expand it
* and getting values from the passed feature attribute map.
* substitutionMap is used to pass custom substitutions, to replace
* each key in the map with the associated value
* @note available in python bindings as doActionFeatureWithSubstitution
* @deprecated use QgsExpressionContext variant instead
*/
void doAction( int index,
const QgsFeature &feat,
const QMap<QString, QVariant> *substitutionMap ) /PyName=doActionFeatureWithSubstitution/;
const QMap<QString, QVariant> *substitutionMap ) /Deprecated,PyName=doActionFeatureWithSubstitution/;

//! Removes all actions
void clearActions();
Expand Down
4 changes: 2 additions & 2 deletions src/app/qgsattributeactiondialog.cpp
Expand Up @@ -298,8 +298,8 @@ void QgsAttributeActionDialog::addDefaultActions()
insertRow( pos++, QgsAction::Generic, tr( "Echo attribute's value" ), "echo \"[% \"MY_FIELD\" %]\"", "", true );
insertRow( pos++, QgsAction::Generic, tr( "Run an application" ), "ogr2ogr -f \"ESRI Shapefile\" \"[% \"OUTPUT_PATH\" %]\" \"[% \"INPUT_FILE\" %]\"", "", true );
insertRow( pos++, QgsAction::GenericPython, tr( "Get feature id" ), "QtGui.QMessageBox.information(None, \"Feature id\", \"feature id is [% $id %]\")", "", false );
insertRow( pos++, QgsAction::GenericPython, tr( "Selected field's value (Identify features tool)" ), "QtGui.QMessageBox.information(None, \"Current field's value\", \"[% $currentfield %]\")", "", false );
insertRow( pos++, QgsAction::GenericPython, tr( "Clicked coordinates (Run feature actions tool)" ), "QtGui.QMessageBox.information(None, \"Clicked coords\", \"layer: [% $layerid %]\\ncoords: ([% $clickx %],[% $clicky %])\")", "", false );
insertRow( pos++, QgsAction::GenericPython, tr( "Selected field's value (Identify features tool)" ), "QtGui.QMessageBox.information(None, \"Current field's value\", \"[% @current_field %]\")", "", false );
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 );
insertRow( pos++, QgsAction::OpenUrl, tr( "Open file" ), "[% \"PATH\" %]", "", false );
insertRow( pos++, QgsAction::OpenUrl, tr( "Search on web based on attribute's value" ), "http://www.google.com/search?q=[% \"ATTRIBUTE\" %]", "", false );
}
Expand Down
13 changes: 12 additions & 1 deletion src/app/qgsmaptoolfeatureaction.cpp
Expand Up @@ -136,14 +136,25 @@ bool QgsMapToolFeatureAction::doAction( QgsVectorLayer *layer, int x, int y )
if ( layer->actions()->defaultAction() >= 0 )
{
// define custom substitutions: layer id and clicked coords

// TODO QGIS 3.0 - remove these deprecated global expression variables!
QMap<QString, QVariant> substitutionMap;
substitutionMap.insert( "$layerid", layer->id() );
point = toLayerCoordinates( layer, point );
substitutionMap.insert( "$clickx", point.x() );
substitutionMap.insert( "$clicky", point.y() );

QgsExpressionContext context;
context << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope()
<< QgsExpressionContextUtils::mapSettingsScope( mCanvas->mapSettings() );
QgsExpressionContextScope* actionScope = new QgsExpressionContextScope();
actionScope->setVariable( "click_x", point.x() );
actionScope->setVariable( "click_y", point.y() );
context << actionScope;

int actionIdx = layer->actions()->defaultAction();
layer->actions()->doAction( actionIdx, feat, &substitutionMap );
layer->actions()->doAction( actionIdx, feat, context, &substitutionMap );
}
else
{
Expand Down
35 changes: 27 additions & 8 deletions src/core/qgsactionmanager.cpp
Expand Up @@ -65,15 +65,34 @@ void QgsActionManager::removeAction( int index )

void QgsActionManager::doAction( int index, const QgsFeature& feat, int defaultValueIndex )
{
QMap<QString, QVariant> substitutionMap;
if ( defaultValueIndex >= 0 )
{
QVariant defaultValue = feat.attribute( defaultValueIndex );
if ( defaultValue.isValid() )
substitutionMap.insert( "$currfield", defaultValue );
}
QgsExpressionContext context = createExpressionContext();
QgsExpressionContextScope* actionScope = new QgsExpressionContextScope();
actionScope->setVariable( "current_field", feat.attribute( defaultValueIndex ) );
context << actionScope;
doAction( index, feat, context );
}

void QgsActionManager::doAction( int index, const QgsFeature& feat, const QgsExpressionContext& context, const QMap<QString, QVariant> *substitutionMap )
{
if ( index < 0 || index >= size() )
return;

const QgsAction &action = at( index );
if ( !action.runable() )
return;

QgsExpressionContext actionContext( context );

if ( mLayer )
actionContext << QgsExpressionContextUtils::layerScope( mLayer );
actionContext.setFeature( feat );

doAction( index, feat, &substitutionMap );
QString expandedAction = QgsExpression::replaceExpressionText( action.action(), &actionContext, substitutionMap );
if ( expandedAction.isEmpty() )
return;

QgsAction newAction( action.type(), action.name(), expandedAction, action.capture() );
runAction( newAction );
}

void QgsActionManager::doAction( int index, const QgsFeature &feat, const QMap<QString, QVariant> *substitutionMap )
Expand Down
20 changes: 17 additions & 3 deletions src/core/qgsactionmanager.h
Expand Up @@ -85,15 +85,29 @@ class CORE_EXPORT QgsActionManager
const QgsFeature &feat,
int defaultValueIndex = 0 );

/** Does the action using the expression engine to replace any embedded expressions
* in the action definition.
* @param index action index
* @param feature feature to run action for
* @param context expression context to evalute expressions under
* @param substitutionMap deprecated - kept for compatibilty with projects, will be removed for 3.0
*/
// TODO QGIS 3.0 remove substition map - force use of expression variables
void doAction( int index,
const QgsFeature& feature,
const QgsExpressionContext& context,
const QMap<QString, QVariant> *substitutionMap = nullptr );

/** Does the action using the expression builder to expand it
* and getting values from the passed feature attribute map.
* substitutionMap is used to pass custom substitutions, to replace
* each key in the map with the associated value
* @note available in python bindings as doActionFeatureWithSubstitution
* @deprecated use QgsExpressionContext variant instead
*/
void doAction( int index,
const QgsFeature &feat,
const QMap<QString, QVariant> *substitutionMap );
Q_DECL_DEPRECATED void doAction( int index,
const QgsFeature &feat,
const QMap<QString, QVariant> *substitutionMap );

//! Removes all actions
void clearActions();
Expand Down

0 comments on commit 3d494ac

Please sign in to comment.