QgsFeatureListModel is sortable by display expression

This commit is contained in:
Matthias Kuhn 2018-05-15 17:32:19 +02:00
parent 14cefe3d3a
commit f1770c7529
No known key found for this signature in database
GPG Key ID: A0E766808764D73F
3 changed files with 132 additions and 37 deletions

View File

@ -102,8 +102,6 @@ for a meaningful error message.
virtual QItemSelection mapSelectionFromMaster( const QItemSelection &selection ) const;
virtual QItemSelection mapSelectionToMaster( const QItemSelection &selection ) const;
virtual QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const;
virtual QModelIndex parent( const QModelIndex &child ) const;
virtual int columnCount( const QModelIndex &parent = QModelIndex() ) const;
@ -115,6 +113,25 @@ for a meaningful error message.
QModelIndexList fidToIndexList( QgsFeatureId fid );
bool sortByDisplayExpression() const;
%Docstring
Sort this model by its display expression.
.. versionadded:: 3.2
%End
void setSortByDisplayExpression( bool sortByDisplayExpression );
%Docstring
Sort this model by its display expression.
.. note::
Not compatible with injectNull, if sorting by display expression is enabled,
injectNull will automatically turned off.
.. versionadded:: 3.2
%End
public slots:
void onBeginRemoveRows( const QModelIndex &parent, int first, int last );
void onEndRemoveRows( const QModelIndex &parent, int first, int last );

View File

