~ubuntu-branches/ubuntu/hardy/qgis/hardy

« back to all changes in this revision

Viewing changes to src/qgsattributeaction.cpp

  • Committer: Bazaar Package Importer
  • Author(s): William Grant
  • Date: 2007-05-06 13:42:32 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20070506134232-pyli6t388w5asd8x
Tags: 0.8.0-3ubuntu1
* Merge from Debian unstable. Remaining Ubuntu changes:
  - debian/rules, debian/qgis.install, debian/qgis.dirs debian/qgis.desktop:
    Add and install .desktop.
* debian/qgis.desktop: Remove Applications category; it's not real.
* Modify Maintainer value to match Debian-Maintainer-Field Spec

Show diffs side-by-side

added added

removed removed

Lines of Context:
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: qgsattributeaction.cpp,v 1.7 2005/01/19 23:59:10 g_j_m Exp $ */
25
 
 
26
 
#include <iostream>
27
 
#include <vector>
28
 
 
29
 
#include <qstringlist.h>
30
 
#include <qdom.h>
31
 
 
32
 
#include "qgsattributeaction.h"
33
 
#include "qgsrunprocess.h"
34
 
 
35
 
static const char * const ident_ = "$Id: qgsattributeaction.cpp,v 1.7 2005/01/19 23:59:10 g_j_m Exp $";
36
 
 
37
 
void QgsAttributeAction::addAction(QString name, QString action,
38
 
                                   bool capture)
39
 
{
40
 
  mActions.push_back(QgsAction(name, action, capture));
41
 
}
42
 
 
43
 
void QgsAttributeAction::doAction(unsigned int index, const std::vector<std::pair<QString, QString> >& values,
44
 
                                  int defaultValueIndex) 
45
 
{
46
 
  aIter action = retrieveAction(index);
47
 
 
48
 
  // A couple of extra options for running the action may be
49
 
  // useful. For example,
50
 
  // - run the action inside a terminal (on unix)
51
 
  // - capture the stdout from the process and display in a dialog
52
 
  //   box
53
 
  //
54
 
  // The capture stdout one is partially implemented. It just needs
55
 
  // the UI and the code in this function to select on the
56
 
  // action.capture() return value.
57
 
 
58
 
  if (action != end())
59
 
  {
60
 
    // The action will be divided into separate arguments that are
61
 
    // passed to a QProcess instance. Spaces are used to delimit
62
 
    // arguments, except for spaces inside pairs of ". A \" will be
63
 
    // replaced by a ". The replacement of the %field_name is done
64
 
    // after the parsing into arguments.
65
 
    bool in_quote = false;
66
 
    QStringList args;
67
 
    QString current_arg;
68
 
    QString cmd = action->action();
69
 
    for (int i = 0; i < cmd.length(); ++i)
70
 
    {
71
 
      // Deal with \"
72
 
      if (i < cmd.length()-1 && cmd[i] == '\\' && cmd[i+1] == '\"')
73
 
      {
74
 
        current_arg += '\"';
75
 
        ++i;
76
 
      }
77
 
      // Found a delimiter, create a new argument
78
 
      else if (cmd[i].isSpace() && !in_quote && current_arg.length() > 0)
79
 
      {
80
 
        QString strippedCmd = current_arg.stripWhiteSpace();
81
 
        if (strippedCmd.length() > 0)
82
 
          args << expandAction(strippedCmd, values, defaultValueIndex);
83
 
        current_arg = "";
84
 
      }
85
 
      // Starting a new quote
86
 
      else if (cmd[i] == '\"' && !in_quote)
87
 
        in_quote = true;
88
 
      // Ending a quote
89
 
      else if (cmd[i] == '\"' && in_quote)
90
 
        in_quote = false;
91
 
      else
92
 
        current_arg += cmd[i];
93
 
    }
94
 
 
95
 
    // Pick up the last argument if it has something of interest
96
 
    if (!current_arg.stripWhiteSpace().isEmpty())
97
 
      args << expandAction(current_arg.stripWhiteSpace(), values, defaultValueIndex);
98
 
 
99
 
    // The QgsRunProcess instance created by this static function
100
 
    // deletes itself when no longer needed.
101
 
    QgsRunProcess::create(args, action->capture());
102
 
  }
103
 
}
104
 
 
105
 
