Allow using NULL values

This commit is contained in:
Matthias Kuhn 2017-10-26 15:30:03 +02:00
parent 2a185a0c9b
commit c661ab1090
No known key found for this signature in database
GPG Key ID: A0E766808764D73F
7 changed files with 101 additions and 25 deletions

View File

@ -141,6 +141,17 @@ class QgsFeatureFilterModel : QAbstractItemModel
:rtype: bool
%End
bool allowNull() const;
%Docstring
Add a NULL entry to the list.
:rtype: bool
%End
void setAllowNull( bool allowNull );
%Docstring
Add a NULL entry to the list.
%End
signals:
void sourceLayerChanged();
@ -211,6 +222,11 @@ class QgsFeatureFilterModel : QAbstractItemModel
Notification that the model change is finished. Will always be emitted in sync with beginUpdate.
%End
void allowNullChanged();
%Docstring
Add a NULL entry to the list.
%End
};
/************************************************************************

View File

@ -92,8 +92,6 @@ class QgsFeatureListComboBox : QComboBox
bool allowNull() const;
%Docstring
Determines if a NULL value should be available in the list.
TODO!
:rtype: bool
%End

View File

@ -165,12 +165,18 @@ void QgsFeatureFilterModel::updateCompleter()
}
mShouldReloadCurrentFeature = false;
if ( mFilterValue.isEmpty() )
reload();
}
else
{
// We got strings for a filter selection
std::sort( entries.begin(), entries.end(), []( const Entry & a, const Entry & b ) { return a.value.localeAwareCompare( b.value ) < 0; } );
if ( mAllowNull )
entries.prepend( Entry( QVariant( QVariant::Int ), tr( "NULL" ) ) );
int newEntriesSize = entries.size();
// Find the index of the extra entry in the new list
@ -196,6 +202,8 @@ void QgsFeatureFilterModel::updateCompleter()
int firstRow = 0;
QgsDebugMsg( QStringLiteral( "Entries 1: %1 " ).arg( mEntries.size() ) );
// Move the extra entry to the first position
if ( mExtraIdentifierValueIndex != -1 )
{
@ -213,13 +221,18 @@ void QgsFeatureFilterModel::updateCompleter()
firstRow = 1;
}
QgsDebugMsg( QStringLiteral( "Entries 2: %1 " ).arg( mEntries.size() ) );
// Remove all entries (except for extra entry if existent)
beginRemoveRows( QModelIndex(), firstRow, mEntries.size() - firstRow );
mEntries.remove( firstRow, mEntries.size() - firstRow );
endRemoveRows();
QgsDebugMsg( QStringLiteral( "Entries 3: %1 " ).arg( mEntries.size() ) );
if ( currentEntryInNewList == -1 )
{
QgsDebugMsg( QStringLiteral( "Current value is NOT in new list" ) );
beginInsertRows( QModelIndex(), 1, entries.size() + 1 );
mEntries += entries;
endInsertRows();
@ -227,6 +240,7 @@ void QgsFeatureFilterModel::updateCompleter()
}
else
{
QgsDebugMsg( QStringLiteral( "Current value is in new list" ) );
if ( currentEntryInNewList != 0 )
{
beginInsertRows( QModelIndex(), 0, currentEntryInNewList - 1 );
@ -335,7 +349,7 @@ void QgsFeatureFilterModel::setExtraIdentifierValueUnguarded( const QVariant &ex
int index = 0;
for ( const Entry &entry : entries )
{
if ( entry.identifierValue == extraIdentifierValue )
if ( entry.identifierValue == extraIdentifierValue && entry.identifierValue.isNull() == extraIdentifierValue.isNull() && entry.identifierValue.isValid() == extraIdentifierValue.isValid() )
{
setExtraIdentifierValueIndex( index );
break;
@ -348,7 +362,10 @@ void QgsFeatureFilterModel::setExtraIdentifierValueUnguarded( const QVariant &ex
if ( mExtraIdentifierValueIndex != index )
{
beginInsertRows( QModelIndex(), 0, 0 );
mEntries.prepend( Entry( extraIdentifierValue, QStringLiteral( "(%1)" ).arg( extraIdentifierValue.toString() ) ) );
if ( extraIdentifierValue.isNull() )
mEntries.prepend( Entry( QVariant( QVariant::Int ), QStringLiteral( "%1" ).arg( tr( "NULL" ) ) ) );
else
mEntries.prepend( Entry( extraIdentifierValue, QStringLiteral( "(%1)" ).arg( extraIdentifierValue.toString() ) ) );
endInsertRows();
setExtraIdentifierValueIndex( 0 );
@ -356,6 +373,22 @@ void QgsFeatureFilterModel::setExtraIdentifierValueUnguarded( const QVariant &ex
}
}
bool QgsFeatureFilterModel::allowNull() const
{
return mAllowNull;
}
void QgsFeatureFilterModel::setAllowNull( bool allowNull )
{
if ( mAllowNull == allowNull )
return;
mAllowNull = allowNull;
emit allowNullChanged();
reload();
}
bool QgsFeatureFilterModel::extraValueDoesNotExist() const
{
return mExtraValueDoesNotExist;
@ -401,7 +434,7 @@ QVariant QgsFeatureFilterModel::extraIdentifierValue() const
void QgsFeatureFilterModel::setExtraIdentifierValue( const QVariant &extraIdentifierValue )
{
if ( extraIdentifierValue == mExtraIdentifierValue && extraIdentifierValue.isNull() == mExtraIdentifierValue.isNull() )
if ( extraIdentifierValue == mExtraIdentifierValue && extraIdentifierValue.isNull() == mExtraIdentifierValue.isNull() && mExtraIdentifierValue.isValid() )
return;
setExtraIdentifierValueUnguarded( extraIdentifierValue );

View File

@ -37,6 +37,7 @@ class CORE_EXPORT QgsFeatureFilterModel : public QAbstractItemModel
Q_PROPERTY( QString displayExpression READ displayExpression WRITE setDisplayExpression NOTIFY displayExpressionChanged )
Q_PROPERTY( QString filterValue READ filterValue WRITE setFilterValue NOTIFY filterValueChanged )
Q_PROPERTY( QString filterExpression READ filterExpression WRITE setFilterExpression NOTIFY filterExpressionChanged )
Q_PROPERTY( bool allowNull READ allowNull WRITE setAllowNull NOTIFY allowNullChanged )
Q_PROPERTY( bool isLoading READ isLoading NOTIFY isLoadingChanged )
/**
@ -167,6 +168,16 @@ class CORE_EXPORT QgsFeatureFilterModel : public QAbstractItemModel
*/
bool extraValueDoesNotExist() const;
/**
* Add a NULL entry to the list.
*/
bool allowNull() const;
/**
* Add a NULL entry to the list.
*/
void setAllowNull( bool allowNull );
signals:
/**
@ -237,6 +248,11 @@ class CORE_EXPORT QgsFeatureFilterModel : public QAbstractItemModel
*/
void endUpdate();
/**
* Add a NULL entry to the list.
*/
void allowNullChanged();
private slots:
void updateCompleter();
void gathererThreadFinished();
@ -274,6 +290,7 @@ class CORE_EXPORT QgsFeatureFilterModel : public QAbstractItemModel
QTimer mReloadTimer;
bool mShouldReloadCurrentFeature = false;
bool mExtraValueDoesNotExist = false;
bool mAllowNull = false;
QString mIdentifierField;

