QGIS API Documentation  2.11.0-Master
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 
25  : QAbstractItemModel( parent )
26  , mLayer( NULL )
27  , mAllowExpression( false )
28 {
29 }
30 
32 {
33  QString fldName( fieldName ); // we may need a copy
34 
35  if ( mLayer )
36  {
37  // the name could be an alias
38  // it would be better to have "display name" directly in QgsFields
39  // rather than having to consult layer in various places in code!
40  QString fieldNameWithAlias = mLayer->attributeAliases().key( fldName );
41  if ( !fieldNameWithAlias.isNull() )
42  fldName = fieldNameWithAlias;
43  }
44 
45  int r = mFields.indexFromName( fldName );
46  QModelIndex idx = index( r, 0 );
47  if ( idx.isValid() )
48  {
49  return idx;
50  }
51 
52  if ( mAllowExpression )
53  {
54  int exprIdx = mExpression.indexOf( fldName );
55  if ( exprIdx != -1 )
56  {
57  return index( mFields.count() + exprIdx, 0 );
58  }
59  }
60 
61  return QModelIndex();
62 }
63 
64 bool QgsFieldModel::isField( const QString& expression )
65 {
66  int index = mFields.indexFromName( expression );
67  return index >= 0;
68 }
69 
71 {
72  if ( mLayer )
73  {
74  disconnect( mLayer, SIGNAL( updatedFields() ), this, SLOT( updateModel() ) );
75  disconnect( mLayer, SIGNAL( layerDeleted() ), this, SLOT( layerDeleted() ) );
76  }
77 
78  if ( !layer )
79  {
80  mLayer = 0;
81  updateModel();
82  return;
83  }
84 
85  mLayer = layer;
86  connect( mLayer, SIGNAL( updatedFields() ), this, SLOT( updateModel() ) );
87  connect( mLayer, SIGNAL( layerDeleted() ), this, SLOT( layerDeleted() ) );
88  updateModel();
89 }
90 
91 void QgsFieldModel::layerDeleted()
92 {
93  mLayer = 0;
94  updateModel();
95 }
96 
98 {
99  if ( mLayer )
100  {
101  QgsFields newFields = mLayer->pendingFields();
102  if ( mFields.toList() != newFields.toList() )
103  {
104  // Try to handle two special cases: addition of a new field and removal of a field.
105  // It would be better to listen directly to attributeAdded/attributeDeleted
106  // so we would not have to check for addition/removal here.
107 
108  if ( mFields.count() == newFields.count() - 1 )
109  {
110  QgsFields tmpNewFields = newFields;
111  tmpNewFields.remove( tmpNewFields.count() - 1 );
112  if ( mFields.toList() == tmpNewFields.toList() )
113  {
114  // the only change is a new field at the end
116  mFields = newFields;
117  endInsertRows();
118  return;
119  }
120  }
121 
122  if ( mFields.count() == newFields.count() + 1 )
123  {
124  QgsFields tmpOldFields = mFields;
125  tmpOldFields.remove( tmpOldFields.count() - 1 );
126  if ( tmpOldFields.toList() == newFields.toList() )
127  {
128  // the only change is a field removed at the end
130  mFields = newFields;
131  endRemoveRows();
132  return;
133  }
134 
135  for ( int i = 0; i < newFields.count(); ++i )
136  {
137  if ( mFields.at( i ) != newFields.at( i ) )
138  {
139  QgsFields tmpOldFields = mFields;
140  tmpOldFields.remove( i );
141  if ( tmpOldFields.toList() != newFields.toList() )
142  break; // the change is more complex - go with general case
143 
144  // the only change is a field removed at index i
145  beginRemoveRows( QModelIndex(), i, i );
146  mFields = newFields;
147  endRemoveRows();
148  return;
149  }
150  }
151  }
152 
153  // general case with reset - not good - resets selections
154  beginResetModel();
156  endResetModel();
157  }
158  else
159  emit dataChanged( index( 0, 0 ), index( rowCount(), 0 ) );
160  }
161  else
162  {
163  beginResetModel();
164  mFields = QgsFields();
165  endResetModel();
166  }
167 }
168 
169 void QgsFieldModel::setAllowExpression( bool allowExpression )
170 {
171  if ( allowExpression == mAllowExpression )
172  return;
173 
175 
176  if ( !mAllowExpression )
177  {
178  int start = mFields.count();
179  int end = start + mExpression.count() - 1;
180  beginRemoveRows( QModelIndex(), start, end );
182  endRemoveRows();
183  }
184 }
185 
186 void QgsFieldModel::setExpression( const QString &expression )
187 {
188  if ( !mAllowExpression )
189  return;
190 
191  QModelIndex idx = indexFromName( expression );
192  if ( idx.isValid() )
193  return;
194 
195  beginResetModel();
197  if ( !expression.isEmpty() )
198  mExpression << expression;
199  endResetModel();
200 }
201 
203 {
204  beginResetModel();
206  endResetModel();
207 }
208 
209 QModelIndex QgsFieldModel::index( int row, int column, const QModelIndex &parent ) const
210 {
211  if ( hasIndex( row, column, parent ) )
212  {
213  return createIndex( row, column, row );
214  }
215 
216  return QModelIndex();
217 }
218 
220 {
221  Q_UNUSED( child );
222  return QModelIndex();
223 }
224 
225 int QgsFieldModel::rowCount( const QModelIndex &parent ) const
226 {
227  if ( parent.isValid() )
228  {
229  return 0;
230  }
231 
233 }
234 
235 int QgsFieldModel::columnCount( const QModelIndex &parent ) const
236 {
237  Q_UNUSED( parent );
238  return 1;
239 }
240 
242 {
243  if ( !index.isValid() )
244  return QVariant();
245 
246  int exprIdx = index.row() - mFields.count();
247 
248  switch ( role )
249  {
250  case FieldNameRole:
251  {
252  if ( exprIdx >= 0 )
253  {
254  return "";
255  }
256  QgsField field = mFields[index.row()];
257  return field.name();
258  }
259 
260  case ExpressionRole:
261  {
262  if ( exprIdx >= 0 )
263  {
264  return mExpression[exprIdx];
265  }
266  else
267  {
268  QgsField field = mFields[index.row()];
269  return field.name();
270  }
271  }
272 
273  case FieldIndexRole:
274  {
275  if ( exprIdx >= 0 )
276  {
277  return QVariant();
278  }
279  return index.row();
280  }
281 
282  case IsExpressionRole:
283  {
284  return exprIdx >= 0;
285  }
286 
288  {
289  if ( exprIdx >= 0 )
290  {
291  QgsExpression exp( mExpression[exprIdx] );
292  exp.prepare( mLayer ? mLayer->pendingFields() : QgsFields() );
293  return !exp.hasParserError();
294  }
295  return true;
296  }
297 
298  case FieldTypeRole:
299  {
300  if ( exprIdx < 0 )
301  {
302  QgsField field = mFields[index.row()];
303  return ( int )field.type();
304  }
305  return QVariant();
306  }
307 
308  case Qt::DisplayRole:
309  case Qt::EditRole:
310  {
311  if ( exprIdx >= 0 )
312  {
313  return mExpression[exprIdx];
314  }
315  else if ( role == Qt::EditRole )
316  {
317  return mFields[index.row()].name();
318  }
319  else if ( mLayer )
320  {
321  return mLayer->attributeDisplayName( index.row() );
322  }
323  else
324  return QVariant();
325  }
326 
327  case Qt::ForegroundRole:
328  {
329  if ( exprIdx >= 0 )
330  {
331  // if expression, test validity
332  QgsExpression exp( mExpression[exprIdx] );
333  exp.prepare( mLayer ? mLayer->pendingFields() : QgsFields() );
334  if ( exp.hasParserError() )
335  {
336  return QBrush( QColor( Qt::red ) );
337  }
338  }
339  return QVariant();
340  }
341 
342  case Qt::FontRole:
343  {
344  if ( exprIdx >= 0 )
345  {
346  // if the line is an expression, set it as italic
347  QFont font = QFont();
348  font.setItalic( true );
349  return font;
350  }
351  return QVariant();
352  }
353 
354  default:
355  return QVariant();
356  }
357 }
bool hasIndex(int row, int column, const QModelIndex &parent) const
QList< QgsField > toList() const
Utility function to return a list of QgsField instances.
Definition: qgsfield.cpp:341
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:86
const QString & name() const
Gets the name of the field.
Definition: qgsfield.cpp:69
static unsigned index
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
Definition: qgsexpression.h:93
bool prepare(const QgsFields &fields)
Get the expression ready for evaluation - find out column indexes.
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:173
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
QgsVectorLayer * layer()
returns the currently used layer
Definition: qgsfieldmodel.h:68
bool isField(const QString &expression)
bool isNull() const
int indexOf(const T &value, int from) const
QVariant data(const QModelIndex &index, int role) const override
bool isValid() const
int count(const T &value) const
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
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...
bool isEmpty() const
void beginRemoveRows(const QModelIndex &parent, int first, int last)
void setLayer(QgsVectorLayer *layer)
set the layer of whch fields are displayed
int row() const
void setAllowExpression(bool allowExpression)
returns the currently used layer
int rowCount(const QModelIndex &parent=QModelIndex()) const override
int count() const
Return number of items.
Definition: qgsfield.cpp:283
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:38
bool mAllowExpression
Definition: qgsfieldmodel.h:85
const QMap< QString, QString > & attributeAliases() const
const QgsField & at(int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfield.cpp:303
void remove(int fieldIdx)
Remove a field with the given index.
Definition: qgsfield.cpp:257
QModelIndex createIndex(int row, int column, void *ptr) const
int indexFromName(const QString &name) const
Look up field's index from name. Returns -1 on error.
Definition: qgsfield.cpp:336
void setItalic(bool enable)
void beginInsertRows(const QModelIndex &parent, int first, int last)
const Key key(const T &value) const
int columnCount(const QModelIndex &parent) const override
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
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
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
QModelIndex indexFromName(const QString &fieldName)
return the index corresponding to a given fieldName
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const
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:74
bool allowExpression()
Definition: qgsfieldmodel.h:55