Quantum GIS API Documentation  1.7.5-Wroclaw
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
qgsattributeaction.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsattributeaction.cpp
3 
4  A class that stores and controls the managment and execution of actions
5  associated. Actions are defined to be external programs that are run
6  with user-specified inputs that can depend on the value of layer
7  attributes.
8 
9  -------------------
10  begin : Oct 24 2004
11  copyright : (C) 2004 by Gavin Macaulay
12  email : gavin at macaulay dot co dot nz
13 
14  ***************************************************************************/
15 
16 /***************************************************************************
17  * *
18  * This program is free software; you can redistribute it and/or modify *
19  * it under the terms of the GNU General Public License as published by *
20  * the Free Software Foundation; either version 2 of the License, or *
21  * (at your option) any later version. *
22  * *
23  ***************************************************************************/
24 /* $Id$ */
25 
26 #include <QList>
27 
28 #include <QStringList>
29 #include <QDomElement>
30 
31 #include "qgsattributeaction.h"
32 #include "qgsrunprocess.h"
33 #include "qgsvectorlayer.h"
34 
35 static const char * const ident_ = "$Id$";
36 
37 void QgsAttributeAction::addAction( QgsAction::ActionType type, QString name, QString action, bool capture )
38 {
39  mActions << QgsAction( type, name, action, capture );
40 }
41 
42 void QgsAttributeAction::doAction( int index, const QgsAttributeMap &attributes,
43  int defaultValueIndex, void ( *executePython )( const QString & ) )
44 {
45  if ( index < 0 || index >= size() )
46  return;
47 
48  const QgsAction &action = at( index );
49 
50  if ( !action.runable() )
51  return;
52 
53  // A couple of extra options for running the action may be
54  // useful. For example,
55  // - run the action inside a terminal (on unix)
56  // - capture the stdout from the process and display in a dialog
57  // box
58  //
59  // The capture stdout one is partially implemented. It just needs
60  // the UI and the code in this function to select on the
61  // action.capture() return value.
62 
63  // The QgsRunProcess instance created by this static function
64  // deletes itself when no longer needed.
65  QString expandedAction = expandAction( action.action(), attributes, defaultValueIndex );
66  if ( action.type() == QgsAction::GenericPython )
67  {
68  if ( executePython )
69  {
70  executePython( expandedAction );
71  }
72  else if ( smPythonExecute )
73  {
74  smPythonExecute( expandedAction );
75  }
76  }
77  else
78  {
79  QgsRunProcess::create( expandedAction, action.capture() );
80  }
81 }
82 
83 QString QgsAttributeAction::expandAction( QString action, const QgsAttributeMap &attributes,
84  uint clickedOnValue )
85 {
86  // This function currently replaces all %% characters in the action
87  // with the value from values[clickedOnValue].second, and then
88  // searches for all strings that go %attribite_name, where
89  // attribute_name is found in values[x].first, and replaces any that
90  // it finds by values[s].second.
91 
92  // Additional substitutions could include symbols for $CWD, $HOME,
93  // etc (and their OSX and Windows equivalents)
94 
95  // This function will potentially fall apart if any of the
96  // substitutions produce text that could match another
97  // substitution. May be better to adopt a two pass approach - identify
98  // all matches and their substitutions and then do a second pass
99  // for the actual substitutions.
100 
101  QString expanded_action;
102  if ( clickedOnValue >= 0 && attributes.contains( clickedOnValue ) )
103  expanded_action = action.replace( "%%", attributes[clickedOnValue].toString() );
104  else
105  expanded_action = action;
106 
107  const QgsFieldMap &fields = mLayer->pendingFields();
108 
109  for ( int i = 0; i < 4; i++ )
110  {
111  for ( QgsAttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); it++ )
112  {
113  QgsFieldMap::const_iterator fit = fields.find( it.key() );
114  if ( fit == fields.constEnd() )
115  continue;
116 
117  QString to_replace;
118  switch ( i )
119  {
120  case 0: to_replace = "[%" + fit->name() + "]"; break;
121  case 1: to_replace = "[%" + mLayer->attributeDisplayName( it.key() ) + "]"; break;
122  case 2: to_replace = "%" + fit->name(); break;
123  case 3: to_replace = "%" + mLayer->attributeDisplayName( it.key() ); break;
124  }
125 
126  expanded_action = expanded_action.replace( to_replace, it.value().toString() );
127  }
128  }
129 
130  return expanded_action;
131 }
132 
133 bool QgsAttributeAction::writeXML( QDomNode& layer_node, QDomDocument& doc ) const
134 {
135  QDomElement aActions = doc.createElement( "attributeactions" );
136 
137  for ( int i = 0; i < mActions.size(); i++ )
138  {
139  QDomElement actionSetting = doc.createElement( "actionsetting" );
140  actionSetting.setAttribute( "type", mActions[i].type() );
141  actionSetting.setAttribute( "name", mActions[i].name() );
142  actionSetting.setAttribute( "action", mActions[i].action() );
143  actionSetting.setAttribute( "capture", mActions[i].capture() );
144  aActions.appendChild( actionSetting );
145  }
146  layer_node.appendChild( aActions );
147 
148  return true;
149 }
150 
151 bool QgsAttributeAction::readXML( const QDomNode& layer_node )
152 {
153  mActions.clear();
154 
155  QDomNode aaNode = layer_node.namedItem( "attributeactions" );
156 
157  if ( !aaNode.isNull() )
158  {
159  QDomNodeList actionsettings = aaNode.childNodes();
160  for ( unsigned int i = 0; i < actionsettings.length(); ++i )
161  {
162  QDomElement setting = actionsettings.item( i ).toElement();
163  addAction(( QgsAction::ActionType ) setting.attributeNode( "type" ).value().toInt(),
164  setting.attributeNode( "name" ).value(),
165  setting.attributeNode( "action" ).value(),
166  setting.attributeNode( "capture" ).value().toInt() != 0 );
167  }
168  }
169  return true;
170 }
171 
172 void ( *QgsAttributeAction::smPythonExecute )( const QString & ) = 0;
173 
174 void QgsAttributeAction::setPythonExecute( void ( *runPython )( const QString & ) )
175 {
176  smPythonExecute = runPython;
177 }