Skip to content

Commit c9c1c34

Browse files
committedNov 10, 2017
Fixes #16852 by adding click_x and click_y variables to resolve actions
1 parent 2ca4ee5 commit c9c1c34

16 files changed

+200
-12
lines changed
 

‎python/core/qgsaction.sip

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,21 @@ Checks if the action is runable on the current platform
184184
.. versionadded:: 3.0
185185
%End
186186

187+
void setExpressionContextScope( const QgsExpressionContextScope &scope );
188+
%Docstring
189+
Sets an expression context scope to use for running the action.
190+
191+
.. versionadded:: 3.0
192+
%End
193+
194+
QgsExpressionContextScope expressionContextScope() const;
195+
%Docstring
196+
Returns an expression context scope used for running the action.
197+
198+
.. versionadded:: 3.0
199+
:rtype: QgsExpressionContextScope
200+
%End
201+
187202
};
188203

189204

‎python/core/qgsactionmanager.sip

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,15 @@ Constructor
6262
.. versionadded:: 3.0
6363
%End
6464

65-
void doAction( const QUuid &actionId, const QgsFeature &feature, int defaultValueIndex = 0 ) /PyName=doActionFeature/;
65+
void doAction( const QUuid &actionId, const QgsFeature &feature, int defaultValueIndex = 0, const QgsExpressionContextScope &scope = QgsExpressionContextScope() ) /PyName=doActionFeature/;
6666
%Docstring
67-
Does the given action. defaultValueIndex is the index of the
68-
field to be used if the action has a $currfield placeholder.
67+
Does the given action.
68+
69+
\param actionId action id
70+
\param feature feature to run action for
71+
\param defaultValueIndex index of the field to be used if the action has a $currfield placeholder.
72+
\param scope expression context scope to add during expression evaluation
73+
6974
.. note::
7075

7176
available in Python bindings as doActionFeature

‎python/gui/qgsactionmenu.sip

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,21 @@ class QgsActionMenu : QMenu
7373
as long as the menu is displayed and the action is running.
7474
%End
7575

76+
void setExpressionContextScope( const QgsExpressionContextScope &scope );
77+
%Docstring
78+
Sets an expression context scope used to resolve underlying actions.
79+
80+
.. versionadded:: 3.0
81+
%End
82+
83+
QgsExpressionContextScope expressionContextScope() const;
84+
%Docstring
85+
Returns an expression context scope used to resolve underlying actions.
86+
87+
.. versionadded:: 3.0
88+
:rtype: QgsExpressionContextScope
89+
%End
90+
7691
signals:
7792
void reinit();
7893

‎python/gui/qgsidentifymenu.sip

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,21 @@ define if the menu will be shown with a single idetify result
7171
:rtype: bool
7272
%End
7373

74+
void setExpressionContextScope( const QgsExpressionContextScope &scope );
75+
%Docstring
76+
Sets an expression context scope used to resolve underlying actions.
77+
78+
.. versionadded:: 3.0
79+
%End
80+
81+
QgsExpressionContextScope expressionContextScope() const;
82+
%Docstring
83+
Returns an expression context scope used to resolve underlying actions.
84+
85+
.. versionadded:: 3.0
86+
:rtype: QgsExpressionContextScope
87+
%End
88+
7489
void setShowFeatureActions( bool showFeatureActions );
7590
%Docstring
7691
define if attribute actions(1) and map layer actions(2) can be listed and run from the menu

‎src/app/qgsidentifyresultsdialog.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1164,6 +1164,8 @@ void QgsIdentifyResultsDialog::clear()
11641164
delete curve;
11651165
mPlotCurves.clear();
11661166

1167+
mExpressionContextScope = QgsExpressionContextScope();
1168+
11671169
// keep it visible but disabled, it can switch from disabled/enabled
11681170
// after raster format change
11691171
mActionPrint->setDisabled( true );
@@ -1245,7 +1247,7 @@ void QgsIdentifyResultsDialog::doAction( QTreeWidgetItem *item, const QString &a
12451247
}
12461248

12471249
int featIdx = featItem->data( 0, Qt::UserRole + 1 ).toInt();
1248-
layer->actions()->doAction( action, mFeatures[ featIdx ], idx );
1250+
layer->actions()->doAction( action, mFeatures[ featIdx ], idx, mExpressionContextScope );
12491251
}
12501252

