Quantum GIS API Documentation
1.7.4
|
00001 /*************************************************************************** 00002 qgsattributeaction.cpp 00003 00004 A class that stores and controls the managment and execution of actions 00005 associated. Actions are defined to be external programs that are run 00006 with user-specified inputs that can depend on the value of layer 00007 attributes. 00008 00009 ------------------- 00010 begin : Oct 24 2004 00011 copyright : (C) 2004 by Gavin Macaulay 00012 email : gavin at macaulay dot co dot nz 00013 00014 ***************************************************************************/ 00015 00016 /*************************************************************************** 00017 * * 00018 * This program is free software; you can redistribute it and/or modify * 00019 * it under the terms of the GNU General Public License as published by * 00020 * the Free Software Foundation; either version 2 of the License, or * 00021 * (at your option) any later version. * 00022 * * 00023 ***************************************************************************/ 00024 /* $Id$ */ 00025 00026 #include <QList> 00027 00028 #include <QStringList> 00029 #include <QDomElement> 00030 00031 #include "qgsattributeaction.h" 00032 #include "qgsrunprocess.h" 00033 #include "qgsvectorlayer.h" 00034 00035 static const char * const ident_ = "$Id$"; 00036 00037 void QgsAttributeAction::addAction( QgsAction::ActionType type, QString name, QString action, bool capture ) 00038 { 00039 mActions << QgsAction( type, name, action, capture ); 00040 } 00041 00042 void QgsAttributeAction::doAction( int index, const QgsAttributeMap &attributes, 00043 int defaultValueIndex, void ( *executePython )( const QString & ) ) 00044 { 00045 if ( index < 0 || index >= size() ) 00046 return; 00047 00048 const QgsAction &action = at( index ); 00049 00050 if ( !action.runable() ) 00051 return; 00052 00053 // A couple of extra options for running the action may be 00054 // useful. For example, 00055 // - run the action inside a terminal (on unix) 00056 // - capture the stdout from the process and display in a dialog 00057 // box 00058 // 00059 // The capture stdout one is partially implemented. It just needs 00060 // the UI and the code in this function to select on the 00061 // action.capture() return value. 00062 00063 // The QgsRunProcess instance created by this static function 00064 // deletes itself when no longer needed. 00065 QString expandedAction = expandAction( action.action(), attributes, defaultValueIndex ); 00066 if ( action.type() == QgsAction::GenericPython ) 00067 { 00068 if ( executePython ) 00069 { 00070 executePython( expandedAction ); 00071 } 00072 else if ( smPythonExecute ) 00073 { 00074 smPythonExecute( expandedAction ); 00075 } 00076 } 00077 else 00078 { 00079 QgsRunProcess::create( expandedAction, action.capture() ); 00080 } 00081 } 00082 00083 QString QgsAttributeAction::expandAction( QString action, const QgsAttributeMap &attributes, 00084 uint clickedOnValue ) 00085 { 00086 // This function currently replaces all %% characters in the action 00087 // with the value from values[clickedOnValue].second, and then 00088 // searches for all strings that go %attribite_name, where 00089 // attribute_name is found in values[x].first, and replaces any that 00090 // it finds by values[s].second. 00091 00092 // Additional substitutions could include symbols for $CWD, $HOME, 00093 // etc (and their OSX and Windows equivalents) 00094 00095 // This function will potentially fall apart if any of the 00096 // substitutions produce text that could match another 00097 // substitution. May be better to adopt a two pass approach - identify 00098 // all matches and their substitutions and then do a second pass 00099 // for the actual substitutions. 00100 00101 QString expanded_action; 00102 if ( clickedOnValue >= 0 && attributes.contains( clickedOnValue ) ) 00103 expanded_action = action.replace( "%%", attributes[clickedOnValue].toString() ); 00104 else 00105 expanded_action = action; 00106 00107 const QgsFieldMap &fields = mLayer->pendingFields(); 00108 00109 for ( int i = 0; i < 4; i++ ) 00110 { 00111 for ( QgsAttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); it++ ) 00112 { 00113 QgsFieldMap::const_iterator fit = fields.find( it.key() ); 00114 if ( fit == fields.constEnd() ) 00115 continue; 00116 00117 QString to_replace; 00118 switch ( i ) 00119 { 00120 case 0: to_replace = "[%" + fit->name() + "]"; break; 00121 case 1: to_replace = "[%" + mLayer->attributeDisplayName( it.key() ) + "]"; break; 00122 case 2: to_replace = "%" + fit->name(); break; 00123 case 3: to_replace = "%" + mLayer->attributeDisplayName( it.key() ); break; 00124 } 00125 00126 expanded_action = expanded_action.replace( to_replace, it.value().toString() ); 00127 } 00128 } 00129 00130 return expanded_action; 00131 } 00132 00133 bool QgsAttributeAction::writeXML( QDomNode& layer_node, QDomDocument& doc ) const 00134 { 00135 QDomElement aActions = doc.createElement( "attributeactions" ); 00136 00137 for ( int i = 0; i < mActions.size(); i++ ) 00138 { 00139 QDomElement actionSetting = doc.createElement( "actionsetting" ); 00140 actionSetting.setAttribute( "type", mActions[i].type() ); 00141 actionSetting.setAttribute( "name", mActions[i].name() ); 00142 actionSetting.setAttribute( "action", mActions[i].action() ); 00143 actionSetting.setAttribute( "capture", mActions[i].capture() ); 00144 aActions.appendChild( actionSetting ); 00145 } 00146 layer_node.appendChild( aActions ); 00147 00148 return true; 00149 } 00150 00151 bool QgsAttributeAction::readXML( const QDomNode& layer_node ) 00152 { 00153 mActions.clear(); 00154 00155 QDomNode aaNode = layer_node.namedItem( "attributeactions" ); 00156 00157 if ( !aaNode.isNull() ) 00158 { 00159 QDomNodeList actionsettings = aaNode.childNodes(); 00160 for ( unsigned int i = 0; i < actionsettings.length(); ++i ) 00161 { 00162 QDomElement setting = actionsettings.item( i ).toElement(); 00163 addAction(( QgsAction::ActionType ) setting.attributeNode( "type" ).value().toInt(), 00164 setting.attributeNode( "name" ).value(), 00165 setting.attributeNode( "action" ).value(), 00166 setting.attributeNode( "capture" ).value().toInt() != 0 ); 00167 } 00168 } 00169 return true; 00170 } 00171 00172 void ( *QgsAttributeAction::smPythonExecute )( const QString & ) = 0; 00173 00174 void QgsAttributeAction::setPythonExecute( void ( *runPython )( const QString & ) ) 00175 { 00176 smPythonExecute = runPython; 00177 }