QGIS API Documentation  2.13.0-Master
qgsfeaturelistmodel.cpp
Go to the documentation of this file.
1 #include "qgsexception.h"
3 #include "qgsfeaturelistmodel.h"
7 
8 #include <QItemSelection>
9 #include <QSettings>
10 
12  : QAbstractProxyModel( parent )
13  , mInjectNull( false )
14 {
15  setSourceModel( sourceModel );
16  mExpression = new QgsExpression( "" );
17 }
18 
20 {
21  delete mExpression;
22 }
23 
25 {
27  mFilterModel = sourceModel;
28  if ( mFilterModel )
29  {
30  // rewire (filter-)change events in the source model so this proxy reflects the changes
31  connect( mFilterModel, SIGNAL( rowsAboutToBeRemoved( const QModelIndex&, int, int ) ), SLOT( onBeginRemoveRows( const QModelIndex&, int, int ) ) );
32  connect( mFilterModel, SIGNAL( rowsRemoved( const QModelIndex&, int, int ) ), SLOT( onEndRemoveRows( const QModelIndex&, int, int ) ) );
33  connect( mFilterModel, SIGNAL( rowsAboutToBeInserted( const QModelIndex&, int, int ) ), SLOT( onBeginInsertRows( const QModelIndex&, int, int ) ) );
34  connect( mFilterModel, SIGNAL( rowsInserted( const QModelIndex&, int, int ) ), SLOT( onEndInsertRows( const QModelIndex&, int, int ) ) );
35  // propagate sort order changes from source model to views connected to this model
36  connect( mFilterModel, SIGNAL( layoutAboutToBeChanged() ), this, SIGNAL( layoutAboutToBeChanged() ) );
37  connect( mFilterModel, SIGNAL( layoutChanged() ), this, SIGNAL( layoutChanged() ) );
38  }
39 }
40 
42 {
43  return mFilterModel->layerCache();
44 }
45 
47 {
48  return mFilterModel->masterModel()->rowToId( mapToMaster( index ).row() );
49 }
50 
52 {
53  return mFilterModel->mapFromMaster( mFilterModel->masterModel()->idToIndex( fid ) );
54 }
55 
57 {
58  if ( mInjectNull && index.row() == 0 )
59  {
60  if ( role == Qt::DisplayRole )
61  {
62  return QSettings().value( "qgis/nullValue", "NULL" ).toString();
63  }
64  else
65  {
66  return QVariant( QVariant::Int );
67  }
68  }
69 
70  if ( role == Qt::DisplayRole || role == Qt::EditRole )
71  {
72  QgsFeature feat;
73 
74  mFilterModel->layerCache()->featureAtId( idxToFid( index ), feat );
75 
76  QgsExpressionContext context;
79  << QgsExpressionContextUtils::layerScope( mFilterModel->layer() );
80  context.setFeature( feat );
81  return mExpression->evaluate( &context );
82  }
83 
84  if ( role == FeatureInfoRole )
85  {
86  FeatureInfo featInfo;
87 
88  QgsFeature feat;
89 
90  mFilterModel->layerCache()->featureAtId( idxToFid( index ), feat );
91 
92  QgsVectorLayerEditBuffer* editBuffer = mFilterModel->layer()->editBuffer();
93 
94  if ( editBuffer )
95  {
96  const QList<QgsFeatureId> addedFeatures = editBuffer->addedFeatures().keys();
97  const QList<QgsFeatureId> changedFeatures = editBuffer->changedAttributeValues().keys();
98 
99  if ( addedFeatures.contains( feat.id() ) )
100  {
101  featInfo.isNew = true;
102  }
103  if ( changedFeatures.contains( feat.id() ) )
104  {
105  featInfo.isEdited = true;
106  }
107  }
108 
109  return QVariant::fromValue( featInfo );
110  }
111  else if ( role == FeatureRole )
112  {
113  QgsFeature feat;
114 
115  mFilterModel->layerCache()->featureAtId( idxToFid( index ), feat );
116 
117  return QVariant::fromValue( feat );
118  }
119 
120  return sourceModel()->data( mapToSource( index ), role );
121 }
122 
124 {
125  return sourceModel()->flags( mapToSource( index ) ) & ~Qt::ItemIsEditable;
126 }
127 
128 void QgsFeatureListModel::setInjectNull( bool injectNull )
129 {
130  if ( mInjectNull != injectNull )
131  {
132  emit beginResetModel();
133  mInjectNull = injectNull;
134  emit endResetModel();
135  }
136 }
137 
139 {
140  return mInjectNull;
141 }
142 
144 {
145  return mFilterModel->masterModel();
146 }
147 
149 {
150  QgsExpression* exp = new QgsExpression( expression );
151 
152  QgsExpressionContext context;
155  << QgsExpressionContextUtils::layerScope( mFilterModel->layer() );
156 
157  exp->prepare( &context );
158 
159  if ( exp->hasParserError() )
160  {
161  mParserErrorString = exp->parserErrorString();
162  delete exp;
163  return false;
164  }
165 
166  delete mExpression;
167  mExpression = exp;
168 
169  emit dataChanged( index( 0, 0 ), index( rowCount() - 1, 0 ) );
170  return true;
171 }
172 
174 {
175  return mParserErrorString;
176 }
177 
179 {
180  return mExpression->expression();
181 }
182 
184 {
185  return mFilterModel->layerCache()->featureAtId( idxToFid( index ), feat );
186 }
187 
188 void QgsFeatureListModel::onBeginRemoveRows( const QModelIndex& parent, int first, int last )
189 {
190  beginRemoveRows( parent, first, last );
191 }
192 
193 void QgsFeatureListModel::onEndRemoveRows( const QModelIndex& parent, int first, int last )
194 {
195  Q_UNUSED( parent )
196  Q_UNUSED( first )
197  Q_UNUSED( last )
198  endRemoveRows();
199 }
200 
201 void QgsFeatureListModel::onBeginInsertRows( const QModelIndex& parent, int first, int last )
202 {
203  beginInsertRows( parent, first, last );
204 }
205 
206 void QgsFeatureListModel::onEndInsertRows( const QModelIndex& parent, int first, int last )
207 {
208  Q_UNUSED( parent )
209  Q_UNUSED( first )
210  Q_UNUSED( last )
211  endInsertRows();
212 }
213 
215 {
216  if ( !proxyIndex.isValid() )
217  return QModelIndex();
218 
219  int offset = mInjectNull ? 1 : 0;
220 
221  return mFilterModel->mapToMaster( mFilterModel->index( proxyIndex.row() - offset, proxyIndex.column() ) );
222 }
223 
225 {
226  if ( !sourceIndex.isValid() )
227  return QModelIndex();
228 
229  int offset = mInjectNull ? 1 : 0;
230 
231  return createIndex( mFilterModel->mapFromMaster( sourceIndex ).row() + offset, 0 );
232 }
233 
235 {
236  return mapSelectionFromSource( mFilterModel->mapSelectionFromSource( selection ) );
237 }
238 
240 {
241  return mFilterModel->mapSelectionToSource( mapSelectionToSource( selection ) );
242 }
243 
244 // Override some methods from QAbstractProxyModel, not that interesting
245 
247 {
248  if ( !proxyIndex.isValid() )
249  return QModelIndex();
250 
251  int offset = mInjectNull ? 1 : 0;
252 
253  return sourceModel()->index( proxyIndex.row() - offset, proxyIndex.column() );
254 }
255 
257 {
258  if ( !sourceIndex.isValid() )
259  return QModelIndex();
260 
261  return createIndex( sourceIndex.row(), 0 );
262 }
263 
264 QModelIndex QgsFeatureListModel::index( int row, int column, const QModelIndex& parent ) const
265 {
266  Q_UNUSED( parent )
267 
268  return createIndex( row, column );
269 }
270 
272 {
273  Q_UNUSED( child )
274  return QModelIndex();
275 }
276 
278 {
279  Q_UNUSED( parent )
280  return 1;
281 }
282 
283 int QgsFeatureListModel::rowCount( const QModelIndex& parent ) const
284 {
285  Q_UNUSED( parent )
286 
287  int offset = mInjectNull ? 1 : 0;
288 
289  return sourceModel()->rowCount() + offset;
290 }
291 
293 {
294  return mapFromMaster( masterModel()->idToIndex( fid ) );
295 }
296 
298 {
299  return QModelIndexList() << fidToIndex( fid );
300 }
QgsFeatureId id() const
Get the feature ID for this feature.
Definition: qgsfeature.cpp:65
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const
bool injectNull()
Returns the current state of null value injection.
Class for parsing and evaluation of expressions (formerly called "search strings").
QModelIndex fidToIndex(QgsFeatureId fid) override
static unsigned index
virtual int rowCount(const QModelIndex &parent) const =0
virtual QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const =0
Q_DECL_DEPRECATED QVariant evaluate(const QgsFeature *f)
Evaluate the feature and return the result.
bool setDisplayExpression(const QString &expression)
Q_DECL_DEPRECATED bool prepare(const QgsFields &fields)
Get the expression ready for evaluation - find out column indexes.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
virtual QModelIndex mapToMaster(const QModelIndex &proxyIndex) const
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const override
virtual int columnCount(const QModelIndex &parent=QModelIndex()) const override
const QgsChangedAttributesMap & changedAttributeValues()
Changed attributes values which are not commited.
virtual QItemSelection mapSelectionFromSource(const QItemSelection &sourceSelection) const
void onEndInsertRows(const QModelIndex &parent, int first, int last)
QModelIndex idToIndex(QgsFeatureId id) const
bool featureByIndex(const QModelIndex &index, QgsFeature &feat)
virtual QItemSelection mapSelectionFromSource(const QItemSelection &sourceSelection) const
virtual QModelIndex mapFromMaster(const QModelIndex &sourceIndex) const
virtual QItemSelection mapSelectionToMaster(const QItemSelection &selection) const
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:187
A model backed by a QgsVectorLayerCache which is able to provide feature/attribute information to a Q...
void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
QString parserErrorString()
Returns a detailed message about errors while parsing a QgsExpression.
virtual void setSourceModel(QgsAttributeTableFilterModel *sourceModel)
void onBeginInsertRows(const QModelIndex &parent, int first, int last)
virtual QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
QgsVectorLayer * layer() const
Returns the layer this filter acts on.
QList< Key > keys() const
void layoutAboutToBeChanged()
bool isValid() const
QgsVectorLayerEditBuffer * editBuffer()
Buffer with uncommitted editing operations. Only valid after editing has been turned on...
void rowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
QgsVectorLayerCache * layerCache() const
Returns the layerCache this filter acts on.
virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const override
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
virtual QModelIndex mapToMaster(const QModelIndex &proxyIndex) const
virtual QVariant data(const QModelIndex &index, int role) const override
virtual QItemSelection mapSelectionToSource(const QItemSelection &proxySelection) const
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void beginRemoveRows(const QModelIndex &parent, int first, int last)
int row() const
QModelIndexList fidToIndexList(QgsFeatureId fid)
virtual void setSourceModel(QAbstractItemModel *sourceModel)
virtual QVariant data(const QModelIndex &index, int role) const =0
virtual Qt::ItemFlags flags(const QModelIndex &index) const override
void rowsRemoved(const QModelIndex &parent, int start, int end)
QModelIndex createIndex(int row, int column, void *ptr) const
QgsAttributeTableModel * masterModel()
virtual QItemSelection mapSelectionToSource(const QItemSelection &proxySelection) const
void onBeginRemoveRows(const QModelIndex &parent, int first, int last)
This class caches features of a given QgsVectorLayer.
bool contains(const T &value) const
QVariant fromValue(const T &value)
void beginInsertRows(const QModelIndex &parent, int first, int last)
const QgsFeatureMap & addedFeatures()
New features which are not commited.
QVariant value(const QString &key, const QVariant &defaultValue) const
QAbstractItemModel * sourceModel() const
QgsAttributeTableModel * masterModel() const
Returns the table model this filter is using.
virtual QModelIndex mapFromMaster(const QModelIndex &sourceIndex) const
bool featureAtId(QgsFeatureId featureId, QgsFeature &feature, bool skipCache=false)
Gets the feature at the given feature id.
QgsFeatureId idxToFid(const QModelIndex &index) const
int column() const
qint64 QgsFeatureId
Definition: qgsfeature.h:31
void onEndRemoveRows(const QModelIndex &parent, int first, int last)
QString expression() const
Return the original, unmodified expression string.
QgsVectorLayerCache * layerCache()
virtual Qt::ItemFlags flags(const QModelIndex &index) const
void setInjectNull(bool injectNull)
If true is specified, a NULL value will be injected.
QgsFeatureId rowToId(int row) const
Maps row to feature id.
static QgsExpressionContextScope * projectScope()
Creates a new scope which contains variables and functions relating to the current QGIS project...
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
void rowsInserted(const QModelIndex &parent, int start, int end)
QModelIndex fidToIdx(const QgsFeatureId fid) const
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const
QString parserErrorString() const
Returns parser error.
virtual QItemSelection mapSelectionFromMaster(const QItemSelection &selection) const
QString toString() const
QgsFeatureListModel(QgsAttributeTableFilterModel *sourceModel, QObject *parent=nullptr)
QString displayExpression() const
typedef ItemFlags