reintroduce reload current feature

This commit is contained in:
Denis Rouzaud 2020-04-25 19:51:00 +02:00
parent 82da0fd962
commit 01516d75e2
4 changed files with 154 additions and 93 deletions

View File

@ -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();

View File

@ -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();

View File

@ -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<QgsFeatureExpressionValuesGatherer::Entry> mEntries;
QgsFeatureExpressionValuesGatherer *mGatherer = nullptr;
QTimer mReloadTimer;
QgsFeatureId mShouldReloadCurrentFeature = 0;
bool mExtraValueDoesNotExist = false;
bool mAllowNull = false;
int mCurrentIndex = -1;
bool mIsSettingCurrentFeature = false;
};
#endif // QGSFEATUREPICKERMODEL_H

View File

@ -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 );
}