QGIS API Documentation  3.22.4-Białowieża (ce8e65e95e)
qgsfeaturepickermodelbase.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsfeaturepickermodelbase.cpp - QgsFeaturePickerModelBase
3  ---------------------
4  begin : 10.3.2017
5  copyright : (C) 2017 by Matthias Kuhn
6  email : [email protected]
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 
18 
19 #include "qgsvectorlayer.h"
20 #include "qgsconditionalstyle.h"
21 #include "qgsapplication.h"
22 #include "qgssettings.h"
23 
24 
26  : QAbstractItemModel( parent )
27 {
28  mReloadTimer.setInterval( 100 );
29  mReloadTimer.setSingleShot( true );
30  connect( &mReloadTimer, &QTimer::timeout, this, &QgsFeaturePickerModelBase::scheduledReload );
31 
32  // The fact that the feature changed is a combination of the 2 signals:
33  // If the extra value is set to a feature currently not fetched, it will go through an intermediate step while the extra value does not exist (as it call reloadFeature)
36 }
37 
38 
40 {
41  if ( mGatherer )
42  connect( mGatherer, &QgsFeatureExpressionValuesGatherer::finished, mGatherer, &QgsFeatureExpressionValuesGatherer::deleteLater );
43 }
44 
45 
47 {
48  return mSourceLayer;
49 }
50 
51 
53 {
54  if ( mSourceLayer == sourceLayer )
55  return;
56 
57  mSourceLayer = sourceLayer;
58  if ( mSourceLayer )
59  mExpressionContext = mSourceLayer->createExpressionContext();
60 
61  reload();
62  emit sourceLayerChanged();
63 
64  if ( mSourceLayer )
65  setDisplayExpression( mSourceLayer->displayExpression() );
66 }
67 
68 
70 {
71  return mDisplayExpression.expression();
72 }
73 
74 
75 void QgsFeaturePickerModelBase::setDisplayExpression( const QString &displayExpression )
76 {
77  if ( mDisplayExpression.expression() == displayExpression )
78  return;
79 
80  mDisplayExpression = QgsExpression( displayExpression );
81  reload();
83 }
84 
85 
87 {
88  return mFilterValue;
89 }
90 
91 
92 void QgsFeaturePickerModelBase::setFilterValue( const QString &filterValue )
93 {
94  if ( mFilterValue == filterValue )
95  return;
96 
97  mFilterValue = filterValue;
98  reload();
99  emit filterValueChanged();
100 }
101 
102 
104 {
105  return mFilterExpression;
106 }
107 
108 
109 void QgsFeaturePickerModelBase::setFilterExpression( const QString &filterExpression )
110 {
111  if ( mFilterExpression == filterExpression )
112  return;
113 
114  mFilterExpression = filterExpression;
115  reload();
117 }
118 
119 
121 {
122  return mGatherer;
123 }
124 
126 {
127  return mExtraIdentifierValue;
128 }
129 
130 
131 QModelIndex QgsFeaturePickerModelBase::index( int row, int column, const QModelIndex &parent ) const
132 {
133  Q_UNUSED( parent )
134  return createIndex( row, column, nullptr );
135 }
136 
137 
138 QModelIndex QgsFeaturePickerModelBase::parent( const QModelIndex &child ) const
139 {
140  Q_UNUSED( child )
141  return QModelIndex();
142 }
143 
144 
145 int QgsFeaturePickerModelBase::rowCount( const QModelIndex &parent ) const
146 {
147  Q_UNUSED( parent )
148  return mEntries.size();
149 }
150 
151 
152 
153 QVariant QgsFeaturePickerModelBase::data( const QModelIndex &index, int role ) const
154 {
155  if ( !index.isValid() )
156  return QVariant();
157 
158  switch ( role )
159  {
160  case Qt::DisplayRole:
161  case Qt::EditRole:
162  case ValueRole:
163  return mEntries.value( index.row() ).value;
164 
165  case FeatureIdRole:
166  return mEntries.value( index.row() ).featureId;
167 
168  case FeatureRole:
169  return mEntries.value( index.row() ).feature;
170 
171  case IdentifierValueRole:
172  {
173  const QVariantList values = mEntries.value( index.row() ).identifierFields;
174  return values.value( 0 );
175  }
176 
178  return mEntries.value( index.row() ).identifierFields;
179 
180 #if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
181  case Qt::BackgroundColorRole:
182  case Qt::TextColorRole:
183 #else
184  case Qt::BackgroundRole:
185  case Qt::ForegroundRole:
186 #endif
187  case Qt::DecorationRole:
188  case Qt::FontRole:
189  {
190  const bool isNull = identifierIsNull( entryIdentifier( mEntries.value( index.row() ) ) );
191  if ( isNull )
192  {
193  // Representation for NULL value
194 #if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
195  if ( role == Qt::TextColorRole )
196 #else
197  if ( role == Qt::ForegroundRole )
198 #endif
199  {
200  return QBrush( QColor( Qt::gray ) );
201  }
202  if ( role == Qt::FontRole )
203  {
204  QFont font = QFont();
205  if ( index.row() == mExtraValueIndex )
206  font.setBold( true );
207  else
208  font.setItalic( true );
209  return font;
210  }
211  }
212  else
213  {
214  // Respect conditional style
215  const QgsConditionalStyle style = featureStyle( mEntries.value( index.row() ).feature );
216 
217  if ( style.isValid() )
218  {
219 #if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
220  if ( role == Qt::BackgroundColorRole && style.validBackgroundColor() )
221 #else
222  if ( role == Qt::BackgroundRole && style.validBackgroundColor() )
223 #endif
224  return style.backgroundColor();
225 #if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
226  if ( role == Qt::TextColorRole && style.validTextColor() )
227 #else
228  if ( role == Qt::ForegroundRole && style.validTextColor() )
229 #endif
230  return style.textColor();
231  if ( role == Qt::DecorationRole )
232  return style.icon();
233  if ( role == Qt::FontRole )
234  return style.font();
235  }
236  }
237  break;
238  }
239  }
240 
241  return QVariant();
242 }
243 
244 
245 void QgsFeaturePickerModelBase::updateCompleter()
246 {
247  emit beginUpdate();
248 
249  QgsFeatureExpressionValuesGatherer *gatherer = qobject_cast<QgsFeatureExpressionValuesGatherer *>( sender() );
250  if ( gatherer->wasCanceled() )
251  {
252  delete gatherer;
253  return;
254  }
255 
256  QVector<QgsFeatureExpressionValuesGatherer::Entry> entries = mGatherer->entries();
257 
258  if ( mExtraValueIndex == -1 )
259  {
261  }
262 
263  // Only reloading the current entry?
264  const bool reloadCurrentFeatureOnly = mGatherer->data().toBool();
265  if ( reloadCurrentFeatureOnly )
266  {
267  if ( !entries.isEmpty() )
268  {
269  mEntries.replace( mExtraValueIndex, entries.at( 0 ) );
270  emit dataChanged( index( mExtraValueIndex, 0, QModelIndex() ), index( mExtraValueIndex, 0, QModelIndex() ) );
271  mShouldReloadCurrentFeature = false;
272  setExtraValueDoesNotExist( false );
273  }
274  else
275  {
276  setExtraValueDoesNotExist( true );
277  }
278 
279  mKeepCurrentEntry = true;
280  mShouldReloadCurrentFeature = false;
281 
282  if ( mFilterValue.isEmpty() )
283  reload();
284  }
285  else
286  {
287  // We got strings for a filter selection
288  std::sort( entries.begin(), entries.end(), []( const QgsFeatureExpressionValuesGatherer::Entry & a, const QgsFeatureExpressionValuesGatherer::Entry & b ) { return a.value.localeAwareCompare( b.value ) < 0; } );
289 
290  if ( mAllowNull && mSourceLayer )
291  {
292  entries.prepend( QgsFeatureExpressionValuesGatherer::nullEntry( mSourceLayer ) );
293  }
294 
295  const int newEntriesSize = entries.size();
296 
297  // fixed entry is either NULL or extra value
298  const int nbFixedEntry = ( mKeepCurrentEntry ? 1 : 0 ) + ( mAllowNull ? 1 : 0 );
299 
300  // Find the index of the current entry in the new list
301  int currentEntryInNewList = -1;
302  if ( mExtraValueIndex != -1 && mExtraValueIndex < mEntries.count() )
303  {
304  for ( int i = 0; i < newEntriesSize; ++i )
305  {
306  if ( compareEntries( entries.at( i ), mEntries.at( mExtraValueIndex ) ) )
307  {
308  mEntries.replace( mExtraValueIndex, entries.at( i ) );
309  currentEntryInNewList = i;
310  setExtraValueDoesNotExist( false );
311  break;
312  }
313  }
314  }
315 
316  int firstRow = 0;
317 
318  // Move current entry to the first position if this is a fixed entry or because
319  // the entry exists in the new list
320  if ( mExtraValueIndex > -1 && ( mExtraValueIndex < nbFixedEntry || currentEntryInNewList != -1 ) )
321  {
322  if ( mExtraValueIndex != 0 )
323  {
324  beginMoveRows( QModelIndex(), mExtraValueIndex, mExtraValueIndex, QModelIndex(), 0 );
325  mEntries.move( mExtraValueIndex, 0 );
326  endMoveRows();
327  }
328  firstRow = 1;
329  }
330 
331  // Remove all entries (except for extra entry if existent)
332  beginRemoveRows( QModelIndex(), firstRow, mEntries.size() - firstRow );
333  mEntries.remove( firstRow, mEntries.size() - firstRow );
334 
335  // if we remove all rows before endRemoveRows, setExtraIdentifierValuesUnguarded will be called
336  // and a null value will be added to mEntries, so we block setExtraIdentifierValuesUnguarded call
337 
338  mIsSettingExtraIdentifierValue = true;
339  endRemoveRows();
340  mIsSettingExtraIdentifierValue = false;
341 
342  if ( currentEntryInNewList == -1 )
343  {
344  beginInsertRows( QModelIndex(), firstRow, entries.size() + 1 );
345  mEntries += entries;
346  endInsertRows();
347 
348  // if all entries have been cleaned (firstRow == 0)
349  // and there is a value in entries, prefer this value over NULL
350  // else chose the first one (the previous one)
351  setExtraIdentifierValueIndex( firstRow == 0 && mAllowNull && !entries.isEmpty() ? 1 : 0, firstRow == 0 );
352  }
353  else
354  {
355  if ( currentEntryInNewList != 0 )
356  {
357  beginInsertRows( QModelIndex(), 0, currentEntryInNewList - 1 );
358  mEntries = entries.mid( 0, currentEntryInNewList ) + mEntries;
359  endInsertRows();
360  }
361  else
362  {
363  mEntries.replace( 0, entries.at( 0 ) );
364  }
365 
366  // don't notify for a change if it's a fixed entry
367  if ( currentEntryInNewList >= nbFixedEntry )
368  {
369  emit dataChanged( index( currentEntryInNewList, 0, QModelIndex() ), index( currentEntryInNewList, 0, QModelIndex() ) );
370  }
371 
372  beginInsertRows( QModelIndex(), currentEntryInNewList + 1, newEntriesSize - currentEntryInNewList - 1 );
373  mEntries += entries.mid( currentEntryInNewList + 1 );
374  endInsertRows();
375  setExtraIdentifierValueIndex( currentEntryInNewList );
376  }
377 
378  emit filterJobCompleted();
379 
380  mKeepCurrentEntry = false;
381  }
382  emit endUpdate();
383 
384  // scheduleReload and updateCompleter lives in the same thread so if the gatherer hasn't been stopped
385  // (checked before), mGatherer still references the current gatherer
386  Q_ASSERT( gatherer == mGatherer );
387  delete mGatherer;
388  mGatherer = nullptr;
389  emit isLoadingChanged();
390 }
391 
392 
393 void QgsFeaturePickerModelBase::scheduledReload()
394 {
395  if ( !mSourceLayer )
396  return;
397 
398  bool wasLoading = false;
399 
400  if ( mGatherer )
401  {
402  mGatherer->stop();
403  wasLoading = true;
404  }
405 
406  QgsFeatureRequest request;
407 
408  if ( mShouldReloadCurrentFeature )
409  {
411  }
412  else
413  {
414  QString filterClause;
415 
416  if ( mFilterValue.isEmpty() && !mFilterExpression.isEmpty() )
417  filterClause = mFilterExpression;
418  else if ( mFilterExpression.isEmpty() && !mFilterValue.isEmpty() )
419  filterClause = QStringLiteral( "(%1) ILIKE '%%2%'" ).arg( mDisplayExpression, mFilterValue );
420  else if ( !mFilterExpression.isEmpty() && !mFilterValue.isEmpty() )
421  filterClause = QStringLiteral( "(%1) AND ((%2) ILIKE '%%3%')" ).arg( mFilterExpression, mDisplayExpression, mFilterValue );
422 
423  if ( !filterClause.isEmpty() )
424  request.setFilterExpression( filterClause );
425  }
426  QSet<QString> attributes = requestedAttributes();
427  if ( !attributes.isEmpty() )
428  {
429  if ( auto *lFilterExpression = request.filterExpression() )
430  attributes += lFilterExpression->referencedColumns();
431  attributes += requestedAttributesForStyle();
432 
433  request.setSubsetOfAttributes( attributes, mSourceLayer->fields() );
434  }
435 
436  if ( !mFetchGeometry )
438  if ( mFetchLimit > 0 )
439  request.setLimit( mFetchLimit );
440 
441  mGatherer = createValuesGatherer( request );
442  mGatherer->setData( mShouldReloadCurrentFeature );
443  connect( mGatherer, &QgsFeatureExpressionValuesGatherer::finished, this, &QgsFeaturePickerModelBase::updateCompleter );
444 
445  mGatherer->start();
446  if ( !wasLoading )
447  emit isLoadingChanged();
448 }
449 
450 
451 QSet<QString> QgsFeaturePickerModelBase::requestedAttributesForStyle() const
452 {
453  QSet<QString> requestedAttrs;
454 
455  const auto rowStyles = mSourceLayer->conditionalStyles()->rowStyles();
456 
457  for ( const QgsConditionalStyle &style : rowStyles )
458  {
459  const QgsExpression exp( style.rule() );
460  requestedAttrs += exp.referencedColumns();
461  }
462 
463  if ( mDisplayExpression.isField() )
464  {
465  const QString fieldName = *mDisplayExpression.referencedColumns().constBegin();
466  const auto constFieldStyles = mSourceLayer->conditionalStyles()->fieldStyles( fieldName );
467  for ( const QgsConditionalStyle &style : constFieldStyles )
468  {
469  const QgsExpression exp( style.rule() );
470  requestedAttrs += exp.referencedColumns();
471  }
472  }
473 
474  return requestedAttrs;
475 }
476 
477 
478 void QgsFeaturePickerModelBase::setExtraIdentifierValueIndex( int index, bool force )
479 {
480  if ( mExtraValueIndex == index && !force )
481  return;
482 
485 }
486 
487 
488 void QgsFeaturePickerModelBase::reloadCurrentFeature()
489 {
490  mShouldReloadCurrentFeature = true;
491  mReloadTimer.start();
492 }
493 
494 
495 void QgsFeaturePickerModelBase::setExtraIdentifierValueUnguarded( const QVariant &identifierValue )
496 {
497  const QVector<QgsFeatureExpressionValuesGatherer::Entry> entries = mEntries;
498 
499  int index = 0;
500  for ( const QgsFeatureExpressionValuesGatherer::Entry &entry : entries )
501  {
502  if ( compareEntries( entry, createEntry( identifierValue ) ) )
503  {
504  setExtraIdentifierValueIndex( index );
505  break;
506  }
507 
508  index++;
509  }
510 
511  // Value not found in current entries
512  if ( mExtraValueIndex != index )
513  {
514  const bool isNull = identifierIsNull( identifierValue );
515  if ( !isNull || mAllowNull )
516  {
517  beginInsertRows( QModelIndex(), 0, 0 );
518  if ( !isNull )
519  {
520  mEntries.prepend( createEntry( identifierValue ) );
521  setExtraValueDoesNotExist( true );
522  reloadCurrentFeature();
523  }
524  else
525  {
526  mEntries.prepend( QgsFeatureExpressionValuesGatherer::nullEntry( mSourceLayer ) );
527  setExtraValueDoesNotExist( false );
528  }
529  endInsertRows();
530 
531  setExtraIdentifierValueIndex( 0, true );
532  }
533  }
534 }
535 
536 
537 QgsConditionalStyle QgsFeaturePickerModelBase::featureStyle( const QgsFeature &feature ) const
538 {
539  if ( !mSourceLayer )
540  return QgsConditionalStyle();
541 
542  QgsVectorLayer *layer = mSourceLayer;
543  const QgsFeatureId fid = feature.id();
544  mExpressionContext.setFeature( feature );
545 
546  auto styles = QgsConditionalStyle::matchingConditionalStyles( layer->conditionalStyles()->rowStyles(), QVariant(), mExpressionContext );
547 
548  if ( mDisplayExpression.referencedColumns().count() == 1 )
549  {
550  // Style specific for this field
551  const QString fieldName = *mDisplayExpression.referencedColumns().constBegin();
552  const auto allStyles = layer->conditionalStyles()->fieldStyles( fieldName );
553  const auto matchingFieldStyles = QgsConditionalStyle::matchingConditionalStyles( allStyles, feature.attribute( fieldName ), mExpressionContext );
554 
555  styles += matchingFieldStyles;
556  }
557 
558  QgsConditionalStyle style;
559  style = QgsConditionalStyle::compressStyles( styles );
560  mEntryStylesMap.insert( fid, style );
561 
562  return style;
563 }
564 
565 
567 {
568  return mAllowNull;
569 }
570 
571 
573 {
574  if ( mAllowNull == allowNull )
575  return;
576 
577  mAllowNull = allowNull;
578  emit allowNullChanged();
579 
580  reload();
581 }
582 
584 {
585  return mFetchGeometry;
586 }
587 
589 {
590  if ( mFetchGeometry == fetchGeometry )
591  return;
592 
593  mFetchGeometry = fetchGeometry;
594  reload();
595 }
596 
598 {
599  return mFetchLimit;
600 }
601 
603 {
604  if ( fetchLimit == mFetchLimit )
605  return;
606 
607  mFetchLimit = fetchLimit;
608  emit fetchLimitChanged();
609 }
610 
611 
613 {
614  return mExtraValueDoesNotExist;
615 }
616 
617 
618 void QgsFeaturePickerModelBase::setExtraValueDoesNotExist( bool extraValueDoesNotExist )
619 {
620  if ( mExtraValueDoesNotExist == extraValueDoesNotExist )
621  return;
622 
623  mExtraValueDoesNotExist = extraValueDoesNotExist;
625 }
626 
627 
629 {
630  return mExtraValueIndex;
631 }
632 
633 
634 void QgsFeaturePickerModelBase::reload()
635 {
636  mReloadTimer.start();
637 }
638 
639 
640 void QgsFeaturePickerModelBase::setExtraIdentifierValue( const QVariant &extraIdentifierValue )
641 {
643  return;
644 
645  if ( mIsSettingExtraIdentifierValue )
646  return;
647 
648  mIsSettingExtraIdentifierValue = true;
649 
651 
653 
654  mIsSettingExtraIdentifierValue = false;
655 
657 }
658 
QgsConditionalStyles rowStyles() const
Returns a list of row styles associated with the layer.
QList< QgsConditionalStyle > fieldStyles(const QString &fieldName) const
Returns the conditional styles set for the field with matching fieldName.
Conditional styling for a rule.
static QgsConditionalStyle compressStyles(const QList< QgsConditionalStyle > &styles)
Compress a list of styles into a single style.
static QList< QgsConditionalStyle > matchingConditionalStyles(const QList< QgsConditionalStyle > &styles, const QVariant &value, QgsExpressionContext &context)
Find and return the matching styles for the value and feature.
QColor backgroundColor() const
The background color for style.
QColor textColor() const
The text color set for style.
QFont font() const
The font for the style.
bool validTextColor() const
Check if the text color is valid for render.
bool isValid() const
isValid Check if this rule is valid.
QPixmap icon() const
The icon set for style generated from the set symbol.
bool validBackgroundColor() const
Check if the background color is valid for render.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Class for parsing and evaluation of expressions (formerly called "search strings").
QString expression() const
Returns the original, unmodified expression string.
bool isField() const
Checks whether an expression consists only of a single field reference.
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
void extraIdentifierValueIndexChanged(int index)
The index at which the extra identifier value is available within the model.
void beginUpdate()
Notification that the model is about to be changed because a job was completed.
virtual QVariant entryIdentifier(const QgsFeatureExpressionValuesGatherer::Entry &entry) const =0
Returns the identifier of the given entry.
void filterValueChanged()
This value will be used to filter the features available from this model.
void setFilterValue(const QString &filterValue)
This value will be used to filter the features available from this model.
void setExtraIdentifierValue(const QVariant &extraIdentifierValue)
Allows specifying one value that does not need to match the filter criteria but will still be availab...
virtual void requestToReloadCurrentFeature(QgsFeatureRequest &request)=0
Update the request to match the current feature to be reloaded.
void filterExpressionChanged()
An additional filter expression to apply, next to the filterValue.
void setFetchLimit(int fetchLimit)
Defines the feature request fetch limit If set to 0, no limit is applied when fetching.
QVariant extraIdentifierValue() const
Allows specifying one value that does not need to match the filter criteria but will still be availab...
void setFetchGeometry(bool fetchGeometry)
Defines if the geometry will be fetched.
void setExtraIdentifierValueUnguarded(const QVariant &identifierValue)
This will set the identifier value to be set in the model even if it doesn't exist currently in the d...
void extraIdentifierValueChanged()
Allows specifying one value that does not need to match the filter criteria but will still be availab...
int mExtraValueIndex
The current index.
QModelIndex parent(const QModelIndex &child) const override
void filterJobCompleted()
Indicates that a filter job has been completed and new data may be available.
void setAllowNull(bool allowNull)
Add a NULL entry to the list.
void setDisplayExpression(const QString &displayExpression)
The display expression will be used for.
QVariant mExtraIdentifierValue
The current identifier value.
QgsFeaturePickerModelBase(QObject *parent=nullptr)
Create a new QgsFeaturePickerModelBase, optionally specifying a parent.
virtual QgsFeatureExpressionValuesGatherer * createValuesGatherer(const QgsFeatureRequest &request) const =0
Creates the value gatherer.
virtual QgsFeatureExpressionValuesGatherer::Entry createEntry(const QVariant &identifier) const =0
Creates an entry with just the identifier so the feature can be retrieved in a next iteration.
bool isLoading() const
Indicator if the model is currently performing any feature iteration in the background.
virtual bool identifierIsNull(const QVariant &identifier) const =0
Returns true if the entry is null The identifier can be either the feature ID or the list of identifi...
QVariant data(const QModelIndex &index, int role) const override
QModelIndex index(int row, int column, const QModelIndex &parent) const override
void fetchLimitChanged()
Emitted when the fetching limit for the feature request changes.
void sourceLayerChanged()
The source layer from which features will be fetched.
virtual QSet< QString > requestedAttributes() const
Returns the attributes to be fetched in the request.
@ FeatureIdRole
Used to retrieve the id of a feature.
@ IdentifierValuesRole
Used to retrieve the identifierValues (primary keys) of a feature.
@ FeatureRole
Used to retrieve the feature, it might be incomplete if the request doesn't fetch all attributes or g...
@ ValueRole
Used to retrieve the displayExpression of a feature.
void setFilterExpression(const QString &filterExpression)
An additional filter expression to apply, next to the filterValue.
void allowNullChanged()
Add a NULL entry to the list.
int rowCount(const QModelIndex &parent) const override
virtual bool compareEntries(const QgsFeatureExpressionValuesGatherer::Entry &a, const QgsFeatureExpressionValuesGatherer::Entry &b) const =0
Returns true if the 2 entries refers to the same feature.
void currentFeatureChanged()
Emitted when the current feature in the model has changed This emitted both when the extra value chan...
void isLoadingChanged()
Indicator if the model is currently performing any feature iteration in the background.
QVector< QgsFeatureExpressionValuesGatherer::Entry > mEntries
virtual QVariant nullIdentifier() const =0
Returns a null identifier.
void endUpdate()
Notification that the model change is finished.
void displayExpressionChanged()
The display expression will be used for.
void extraValueDoesNotExistChanged()
Flag indicating that the extraIdentifierValue does not exist in the data.
void setSourceLayer(QgsVectorLayer *sourceLayer)
The source layer from which features will be fetched.
bool extraValueDoesNotExist() const
Flag indicating that the extraIdentifierValue does not exist in the data.
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setLimit(long long limit)
Set the maximum number of features to request.
QgsExpression * filterExpression() const
Returns the filter expression (if set).
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Definition: qgsfeature.cpp:320
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
Represents a vector layer which manages a vector based data sets.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
QgsExpressionContext createExpressionContext() const FINAL
This method needs to be reimplemented in all classes which implement this interface and return an exp...
QString displayExpression
QgsConditionalLayerStyles * conditionalStyles() const
Returns the conditional styles that are set for this layer.
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28