QGIS API Documentation 3.99.0-Master (2fe06baccd8)
Loading...
Searching...
No Matches
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
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
17
18#include "qgsconditionalstyle.h"
22#include "qgsvectorlayer.h"
23
24#include "moc_qgsfeaturepickermodelbase.cpp"
25
27 : QAbstractItemModel( parent )
28{
29 mReloadTimer.setInterval( 100 );
30 mReloadTimer.setSingleShot( true );
31 connect( &mReloadTimer, &QTimer::timeout, this, &QgsFeaturePickerModelBase::scheduledReload );
32
33 // The fact that the feature changed is a combination of the 2 signals:
34 // 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
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
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
110{
111 if ( mFilterExpression == filterExpression )
112 return;
113
114 mFilterExpression = filterExpression;
115 reload();
117}
118
120{
121 return mFormFeature;
122}
123
125{
126 if ( mFormFeature == feature )
127 return;
128
129 mFormFeature = feature;
130 if ( !mFilterExpression.isEmpty() && QgsValueRelationFieldFormatter::expressionRequiresFormScope( mFilterExpression ) )
131 {
132 reload();
133 }
134 emit formFeatureChanged();
135}
136
138{
139 return mParentFormFeature;
140}
141
143{
144 if ( mParentFormFeature == feature )
145 return;
146
147 mParentFormFeature = feature;
148 if ( !mFilterExpression.isEmpty() && QgsValueRelationFieldFormatter::expressionRequiresParentFormScope( mFilterExpression ) )
149 {
150 reload();
151 }
153}
154
156{
157 return mGatherer;
158}
159
164
165
166QModelIndex QgsFeaturePickerModelBase::index( int row, int column, const QModelIndex &parent ) const
167{
168 Q_UNUSED( parent )
169 return createIndex( row, column, nullptr );
170}
171
172
173QModelIndex QgsFeaturePickerModelBase::parent( const QModelIndex &child ) const
174{
175 Q_UNUSED( child )
176 return QModelIndex();
177}
178
179
180int QgsFeaturePickerModelBase::rowCount( const QModelIndex &parent ) const
181{
182 Q_UNUSED( parent )
183 return mEntries.size();
184}
185
186
187
188QVariant QgsFeaturePickerModelBase::data( const QModelIndex &index, int role ) const
189{
190 if ( !index.isValid() )
191 return QVariant();
192
193 switch ( role )
194 {
195 case Qt::DisplayRole:
196 case Qt::EditRole:
197 case static_cast< int >( CustomRole::Value ):
198 return mEntries.value( index.row() ).value;
199
200 case static_cast< int >( CustomRole::FeatureId ):
201 return mEntries.value( index.row() ).featureId;
202
203 case static_cast< int >( CustomRole::Feature ):
204 return mEntries.value( index.row() ).feature;
205
206 case static_cast< int >( CustomRole::IdentifierValue ):
207 {
208 const QVariantList values = mEntries.value( index.row() ).identifierFields;
209 return values.value( 0 );
210 }
211
212 case static_cast< int >( CustomRole::IdentifierValues ):
213 return mEntries.value( index.row() ).identifierFields;
214
215 case Qt::BackgroundRole:
216 case Qt::ForegroundRole:
217 case Qt::DecorationRole:
218 case Qt::FontRole:
219 {
220 const bool isNull = identifierIsNull( entryIdentifier( mEntries.value( index.row() ) ) );
221 if ( isNull )
222 {
223 // Representation for NULL value
224 if ( role == Qt::ForegroundRole )
225 {
226 return QBrush( QColor( Qt::gray ) );
227 }
228 if ( role == Qt::FontRole )
229 {
230 QFont font = QFont();
231 if ( index.row() == mExtraValueIndex )
232 font.setBold( true );
233 else
234 font.setItalic( true );
235 return font;
236 }
237 }
238 else
239 {
240 // Respect conditional style
241 const QgsConditionalStyle style = featureStyle( mEntries.value( index.row() ).feature );
242
243 if ( style.isValid() )
244 {
245 if ( role == Qt::BackgroundRole && style.validBackgroundColor() )
246 return style.backgroundColor();
247 if ( role == Qt::ForegroundRole && style.validTextColor() )
248 return style.textColor();
249 if ( role == Qt::DecorationRole )
250 return style.icon();
251 if ( role == Qt::FontRole )
252 return style.font();
253 }
254 }
255 break;
256 }
257 }
258
259 return QVariant();
260}
261
262
263void QgsFeaturePickerModelBase::updateCompleter()
264{
265 emit beginUpdate();
266
267 QgsFeatureExpressionValuesGatherer *gatherer = qobject_cast<QgsFeatureExpressionValuesGatherer *>( sender() );
268 if ( gatherer->wasCanceled() )
269 {
270 delete gatherer;
271 return;
272 }
273
274 QVector<QgsFeatureExpressionValuesGatherer::Entry> entries = mGatherer->entries();
275
276 if ( mExtraValueIndex == -1 )
277 {
279 }
280
281 // Only reloading the current entry?
282 const bool reloadCurrentFeatureOnly = mGatherer->data().toBool();
283 if ( reloadCurrentFeatureOnly )
284 {
285 if ( !entries.isEmpty() )
286 {
287 mEntries.replace( mExtraValueIndex, entries.at( 0 ) );
288 emit dataChanged( index( mExtraValueIndex, 0, QModelIndex() ), index( mExtraValueIndex, 0, QModelIndex() ) );
289 mShouldReloadCurrentFeature = false;
290 setExtraValueDoesNotExist( false );
291 }
292 else
293 {
294 setExtraValueDoesNotExist( true );
295 }
296
297 mKeepCurrentEntry = true;
298 mShouldReloadCurrentFeature = false;
299
300 if ( mFilterValue.isEmpty() )
301 reload();
302 }
303 else
304 {
305 // We got strings for a filter selection
306 std::sort( entries.begin(), entries.end(), [&]( const QgsFeatureExpressionValuesGatherer::Entry & a, const QgsFeatureExpressionValuesGatherer::Entry & b )
307 {
308 bool ok = false;
309 double aNumericOrderValue = a.orderValue.toDouble( &ok );
310 if ( ok )
311 {
312 double bNumericOrderValue = b.orderValue.toDouble( &ok );
313 if ( ok )
314 {
315 if ( mSortOrder == Qt::DescendingOrder )
316 {
317 return aNumericOrderValue > bNumericOrderValue;
318 }
319 else
320 {
321 return aNumericOrderValue < bNumericOrderValue;
322 }
323 }
324 }
325 if ( mSortOrder == Qt::DescendingOrder )
326 {
327 return a.orderValue.localeAwareCompare( b.orderValue ) > 0;
328 }
329 else
330 {
331 return a.orderValue.localeAwareCompare( b.orderValue ) < 0;
332 }
333
334 } );
335
336 if ( mAllowNull && mSourceLayer )
337 {
338 entries.prepend( QgsFeatureExpressionValuesGatherer::nullEntry( mSourceLayer ) );
339 }
340
341 const int newEntriesSize = entries.size();
342
343 // fixed entry is either NULL or extra value
344 const int nbFixedEntry = ( mKeepCurrentEntry ? 1 : 0 ) + ( mAllowNull ? 1 : 0 );
345
346 // Find the index of the current entry in the new list
347 int currentEntryInNewList = -1;
348 if ( mExtraValueIndex != -1 && mExtraValueIndex < mEntries.count() )
349 {
350 for ( int i = 0; i < newEntriesSize; ++i )
351 {
352 if ( compareEntries( entries.at( i ), mEntries.at( mExtraValueIndex ) ) )
353 {
354 mEntries.replace( mExtraValueIndex, entries.at( i ) );
355 currentEntryInNewList = i;
356 setExtraValueDoesNotExist( false );
357 break;
358 }
359 }
360 }
361
362 int firstRow = 0;
363
364 // Move current entry to the first position if this is a fixed entry or because
365 // the entry exists in the new list
366 if ( mExtraValueIndex > -1 && ( mExtraValueIndex < nbFixedEntry || currentEntryInNewList != -1 ) )
367 {
368 if ( mExtraValueIndex != 0 )
369 {
370 beginMoveRows( QModelIndex(), mExtraValueIndex, mExtraValueIndex, QModelIndex(), 0 );
371 mEntries.move( mExtraValueIndex, 0 );
372 endMoveRows();
373 }
374 firstRow = 1;
375 }
376
377 // Remove all entries (except for extra entry if existent)
378 beginRemoveRows( QModelIndex(), firstRow, mEntries.size() - firstRow );
379 mEntries.remove( firstRow, mEntries.size() - firstRow );
380
381 // if we remove all rows before endRemoveRows, setExtraIdentifierValuesUnguarded will be called
382 // and a null value will be added to mEntries, so we block setExtraIdentifierValuesUnguarded call
383
384 mIsSettingExtraIdentifierValue = true;
385 endRemoveRows();
386 mIsSettingExtraIdentifierValue = false;
387
388 if ( currentEntryInNewList == -1 )
389 {
390 beginInsertRows( QModelIndex(), firstRow, entries.size() + 1 );
391 mEntries += entries;
392 endInsertRows();
393
394 // if all entries have been cleaned (firstRow == 0)
395 // and there is a value in entries, prefer this value over NULL
396 // else chose the first one (the previous one)
397 setExtraIdentifierValueIndex( firstRow == 0 && mAllowNull && !entries.isEmpty() ? 1 : 0, firstRow == 0 );
398 }
399 else
400 {
401 if ( currentEntryInNewList != 0 )
402 {
403 beginInsertRows( QModelIndex(), 0, currentEntryInNewList - 1 );
404 mEntries = entries.mid( 0, currentEntryInNewList ) + mEntries;
405 endInsertRows();
406 }
407 else
408 {
409 mEntries.replace( 0, entries.at( 0 ) );
410 }
411
412 // don't notify for a change if it's a fixed entry
413 if ( currentEntryInNewList >= nbFixedEntry )
414 {
415 emit dataChanged( index( currentEntryInNewList, 0, QModelIndex() ), index( currentEntryInNewList, 0, QModelIndex() ) );
416 }
417
418 beginInsertRows( QModelIndex(), currentEntryInNewList + 1, newEntriesSize - currentEntryInNewList - 1 );
419 mEntries += entries.mid( currentEntryInNewList + 1 );
420 endInsertRows();
421 setExtraIdentifierValueIndex( currentEntryInNewList );
422 }
423
424 emit filterJobCompleted();
425
426 mKeepCurrentEntry = false;
427 }
428 emit endUpdate();
429
430 // scheduleReload and updateCompleter lives in the same thread so if the gatherer hasn't been stopped
431 // (checked before), mGatherer still references the current gatherer
432 Q_ASSERT( gatherer == mGatherer );
433 delete mGatherer;
434 mGatherer = nullptr;
435 emit isLoadingChanged();
436}
437
438
439void QgsFeaturePickerModelBase::scheduledReload()
440{
441 if ( !mSourceLayer )
442 return;
443
444 bool wasLoading = false;
445
446 if ( mGatherer )
447 {
448 mGatherer->stop();
449 wasLoading = true;
450 }
451
452 QgsFeatureRequest request;
453
454 if ( mShouldReloadCurrentFeature )
455 {
457 }
458 else
459 {
460 QString filterClause;
461
462 if ( mFilterValue.isEmpty() && !mFilterExpression.isEmpty() )
463 filterClause = mFilterExpression;
464 else if ( mFilterExpression.isEmpty() && !mFilterValue.isEmpty() )
465 filterClause = QStringLiteral( "(%1) ILIKE '%%2%'" ).arg( mDisplayExpression, mFilterValue );
466 else if ( !mFilterExpression.isEmpty() && !mFilterValue.isEmpty() )
467 filterClause = QStringLiteral( "(%1) AND ((%2) ILIKE '%%3%')" ).arg( mFilterExpression, mDisplayExpression, mFilterValue );
468
469 if ( !filterClause.isEmpty() )
470 {
471 request.setFilterExpression( filterClause );
473
474 if ( !mFilterExpression.isEmpty() )
475 {
476 if ( mFormFeature.isValid() && QgsValueRelationFieldFormatter::expressionRequiresFormScope( mFilterExpression ) )
477 {
479 }
480 if ( mParentFormFeature.isValid() && QgsValueRelationFieldFormatter::expressionRequiresParentFormScope( mFilterExpression ) )
481 {
483 }
484 }
485 }
486 }
487 QSet<QString> attributes = requestedAttributes();
488 if ( !attributes.isEmpty() )
489 {
490 if ( auto *lFilterExpression = request.filterExpression() )
491 attributes += lFilterExpression->referencedColumns();
492 attributes += requestedAttributesForStyle();
493
494 request.setSubsetOfAttributes( attributes, mSourceLayer->fields() );
495 }
496
497 if ( !mFetchGeometry )
499 if ( mFetchLimit > 0 )
500 request.setLimit( mFetchLimit );
501
502 mGatherer = createValuesGatherer( request );
503 mGatherer->setData( mShouldReloadCurrentFeature );
504 connect( mGatherer, &QgsFeatureExpressionValuesGatherer::finished, this, &QgsFeaturePickerModelBase::updateCompleter );
505
506 mGatherer->start();
507 if ( !wasLoading )
508 emit isLoadingChanged();
509}
510
511
512QSet<QString> QgsFeaturePickerModelBase::requestedAttributesForStyle() const
513{
514 QSet<QString> requestedAttrs;
515
516 const auto rowStyles = mSourceLayer->conditionalStyles()->rowStyles();
517
518 for ( const QgsConditionalStyle &style : rowStyles )
519 {
520 const QgsExpression exp( style.rule() );
521 requestedAttrs += exp.referencedColumns();
522 }
523
524 if ( mDisplayExpression.isField() )
525 {
526 const QString fieldName = *mDisplayExpression.referencedColumns().constBegin();
527 const auto constFieldStyles = mSourceLayer->conditionalStyles()->fieldStyles( fieldName );
528 for ( const QgsConditionalStyle &style : constFieldStyles )
529 {
530 const QgsExpression exp( style.rule() );
531 requestedAttrs += exp.referencedColumns();
532 }
533 }
534
535 return requestedAttrs;
536}
537
538
539void QgsFeaturePickerModelBase::setExtraIdentifierValueIndex( int index, bool force )
540{
541 if ( mExtraValueIndex == index && !force )
542 return;
543
546}
547
548
549void QgsFeaturePickerModelBase::reloadCurrentFeature()
550{
551 mShouldReloadCurrentFeature = true;
552 mReloadTimer.start();
553}
554
555
557{
558 const QVector<QgsFeatureExpressionValuesGatherer::Entry> entries = mEntries;
559
560 int index = 0;
561 for ( const QgsFeatureExpressionValuesGatherer::Entry &entry : entries )
562 {
563 if ( compareEntries( entry, createEntry( identifierValue ) ) )
564 {
565 setExtraIdentifierValueIndex( index );
566 break;
567 }
568
569 index++;
570 }
571
572 // Value not found in current entries
573 if ( mExtraValueIndex != index )
574 {
575 const bool isNull = identifierIsNull( identifierValue );
576 if ( !isNull || mAllowNull )
577 {
578 beginInsertRows( QModelIndex(), 0, 0 );
579 if ( !isNull )
580 {
581 mEntries.prepend( createEntry( identifierValue ) );
582 setExtraValueDoesNotExist( true );
583 reloadCurrentFeature();
584 }
585 else
586 {
587 mEntries.prepend( QgsFeatureExpressionValuesGatherer::nullEntry( mSourceLayer ) );
588 setExtraValueDoesNotExist( false );
589 }
590 endInsertRows();
591
592 setExtraIdentifierValueIndex( 0, true );
593 }
594 }
595}
596
597
598QgsConditionalStyle QgsFeaturePickerModelBase::featureStyle( const QgsFeature &feature ) const
599{
600 if ( !mSourceLayer )
601 return QgsConditionalStyle();
602
603 QgsVectorLayer *layer = mSourceLayer;
604 const QgsFeatureId fid = feature.id();
605 mExpressionContext.setFeature( feature );
606
607 auto styles = QgsConditionalStyle::matchingConditionalStyles( layer->conditionalStyles()->rowStyles(), QVariant(), mExpressionContext );
608
609 if ( mDisplayExpression.referencedColumns().count() == 1 )
610 {
611 // Style specific for this field
612 const QString fieldName = *mDisplayExpression.referencedColumns().constBegin();
613 const auto allStyles = layer->conditionalStyles()->fieldStyles( fieldName );
614 const auto matchingFieldStyles = QgsConditionalStyle::matchingConditionalStyles( allStyles, feature.attribute( fieldName ), mExpressionContext );
615
616 styles += matchingFieldStyles;
617 }
618
619 QgsConditionalStyle style;
620 style = QgsConditionalStyle::compressStyles( styles );
621 mEntryStylesMap.insert( fid, style );
622
623 return style;
624}
625
626
628{
629 return mAllowNull;
630}
631
632
634{
635 if ( mAllowNull == allowNull )
636 return;
637
638 mAllowNull = allowNull;
639 emit allowNullChanged();
640
641 reload();
642}
643
645{
646 return mFetchGeometry;
647}
648
650{
651 if ( mFetchGeometry == fetchGeometry )
652 return;
653
654 mFetchGeometry = fetchGeometry;
655 reload();
656}
657
659{
660 return mFetchLimit;
661}
662
664{
665 if ( fetchLimit == mFetchLimit )
666 return;
667
668 mFetchLimit = fetchLimit;
669 emit fetchLimitChanged();
670
671 reload();
672}
673
674
676{
677 return mExtraValueDoesNotExist;
678}
679
680
681void QgsFeaturePickerModelBase::setExtraValueDoesNotExist( bool extraValueDoesNotExist )
682{
683 if ( mExtraValueDoesNotExist == extraValueDoesNotExist )
684 return;
685
686 mExtraValueDoesNotExist = extraValueDoesNotExist;
687 emit extraValueDoesNotExistChanged( mExtraValueDoesNotExist );
688}
689
690
695
696
697void QgsFeaturePickerModelBase::reload()
698{
699 mReloadTimer.start();
700}
701
702
704{
706 return;
707
708 if ( mIsSettingExtraIdentifierValue )
709 return;
710
711 mIsSettingExtraIdentifierValue = true;
712
714
716
717 mIsSettingExtraIdentifierValue = false;
718
720}
721
722
724{
725 return mOrderExpression.expression();
726}
727
728
730{
731 if ( mOrderExpression.expression() == orderExpression )
732 return;
733
734 mOrderExpression = QgsExpression( orderExpression );
735 reload();
737}
738
739
741{
742 return mSortOrder;
743}
744
745
747{
748 if ( mSortOrder == sortOrder )
749 return;
750
751 mSortOrder = sortOrder;
752 reload();
753 emit sortOrderChanged();
754}
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Definition qgis.h:2196
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.
static QgsExpressionContextScope * parentFormScope(const QgsFeature &formFeature=QgsFeature(), const QString &formMode=QString())
Creates a new scope which contains functions and variables from the current parent attribute form/tab...
static QgsExpressionContextScope * formScope(const QgsFeature &formFeature=QgsFeature(), const QString &formMode=QString())
Creates a new scope which contains functions and variables from the current attribute form/table form...
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
Handles parsing and evaluation of expressions (formerly called "search strings").
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 setParentFormFeature(const QgsFeature &feature)
Sets a parent attribute form feature to be used with the filter expression.
void parentFormFeatureChanged()
A parent attribute form feature to be used alongside the filter expression.
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 extraValueDoesNotExistChanged(bool found)
Notification whether the model has found a feature tied to the extraIdentifierValue or not.
QgsFeature formFeature() const
Returns an attribute form feature to be used with the filter expression.
virtual QgsFeatureExpressionValuesGatherer * createValuesGatherer(const QgsFeatureRequest &request) const =0
Creates the value gatherer.
void setSortOrder(const Qt::SortOrder sortOrder)
The order direction will be used for sort values in the combobox.
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...
void setOrderExpression(const QString &orderExpression)
The order expression will be used for sort values in the combobox.
virtual QSet< QString > requestedAttributes() const
Returns the attributes to be fetched in the request.
@ IdentifierValues
Used to retrieve the identifierValues (primary keys) of a feature.
@ FeatureId
Used to retrieve the id of a feature.
@ IdentifierValue
Used to retrieve the identifier value (primary key) of a feature.
@ Feature
Used to retrieve the feature, it might be incomplete if the request doesn't fetch all attributes or g...
@ Value
Used to retrieve the displayExpression of a feature.
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::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.
void setFormFeature(const QgsFeature &feature)
Sets an attribute form feature to be used with the filter expression.
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.
QgsFeature parentFormFeature() const
Returns a parent attribute form feature to be used with the filter expression.
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 orderExpressionChanged()
An expression for generating values for sorting.
void sortOrderChanged()
The direction used for sorting.
void isLoadingChanged()
Indicator if the model is currently performing any feature iteration in the background.
void formFeatureChanged()
An attribute form feature to be used alongside the filter expression.
QVector< QgsFeatureExpressionValuesGatherer::Entry > mEntries
virtual QVariant nullIdentifier() const =0
Returns a null identifier.
void displayExpressionChanged()
The display expression will be used for.
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.
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setLimit(long long limit)
Set the maximum number of features to request.
QgsExpressionContext * expressionContext()
Returns the expression context used to evaluate filter expressions.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsExpression * filterExpression() const
Returns the filter expression (if set).
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:58
QgsFeatureId id
Definition qgsfeature.h:66
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
static bool expressionRequiresFormScope(const QString &expression)
Check if the expression requires a form scope (i.e.
static bool expressionRequiresParentFormScope(const QString &expression)
Check if the expression requires a parent form scope (i.e.
Represents a vector layer which manages a vector based dataset.
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