Quantum GIS API Documentation  1.7.4
src/core/qgsattributeaction.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines