Skip to content
Permalink
Browse files

Attribute table selection: performance improvements

When selecting features with the mouse (click and drag) only redraw
the map canvas, once the mouse is released.
  • Loading branch information
m-kuhn committed Apr 8, 2013
1 parent af4c4be commit 43dfeb5759b2889d31cf36d4eb7d7cd27bfe44bd
@@ -179,7 +179,10 @@ void QgsAttributeTableFilterModel::masterSelectionChanged( const QItemSelection
}

// Now emit the signal
layer()->setSelectedFeatures( layer()->selectedFeaturesIds() );
if ( mSyncSelection )
{
layer()->setSelectedFeatures( layer()->selectedFeaturesIds() );
}

connect( layer(), SIGNAL( selectionChanged() ), this, SLOT( selectionChanged() ) );
}
@@ -321,6 +324,17 @@ QItemSelectionModel* QgsAttributeTableFilterModel::masterSelection()
return mMasterSelection;
}

void QgsAttributeTableFilterModel::disableSelectionSync()
{
mSyncSelection = false;
}

void QgsAttributeTableFilterModel::enableSelectionSync()
{
mSyncSelection = true;
layer()->setSelectedFeatures( layer()->selectedFeaturesIds() );
}

QModelIndex QgsAttributeTableFilterModel::mapToMaster( const QModelIndex &proxyIndex ) const
{
// Master is source
@@ -91,6 +91,11 @@ class GUI_EXPORT QgsAttributeTableFilterModel: public QSortFilterProxyModel
*/
inline QgsVectorLayer *layer() const { return masterModel()->layer(); }

/**
* Returns the layerCache this filter acts on.
*
* @return The layer cache
*/
inline QgsVectorLayerCache *layerCache() const { return masterModel()->layerCache(); }

/**
@@ -120,6 +125,21 @@ class GUI_EXPORT QgsAttributeTableFilterModel: public QSortFilterProxyModel
*/
QItemSelectionModel* masterSelection();

/**
* Disables selection synchronisation with the map canvas. Changes to the selection in the master
* model are propagated to the layer, but no redraw is requested until @link{enableSelectionSync()}
* is called.
*/
void disableSelectionSync();

/**
* Enables selection synchronisation with the map canvas. Changes to the selection in the master
* are propagated and upon every change, a redraw will be requested. This method will update the
* selection to account for any cached selection change since @link{disableSelectionSync()} was
* called.
*/
void enableSelectionSync();

virtual QModelIndex mapToMaster( const QModelIndex &proxyIndex ) const;

virtual QModelIndex mapFromMaster( const QModelIndex &sourceIndex ) const;
@@ -194,6 +214,7 @@ class GUI_EXPORT QgsAttributeTableFilterModel: public QSortFilterProxyModel
bool mSelectedOnTop;
QItemSelectionModel* mMasterSelection;
QgsAttributeTableModel* mTableModel;
bool mSyncSelection;
};

#endif
@@ -46,7 +46,7 @@ QgsAttributeTableView::QgsAttributeTableView( QWidget *parent )
setSelectionMode( QAbstractItemView::ExtendedSelection );
setSortingEnabled( true );

connect( verticalHeader(), SIGNAL( sectionClicked( int ) ), SLOT( onVerticalHeaderSectionClicked( int ) ) );
verticalHeader()->viewport()->installEventFilter( this );
}

QgsAttributeTableView::~QgsAttributeTableView()
@@ -75,6 +75,30 @@ void QgsAttributeTableView::setCanvasAndLayerCache( QgsMapCanvas *canvas, QgsVec
delete filterModel;
}

bool QgsAttributeTableView::eventFilter(QObject *object, QEvent *event)
{
if ( object == verticalHeader()->viewport() )
{

qDebug() << "Event " << event->type();

switch ( event->type() )
{
case QEvent::MouseButtonPress:
mFilterModel->disableSelectionSync();
break;

case QEvent::MouseButtonRelease:
mFilterModel->enableSelectionSync();
break;

default:
break;
}
}
return false;
}

void QgsAttributeTableView::setModel( QgsAttributeTableFilterModel* filterModel )
{
if ( mFilterModel )
@@ -158,22 +182,6 @@ void QgsAttributeTableView::keyPressEvent( QKeyEvent *event )
}
}