QgsAttributeAction::aIter QgsAttributeAction::retrieveAction(unsigned int index) const
106
 
{
107
 
  // This function returns an iterator so that it's easy to deal with
108
 
  // an invalid index being given.
109
 
  aIter a_iter = end();
110
 
 
111
 
  if (index >= 0 && index < mActions.size())
112
 
  {
113
 
    a_iter = mActions.begin();
114
 
    for (int i = 0; i < index; ++i, ++a_iter)
115
 
      {}
116
 
  }
117
 
  return a_iter;
118
 
}
119
 
 
120
 
QString QgsAttributeAction::expandAction(QString action, const std::vector<std::pair<QString, QString> >& values, 
121
 
                                         int clickedOnValue)
122
 
{
123
 
  // This function currently replaces all %% characters in the action
124
 
  // with the value from values[clickedOnValue].second, and then
125
 
  // searches for all strings that go %attribite_name, where
126
 
  // attribute_name is found in values[x].first, and replaces any that
127
 
  // it finds by values[s].second.
128
 
 
129
 
  // Additional substitutions could include symbols for $CWD, $HOME,
130
 
  // etc (and their OSX and Windows equivalents)
131
 
 
132
 
  // This function will potentially fall apart if any of the
133
 
  // substitutions produce text that could match another
134
 
  // substitution. May be better to adopt a two pass approach - identify
135
 
  // all matches and their substitutions and then do a second pass 
136
 
  // for the actual substitutions.
137
 
 
138
 
  QString expanded_action;
139
 
  if (clickedOnValue >= 0 && clickedOnValue < values.size())
140
 
    expanded_action = action.replace("%%", values[clickedOnValue].second);
141
 
  else
142
 
    expanded_action = action;
143
 
 
144
 
  for (int i = 0; i < values.size(); ++i)
145
 
    {
146
 
      QString to_replace = "%" + values[i].first;
147
 
      expanded_action = expanded_action.replace(to_replace, values[i].second);
148
 
    }
149
 
 
150
 
  return expanded_action;
151
 
}
152
 
 
153
 
bool QgsAttributeAction::writeXML(QDomNode& layer_node, QDomDocument& doc) const
154
 
{
155
 
  QDomElement aActions = doc.createElement("attributeactions");
156
 
 
157
 
  aIter a_iter = begin();
158
 
 
159
 
  for (; a_iter != end(); ++a_iter)
160
 
  {
161
 
    QDomElement actionSetting = doc.createElement("actionsetting");
162
 
    actionSetting.setAttribute("name", a_iter->name());
163
 
    actionSetting.setAttribute("action", a_iter->action());
164
 
    actionSetting.setAttribute("capture", a_iter->capture());
165
 
    aActions.appendChild(actionSetting);
166
 
  }
167
 
  layer_node.appendChild(aActions);
168
 
 
169
 
  return true;
170
 
}
171
 
 
172
 
bool QgsAttributeAction::readXML(QDomNode& layer_node)
173
 
{
174
 
  QDomNode aaNode = layer_node.namedItem("attributeactions");
175
 
 
176
 
  if (!aaNode.isNull())
177
 
  {
178
 
    QDomNodeList actionsettings = aaNode.childNodes();
179
 
    for (int i = 0; i < actionsettings.length(); ++i)
180
 
    {
181
 
      QDomElement setting = actionsettings.item(i).toElement();
182
 
      int capture = setting.attributeNode("capture").value().toInt();
183
 
      addAction(setting.attributeNode("name").value(),
184
 
                setting.attributeNode("action").value(),
185
 
                capture == 0 ? false : true);
186
 
    }
187
 
  }
188
 
  return true;
189
 
}
190