@ -30,12 +30,13 @@ QgsFeatureListModel::QgsFeatureListModel( QgsAttributeTableFilterModel *sourceMo
void QgsFeatureListModel::setSourceModel( QgsAttributeTableFilterModel *sourceModel )
{
QAbstractProxyModel::setSourceModel( sourceModel );
QSortFilterProxyModel::setSourceModel( sourceModel );
mExpressionContext = sourceModel->layer()->createExpressionContext();
mFilterModel = sourceModel;
if ( mFilterModel )
{
#if 0
// rewire (filter-)change events in the source model so this proxy reflects the changes
connect( mFilterModel, &QAbstractItemModel::rowsAboutToBeRemoved, this, &QgsFeatureListModel::onBeginRemoveRows );
connect( mFilterModel, &QAbstractItemModel::rowsRemoved, this, &QgsFeatureListModel::onEndRemoveRows );
@ -46,6 +47,7 @@ void QgsFeatureListModel::setSourceModel( QgsAttributeTableFilterModel *sourceMo
connect( mFilterModel, &QAbstractItemModel::layoutChanged, this, &QAbstractItemModel::layoutChanged );
connect( mFilterModel, &QAbstractItemModel::modelAboutToBeReset, this, &QAbstractItemModel::modelAboutToBeReset );
connect( mFilterModel, &QAbstractItemModel::modelReset, this, &QAbstractItemModel::modelReset );
#endif
}
}
@ -61,7 +63,7 @@ QgsFeatureId QgsFeatureListModel::idxToFid( const QModelIndex &index ) const
QModelIndex QgsFeatureListModel::fidToIdx( const QgsFeatureId fid ) const
{
return mFilterModel->mapFromMaster( mFilterModel->masterModel()->idToIndex( fid ) );
return mapFromMaster( mFilterModel->masterModel()->idToIndex( fid ) );
}
QVariant QgsFeatureListModel::data( const QModelIndex &index, int role ) const
@ -192,12 +194,15 @@ Qt::ItemFlags QgsFeatureListModel::flags( const QModelIndex &index ) const
void QgsFeatureListModel::setInjectNull( bool injectNull )
{
if ( mInjectNull != injectNull )
{
beginResetModel();
mInjectNull = injectNull;
endResetModel();
}
if ( mInjectNull == injectNull )
return;
if ( injectNull )
setSortByDisplayExpression( false );
beginResetModel();
mInjectNull = injectNull;
endResetModel();
}
bool QgsFeatureListModel::injectNull()
@ -224,7 +229,12 @@ bool QgsFeatureListModel::setDisplayExpression( const QString &expression )
mDisplayExpression = exp;
if ( mSortByDisplayExpression )
masterModel()->prefetchSortData( expression, 1 );
emit dataChanged( index( 0, 0 ), index( rowCount() - 1, 0 ) );
invalidate();
return true;
}
@ -269,24 +279,63 @@ void QgsFeatureListModel::onEndInsertRows( const QModelIndex &parent, int first,
endInsertRows();
}
QModelIndex QgsFeatureListModel::mapToMaster( const QModelIndex &proxyIndex ) const
bool QgsFeatureListModel::sortByDisplayExpression() const
{
if ( !proxyIndex.isValid() )
return QModelIndex();
int offset = mInjectNull ? 1 : 0;
return mFilterModel->mapToMaster( mFilterModel->index( proxyIndex.row() - offset, proxyIndex.column() ) );
return mSortByDisplayExpression;
}
QModelIndex QgsFeatureListModel::mapFromMaster( const QModelIndex &sourceIndex ) const
void QgsFeatureListModel::setSortByDisplayExpression( bool sortByDisplayExpression )
{
if ( !sourceIndex.isValid() )
return QModelIndex();
mSortByDisplayExpression = sortByDisplayExpression;
int offset = mInjectNull ? 1 : 0;
// If we are sorting by display expression, we do not support injected null
if ( sortByDisplayExpression )
setInjectNull( false );
return createIndex( mFilterModel->mapFromMaster( sourceIndex ).row() + offset, 0 );
setSortRole( QgsAttributeTableModel::SortRole + 1 );
setDynamicSortFilter( mSortByDisplayExpression );
sort( 0 );
}
QModelIndex QgsFeatureListModel::mapToMaster( const QModelIndex &proxyIndex ) const
{
QModelIndex masterIndex;
if ( proxyIndex.isValid() )
{
if ( mSortByDisplayExpression )
{
masterIndex = mFilterModel->mapToMaster( mapToSource( proxyIndex ) );
}
else
{
int offset = mInjectNull ? 1 : 0;
masterIndex = mFilterModel->mapToMaster( mFilterModel->index( proxyIndex.row() - offset, proxyIndex.column() ) );
}
}
return masterIndex;
}
QModelIndex QgsFeatureListModel::mapFromMaster( const QModelIndex &masterIndex ) const
{
QModelIndex proxyIndex;
if ( masterIndex.isValid() )
{
if ( mSortByDisplayExpression )
{
proxyIndex = mapFromSource( mFilterModel->mapFromMaster( masterIndex ) );
}
else
{
int offset = mInjectNull ? 1 : 0;
return createIndex( mFilterModel->mapFromMaster( masterIndex ).row() + offset, 0 );
}
}
return proxyIndex;
}
QItemSelection QgsFeatureListModel::mapSelectionFromMaster( const QItemSelection &selection ) const
@ -303,27 +352,40 @@ QItemSelection QgsFeatureListModel::mapSelectionToMaster( const QItemSelection &
QModelIndex QgsFeatureListModel::mapToSource( const QModelIndex &proxyIndex ) const
{
if ( !proxyIndex.isValid() )
return QModelIndex();
QModelIndex sourceIndex;
int offset = mInjectNull ? 1 : 0;
if ( mSortByDisplayExpression )
{
sourceIndex = QSortFilterProxyModel::mapToSource( proxyIndex );
}
else
{
if ( !proxyIndex.isValid() )
return QModelIndex();
return sourceModel()->index( proxyIndex.row() - offset, proxyIndex.column() );
int offset = mInjectNull ? 1 : 0;
sourceIndex = sourceModel()->index( proxyIndex.row() - offset, proxyIndex.column() );
}
return sourceIndex;
}
QModelIndex QgsFeatureListModel::mapFromSource( const QModelIndex &sourceIndex ) const
{
if ( !sourceIndex.isValid() )
return QModelIndex();
QModelIndex proxyIndex;
return createIndex( sourceIndex.row(), 0 );
}
if ( mSortByDisplayExpression )
{
proxyIndex = QSortFilterProxyModel::mapFromSource( sourceIndex );
}
else
{
if ( sourceIndex.isValid() )
proxyIndex = createIndex( sourceIndex.row(), 0 );
}
QModelIndex QgsFeatureListModel::index( int row, int column, const QModelIndex &parent ) const
{
Q_UNUSED( parent )
return createIndex( row, column );
return proxyIndex;
}
QModelIndex QgsFeatureListModel::parent( const QModelIndex &child ) const

View File

@ -56,7 +56,7 @@ class GUI_EXPORT QgsFeatureListModel : public QSortFilterProxyModel, public QgsF
enum Role
{
FeatureInfoRole = Qt::UserRole,
FeatureInfoRole = 0x1000, // Make sure no collisions with roles on QgsAttributeTableModel
FeatureRole
};
@ -114,7 +114,6 @@ class GUI_EXPORT QgsFeatureListModel : public QSortFilterProxyModel, public QgsF
virtual QItemSelection mapSelectionFromMaster( const QItemSelection &selection ) const;
virtual QItemSelection mapSelectionToMaster( const QItemSelection &selection ) const;
QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const override;
QModelIndex parent( const QModelIndex &child ) const override;
int columnCount( const QModelIndex &parent = QModelIndex() ) const override;
int rowCount( const QModelIndex &parent = QModelIndex() ) const override;
@ -122,6 +121,23 @@ class GUI_EXPORT QgsFeatureListModel : public QSortFilterProxyModel, public QgsF
QModelIndex fidToIndex( QgsFeatureId fid ) override;
QModelIndexList fidToIndexList( QgsFeatureId fid );
/**
* Sort this model by its display expression.
*
* \since QGIS 3.2
*/
bool sortByDisplayExpression() const;
/**
* Sort this model by its display expression.
*
* \note Not compatible with injectNull, if sorting by display expression is enabled,
* injectNull will automatically turned off.
*
* \since QGIS 3.2
*/
void setSortByDisplayExpression( bool sortByDisplayExpression );
public slots:
void onBeginRemoveRows( const QModelIndex &parent, int first, int last );
void onEndRemoveRows( const QModelIndex &parent, int first, int last );