2222 * *
2323 ***************************************************************************/
2424
25- #include < QList>
26-
27- #include < QStringList>
28- #include < QDomElement>
29-
3025#include " qgsattributeaction.h"
3126#include " qgspythonrunner.h"
3227#include " qgsrunprocess.h"
3328#include " qgsvectorlayer.h"
29+ #include " qgsproject.h"
30+ #include < qgslogger.h>
31+ #include " qgsexpression.h"
32+
33+ #include < QList>
34+ #include < QStringList>
35+ #include < QDomElement>
36+ #include < QSettings>
37+ #include < QDesktopServices>
38+ #include < QUrl>
39+ #include < QDir>
40+ #include < QFileInfo>
41+
3442
3543void QgsAttributeAction::addAction ( QgsAction::ActionType type, QString name, QString action, bool capture )
3644{
@@ -44,7 +52,6 @@ void QgsAttributeAction::doAction( int index, const QgsAttributeMap &attributes,
4452 return ;
4553
4654 const QgsAction &action = at ( index );
47-
4855 if ( !action.runable () )
4956 return ;
5057
@@ -58,29 +65,67 @@ void QgsAttributeAction::doAction( int index, const QgsAttributeMap &attributes,
5865 // the UI and the code in this function to select on the
5966 // action.capture() return value.
6067
61- // The QgsRunProcess instance created by this static function
62- // deletes itself when no longer needed.
6368 QString expandedAction = expandAction ( action.action (), attributes, defaultValueIndex );
69+ if ( expandedAction.isEmpty () )
70+ return ;
71+
72+ QgsAction newAction ( action.type (), action.name (), expandedAction, action.capture () );
73+ runAction ( newAction, executePython );
74+ }
75+
76+ void QgsAttributeAction::doAction ( int index, QgsFeature &feat, int defaultValueIndex )
77+ {
78+ QMap<QString, QVariant> substitutionMap;
79+ if ( defaultValueIndex >= 0 )
80+ substitutionMap.insert ( " $currfield" , QVariant ( defaultValueIndex ) );
81+
82+ doAction ( index, feat, &substitutionMap );
83+ }
84+
85+ void QgsAttributeAction::doAction ( int index, QgsFeature &feat,
86+ const QMap<QString, QVariant> *substitutionMap )
87+ {
88+ if ( index < 0 || index >= size () )
89+ return ;
90+
91+ const QgsAction &action = at ( index );
92+ if ( !action.runable () )
93+ return ;
94+
95+ // search for expressions while expanding actions
96+ QString expandedAction = expandAction ( action.action (), feat, substitutionMap );
97+ if ( expandedAction.isEmpty () )
98+ return ;
99+
100+ QgsAction newAction ( action.type (), action.name (), expandedAction, action.capture () );
101+ runAction ( newAction );
102+ }
103+
104+ void QgsAttributeAction::runAction ( const QgsAction &action, void ( *executePython )( const QString & ) )
105+ {
64106 if ( action.type () == QgsAction::GenericPython )
65107 {
66108 if ( executePython )
67109 {
68110 // deprecated
69- executePython ( expandedAction );
111+ executePython ( action. action () );
70112 }
71113 else if ( smPythonExecute )
72114 {
73115 // deprecated
74- smPythonExecute ( expandedAction );
116+ smPythonExecute ( action. action () );
75117 }
76118 else
77119 {
78- QgsPythonRunner::run ( expandedAction );
120+ // TODO: capture output from QgsPythonRunner
121+ QgsPythonRunner::run ( action.action () );
79122 }
80123 }
81124 else
82125 {
83- QgsRunProcess::create ( expandedAction, action.capture () );
126+ // The QgsRunProcess instance created by this static function
127+ // deletes itself when no longer needed.
128+ QgsRunProcess::create ( action.action (), action.capture () );
84129 }
85130}
86131
@@ -89,7 +134,7 @@ QString QgsAttributeAction::expandAction( QString action, const QgsAttributeMap
89134{
90135 // This function currently replaces all %% characters in the action
91136 // with the value from values[clickedOnValue].second, and then
92- // searches for all strings that go %attribite_name , where
137+ // searches for all strings that go %attribute_name , where
93138 // attribute_name is found in values[x].first, and replaces any that
94139 // it finds by values[s].second.
95140
@@ -134,6 +179,63 @@ QString QgsAttributeAction::expandAction( QString action, const QgsAttributeMap
134179 return expanded_action;
135180}
136181
182+ QString QgsAttributeAction::expandAction ( QString action, QgsFeature &feat, const QMap<QString, QVariant> *substitutionMap )
183+ {
184+ // This function currently replaces each expression between [% and %]
185+ // in the action with the result of its evaluation on the feature
186+ // passed as argument.
187+
188+ // Additional substitutions can be passed through the substitutionMap
189+ // parameter
190+
191+ QString expr_action;
192+
193+ int index = 0 ;
194+ while ( index < action.size () )
195+ {
196+ QRegExp rx = QRegExp ( " \\ [%([^\\ ]]+)%\\ ]" );
197+
198+ int pos = rx.indexIn ( action, index );
199+ if ( pos < 0 )
200+ break ;
201+
202+ int start = index;
203+ index = pos + rx.matchedLength ();
204+
205+ QString to_replace = rx.cap (1 ).trimmed ();
206+ QgsDebugMsg ( " Found expression:" + to_replace );
207+
208+ if ( substitutionMap && substitutionMap->contains ( to_replace ) )
209+ {
210+ expr_action += action.mid ( start, pos - start ) + substitutionMap->value ( to_replace ).toString ();
211+ continue ;
212+ }
213+
214+ QgsExpression* exp = new QgsExpression ( to_replace );
215+ if ( exp->hasParserError () )
216+ {
217+ QgsDebugMsg ( " Expression parser error:" + exp->parserErrorString () );
218+ expr_action += action.mid ( start, index - start );
219+ continue ;
220+ }
221+
222+ QVariant result = exp->evaluate ( &feat, mLayer ->pendingFields () );
223+ if ( exp->hasEvalError () )
224+ {
225+ QgsDebugMsg ( " Expression parser eval error:" + exp->evalErrorString () );
226+ expr_action += action.mid ( start, index - start );
227+ continue ;
228+ }
229+
230+ QgsDebugMsg ( " Expression result is: " + result.toString () );
231+ expr_action += action.mid ( start, pos - start ) + result.toString ();
232+ }
233+
234+ expr_action += action.mid ( index );
235+ return expr_action;
236+ }
237+
238+
137239bool QgsAttributeAction::writeXML ( QDomNode& layer_node, QDomDocument& doc ) const
138240{
139241 QDomElement aActions = doc.createElement ( " attributeactions" );
0 commit comments