12511253
void QgsIdentifyResultsDialog::doMapLayerAction( QTreeWidgetItem *item, QgsMapLayerAction *action )
@@ -1978,3 +1980,13 @@ void QgsIdentifyResultsDialog::showHelp()
19781980
{
19791981
QgsHelp::openHelp( QStringLiteral( "introduction/general_tools.html#identify" ) );
19801982
}
1983+
1984+
void QgsIdentifyResultsDialog::setExpressionContextScope( const QgsExpressionContextScope &scope )
1985+
{
1986+
mExpressionContextScope = scope;
1987+
}
1988+
1989+
QgsExpressionContextScope QgsIdentifyResultsDialog::expressionContextScope() const
1990+
{
1991+
return mExpressionContextScope;
1992+
}

‎src/app/qgsidentifyresultsdialog.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "qgscoordinatereferencesystem.h"
2626
#include "qgsmaptoolidentify.h"
2727
#include "qgswebview.h"
28+
#include "qgsexpressioncontext.h"
2829

2930
#include <QWidget>
3031
#include <QList>
@@ -150,6 +151,22 @@ class APP_EXPORT QgsIdentifyResultsDialog: public QDialog, private Ui::QgsIdenti
150151
//! Map tool was activated
151152
void activate();
152153

154+
/**
155+
* Sets an expression context scope to consider for resolving underlying
156+
* actions.
157+
*
158+
* \since QGIS 3.0
159+
*/
160+
void setExpressionContextScope( const QgsExpressionContextScope &scope );
161+
162+
/**
163+
* Returns an expression context scope used for resolving underlying
164+
* actions.
165+
*
166+
* \since QGIS 3.0
167+
*/
168+
QgsExpressionContextScope expressionContextScope() const;
169+
153170
signals:
154171
void selectedFeatureChanged( QgsVectorLayer *, QgsFeatureId featureId );
155172

@@ -233,6 +250,7 @@ class APP_EXPORT QgsIdentifyResultsDialog: public QDialog, private Ui::QgsIdenti
233250
QgsMapCanvas *mCanvas = nullptr;
234251
QList<QgsFeature> mFeatures;
235252
QMap< QString, QMap< QString, QVariant > > mWidgetCaches;
253+
QgsExpressionContextScope mExpressionContextScope;
236254

237255
QgsMapLayer *layer( QTreeWidgetItem *item );
238256
QgsVectorLayer *vectorLayer( QTreeWidgetItem *item );

‎src/app/qgsmaptoolidentifyaction.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "qgsrenderer.h"
3838
#include "qgsunittypes.h"
3939
#include "qgsstatusbar.h"
40+
#include "qgsactionscoperegistry.h"
4041

4142
#include "qgssettings.h"
4243
#include <QMouseEvent>
@@ -119,6 +120,8 @@ void QgsMapToolIdentifyAction::canvasReleaseEvent( QgsMapMouseEvent *e )
119120
connect( this, &QgsMapToolIdentifyAction::identifyProgress, QgisApp::instance(), &QgisApp::showProgress );
120121
connect( this, &QgsMapToolIdentifyAction::identifyMessage, QgisApp::instance(), &QgisApp::showStatusMessage );
121122

123+
setClickContextScope( toMapCoordinates( e->pos() ) );
124+
122125
identifyMenu()->setResultsIfExternalAction( false );
123126

124127
// enable the right click for extended menu so it behaves as a contextual menu
@@ -201,4 +204,16 @@ void QgsMapToolIdentifyAction::handleCopyToClipboard( QgsFeatureStore &featureSt
201204
emit copyToClipboard( featureStore );
202205
}
203206

207+
void QgsMapToolIdentifyAction::setClickContextScope( const QgsPointXY &point )
208+
{
209+
QgsExpressionContextScope clickScope;
210+
clickScope.addVariable( QgsExpressionContextScope::StaticVariable( QString( "click_x" ), point.x(), true ) );
211+
clickScope.addVariable( QgsExpressionContextScope::StaticVariable( QString( "click_y" ), point.y(), true ) );
212+
213+
resultsDialog()->setExpressionContextScope( clickScope );
204214

215+
if ( mIdentifyMenu )
216+
{
217+
mIdentifyMenu->setExpressionContextScope( clickScope );
218+
}
219+
}

‎src/app/qgsmaptoolidentifyaction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,9 @@ class APP_EXPORT QgsMapToolIdentifyAction : public QgsMapToolIdentify
7878

7979
virtual QgsUnitTypes::DistanceUnit displayDistanceUnits() const override;
8080
virtual QgsUnitTypes::AreaUnit displayAreaUnits() const override;
81+
void setClickContextScope( const QgsPointXY &point );
8182

