QGIS API Documentation  2.5.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgsfieldmodel.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsfieldmodel.cpp
3  --------------------------------------
4  Date : 01.04.2014
5  Copyright : (C) 2014 Denis Rouzaud
6  Email : denis.rouzaud@gmail.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 <QFont>
17 
18 #include "qgsfieldmodel.h"
19 #include "qgsmaplayermodel.h"
20 #include "qgsmaplayerproxymodel.h"
21 #include "qgslogger.h"
22 
23 
24 QgsFieldModel::QgsFieldModel( QObject *parent )
25  : QAbstractItemModel( parent )
26  , mLayer( NULL )
27  , mAllowExpression( false )
28 {
29 }
30 
31 QModelIndex QgsFieldModel::indexFromName( const QString &fieldName )
32 {
33  int r = mFields.indexFromName( fieldName );
34  QModelIndex idx = index( r, 0 );
35  if ( idx.isValid() )
36  {
37  return idx;
38  }
39 
40  if ( mAllowExpression )
41  {
42  int exprIdx = mExpression.indexOf( fieldName );
43  if ( exprIdx != -1 )
44  {
45  return index( mFields.count() + exprIdx , 0 );
46  }
47  }
48 
49  return QModelIndex();
50 }
51 
52 bool QgsFieldModel::isField( const QString& expression )
53 {
54  int index = mFields.indexFromName( expression );
55  return index >= 0;
56 }
57 
59 {
60  if ( mLayer )
61  {
62  disconnect( mLayer, SIGNAL( updatedFields() ), this, SLOT( updateModel() ) );
63  disconnect( mLayer, SIGNAL( layerDeleted() ), this, SLOT( layerDeleted() ) );
64  }
65 
66  if ( !layer )
67  {
68  mLayer = 0;
69  updateModel();
70  return;
71  }
72 
73  mLayer = layer;
74  connect( mLayer, SIGNAL( updatedFields() ), this, SLOT( updateModel() ) );
75  connect( mLayer, SIGNAL( layerDeleted() ), this, SLOT( layerDeleted() ) );
76  updateModel();
77 }
78 
80 {
81  mLayer = 0;
82  updateModel();
83 }
84 
86 {
87  if ( mLayer )
88  {
89  QgsFields newFields = mLayer->pendingFields();
90  if ( mFields.toList() != newFields.toList() )
91  {
92  // Try to handle two special cases: addition of a new field and removal of a field.
93  // It would be better to listen directly to attributeAdded/attributeDeleted
94  // so we would not have to check for addition/removal here.
95 
96  if ( mFields.count() == newFields.count() - 1 )
97  {
98  QgsFields tmpNewFields = newFields;
99  tmpNewFields.remove( tmpNewFields.count() - 1 );
100  if ( mFields.toList() == tmpNewFields.toList() )
101  {
102  // the only change is a new field at the end
103  beginInsertRows( QModelIndex(), mFields.count(), mFields.count() );
104  mFields = newFields;
105  endInsertRows();
106  return;
107  }
108  }
109 
110  if ( mFields.count() == newFields.count() + 1 )
111  {
112  QgsFields tmpOldFields = mFields;
113  tmpOldFields.remove( tmpOldFields.count() - 1 );
114  if ( tmpOldFields.toList() == newFields.toList() )
115  {
116  // the only change is a field removed at the end
117  beginRemoveRows( QModelIndex(), mFields.count() - 1, mFields.count() - 1 );
118  mFields = newFields;
119  endRemoveRows();
120  return;
121  }
122 
123  for ( int i = 0; i < newFields.count(); ++i )
124  {
125  if ( mFields.at( i ) != newFields.at( i ) )
126  {
127  QgsFields tmpOldFields = mFields;
128  tmpOldFields.remove( i );
129  if ( tmpOldFields.toList() != newFields.toList() )
130  break; // the change is more complex - go with general case
131 
132  // the only change is a field removed at index i
133  beginRemoveRows( QModelIndex(), i, i );
134  mFields = newFields;
135  endRemoveRows();
136  return;
137  }
138  }
139  }
140 
141  // general case with reset - not good - resets selections
142  beginResetModel();
144  endResetModel();
145  }
146  else
147  emit dataChanged( index( 0, 0 ), index( rowCount(), 0 ) );
148  }
149  else
150  {
151  beginResetModel();
152  mFields = QgsFields();
153  endResetModel();
154  }
155 }
156 
157 void QgsFieldModel::setAllowExpression( bool allowExpression )
158 {
159  if ( allowExpression == mAllowExpression )
160  return;
161 
163 
164  if ( !mAllowExpression )
165  {
166  int start = mFields.count();
167  int end = start + mExpression.count() - 1;
168  beginRemoveRows( QModelIndex(), start, end );
169  mExpression = QList<QString>();
170  endRemoveRows();
171  }
172 }
173 
174 void QgsFieldModel::setExpression( const QString &expression )
175 {
176  if ( !mAllowExpression )
177  return;
178 
179  QModelIndex idx = indexFromName( expression );
180  if ( idx.isValid() )
181  return;
182 
183  beginResetModel();
184  mExpression = QList<QString>();
185  if ( !expression.isEmpty() )
186  mExpression << expression;
187  endResetModel();
188 }
189 
191 {
192  beginResetModel();
193  mExpression = QList<QString>();
194  endResetModel();
195 }
196 
197 QModelIndex QgsFieldModel::index( int row, int column, const QModelIndex &parent ) const
198 {
199  if ( hasIndex( row, column, parent ) )
200  {
201  return createIndex( row, column, row );
202  }
203 
204  return QModelIndex();
205 }
206 
207 QModelIndex QgsFieldModel::parent( const QModelIndex &child ) const
208 {
209  Q_UNUSED( child );
210  return QModelIndex();
211 }
212 
213 int QgsFieldModel::rowCount( const QModelIndex &parent ) const
214 {
215  if ( parent.isValid() )
216  {
217  return 0;
218  }
219 
220  return mAllowExpression ? mFields.count() + mExpression.count() : mFields.count();
221 }
222 
223 int QgsFieldModel::columnCount( const QModelIndex &parent ) const
224 {
225  Q_UNUSED( parent );
226  return 1;
227 }
228 
229 QVariant QgsFieldModel::data( const QModelIndex &index, int role ) const
230 {
231  if ( !index.isValid() )
232  return QVariant();
233 
234  qint64 exprIdx = index.internalId() - mFields.count();
235 
236  switch ( role )
237  {
238  case FieldNameRole:
239  {
240  if ( exprIdx >= 0 )
241  {
242  return "";
243  }
244  QgsField field = mFields[index.internalId()];
245  return field.name();
246  }
247 
248  case ExpressionRole:
249  {
250  if ( exprIdx >= 0 )
251  {
252  return mExpression[exprIdx];
253  }
254  else
255  {
256  QgsField field = mFields[index.internalId()];
257  return field.name();
258  }
259  }
260 
261  case FieldIndexRole:
262  {
263  if ( exprIdx >= 0 )
264  {
265  return QVariant();
266  }
267  return index.internalId();
268  }
269 
270  case IsExpressionRole:
271  {
272  return exprIdx >= 0;
273  }
274 
276  {
277  if ( exprIdx >= 0 )
278  {
279  QgsExpression exp( mExpression[exprIdx] );
280  exp.prepare( mLayer ? mLayer->pendingFields() : QgsFields() );
281  return !exp.hasParserError();
282  }
283  return true;
284  }
285 
286  case FieldTypeRole:
287  {
288  if ( exprIdx < 0 )
289  {
290  QgsField field = mFields[index.internalId()];
291  return ( int )field.type();
292  }
293  return QVariant();
294  }
295 
296  case Qt::DisplayRole:
297  case Qt::EditRole:
298  {
299  if ( exprIdx >= 0 )
300  {
301  return mExpression[exprIdx];
302  }
303  else if ( role == Qt::EditRole )
304  {
305  return mFields[index.internalId()].name();
306  }
307  else if ( mLayer )
308  {
309  return mLayer->attributeDisplayName( index.internalId() );
310  }
311  else
312  return QVariant();
313  }
314 
315  case Qt::ForegroundRole:
316  {
317  if ( exprIdx >= 0 )
318  {
319  // if expression, test validity
320  QgsExpression exp( mExpression[exprIdx] );
321  exp.prepare( mLayer ? mLayer->pendingFields() : QgsFields() );
322  if ( exp.hasParserError() )
323  {
324  return QBrush( QColor( Qt::red ) );
325  }
326  }
327  return QVariant();
328  }
329 
330  case Qt::FontRole:
331  {
332  if ( exprIdx >= 0 )
333  {
334  // if the line is an expression, set it as italic
335  QFont font = QFont();
336  font.setItalic( true );
337  return font;
338  }
339  return QVariant();
340  }
341 
342  default:
343  return QVariant();
344  }
345 }
QList< QgsField > toList() const
Utility function to return a list of QgsField instances.
Definition: qgsfield.cpp:178
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:89
const QString & name() const
Gets the name of the field.
Definition: qgsfield.cpp:58
static unsigned index
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
Definition: qgsexpression.h:96
bool prepare(const QgsFields &fields)
Get the expression ready for evaluation - find out column indexes.
QModelIndex parent(const QModelIndex &child) const
void setExpression(const QString &expression)
setExpression sets a single expression to be added after the fields at the end of the model ...
Container of fields for a vector layer.
Definition: qgsfield.h:163
const QgsField & at(int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfield.h:213
QgsVectorLayer * layer()
returns the currently used layer
Definition: qgsfieldmodel.h:68
bool isField(const QString &expression)
void removeExpression()
remove expressions from the model
QString attributeDisplayName(int attributeIndex) const
Convenience function that returns the attribute alias if defined or the field name else...
void setLayer(QgsVectorLayer *layer)
set the layer of whch fields are displayed
QVariant data(const QModelIndex &index, int role) const
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const
void setAllowExpression(bool allowExpression)
returns the currently used layer
int count() const
Return number of items.
Definition: qgsfield.h:200
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:33
bool mAllowExpression
Definition: qgsfieldmodel.h:85
void remove(int fieldIdx)
Remove a field with the given index.
Definition: qgsfield.cpp:164
int indexFromName(const QString &name) const
Look up field's index from name. Returns -1 on error.
Definition: qgsfield.h:227
int columnCount(const QModelIndex &parent) const
virtual void updateModel()
QgsFieldModel(QObject *parent=0)
QgsFieldModel creates a model to display the fields of a given layer.
QgsFields mFields
Definition: qgsfieldmodel.h:81
QList< QString > mExpression
Definition: qgsfieldmodel.h:82
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
QgsVectorLayer * mLayer
Definition: qgsfieldmodel.h:84
int rowCount(const QModelIndex &parent=QModelIndex()) const
QModelIndex indexFromName(const QString &fieldName)
return the index corresponding to a given fieldName
Represents a vector layer which manages a vector based data sets.
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
Definition: qgsfield.cpp:63
bool allowExpression()
Definition: qgsfieldmodel.h:55