QGIS API Documentation  2.9.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
qgsdatadefined.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsdatadefined.cpp - Data defined container class
3  --------------------------------------
4  Date : 9-May-2013
5  Copyright : (C) 2013 by Larry Shaffer
6  Email : larrys at dakcarto dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsdatadefined.h"
17 
18 #include "qgslogger.h"
19 #include "qgsexpression.h"
20 #include "qgsfield.h"
21 #include "qgsvectorlayer.h"
22 
24  bool useexpr,
25  const QString& expr,
26  const QString& field )
27  : mActive( active )
28  , mUseExpression( useexpr )
29  , mExpressionString( expr )
30  , mField( field )
31 {
32  mExpression = 0;
33  mExpressionPrepared = false;
34 }
35 
37  : mActive( bool( expression ) )
38  , mUseExpression( expression && expression->rootNode() && !dynamic_cast<const QgsExpression::NodeColumnRef*>( expression->rootNode() ) )
39  , mExpressionString( mUseExpression ? expression->expression() : "" )
40  , mField( !mUseExpression ? ( expression ? expression->expression() : "" ) : "" )
41 {
42  mExpression = 0;
43  mExpressionPrepared = false;
44 }
45 
47  : mExpression( 0 )
48  , mActive( other.isActive() )
49  , mUseExpression( other.useExpression() )
50  , mExpressionString( other.expressionString() )
51  , mField( other.field() )
52  , mExpressionParams( other.expressionParams() )
53  , mExpressionPrepared( false )
54 {
55 
56 }
57 
59 {
60  delete mExpression;
61 }
62 
64 {
65  return ( !mActive && !mUseExpression && mExpressionString.isEmpty() && mField.isEmpty() );
66 }
67 
68 void QgsDataDefined::setExpressionString( const QString &expr )
69 {
70  mExpressionString = expr;
71  mExpressionPrepared = false;
72 }
73 
75 {
76  if ( layer )
77  {
78  return prepareExpression( layer->pendingFields() );
79  }
80  else
81  {
82  //preparing expression without a layer set, so pass empty field list
83  QgsFields empty;
84  return prepareExpression( empty );
85  }
86 }
87 
89 {
90  if ( !mUseExpression || mExpressionString.isEmpty() )
91  {
92  return false;
93  }
94 
95  mExpression = new QgsExpression( mExpressionString );
96  if ( mExpression->hasParserError() )
97  {
98  QgsDebugMsg( "Parser error:" + mExpression->parserErrorString() );
99  return false;
100  }
101 
102  // setup expression parameters
103  QVariant scaleV = mExpressionParams.value( "scale" );
104  if ( scaleV.isValid() )
105  {
106  bool ok;
107  double scale = scaleV.toDouble( &ok );
108  if ( ok )
109  {
110  mExpression->setScale( scale );
111  }
112  }
113 
114  mExpression->prepare( fields );
115 
116  if ( mExpression->hasEvalError() )
117  {
118  QgsDebugMsg( "Prepare error:" + mExpression->evalErrorString() );
119  return false;
120  }
121 
122  mExpressionPrepared = true;
123  mExprRefColumns = mExpression->referencedColumns();
124 
125  return true;
126 }
127 
129 {
130  if ( !mExprRefColumns.isEmpty() )
131  {
132  return mExprRefColumns;
133  }
134 
135  if ( mUseExpression )
136  {
137  if ( !mExpression || !mExpressionPrepared )
138  {
139  prepareExpression( layer );
140  }
141  }
142  else if ( !mField.isEmpty() )
143  {
144  mExprRefColumns << mField;
145  }
146 
147  return mExprRefColumns;
148 }
149 
150 void QgsDataDefined::insertExpressionParam( QString key, QVariant param )
151 {
152  mExpressionParams.insert( key, param );
153 }
154 
155 QMap< QString, QString > QgsDataDefined::toMap()
156 {
157  QMap< QString, QString > map;
158  map.insert( "active", ( mActive ? "1" : "0" ) );
159  map.insert( "useexpr", ( mUseExpression ? "1" : "0" ) );
160  map.insert( "expression", mExpressionString );
161  map.insert( "field", mField );
162 
163  return map;
164 }
165 
166 QDomElement QgsDataDefined::toXmlElement( QDomDocument &document, const QString& elementName ) const
167 {
168  QDomElement element = document.createElement( elementName );
169  element.setAttribute( "active", mActive ? "true" : "false" );
170  element.setAttribute( "useExpr", mUseExpression ? "true" : "false" );
171  element.setAttribute( "expr", mExpressionString );
172  element.setAttribute( "field", mField );
173  return element;
174 }
175 
176 bool QgsDataDefined::setFromXmlElement( const QDomElement &element )
177 {
178  if ( element.isNull() )
179  {
180  return false;
181  }
182 
183  mActive = element.attribute( "active" ).compare( "true", Qt::CaseInsensitive ) == 0;
184  mUseExpression = element.attribute( "useExpr" ).compare( "true", Qt::CaseInsensitive ) == 0;
185  mField = element.attribute( "field" );
186  setExpressionString( element.attribute( "expr" ) );
187  return true;
188 }
189 
190 bool QgsDataDefined::operator==( const QgsDataDefined &other ) const
191 {
192  return other.isActive() == mActive && other.useExpression() == mUseExpression &&
193  other.field() == mField && other.expressionString() == mExpressionString;
194 }
195 
196 bool QgsDataDefined::operator!=( const QgsDataDefined &other ) const
197 {
198  return !( *this == other );
199 }
200 
202 {
203  if ( &rhs == this )
204  return *this;
205 
206  delete mExpression;
207  mExpression = 0;
208  mActive = rhs.isActive();
209  mUseExpression = rhs.useExpression();
210  mExpressionString = rhs.expressionString();
211  mField = rhs.field();
212  mExpressionParams = rhs.expressionParams();
213  mExpressionPrepared = false;
214  mExprRefColumns.clear();
215  return *this;
216 }
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:86
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
QgsDataDefined & operator=(QgsDataDefined const &rhs)
Assignment operator.
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
Definition: qgsexpression.h:93
QStringList referencedColumns() const
Get list of columns referenced by the expression.
A container class for data source field mapping or expression.
bool operator!=(const QgsDataDefined &other) const
QString field() const
bool prepare(const QgsFields &fields)
Get the expression ready for evaluation - find out column indexes.
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
void insertExpressionParam(QString key, QVariant param)
Container of fields for a vector layer.
Definition: qgsfield.h:172
QString expressionString() const
bool setFromXmlElement(const QDomElement &element)
Sets the properties of the data defined container from an XML element.
QMap< QString, QString > toMap()
QDomElement toXmlElement(QDomDocument &document, const QString &elementName) const
Returns a DOM element containing the properties of the data defined container.
bool operator==(const QgsDataDefined &other) const
QMap< QString, QVariant > expressionParams() const
bool useExpression() const
QgsDataDefined(bool active=false, bool useexpr=false, const QString &expr=QString(), const QString &field=QString())
Construct a new data defined object.
bool prepareExpression(QgsVectorLayer *layer)
Prepares the expression using a vector layer.
bool hasDefaultValues() const
Returns whether the data defined container is set to all the default values, ie, disabled, with empty expression and no assigned field.
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
void setScale(double scale)
Represents a vector layer which manages a vector based data sets.
QString parserErrorString() const
Returns parser error.
Definition: qgsexpression.h:95
QString evalErrorString() const
Returns evaluation error.
void setExpressionString(const QString &expr)
bool isActive() const
QStringList referencedColumns(QgsVectorLayer *layer)