From 01516d75e22c0cde135b719f4a4959cdee253a6d Mon Sep 17 00:00:00 2001 From: Denis Rouzaud Date: Sat, 25 Apr 2020 19:51:00 +0200 Subject: [PATCH] reintroduce reload current feature --- .../qgsfeaturepickermodel.sip.in | 5 + src/core/qgsfeaturepickermodel.cpp | 231 +++++++++++------- src/core/qgsfeaturepickermodel.h | 9 +- src/gui/qgsfeaturepickerwidget.cpp | 2 +- 4 files changed, 154 insertions(+), 93 deletions(-) diff --git a/python/core/auto_generated/qgsfeaturepickermodel.sip.in b/python/core/auto_generated/qgsfeaturepickermodel.sip.in index 7aea37eb2f8..e0975b01499 100644 --- a/python/core/auto_generated/qgsfeaturepickermodel.sip.in +++ b/python/core/auto_generated/qgsfeaturepickermodel.sip.in @@ -171,6 +171,11 @@ Indicator if the model is currently performing any feature iteration in the back void filterJobCompleted(); %Docstring Indicates that a filter job has been completed and new data may be available. +%End + + void extraValueDoesNotExistChanged(); +%Docstring +Flag indicating that the extraIdentifierValue does not exist in the data. %End void beginUpdate(); diff --git a/src/core/qgsfeaturepickermodel.cpp b/src/core/qgsfeaturepickermodel.cpp index 79cdf0ce6ec..c6c77f2b866 100644 --- a/src/core/qgsfeaturepickermodel.cpp +++ b/src/core/qgsfeaturepickermodel.cpp @@ -211,97 +211,121 @@ void QgsFeaturePickerModel::updateCompleter() { setCurrentFeatureUnguarded( FID_NULL ); } - // We got strings for a filter selection - std::sort( entries.begin(), entries.end(), []( const QgsFeatureExpressionValuesGatherer::Entry & a, const QgsFeatureExpressionValuesGatherer::Entry & b ) { return a.value.localeAwareCompare( b.value ) < 0; } ); - if ( mAllowNull ) + // Only reloading the current entry? + bool reloadCurrentFeatureOnly = mGatherer->data().toBool(); + if ( reloadCurrentFeatureOnly ) { - entries.prepend( QgsFeatureExpressionValuesGatherer::nullEntry() ); - } - - const int newEntriesSize = entries.size(); - - // fixed entry is either NULL or extra value - const int nbFixedEntry = mAllowNull ? 1 : 0 ; - - // Find the index of the current entry in the new list - int currentEntryInNewList = -1; - if ( mCurrentIndex != -1 && mCurrentIndex < mEntries.count() ) - { - for ( int i = 0; i < newEntriesSize; ++i ) + if ( !entries.isEmpty() ) { - if ( entries.at( i ).feature.id() == mEntries.at( mCurrentIndex ).feature.id() ) - { - mEntries.replace( mCurrentIndex, entries.at( i ) ); - currentEntryInNewList = i; - break; - } - } - } - - int firstRow = 0; - - // Move current entry to the first position if this is a fixed entry or because - // the entry exists in the new list - if ( mCurrentIndex > -1 && ( mCurrentIndex < nbFixedEntry || currentEntryInNewList != -1 ) ) - { - if ( mCurrentIndex != 0 ) - { - beginMoveRows( QModelIndex(), mCurrentIndex, mCurrentIndex, QModelIndex(), 0 ); - mEntries.move( mCurrentIndex, 0 ); - endMoveRows(); - } - firstRow = 1; - } - - // Remove all entries (except for extra entry if existent) - beginRemoveRows( QModelIndex(), firstRow, mEntries.size() - firstRow ); - mEntries.remove( firstRow, mEntries.size() - firstRow ); - - // if we remove all rows before endRemoveRows, setExtraIdentifierValuesUnguarded will be called - // and a null value will be added to mEntries, so we block setExtraIdentifierValuesUnguarded call - - endRemoveRows(); - - - if ( currentEntryInNewList == -1 ) - { - beginInsertRows( QModelIndex(), firstRow, entries.size() + 1 ); - mEntries += entries; - endInsertRows(); - - // if all entries have been cleaned (firstRow == 0) - // and there is a value in entries, prefer this value over NULL - // else chose the first one (the previous one) - setCurrentIndex( firstRow == 0 && mAllowNull && !entries.isEmpty() ? 1 : 0, firstRow == 0 ); - } - else - { - if ( currentEntryInNewList != 0 ) - { - beginInsertRows( QModelIndex(), 0, currentEntryInNewList - 1 ); - mEntries = entries.mid( 0, currentEntryInNewList ) + mEntries; - endInsertRows(); + mEntries.replace( mCurrentIndex, entries.at( 0 ) ); + emit dataChanged( index( mCurrentIndex, 0, QModelIndex() ), index( mCurrentIndex, 0, QModelIndex() ) ); + mShouldReloadCurrentFeature = 0; + setExtraValueDoesNotExist( false ); } else { - mEntries.replace( 0, entries.at( 0 ) ); + setExtraValueDoesNotExist( true ); } - // don't notify for a change if it's a fixed entry - if ( currentEntryInNewList >= nbFixedEntry ) - { - emit dataChanged( index( currentEntryInNewList, 0, QModelIndex() ), index( currentEntryInNewList, 0, QModelIndex() ) ); - } + mShouldReloadCurrentFeature = 0; - beginInsertRows( QModelIndex(), currentEntryInNewList + 1, newEntriesSize - currentEntryInNewList - 1 ); - mEntries += entries.mid( currentEntryInNewList + 1 ); - endInsertRows(); - setCurrentIndex( currentEntryInNewList ); + if ( mFilterValue.isEmpty() ) + reload(); } + else + { + // We got strings for a filter selection + std::sort( entries.begin(), entries.end(), []( const QgsFeatureExpressionValuesGatherer::Entry & a, const QgsFeatureExpressionValuesGatherer::Entry & b ) { return a.value.localeAwareCompare( b.value ) < 0; } ); - emit filterJobCompleted(); + if ( mAllowNull ) + { + entries.prepend( QgsFeatureExpressionValuesGatherer::nullEntry() ); + } + const int newEntriesSize = entries.size(); + + // fixed entry is either NULL or extra value + const int nbFixedEntry = ( mExtraValueDoesNotExist ? 1 : 0 ) + ( mAllowNull ? 1 : 0 ); + + // Find the index of the current entry in the new list + int currentEntryInNewList = -1; + if ( mCurrentIndex != -1 && mCurrentIndex < mEntries.count() ) + { + for ( int i = 0; i < newEntriesSize; ++i ) + { + if ( entries.at( i ).feature.id() == mEntries.at( mCurrentIndex ).feature.id() ) + { + mEntries.replace( mCurrentIndex, entries.at( i ) ); + currentEntryInNewList = i; + break; + } + } + } + + int firstRow = 0; + + // Move current entry to the first position if this is a fixed entry or because + // the entry exists in the new list + if ( mCurrentIndex > -1 && ( mCurrentIndex < nbFixedEntry || currentEntryInNewList != -1 ) ) + { + if ( mCurrentIndex != 0 ) + { + beginMoveRows( QModelIndex(), mCurrentIndex, mCurrentIndex, QModelIndex(), 0 ); + mEntries.move( mCurrentIndex, 0 ); + endMoveRows(); + } + firstRow = 1; + } + + // Remove all entries (except for extra entry if existent) + beginRemoveRows( QModelIndex(), firstRow, mEntries.size() - firstRow ); + mEntries.remove( firstRow, mEntries.size() - firstRow ); + + // if we remove all rows before endRemoveRows, setExtraIdentifierValuesUnguarded will be called + // and a null value will be added to mEntries, so we block setExtraIdentifierValuesUnguarded call + + endRemoveRows(); + + + if ( currentEntryInNewList == -1 ) + { + beginInsertRows( QModelIndex(), firstRow, entries.size() + 1 ); + mEntries += entries; + endInsertRows(); + + // if all entries have been cleaned (firstRow == 0) + // and there is a value in entries, prefer this value over NULL + // else chose the first one (the previous one) + setCurrentIndex( firstRow == 0 && mAllowNull && !entries.isEmpty() ? 1 : 0, firstRow == 0 ); + } + else + { + if ( currentEntryInNewList != 0 ) + { + beginInsertRows( QModelIndex(), 0, currentEntryInNewList - 1 ); + mEntries = entries.mid( 0, currentEntryInNewList ) + mEntries; + endInsertRows(); + } + else + { + mEntries.replace( 0, entries.at( 0 ) ); + } + + // don't notify for a change if it's a fixed entry + if ( currentEntryInNewList >= nbFixedEntry ) + { + emit dataChanged( index( currentEntryInNewList, 0, QModelIndex() ), index( currentEntryInNewList, 0, QModelIndex() ) ); + } + + beginInsertRows( QModelIndex(), currentEntryInNewList + 1, newEntriesSize - currentEntryInNewList - 1 ); + mEntries += entries.mid( currentEntryInNewList + 1 ); + endInsertRows(); + setCurrentIndex( currentEntryInNewList ); + } + + emit filterJobCompleted(); + } emit endUpdate(); @@ -328,20 +352,28 @@ void QgsFeaturePickerModel::scheduledReload() QgsFeatureRequest request; - QString filterClause; - if ( mFilterValue.isEmpty() && !mFilterExpression.isEmpty() ) - filterClause = mFilterExpression; - else if ( mFilterExpression.isEmpty() && !mFilterValue.isEmpty() ) - filterClause = QStringLiteral( "(%1) ILIKE '%%2%'" ).arg( mDisplayExpression, mFilterValue ); - else if ( !mFilterExpression.isEmpty() && !mFilterValue.isEmpty() ) - filterClause = QStringLiteral( "(%1) AND ((%2) ILIKE '%%3%')" ).arg( mFilterExpression, mDisplayExpression, mFilterValue ); + if ( mShouldReloadCurrentFeature != 0 ) + { + request.setFilterFid( mShouldReloadCurrentFeature ); + } + else + { + QString filterClause; + if ( mFilterValue.isEmpty() && !mFilterExpression.isEmpty() ) + filterClause = mFilterExpression; + else if ( mFilterExpression.isEmpty() && !mFilterValue.isEmpty() ) + filterClause = QStringLiteral( "(%1) ILIKE '%%2%'" ).arg( mDisplayExpression, mFilterValue ); + else if ( !mFilterExpression.isEmpty() && !mFilterValue.isEmpty() ) + filterClause = QStringLiteral( "(%1) AND ((%2) ILIKE '%%3%')" ).arg( mFilterExpression, mDisplayExpression, mFilterValue ); - if ( !filterClause.isEmpty() ) - request.setFilterExpression( filterClause ); + if ( !filterClause.isEmpty() ) + request.setFilterExpression( filterClause ); + } request.setLimit( QgsSettings().value( QStringLiteral( "maxEntriesRelationWidget" ), 100, QgsSettings::Gui ).toInt() ); mGatherer = new QgsFeatureExpressionValuesGatherer( mSourceLayer, mDisplayExpression, request ); + mGatherer->setData( mShouldReloadCurrentFeature ); connect( mGatherer, &QgsFeatureExpressionValuesGatherer::finished, this, &QgsFeaturePickerModel::updateCompleter ); mGatherer->start(); @@ -390,15 +422,32 @@ void QgsFeaturePickerModel::setCurrentFeatureUnguarded( const QgsFeatureId &feat } // Value not found in current entries - if ( mCurrentIndex != index && ( mAllowNull || featureId == 0 ) ) + if ( mCurrentIndex != index && ( mAllowNull || featureId != 0 ) ) { beginInsertRows( QModelIndex(), 0, 0 ); - mEntries.prepend( QgsFeatureExpressionValuesGatherer::nullEntry() ); + if ( featureId != 0 ) + { + mShouldReloadCurrentFeature = featureId; + mReloadTimer.start(); + } + else + { + mEntries.prepend( QgsFeatureExpressionValuesGatherer::nullEntry() ); + } endInsertRows(); setCurrentIndex( 0, true ); } } +void QgsFeaturePickerModel::setExtraValueDoesNotExist( bool extraValueDoesNotExist ) +{ + if ( mExtraValueDoesNotExist == extraValueDoesNotExist ) + return; + + mExtraValueDoesNotExist = extraValueDoesNotExist; + emit extraValueDoesNotExistChanged(); +} + QgsConditionalStyle QgsFeaturePickerModel::featureStyle( const QgsFeature &feature ) const { if ( !mSourceLayer ) @@ -445,7 +494,7 @@ void QgsFeaturePickerModel::setAllowNull( bool allowNull ) QgsFeature QgsFeaturePickerModel::currentFeature() const { - if ( mCurrentIndex < mEntries.count() ) + if ( mCurrentIndex >= 0 && mCurrentIndex < mEntries.count() ) return mEntries.at( mCurrentIndex ).feature; else return QgsFeature(); diff --git a/src/core/qgsfeaturepickermodel.h b/src/core/qgsfeaturepickermodel.h index 95d627aa8a5..0446a286ae9 100644 --- a/src/core/qgsfeaturepickermodel.h +++ b/src/core/qgsfeaturepickermodel.h @@ -189,6 +189,11 @@ class CORE_EXPORT QgsFeaturePickerModel : public QAbstractItemModel */ void filterJobCompleted(); + /** + * Flag indicating that the extraIdentifierValue does not exist in the data. + */ + void extraValueDoesNotExistChanged(); + /** * Notification that the model is about to be changed because a job was completed. */ @@ -212,6 +217,7 @@ class CORE_EXPORT QgsFeaturePickerModel : public QAbstractItemModel void setCurrentIndex( int index, bool force = false ); void reload(); void setCurrentFeatureUnguarded( const QgsFeatureId &featureId ); + void setExtraValueDoesNotExist( bool extraValueDoesNotExist ); QgsConditionalStyle featureStyle( const QgsFeature &feature ) const; QgsVectorLayer *mSourceLayer = nullptr; @@ -224,11 +230,12 @@ class CORE_EXPORT QgsFeaturePickerModel : public QAbstractItemModel QVector mEntries; QgsFeatureExpressionValuesGatherer *mGatherer = nullptr; QTimer mReloadTimer; + QgsFeatureId mShouldReloadCurrentFeature = 0; + bool mExtraValueDoesNotExist = false; bool mAllowNull = false; int mCurrentIndex = -1; bool mIsSettingCurrentFeature = false; - }; #endif // QGSFEATUREPICKERMODEL_H diff --git a/src/gui/qgsfeaturepickerwidget.cpp b/src/gui/qgsfeaturepickerwidget.cpp index 41ea4f975cf..513802a9c0d 100644 --- a/src/gui/qgsfeaturepickerwidget.cpp +++ b/src/gui/qgsfeaturepickerwidget.cpp @@ -75,7 +75,7 @@ void QgsFeaturePickerWidget::setLayer( QgsVectorLayer *sourceLayer ) mModel->setSourceLayer( sourceLayer ); } -void QgsFeaturePickerWidget::setCurrentFeature(QgsFeatureId featureId ) +void QgsFeaturePickerWidget::setCurrentFeature( QgsFeatureId featureId ) { mModel->setCurrentFeature( featureId ); }