Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgsfeaturepickermodelbase.cpp - QgsFeaturePickerModelBase
3 : : ---------------------
4 : : begin : 10.3.2017
5 : : copyright : (C) 2017 by Matthias Kuhn
6 : : email : matthias@opengis.ch
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 "qgsfeaturepickermodelbase.h"
17 : : #include "qgsfeatureexpressionvaluesgatherer.h"
18 : :
19 : : #include "qgsvectorlayer.h"
20 : : #include "qgsconditionalstyle.h"
21 : : #include "qgsapplication.h"
22 : : #include "qgssettings.h"
23 : :
24 : :
25 : 0 : QgsFeaturePickerModelBase::QgsFeaturePickerModelBase( QObject *parent )
26 : 0 : : QAbstractItemModel( parent )
27 : 0 : {
28 : 0 : mReloadTimer.setInterval( 100 );
29 : 0 : mReloadTimer.setSingleShot( true );
30 : 0 : 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)
34 : 0 : connect( this, &QgsFeaturePickerModelBase::extraIdentifierValueChanged, this, &QgsFeaturePickerModelBase::currentFeatureChanged );
35 : 0 : connect( this, &QgsFeaturePickerModelBase::extraValueDoesNotExistChanged, this, &QgsFeaturePickerModelBase::currentFeatureChanged );
36 : 0 : }
37 : :
38 : :
39 : 0 : QgsFeaturePickerModelBase::~QgsFeaturePickerModelBase()
40 : 0 : {
41 : 0 : if ( mGatherer )
42 : 0 : connect( mGatherer, &QgsFeatureExpressionValuesGatherer::finished, mGatherer, &QgsFeatureExpressionValuesGatherer::deleteLater );
43 : 0 : }
44 : :
45 : :
46 : 0 : QgsVectorLayer *QgsFeaturePickerModelBase::sourceLayer() const
47 : : {
48 : 0 : return mSourceLayer;
49 : : }
50 : :
51 : :
52 : 0 : void QgsFeaturePickerModelBase::setSourceLayer( QgsVectorLayer *sourceLayer )
53 : : {
54 : 0 : if ( mSourceLayer == sourceLayer )
55 : 0 : return;
56 : :
57 : 0 : mSourceLayer = sourceLayer;
58 : 0 : if ( mSourceLayer )
59 : 0 : mExpressionContext = mSourceLayer->createExpressionContext();
60 : :
61 : 0 : reload();
62 : 0 : emit sourceLayerChanged();
63 : :
64 : 0 : if ( mSourceLayer )
65 : 0 : setDisplayExpression( mSourceLayer->displayExpression() );
66 : 0 : }
67 : :
68 : :
69 : 0 : QString QgsFeaturePickerModelBase::displayExpression() const
70 : : {
71 : 0 : return mDisplayExpression.expression();
72 : : }
73 : :
74 : :
75 : 0 : void QgsFeaturePickerModelBase::setDisplayExpression( const QString &displayExpression )
76 : : {
77 : 0 : if ( mDisplayExpression.expression() == displayExpression )
78 : 0 : return;
79 : :
80 : 0 : mDisplayExpression = QgsExpression( displayExpression );
81 : 0 : reload();
82 : 0 : emit displayExpressionChanged();
83 : 0 : }
84 : :
85 : :
86 : 0 : QString QgsFeaturePickerModelBase::filterValue() const
87 : : {
88 : 0 : return mFilterValue;
89 : : }
90 : :
91 : :
92 : 0 : void QgsFeaturePickerModelBase::setFilterValue( const QString &filterValue )
93 : : {
94 : 0 : if ( mFilterValue == filterValue )
95 : 0 : return;
96 : :
97 : 0 : mFilterValue = filterValue;
98 : 0 : reload();
99 : 0 : emit filterValueChanged();
100 : 0 : }
101 : :
102 : :
103 : 0 : QString QgsFeaturePickerModelBase::filterExpression() const
104 : : {
105 : 0 : return mFilterExpression;
106 : : }
107 : :
108 : :
109 : 0 : void QgsFeaturePickerModelBase::setFilterExpression( const QString &filterExpression )
110 : : {
111 : 0 : if ( mFilterExpression == filterExpression )
112 : 0 : return;
113 : :
114 : 0 : mFilterExpression = filterExpression;
115 : 0 : reload();
116 : 0 : emit filterExpressionChanged();
117 : 0 : }
118 : :
119 : :
120 : 0 : bool QgsFeaturePickerModelBase::isLoading() const
121 : : {
122 : 0 : return mGatherer;
123 : : }
124 : :
125 : 0 : QVariant QgsFeaturePickerModelBase::extraIdentifierValue() const
126 : : {
127 : 0 : return mExtraIdentifierValue;
128 : : }
129 : :
130 : :
131 : 0 : QModelIndex QgsFeaturePickerModelBase::index( int row, int column, const QModelIndex &parent ) const
132 : : {
133 : 0 : Q_UNUSED( parent )
134 : 0 : return createIndex( row, column, nullptr );
135 : : }
136 : :
137 : :
138 : 0 : QModelIndex QgsFeaturePickerModelBase::parent( const QModelIndex &child ) const
139 : : {
140 : 0 : Q_UNUSED( child )
141 : 0 : return QModelIndex();
142 : : }
143 : :
144 : :
145 : 0 : int QgsFeaturePickerModelBase::rowCount( const QModelIndex &parent ) const
146 : : {
147 : 0 : Q_UNUSED( parent )
148 : 0 : return mEntries.size();
149 : : }
150 : :
151 : :
152 : :
153 : 0 : QVariant QgsFeaturePickerModelBase::data( const QModelIndex &index, int role ) const
154 : : {
155 : 0 : if ( !index.isValid() )
156 : 0 : return QVariant();
157 : :
158 : 0 : switch ( role )
159 : : {
160 : : case Qt::DisplayRole:
161 : : case Qt::EditRole:
162 : : case ValueRole:
163 : 0 : return mEntries.value( index.row() ).value;
164 : :
165 : : case FeatureIdRole:
166 : 0 : return mEntries.value( index.row() ).featureId;
167 : :
168 : : case FeatureRole:
169 : 0 : return mEntries.value( index.row() ).feature;
170 : :
171 : : case IdentifierValueRole:
172 : : {
173 : 0 : const QVariantList values = mEntries.value( index.row() ).identifierFields;
174 : 0 : return values.value( 0 );
175 : 0 : }
176 : :
177 : : case IdentifierValuesRole:
178 : 0 : 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 : 0 : bool isNull = identifierIsNull( entryIdentifier( mEntries.value( index.row() ) ) );
191 : 0 : 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 : 0 : if ( role == Qt::ForegroundRole )
198 : : #endif
199 : : {
200 : 0 : return QBrush( QColor( Qt::gray ) );
201 : : }
202 : 0 : if ( role == Qt::FontRole )
203 : : {
204 : 0 : QFont font = QFont();
205 : 0 : if ( index.row() == mExtraValueIndex )
206 : 0 : font.setBold( true );
207 : : else
208 : 0 : font.setItalic( true );
209 : 0 : return font;
210 : 0 : }
211 : 0 : }
212 : : else
213 : : {
214 : : // Respect conditional style
215 : 0 : const QgsConditionalStyle style = featureStyle( mEntries.value( index.row() ).feature );
216 : :
217 : 0 : if ( style.isValid() )
218 : : {
219 : : #if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
220 : : if ( role == Qt::BackgroundColorRole && style.validBackgroundColor() )
221 : : #else
222 : 0 : if ( role == Qt::BackgroundRole && style.validBackgroundColor() )
223 : : #endif
224 : 0 : return style.backgroundColor();
225 : : #if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
226 : : if ( role == Qt::TextColorRole && style.validTextColor() )
227 : : #else
228 : 0 : if ( role == Qt::ForegroundRole && style.validTextColor() )
229 : : #endif
230 : 0 : return style.textColor();
231 : 0 : if ( role == Qt::DecorationRole )
232 : 0 : return style.icon();
233 : 0 : if ( role == Qt::FontRole )
234 : 0 : return style.font();
235 : 0 : }
236 : 0 : }
237 : 0 : break;
238 : : }
239 : : }
240 : :
241 : 0 : return QVariant();
242 : 0 : }
243 : :
244 : :
245 : 0 : void QgsFeaturePickerModelBase::updateCompleter()
246 : : {
247 : 0 : emit beginUpdate();
248 : :
249 : 0 : QgsFeatureExpressionValuesGatherer *gatherer = qobject_cast<QgsFeatureExpressionValuesGatherer *>( sender() );
250 : 0 : if ( gatherer->wasCanceled() )
251 : : {
252 : 0 : delete gatherer;
253 : 0 : return;
254 : : }
255 : :
256 : 0 : QVector<QgsFeatureExpressionValuesGatherer::Entry> entries = mGatherer->entries();
257 : :
258 : 0 : if ( mExtraValueIndex == -1 )
259 : : {
260 : 0 : setExtraIdentifierValueUnguarded( nullIdentifier() );
261 : 0 : }
262 : :
263 : : // Only reloading the current entry?
264 : 0 : bool reloadCurrentFeatureOnly = mGatherer->data().toBool();
265 : 0 : if ( reloadCurrentFeatureOnly )
266 : : {
267 : 0 : if ( !entries.isEmpty() )
268 : : {
269 : 0 : mEntries.replace( mExtraValueIndex, entries.at( 0 ) );
270 : 0 : emit dataChanged( index( mExtraValueIndex, 0, QModelIndex() ), index( mExtraValueIndex, 0, QModelIndex() ) );
271 : 0 : mShouldReloadCurrentFeature = false;
272 : 0 : setExtraValueDoesNotExist( false );
273 : 0 : }
274 : : else
275 : : {
276 : 0 : setExtraValueDoesNotExist( true );
277 : : }
278 : :
279 : 0 : mKeepCurrentEntry = true;
280 : 0 : mShouldReloadCurrentFeature = false;
281 : :
282 : 0 : if ( mFilterValue.isEmpty() )
283 : 0 : reload();
284 : 0 : }
285 : : else
286 : : {
287 : : // We got strings for a filter selection
288 : 0 : std::sort( entries.begin(), entries.end(), []( const QgsFeatureExpressionValuesGatherer::Entry & a, const QgsFeatureExpressionValuesGatherer::Entry & b ) { return a.value.localeAwareCompare( b.value ) < 0; } );
289 : :
290 : 0 : if ( mAllowNull && mSourceLayer )
291 : : {
292 : 0 : entries.prepend( QgsFeatureExpressionValuesGatherer::nullEntry( mSourceLayer ) );
293 : 0 : }
294 : :
295 : 0 : const int newEntriesSize = entries.size();
296 : :
297 : : // fixed entry is either NULL or extra value
298 : 0 : const int nbFixedEntry = ( mKeepCurrentEntry ? 1 : 0 ) + ( mAllowNull ? 1 : 0 );
299 : :
300 : : // Find the index of the current entry in the new list
301 : 0 : int currentEntryInNewList = -1;
302 : 0 : if ( mExtraValueIndex != -1 && mExtraValueIndex < mEntries.count() )
303 : : {
304 : 0 : for ( int i = 0; i < newEntriesSize; ++i )
305 : : {
306 : 0 : if ( compareEntries( entries.at( i ), mEntries.at( mExtraValueIndex ) ) )
307 : : {
308 : 0 : mEntries.replace( mExtraValueIndex, entries.at( i ) );
309 : 0 : currentEntryInNewList = i;
310 : 0 : setExtraValueDoesNotExist( false );
311 : 0 : break;
312 : : }
313 : 0 : }
314 : 0 : }
315 : :
316 : 0 : 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 : 0 : if ( mExtraValueIndex > -1 && ( mExtraValueIndex < nbFixedEntry || currentEntryInNewList != -1 ) )
321 : : {
322 : 0 : if ( mExtraValueIndex != 0 )
323 : : {
324 : 0 : beginMoveRows( QModelIndex(), mExtraValueIndex, mExtraValueIndex, QModelIndex(), 0 );
325 : 0 : mEntries.move( mExtraValueIndex, 0 );
326 : 0 : endMoveRows();
327 : 0 : }
328 : 0 : firstRow = 1;
329 : 0 : }
330 : :
331 : : // Remove all entries (except for extra entry if existent)
332 : 0 : beginRemoveRows( QModelIndex(), firstRow, mEntries.size() - firstRow );
333 : 0 : 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 : 0 : mIsSettingExtraIdentifierValue = true;
339 : 0 : endRemoveRows();
340 : 0 : mIsSettingExtraIdentifierValue = false;
341 : :
342 : 0 : if ( currentEntryInNewList == -1 )
343 : : {
344 : 0 : beginInsertRows( QModelIndex(), firstRow, entries.size() + 1 );
345 : 0 : mEntries += entries;
346 : 0 : endInsertRows();
347 : 0 :
348 : 0 : // 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 : 0 : setExtraIdentifierValueIndex( firstRow == 0 && mAllowNull && !entries.isEmpty() ? 1 : 0, firstRow == 0 );
352 : 0 : }
353 : 0 : else
354 : 0 : {
355 : 0 : if ( currentEntryInNewList != 0 )
356 : : {
357 : 0 : beginInsertRows( QModelIndex(), 0, currentEntryInNewList - 1 );
358 : 0 : mEntries = entries.mid( 0, currentEntryInNewList ) + mEntries;
359 : 0 : endInsertRows();
360 : 0 : }
361 : : else
362 : : {
363 : 0 : mEntries.replace( 0, entries.at( 0 ) );
364 : : }
365 : :
366 : : // don't notify for a change if it's a fixed entry
367 : 0 : if ( currentEntryInNewList >= nbFixedEntry )
368 : : {
369 : 0 : emit dataChanged( index( currentEntryInNewList, 0, QModelIndex() ), index( currentEntryInNewList, 0, QModelIndex() ) );
370 : 0 : }
371 : :
372 : 0 : beginInsertRows( QModelIndex(), currentEntryInNewList + 1, newEntriesSize - currentEntryInNewList - 1 );
373 : 0 : mEntries += entries.mid( currentEntryInNewList + 1 );
374 : 0 : endInsertRows();
375 : 0 : setExtraIdentifierValueIndex( currentEntryInNewList );
376 : : }
377 : :
378 : 0 : emit filterJobCompleted();
379 : :
380 : 0 : mKeepCurrentEntry = false;
381 : : }
382 : 0 : 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 : 0 : delete mGatherer;
388 : 0 : mGatherer = nullptr;
389 : 0 : emit isLoadingChanged();
390 : 0 : }
391 : :
392 : :
393 : 0 : void QgsFeaturePickerModelBase::scheduledReload()
394 : : {
395 : 0 : if ( !mSourceLayer )
396 : 0 : return;
397 : :
398 : 0 : bool wasLoading = false;
399 : :
400 : 0 : if ( mGatherer )
401 : : {
402 : 0 : mGatherer->stop();
403 : 0 : wasLoading = true;
404 : 0 : }
405 : :
406 : 0 : QgsFeatureRequest request;
407 : :
408 : 0 : if ( mShouldReloadCurrentFeature )
409 : : {
410 : 0 : requestToReloadCurrentFeature( request );
411 : 0 : }
412 : : else
413 : : {
414 : 0 : QString filterClause;
415 : :
416 : 0 : if ( mFilterValue.isEmpty() && !mFilterExpression.isEmpty() )
417 : 0 : filterClause = mFilterExpression;
418 : 0 : else if ( mFilterExpression.isEmpty() && !mFilterValue.isEmpty() )
419 : 0 : filterClause = QStringLiteral( "(%1) ILIKE '%%2%'" ).arg( mDisplayExpression, mFilterValue );
420 : 0 : else if ( !mFilterExpression.isEmpty() && !mFilterValue.isEmpty() )
421 : 0 : filterClause = QStringLiteral( "(%1) AND ((%2) ILIKE '%%3%')" ).arg( mFilterExpression, mDisplayExpression, mFilterValue );
422 : :
423 : 0 : if ( !filterClause.isEmpty() )
424 : 0 : request.setFilterExpression( filterClause );
425 : 0 : }
426 : 0 : QSet<QString> attributes = requestedAttributes();
427 : 0 : if ( !attributes.isEmpty() )
428 : : {
429 : 0 : if ( auto *lFilterExpression = request.filterExpression() )
430 : 0 : attributes += lFilterExpression->referencedColumns();
431 : 0 : attributes += requestedAttributesForStyle();
432 : :
433 : 0 : request.setSubsetOfAttributes( attributes, mSourceLayer->fields() );
434 : 0 : }
435 : :
436 : 0 : if ( !mFetchGeometry )
437 : 0 : request.setFlags( QgsFeatureRequest::NoGeometry );
438 : 0 : if ( mFetchLimit > 0 )
439 : 0 : request.setLimit( mFetchLimit );
440 : :
441 : 0 : mGatherer = createValuesGatherer( request );
442 : 0 : mGatherer->setData( mShouldReloadCurrentFeature );
443 : 0 : connect( mGatherer, &QgsFeatureExpressionValuesGatherer::finished, this, &QgsFeaturePickerModelBase::updateCompleter );
444 : :
445 : 0 : mGatherer->start();
446 : 0 : if ( !wasLoading )
447 : 0 : emit isLoadingChanged();
448 : 0 : }
449 : :
450 : :
451 : 0 : QSet<QString> QgsFeaturePickerModelBase::requestedAttributesForStyle() const
452 : : {
453 : 0 : QSet<QString> requestedAttrs;
454 : :
455 : 0 : const auto rowStyles = mSourceLayer->conditionalStyles()->rowStyles();
456 : :
457 : 0 : for ( const QgsConditionalStyle &style : rowStyles )
458 : : {
459 : 0 : QgsExpression exp( style.rule() );
460 : 0 : requestedAttrs += exp.referencedColumns();
461 : 0 : }
462 : :
463 : 0 : if ( mDisplayExpression.isField() )
464 : : {
465 : 0 : QString fieldName = *mDisplayExpression.referencedColumns().constBegin();
466 : 0 : const auto constFieldStyles = mSourceLayer->conditionalStyles()->fieldStyles( fieldName );
467 : 0 : for ( const QgsConditionalStyle &style : constFieldStyles )
468 : : {
469 : 0 : QgsExpression exp( style.rule() );
470 : 0 : requestedAttrs += exp.referencedColumns();
471 : 0 : }
472 : 0 : }
473 : :
474 : 0 : return requestedAttrs;
475 : 0 : }
476 : :
477 : :
478 : 0 : void QgsFeaturePickerModelBase::setExtraIdentifierValueIndex( int index, bool force )
479 : : {
480 : 0 : if ( mExtraValueIndex == index && !force )
481 : 0 : return;
482 : :
483 : 0 : mExtraValueIndex = index;
484 : 0 : emit extraIdentifierValueIndexChanged( index );
485 : 0 : }
486 : :
487 : :
488 : 0 : void QgsFeaturePickerModelBase::reloadCurrentFeature()
489 : : {
490 : 0 : mShouldReloadCurrentFeature = true;
491 : 0 : mReloadTimer.start();
492 : 0 : }
493 : :
494 : :
495 : 0 : void QgsFeaturePickerModelBase::setExtraIdentifierValueUnguarded( const QVariant &identifierValue )
496 : : {
497 : 0 : const QVector<QgsFeatureExpressionValuesGatherer::Entry> entries = mEntries;
498 : :
499 : 0 : int index = 0;
500 : 0 : for ( const QgsFeatureExpressionValuesGatherer::Entry &entry : entries )
501 : : {
502 : 0 : if ( compareEntries( entry, createEntry( identifierValue ) ) )
503 : : {
504 : 0 : setExtraIdentifierValueIndex( index );
505 : 0 : break;
506 : : }
507 : :
508 : 0 : index++;
509 : : }
510 : :
511 : : // Value not found in current entries
512 : 0 : if ( mExtraValueIndex != index )
513 : : {
514 : 0 : bool isNull = identifierIsNull( identifierValue );
515 : 0 : if ( !isNull || mAllowNull )
516 : : {
517 : 0 : beginInsertRows( QModelIndex(), 0, 0 );
518 : 0 : if ( !isNull )
519 : : {
520 : 0 : mEntries.prepend( createEntry( identifierValue ) );
521 : 0 : setExtraValueDoesNotExist( true );
522 : 0 : reloadCurrentFeature();
523 : 0 : }
524 : : else
525 : : {
526 : 0 : mEntries.prepend( QgsFeatureExpressionValuesGatherer::nullEntry( mSourceLayer ) );
527 : 0 : setExtraValueDoesNotExist( false );
528 : : }
529 : 0 : endInsertRows();
530 : :
531 : 0 : setExtraIdentifierValueIndex( 0, true );
532 : 0 : }
533 : 0 : }
534 : 0 : }
535 : :
536 : :
537 : 0 : QgsConditionalStyle QgsFeaturePickerModelBase::featureStyle( const QgsFeature &feature ) const
538 : : {
539 : 0 : if ( !mSourceLayer )
540 : 0 : return QgsConditionalStyle();
541 : :
542 : 0 : QgsVectorLayer *layer = mSourceLayer;
543 : 0 : QgsFeatureId fid = feature.id();
544 : 0 : mExpressionContext.setFeature( feature );
545 : :
546 : 0 : auto styles = QgsConditionalStyle::matchingConditionalStyles( layer->conditionalStyles()->rowStyles(), QVariant(), mExpressionContext );
547 : :
548 : 0 : if ( mDisplayExpression.referencedColumns().count() == 1 )
549 : : {
550 : : // Style specific for this field
551 : 0 : QString fieldName = *mDisplayExpression.referencedColumns().constBegin();
552 : 0 : const auto allStyles = layer->conditionalStyles()->fieldStyles( fieldName );
553 : 0 : const auto matchingFieldStyles = QgsConditionalStyle::matchingConditionalStyles( allStyles, feature.attribute( fieldName ), mExpressionContext );
554 : :
555 : 0 : styles += matchingFieldStyles;
556 : 0 : }
557 : :
558 : 0 : QgsConditionalStyle style;
559 : 0 : style = QgsConditionalStyle::compressStyles( styles );
560 : 0 : mEntryStylesMap.insert( fid, style );
561 : :
562 : 0 : return style;
563 : 0 : }
564 : :
565 : :
566 : 0 : bool QgsFeaturePickerModelBase::allowNull() const
567 : : {
568 : 0 : return mAllowNull;
569 : : }
570 : :
571 : :
572 : 0 : void QgsFeaturePickerModelBase::setAllowNull( bool allowNull )
573 : : {
574 : 0 : if ( mAllowNull == allowNull )
575 : 0 : return;
576 : :
577 : 0 : mAllowNull = allowNull;
578 : 0 : emit allowNullChanged();
579 : :
580 : 0 : reload();
581 : 0 : }
582 : :
583 : 0 : bool QgsFeaturePickerModelBase::fetchGeometry() const
584 : : {
585 : 0 : return mFetchGeometry;
586 : : }
587 : :
588 : 0 : void QgsFeaturePickerModelBase::setFetchGeometry( bool fetchGeometry )
589 : : {
590 : 0 : if ( mFetchGeometry == fetchGeometry )
591 : 0 : return;
592 : :
593 : 0 : mFetchGeometry = fetchGeometry;
594 : 0 : reload();
595 : 0 : }
596 : :
597 : 0 : int QgsFeaturePickerModelBase::fetchLimit() const
598 : : {
599 : 0 : return mFetchLimit;
600 : : }
601 : :
602 : 0 : void QgsFeaturePickerModelBase::setFetchLimit( int fetchLimit )
603 : : {
604 : 0 : if ( fetchLimit == mFetchLimit )
605 : 0 : return;
606 : :
607 : 0 : mFetchLimit = fetchLimit;
608 : 0 : emit fetchLimitChanged();
609 : 0 : }
610 : :
611 : :
612 : 0 : bool QgsFeaturePickerModelBase::extraValueDoesNotExist() const
613 : : {
614 : 0 : return mExtraValueDoesNotExist;
615 : : }
616 : :
617 : :
618 : 0 : void QgsFeaturePickerModelBase::setExtraValueDoesNotExist( bool extraValueDoesNotExist )
619 : : {
620 : 0 : if ( mExtraValueDoesNotExist == extraValueDoesNotExist )
621 : 0 : return;
622 : :
623 : 0 : mExtraValueDoesNotExist = extraValueDoesNotExist;
624 : 0 : emit extraValueDoesNotExistChanged();
625 : 0 : }
626 : :
627 : :
628 : 0 : int QgsFeaturePickerModelBase::extraIdentifierValueIndex() const
629 : : {
630 : 0 : return mExtraValueIndex;
631 : : }
632 : :
633 : :
634 : 0 : void QgsFeaturePickerModelBase::reload()
635 : : {
636 : 0 : mReloadTimer.start();
637 : 0 : }
638 : :
639 : :
640 : 0 : void QgsFeaturePickerModelBase::setExtraIdentifierValue( const QVariant &extraIdentifierValue )
641 : : {
642 : 0 : if ( extraIdentifierValue == mExtraIdentifierValue && !identifierIsNull( extraIdentifierValue ) && !identifierIsNull( mExtraIdentifierValue ) )
643 : 0 : return;
644 : :
645 : 0 : if ( mIsSettingExtraIdentifierValue )
646 : 0 : return;
647 : :
648 : 0 : mIsSettingExtraIdentifierValue = true;
649 : :
650 : 0 : mExtraIdentifierValue = extraIdentifierValue;
651 : :
652 : 0 : setExtraIdentifierValueUnguarded( extraIdentifierValue );
653 : :
654 : 0 : mIsSettingExtraIdentifierValue = false;
655 : :
656 : 0 : emit extraIdentifierValueChanged();
657 : 0 : }
658 : :
|