View File

@ -677,8 +677,7 @@ void QgsRelationReferenceWidget::mapIdentification()
void QgsRelationReferenceWidget::comboReferenceChanged( int index )
{
QgsFeatureId fid = mComboBox->itemData( index, QgsAttributeTableModel::FeatureIdRole ).value<QgsFeatureId>();
mReferencedLayer->getFeatures( QgsFeatureRequest().setFilterFid( fid ) ).nextFeature( mFeature );
mReferencedLayer->getFeatures( mComboBox->currentFeatureRequest() ).nextFeature( mFeature );
highlightFeature( mFeature );
updateAttributeEditorFrame( mFeature );
emit foreignKeyChanged( mFeature.attribute( mReferencedFieldIdx ) );

View File

@ -38,6 +38,7 @@ QgsFeatureListComboBox::QgsFeatureListComboBox( QWidget *parent )
connect( mModel, &QgsFeatureFilterModel::filterExpressionChanged, this, &QgsFeatureListComboBox::filterExpressionChanged );
connect( mModel, &QgsFeatureFilterModel::isLoadingChanged, this, &QgsFeatureListComboBox::onLoadingChanged );
connect( mModel, &QgsFeatureFilterModel::filterJobCompleted, this, &QgsFeatureListComboBox::onFilterUpdateCompleted );
connect( mModel, &QgsFeatureFilterModel::allowNullChanged, this, &QgsFeatureListComboBox::allowNullChanged );
connect( mModel, &QgsFeatureFilterModel::extraIdentifierValueChanged, this, &QgsFeatureListComboBox::identifierValueChanged );
connect( mModel, &QgsFeatureFilterModel::extraIdentifierValueIndexChanged, this, &QgsFeatureListComboBox::setCurrentIndex );
connect( mModel, &QgsFeatureFilterModel::identifierFieldChanged, this, &QgsFeatureListComboBox::identifierFieldChanged );
@ -45,6 +46,7 @@ QgsFeatureListComboBox::QgsFeatureListComboBox( QWidget *parent )
connect( mCompleter, static_cast<void( QCompleter::* )( const QModelIndex & )>( &QCompleter::activated ), this, &QgsFeatureListComboBox::onActivated );
connect( mModel, &QgsFeatureFilterModel::beginUpdate, this, &QgsFeatureListComboBox::storeLineEditState );
connect( mModel, &QgsFeatureFilterModel::endUpdate, this, &QgsFeatureListComboBox::restoreLineEditState );
connect( mModel, &QgsFeatureFilterModel::dataChanged, this, &QgsFeatureListComboBox::onDataChanged );
connect( this, static_cast<void( QgsFeatureListComboBox::* )( int )>( &QgsFeatureListComboBox::currentIndexChanged ), this, &QgsFeatureListComboBox::onCurrentIndexChanged );
@ -55,10 +57,7 @@ QgsFeatureListComboBox::QgsFeatureListComboBox( QWidget *parent )
connect( mLineEdit, &QgsFilterLineEdit::textEdited, this, &QgsFeatureListComboBox::onCurrentTextChanged );
connect( mLineEdit, &QgsFilterLineEdit::textChanged, this, []( const QString & text )
{
QgsDebugMsg( QStringLiteral( "Edit text changed to %1" ).arg( text ) );
} );
setToolTip( tr( "Just start typing what you are looking for." ) );
}
QgsVectorLayer *QgsFeatureListComboBox::sourceLayer() const
@ -83,6 +82,7 @@ void QgsFeatureListComboBox::setDisplayExpression( const QString &expression )
void QgsFeatureListComboBox::onCurrentTextChanged( const QString &text )
{
mIsCurrentlyEdited = true;
mPopupRequested = true;
mModel->setFilterValue( text );
}
@ -107,6 +107,7 @@ void QgsFeatureListComboBox::onItemSelected( const QModelIndex &index )
void QgsFeatureListComboBox::onCurrentIndexChanged( int i )
{
mIsCurrentlyEdited = false;
QModelIndex modelIndex = mModel->index( i, 0, QModelIndex() );
mModel->setExtraIdentifierValue( mModel->data( modelIndex, QgsFeatureFilterModel::IdentifierValueRole ) );
mLineEdit->setText( mModel->data( modelIndex, QgsFeatureFilterModel::ValueRole ).toString() );
@ -115,19 +116,33 @@ void QgsFeatureListComboBox::onCurrentIndexChanged( int i )
void QgsFeatureListComboBox::onActivated( QModelIndex modelIndex )
{
setIdentifierValue( mModel->data( modelIndex, QgsFeatureFilterModel::IdentifierValueRole ) );
QgsDebugMsg( QStringLiteral( "Activated index" ) );
QgsDebugMsg( QStringLiteral( "%1 %2" ).arg( QString::number( modelIndex.row() ), mModel->data( modelIndex, QgsFeatureFilterModel::ValueRole ).toString() ) );
mLineEdit->setText( mModel->data( modelIndex, QgsFeatureFilterModel::ValueRole ).toString() );
}
void QgsFeatureListComboBox::storeLineEditState()
{
mLineEditState.store( mLineEdit );
if ( mIsCurrentlyEdited )
mLineEditState.store( mLineEdit );
}
void QgsFeatureListComboBox::restoreLineEditState()
{
mLineEditState.restore( mLineEdit );
if ( mIsCurrentlyEdited )
mLineEditState.restore( mLineEdit );
}
void QgsFeatureListComboBox::onDataChanged( const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles )
{
Q_UNUSED( roles )
if ( !mIsCurrentlyEdited )
{
const int currentIndex = mModel->extraIdentifierValueIndex();
if ( currentIndex >= topLeft.row() && currentIndex <= bottomRight.row() )
{
QModelIndex modelIndex = mModel->index( currentIndex, 0, QModelIndex() );
mLineEdit->setText( mModel->data( modelIndex, QgsFeatureFilterModel::ValueRole ).toString() );
}
}
}
QString QgsFeatureListComboBox::identifierField() const
@ -163,16 +178,12 @@ void QgsFeatureListComboBox::keyPressEvent( QKeyEvent *event )
bool QgsFeatureListComboBox::allowNull() const
{
return mAllowNull;
return mModel->allowNull();
}
void QgsFeatureListComboBox::setAllowNull( bool allowNull )
{
if ( mAllowNull == allowNull )
return;
mAllowNull = allowNull;
emit allowNullChanged();
mModel->setAllowNull( allowNull );
}
QVariant QgsFeatureListComboBox::identifierValue() const
@ -187,7 +198,10 @@ void QgsFeatureListComboBox::setIdentifierValue( const QVariant &identifierValue
QgsFeatureRequest QgsFeatureListComboBox::currentFeatureRequest() const
{
return QgsFeatureRequest().setFilterExpression( QStringLiteral( "%1 = %2" ).arg( QgsExpression::quotedColumnRef( mModel->identifierField() ), QgsExpression::quotedValue( mModel->extraIdentifierValue() ) ) );
if ( mModel->extraIdentifierValue().isNull() )
return QgsFeatureRequest().setFilterFids( QgsFeatureIds() ); // NULL: Return a request that's guaranteed to not return anything
else
return QgsFeatureRequest().setFilterExpression( QStringLiteral( "%1 = %2" ).arg( QgsExpression::quotedColumnRef( mModel->identifierField() ), QgsExpression::quotedValue( mModel->extraIdentifierValue() ) ) );
}
QString QgsFeatureListComboBox::filterExpression() const

View File

@ -48,6 +48,7 @@ class GUI_EXPORT QgsFeatureListComboBox : public QComboBox
Q_PROPERTY( bool allowNull READ allowNull WRITE setAllowNull NOTIFY allowNullChanged )
public:
/**
* Create a new QgsFeatureListComboBox, optionally specifying a \a parent.
*/
@ -109,8 +110,6 @@ class GUI_EXPORT QgsFeatureListComboBox : public QComboBox
/**
* Determines if a NULL value should be available in the list.
*
* TODO!
*/
bool allowNull() const;
@ -185,6 +184,7 @@ class GUI_EXPORT QgsFeatureListComboBox : public QComboBox
void onActivated( QModelIndex index );
void storeLineEditState();
void restoreLineEditState();
void onDataChanged( const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int>() );
private:
struct LineEditState
@ -202,7 +202,6 @@ class GUI_EXPORT QgsFeatureListComboBox : public QComboBox
QCompleter *mCompleter;
QString mDisplayExpression;
QgsFilterLineEdit *mLineEdit;
bool mAllowNull = true;
bool mPopupRequested = false;
bool mIsCurrentlyEdited = false;
LineEditState mLineEditState;