void QgsAttributeTableView::onVerticalHeaderSectionClicked( int logicalIndex )
{
Q_UNUSED( logicalIndex )

QgsFeatureIds selectedFeatures;

QModelIndexList selectedRows = selectionModel()->selectedRows();

foreach ( QModelIndex row, selectedRows )
{
selectedFeatures.insert( mFilterModel->rowToId( row ) );
}

emit selectionChangeFinished( selectedFeatures );
}

void QgsAttributeTableView::onFilterAboutToBeInvalidated()
{
disconnect( selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ), this, SLOT( onSelectionChanged( QItemSelection, QItemSelection ) ) );
@@ -63,6 +63,18 @@ class GUI_EXPORT QgsAttributeTableView : public QTableView
*/
void setCanvasAndLayerCache( QgsMapCanvas *canvas, QgsVectorLayerCache *layerCache );

/**
* This event filter is installed on the verticalHeader to intercept mouse press and release
* events. These are used to disable / enable live synchronisation with the map canvas selection
* which can be slow due to recurring canvas repaints. Updating the
*
* @param object The object which is the target of the event.
* @param event The intercepted event
*
* @return Returns always false, so the event gets processed
*/
virtual bool eventFilter( QObject* object, QEvent* event );

protected:
/**
* Called for mouse press events on a table cell.
@@ -124,23 +136,7 @@ class GUI_EXPORT QgsAttributeTableView : public QTableView

void finished();

/**
* @brief
* Is emitted, after the selection has been changed.
*
* @param selectedFeatures A list of currently selected features.
*/
void selectionChangeFinished( const QgsFeatureIds &selectedFeatures );

public slots:
/**
* Is triggered after a mouse release event on the vertical header.
* Emits a selectionChangeFinished() signal, so the underlying sort filter
* can adapt to the current selection without disturbing the users current interaction.
*
* @param logicalIndex The section's logical index
*/
void onVerticalHeaderSectionClicked( int logicalIndex );
void onFilterAboutToBeInvalidated();
void onFilterInvalidated();
void onSelectionChanged( const QItemSelection& selected, const QItemSelection& deselected );
@@ -238,3 +238,13 @@ int QgsFeatureListModel::rowCount( const QModelIndex& parent ) const
Q_UNUSED( parent )
return sourceModel()->rowCount();
}

void QgsFeatureListModel::disableSelectionSync()
{
mFilterModel->disableSelectionSync();
}

void QgsFeatureListModel::enableSelectionSync()
{
mFilterModel->enableSelectionSync();
}
@@ -85,6 +85,21 @@ class QgsFeatureListModel : public QAbstractProxyModel
virtual int columnCount( const QModelIndex&parent = QModelIndex() ) const;
virtual int rowCount( const QModelIndex& parent = QModelIndex() ) const;

/**
* Disables selection synchronisation with the map canvas. Changes to the selection in the master
* model are propagated to the layer, but no redraw is requested until @link{enableSelectionSync()}
* is called.
*/
void disableSelectionSync();

/**
* Enables selection synchronisation with the map canvas. Changes to the selection in the master
* are propagated and upon every change, a redraw will be requested. This method will update the
* selection to account for any cached selection change since @link{disableSelectionSync()} was
* called.
*/
void enableSelectionSync();

public slots:
void onBeginRemoveRows( const QModelIndex& parent, int first, int last );
void onEndRemoveRows( const QModelIndex& parent, int first, int last );
@@ -115,15 +115,22 @@ void QgsFeatureListView::mousePressEvent( QMouseEvent *event )
}
else
{
mModel->disableSelectionSync();
QListView::mousePressEvent( event );
}
}

void QgsFeatureListView::mouseReleaseEvent( QMouseEvent *event )
{
mEditSelectionDrag = false;

QListView::mouseReleaseEvent( event );
if ( mEditSelectionDrag )
{
mEditSelectionDrag = false;
}
else
{
QListView::mouseReleaseEvent( event );
mModel->enableSelectionSync();
}
}

void QgsFeatureListView::editSelectionChanged( QItemSelection deselected, QItemSelection selected )

0 comments on commit 43dfeb5

Please sign in to comment.
You can’t perform that action at this time.