83+
friend class TestQgsMapToolIdentifyAction;
8284
};
8385

8486
#endif

‎src/core/qgsaction.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,11 @@ void QgsAction::run( const QgsExpressionContext &expressionContext ) const
5959
return;
6060
}
6161

62-
QString expandedAction = QgsExpression::replaceExpressionText( mCommand, &expressionContext );
62+
QgsExpressionContextScope *scope = new QgsExpressionContextScope( mExpressionContextScope );
63+
QgsExpressionContext context( expressionContext );
64+
context << scope;
65+
66+
QString expandedAction = QgsExpression::replaceExpressionText( mCommand, &context );
6367

6468
if ( mType == QgsAction::OpenUrl )
6569
{
@@ -146,3 +150,13 @@ void QgsAction::writeXml( QDomNode &actionsNode ) const
146150

147151
actionsNode.appendChild( actionSetting );
148152
}
153+
154+
void QgsAction::setExpressionContextScope( const QgsExpressionContextScope &scope )
155+
{
156+
mExpressionContextScope = scope;
157+
}
158+
159+
QgsExpressionContextScope QgsAction::expressionContextScope() const
160+
{
161+
return mExpressionContextScope;
162+
};

‎src/core/qgsaction.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,20 @@ class CORE_EXPORT QgsAction
191191
*/
192192
void writeXml( QDomNode &actionsNode ) const;
193193

194+
/**
195+
* Sets an expression context scope to use for running the action.
196+
*
197+
* \since QGIS 3.0
198+
*/
199+
void setExpressionContextScope( const QgsExpressionContextScope &scope );
200+
201+
/**
202+
* Returns an expression context scope used for running the action.
203+
*
204+
* \since QGIS 3.0
205+
*/
206+
QgsExpressionContextScope expressionContextScope() const;
207+
194208
private:
195209
ActionType mType = Generic;
196210
QString mDescription;
@@ -202,6 +216,7 @@ class CORE_EXPORT QgsAction
202216
QString mNotificationMessage;
203217
mutable std::shared_ptr<QAction> mAction;
204218
QUuid mId;
219+
QgsExpressionContextScope mExpressionContextScope;
205220
};
206221

207222
Q_DECLARE_METATYPE( QgsAction )

‎src/core/qgsactionmanager.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,10 @@ void QgsActionManager::removeAction( const QUuid &actionId )
123123
}
124124
}
125125

126-
void QgsActionManager::doAction( const QUuid &actionId, const QgsFeature &feature, int defaultValueIndex )
126+
void QgsActionManager::doAction( const QUuid &actionId, const QgsFeature &feature, int defaultValueIndex, const QgsExpressionContextScope &scope )
127127
{
128128
QgsExpressionContext context = createExpressionContext();
129-
QgsExpressionContextScope *actionScope = new QgsExpressionContextScope();
129+
QgsExpressionContextScope *actionScope = new QgsExpressionContextScope( scope );
130130
actionScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "field_index" ), defaultValueIndex, true ) );
131131
if ( defaultValueIndex >= 0 && defaultValueIndex < feature.fields().size() )
132132
actionScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "field_name" ), feature.fields().at( defaultValueIndex ).name(), true ) );

‎src/core/qgsactionmanager.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,16 @@ class CORE_EXPORT QgsActionManager: public QObject
8989
void removeAction( const QUuid &actionId );
9090

9191
/**
92-
* Does the given action. defaultValueIndex is the index of the
93-
* field to be used if the action has a $currfield placeholder.
94-
* \note available in Python bindings as doActionFeature
92+
* Does the given action.
93+
*
94+
* \param actionId action id
95+
* \param feature feature to run action for
96+
* \param defaultValueIndex index of the field to be used if the action has a $currfield placeholder.
97+
* \param scope expression context scope to add during expression evaluation
98+
*
99+
* \note available in Python bindings as doActionFeature
95100
*/
96-
void doAction( const QUuid &actionId, const QgsFeature &feature, int defaultValueIndex = 0 ) SIP_PYNAME( doActionFeature );
101+
void doAction( const QUuid &actionId, const QgsFeature &feature, int defaultValueIndex = 0, const QgsExpressionContextScope &scope = QgsExpressionContextScope() ) SIP_PYNAME( doActionFeature );
97102

