From 7c1fb3639049bf0f744b992cde4757b7af3811b0 Mon Sep 17 00:00:00 2001 From: Matthias Kuhn Date: Sun, 1 May 2016 14:26:43 +0200 Subject: [PATCH] Fix attribute table column "resync after change" --- .../qgsattributetablefiltermodel.cpp | 102 +++++++++++++----- .../qgsattributetablefiltermodel.h | 2 +- 2 files changed, 74 insertions(+), 30 deletions(-) diff --git a/src/gui/attributetable/qgsattributetablefiltermodel.cpp b/src/gui/attributetable/qgsattributetablefiltermodel.cpp index 8fd7b3d51e67..2e974a8ea1f0 100644 --- a/src/gui/attributetable/qgsattributetablefiltermodel.cpp +++ b/src/gui/attributetable/qgsattributetablefiltermodel.cpp @@ -114,50 +114,86 @@ void QgsAttributeTableFilterModel::setAttributeTableConfig( const QgsAttributeTa mConfig = config; mConfig.update( layer()->fields() ); - int columnIndex = 0; - int configIndex = 0; - bool resetModel = false; + QVector newColumnMapping; - for ( ; configIndex < mConfig.columns().size(); ++configIndex ) + Q_FOREACH ( const QgsAttributeTableConfig::ColumnConfig& columnConfig, mConfig.columns() ) { - const QgsAttributeTableConfig::ColumnConfig& columnConfig = mConfig.columns().at( configIndex ); - - // Hidden? No reason for further checks + // Hidden? Forget about this column if ( columnConfig.mHidden ) continue; - // Do the previous and current definition match? - if ( mColumnMapping.size() > columnIndex ) + // The new value for the mapping (field index or -1 for action column) + int newValue = ( columnConfig.mType == QgsAttributeTableConfig::Action ) ? -1 : layer()->fieldNameIndex( columnConfig.mName ); + newColumnMapping << newValue; + } + + if ( newColumnMapping != mColumnMapping ) + { + bool requiresReset = false; + int firstRemovedColumn = -1; + int removedColumnCount = 0; + + // Check if there have a contiguous set of columns have been removed or if we require a full reset + for ( int i = 0; i < qMin( newColumnMapping.size(), mColumnMapping.size() - removedColumnCount ); ++i ) { - if (( columnConfig.mType == QgsAttributeTableConfig::Action && mColumnMapping.at( columnIndex ) == -1 ) || - ( columnConfig.mType == QgsAttributeTableConfig::Field && mColumnMapping.at( columnIndex ) == layer()->fieldNameIndex( columnConfig.mName ) ) ) - { - ++columnIndex; + if ( newColumnMapping.at( i ) == mColumnMapping.at( i + removedColumnCount ) ) continue; + + if ( firstRemovedColumn == -1 ) + { + firstRemovedColumn = i; + + while ( i < mColumnMapping.size() - removedColumnCount && mColumnMapping.at( i + removedColumnCount ) != newColumnMapping.at( i ) ) + { + ++removedColumnCount; + } } - else // There is a mismatch between previous and current configuration: remove all remaining columns, they will be readded + else { - mColumnMapping.remove( columnIndex, mColumnMapping.count() - columnIndex ); + requiresReset = true; + break; } } - if ( ! resetModel ) + // No difference found so far + if ( firstRemovedColumn == -1 ) { - beginResetModel(); - resetModel = true; + if ( newColumnMapping.size() > mColumnMapping.size() ) + { + // More columns: appended to the end + beginInsertColumns( QModelIndex(), mColumnMapping.size(), newColumnMapping.size() - 1 ); + mColumnMapping = newColumnMapping; + endInsertColumns(); + } + else + { + // Less columns: removed from the end + beginRemoveColumns( QModelIndex(), newColumnMapping.size(), mColumnMapping.size() - 1 ); + mColumnMapping = newColumnMapping; + endRemoveColumns(); + } } - - // New column? append - Q_ASSERT( mColumnMapping.size() == columnIndex ); - if ( columnConfig.mType == QgsAttributeTableConfig::Action ) - mColumnMapping.append( -1 ); else - mColumnMapping.append( layer()->fieldNameIndex( columnConfig.mName ) ); + { + if ( newColumnMapping.size() == mColumnMapping.size() - removedColumnCount ) + { + beginRemoveColumns( QModelIndex(), firstRemovedColumn, firstRemovedColumn + removedColumnCount ); + mColumnMapping = newColumnMapping; + endRemoveColumns(); + } + else + { + requiresReset = true; + } + } - ++columnIndex; + if ( requiresReset ) + { + beginResetModel(); + mColumnMapping = newColumnMapping; + endResetModel(); + } } - if ( resetModel ) - endResetModel(); } void QgsAttributeTableFilterModel::setSelectedOnTop( bool selectedOnTop ) @@ -185,7 +221,15 @@ void QgsAttributeTableFilterModel::setSourceModel( QgsAttributeTableModel* sourc } QSortFilterProxyModel::setSourceModel( sourceModel ); - disconnect( mTableModel, SIGNAL( columnsAboutToBeInserted( QModelIndex, int, int ) ), this, SLOT( onColumnsAboutToBeInserted() ) ); + + // Disconnect any code to update columns in the parent, we handle this manually + disconnect( sourceModel, SIGNAL( columnsAboutToBeInserted( QModelIndex, int, int ) ), this, SLOT( _q_sourceColumnsAboutToBeInserted( QModelIndex, int, int ) ) ); + disconnect( sourceModel, SIGNAL( columnsInserted( QModelIndex, int, int ) ), this, SLOT( _q_sourceColumnsInserted( QModelIndex, int, int ) ) ); + disconnect( sourceModel, SIGNAL( columnsAboutToBeRemoved( QModelIndex, int, int ) ), this, SLOT( _q_sourceColumnsAboutToBeRemoved( QModelIndex, int, int ) ) ); + disconnect( sourceModel, SIGNAL( columnsRemoved( QModelIndex, int, int ) ), this, SLOT( _q_sourceColumnsRemoved( QModelIndex, int, int ) ) ); + + connect( mTableModel, SIGNAL( columnsAboutToBeInserted( QModelIndex, int, int ) ), this, SLOT( onColumnsChanged() ) ); + connect( mTableModel, SIGNAL( columnsAboutToBeRemoved( QModelIndex, int, int ) ), this, SLOT( onColumnsChanged() ) ); } bool QgsAttributeTableFilterModel::selectedOnTop() @@ -293,7 +337,7 @@ void QgsAttributeTableFilterModel::selectionChanged() } } -void QgsAttributeTableFilterModel::onColumnsAboutToBeInserted() +void QgsAttributeTableFilterModel::onColumnsChanged() { setAttributeTableConfig( mConfig ); } diff --git a/src/gui/attributetable/qgsattributetablefiltermodel.h b/src/gui/attributetable/qgsattributetablefiltermodel.h index 7a59082d09f7..f456cf721c01 100644 --- a/src/gui/attributetable/qgsattributetablefiltermodel.h +++ b/src/gui/attributetable/qgsattributetablefiltermodel.h @@ -228,7 +228,7 @@ class GUI_EXPORT QgsAttributeTableFilterModel: public QSortFilterProxyModel, pub private slots: void selectionChanged(); - void onColumnsAboutToBeInserted(); + void onColumnsChanged(); private: QgsFeatureIds mFilteredFeatures;