QGIS API Documentation  2.7.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules 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  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
115  beginInsertRows( QModelIndex(), mFields.count(), mFields.count() );
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
129  beginRemoveRows( QModelIndex(), mFields.count() - 1, mFields.count() - 1 );
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 );
181  mExpression = QList<QString>();
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();
196  mExpression = QList<QString>();
197  if ( !expression.isEmpty() )
198  mExpression << expression;
199  endResetModel();
200 }
201 
203 {
204  beginResetModel();
205  mExpression = QList<QString>();
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 
219 QModelIndex QgsFieldModel::parent( const QModelIndex &child ) const
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 
232  return mAllowExpression ? mFields.count() + mExpression.count() : mFields.count();
233 }
234 
235 int QgsFieldModel::columnCount( const QModelIndex &parent ) const
236 {
237  Q_UNUSED( parent );
238  return 1;
239 }
240 
241 QVariant QgsFieldModel::data( const QModelIndex &index, int role ) const
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 }
QList< QgsField > toList() const
Utility function to return a list of QgsField instances.
Definition: qgsfield.cpp:200
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:87
const QString & name() const
Gets the name of the field.
Definition: qgsfield.cpp:59
static unsigned index
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
Definition: qgsexpression.h:94
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:172
const QgsField & at(int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfield.h:227
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:214
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:33
bool mAllowExpression
Definition: qgsfieldmodel.h:85
const QMap< QString, QString > & attributeAliases() const
void remove(int fieldIdx)
Remove a field with the given index.
Definition: qgsfield.cpp:186
int indexFromName(const QString &name) const
Look up field's index from name. Returns -1 on error.
Definition: qgsfield.h:241
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:64
bool allowExpression()
Definition: qgsfieldmodel.h:55