98103
/**
99104
* Does the action using the expression engine to replace any embedded expressions

‎src/gui/qgsactionmenu.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,11 @@ void QgsActionMenu::reloadActions()
107107

108108
Q_FOREACH ( const QgsAction &action, mActions )
109109
{
110+
QgsAction act( action );
111+
act.setExpressionContextScope( mExpressionContextScope );
112+
110113
QAction *qAction = new QAction( action.icon(), action.name(), this );
111-
qAction->setData( QVariant::fromValue<ActionData>( ActionData( action, mFeatureId, mLayer ) ) );
114+
qAction->setData( QVariant::fromValue<ActionData>( ActionData( act, mFeatureId, mLayer ) ) );
112115
qAction->setIcon( action.icon() );
113116

114117
// Only enable items on supported platforms
@@ -160,3 +163,15 @@ QgsActionMenu::ActionData::ActionData( const QgsAction &action, QgsFeatureId fea
160163
, featureId( featureId )
161164
, mapLayer( mapLayer )
162165
{}
166+
167+
168+
void QgsActionMenu::setExpressionContextScope( const QgsExpressionContextScope &scope )
169+
{
170+
mExpressionContextScope = scope;
171+
reloadActions();
172+
}
173+
174+
QgsExpressionContextScope QgsActionMenu::expressionContextScope() const
175+
{
176+
return mExpressionContextScope;
177+
}

‎src/gui/qgsactionmenu.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,20 @@ class GUI_EXPORT QgsActionMenu : public QMenu
9191
*/
9292
void setFeature( const QgsFeature &feature );
9393

94+
/**
95+
* Sets an expression context scope used to resolve underlying actions.
96+
*
97+
* \since QGIS 3.0
98+
*/
99+
void setExpressionContextScope( const QgsExpressionContextScope &scope );
100+
101+
/**
102+
* Returns an expression context scope used to resolve underlying actions.
103+
*
104+
* \since QGIS 3.0
105+
*/
106+
QgsExpressionContextScope expressionContextScope() const;
107+
94108
signals:
95109
void reinit();
96110

@@ -107,6 +121,7 @@ class GUI_EXPORT QgsActionMenu : public QMenu
107121
QgsFeature mFeature;
108122
QgsFeatureId mFeatureId;
109123
QString mActionScope;
124+
QgsExpressionContextScope mExpressionContextScope;
110125
};
111126

112127

‎src/gui/qgsidentifymenu.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ void QgsIdentifyMenu::addVectorLayer( QgsVectorLayer *layer, const QList<QgsMapT
345345
if ( mShowFeatureActions )
346346
{
347347
featureActionMenu = new QgsActionMenu( layer, result.mFeature, QStringLiteral( "Feature" ), layerMenu );
348+
featureActionMenu->setExpressionContextScope( mExpressionContextScope );
348349
}
349350

350351
// feature title
@@ -639,3 +640,13 @@ void QgsIdentifyMenu::removeCustomActions()
639640
mCustomActionRegistry.clear();
640641

641642
}
643+
644+
void QgsIdentifyMenu::setExpressionContextScope( const QgsExpressionContextScope &scope )
645+
{
646+
mExpressionContextScope = scope;
647+
}
648+
649+
QgsExpressionContextScope QgsIdentifyMenu::expressionContextScope() const
650+
{
651+
return mExpressionContextScope;
652+
}

‎src/gui/qgsidentifymenu.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,20 @@ class GUI_EXPORT QgsIdentifyMenu : public QMenu
103103
void setExecWithSingleResult( bool execWithSingleResult ) { mExecWithSingleResult = execWithSingleResult;}
104104
bool execWithSingleResult() { return mExecWithSingleResult;}
105105

106+
/**
107+
* Sets an expression context scope used to resolve underlying actions.
108+
*
109+
* \since QGIS 3.0
110+
*/
111+
void setExpressionContextScope( const QgsExpressionContextScope &scope );
112+
113+
/**
114+
* Returns an expression context scope used to resolve underlying actions.
115+
*
116+
* \since QGIS 3.0
117+
*/
118+
QgsExpressionContextScope expressionContextScope() const;
119+
106120
/**
107121
* \brief define if attribute actions(1) and map layer actions(2) can be listed and run from the menu
108122
* \note custom actions will be shown in any case if they exist.
@@ -178,6 +192,8 @@ class GUI_EXPORT QgsIdentifyMenu : public QMenu
178192
int mMaxLayerDisplay;
179193
int mMaxFeatureDisplay;
180194

195+
QgsExpressionContextScope mExpressionContextScope;
196+
181197
// name of the action to be displayed for feature default action, if other actions are shown
182198
QString mDefaultActionName;
183199

0 commit comments

Comments
 (0)
Please sign in to comment.