Skip to content
Permalink
Browse files

Fix action column widget rendering artifacts

This creates an action column widget when the widget is rendered for the
first time.
The original approach was to create an image and render the buffered
image onto the cell until the first mouse action triggered the creation
of the real widget. This led to several rendering problems and triggered
some strange ownership issues with crashes under certain situations.

Followup a05b2ad
  • Loading branch information
m-kuhn committed Jun 14, 2016
1 parent 6d1e554 commit 3fcabc96fed7d68a59a7ba8e6face5650a23a8a7
@@ -40,8 +40,14 @@ class QgsAttributeTableDelegate : QItemDelegate

void setFeatureSelectionModel( QgsFeatureSelectionModel* featureSelectionModel );

signals:
/**
* Set an image that represents an action widget
* Is emitted when an action column item is painted.
* The consumer of this signal can initialize the index widget.
*
* @note This signal is emitted repeatedly whenever the item is being painted.
* It is the consumers responsibility to check if initialization has already
* happened before.
*/
void setActionWidgetImage( const QImage& image );
void actionColumnItemPainted( const QModelIndex& index ) const;
};
@@ -118,20 +118,13 @@ void QgsAttributeTableDelegate::setFeatureSelectionModel( QgsFeatureSelectionMod
mFeatureSelectionModel = featureSelectionModel;
}

void QgsAttributeTableDelegate::setActionWidgetImage( const QImage& image )
{
mActionWidgetImage = image;
}


void QgsAttributeTableDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
QgsAttributeTableFilterModel::ColumnType columnType = static_cast<QgsAttributeTableFilterModel::ColumnType>( index.model()->data( index, QgsAttributeTableFilterModel::TypeRole ).toInt() );

if ( columnType == QgsAttributeTableFilterModel::ColumnTypeActionButton )
{
QRect r = option.rect.adjusted( -1, 0, 0, 0 );
painter->drawImage( r.x(), r.y(), mActionWidgetImage );
emit actionColumnItemPainted( index );
}
else
{
@@ -77,15 +77,20 @@ class GUI_EXPORT QgsAttributeTableDelegate : public QItemDelegate

void setFeatureSelectionModel( QgsFeatureSelectionModel* featureSelectionModel );

signals:
/**
* Set an image that represents an action widget
* Is emitted when an action column item is painted.
* The consumer of this signal can initialize the index widget.
*
* @note This signal is emitted repeatedly whenever the item is being painted.
* It is the consumers responsibility to check if initialization has already
* happened before.
*/
void setActionWidgetImage( const QImage& image );
void actionColumnItemPainted( const QModelIndex& index ) const;

private:
QgsVectorLayer* mLayer;
QgsFeatureSelectionModel* mFeatureSelectionModel;
QImage mActionWidgetImage;
};

#endif //QGSATTRIBUTETABLEDELEGATE_H
@@ -35,15 +35,12 @@

QgsAttributeTableView::QgsAttributeTableView( QWidget *parent )
: QTableView( parent )
, mMasterModel( nullptr )
, mFilterModel( nullptr )
, mFeatureSelectionModel( nullptr )
, mFeatureSelectionManager( nullptr )
, mModel( nullptr )
, mActionPopup( nullptr )
, mRowSectionAnchor( 0 )
, mCtrlDragSelectionFlag( QItemSelectionModel::Select )
, mActionWidget( nullptr )
{
QSettings settings;
restoreGeometry( settings.value( "/BetterAttributeTable/geometry" ).toByteArray() );
@@ -52,8 +49,6 @@ QgsAttributeTableView::QgsAttributeTableView( QWidget *parent )
horizontalHeader()->setHighlightSections( false );

// We need mouse move events to create the action button on hover
setMouseTracking( true );

mTableDelegate = new QgsAttributeTableDelegate( this );
setItemDelegate( mTableDelegate );

@@ -121,6 +116,7 @@ void QgsAttributeTableView::setModel( QgsAttributeTableFilterModel* filterModel
if ( mFilterModel )
{
connect( mFilterModel, SIGNAL( destroyed() ), this, SLOT( modelDeleted() ) );
connect( mTableDelegate, SIGNAL( actionColumnItemPainted( QModelIndex ) ), this, SLOT( onActionColumnItemPainted( QModelIndex ) ) );
}

delete mFeatureSelectionModel;
@@ -138,10 +134,6 @@ void QgsAttributeTableView::setModel( QgsAttributeTableFilterModel* filterModel
mTableDelegate->setFeatureSelectionModel( mFeatureSelectionModel );
connect( mFeatureSelectionModel, SIGNAL( requestRepaint( QModelIndexList ) ), this, SLOT( repaintRequested( QModelIndexList ) ) );
connect( mFeatureSelectionModel, SIGNAL( requestRepaint() ), this, SLOT( repaintRequested() ) );

mActionWidget.reset( createActionWidget( 0 ) );
mActionWidget->setVisible( false );
updateActionImage( mActionWidget.data() );
}
}

@@ -238,15 +230,6 @@ void QgsAttributeTableView::mouseReleaseEvent( QMouseEvent *event )

void QgsAttributeTableView::mouseMoveEvent( QMouseEvent *event )
{
QModelIndex index = indexAt( event->pos() );
if ( index.data( QgsAttributeTableFilterModel::TypeRole ) == QgsAttributeTableFilterModel::ColumnTypeActionButton )
{
Q_ASSERT( index.isValid() );

if ( !indexWidget( index ) )
setIndexWidget( index, createActionWidget( mFilterModel->data( index, QgsAttributeTableModel::FeatureIdRole ).toLongLong() ) );
}

setSelectionMode( QAbstractItemView::NoSelection );
QTableView::mouseMoveEvent( event );
setSelectionMode( QAbstractItemView::ExtendedSelection );
@@ -396,18 +379,13 @@ void QgsAttributeTableView::actionTriggered()
void QgsAttributeTableView::columnSizeChanged( int index, int oldWidth, int newWidth )
{
Q_UNUSED( oldWidth )
if ( mFilterModel->actionColumnIndex() == index )
{
mActionWidget->resize( newWidth, mActionWidget->height() );
updateActionImage( mActionWidget.data() );
}
emit columnResized( index, newWidth );
}

void QgsAttributeTableView::updateActionImage( QWidget* widget )
void QgsAttributeTableView::onActionColumnItemPainted( const QModelIndex& index )
{
QImage image( widget->size(), QImage::Format_ARGB32_Premultiplied );
QPainter painter( &image );
widget->render( &painter );
mTableDelegate->setActionWidgetImage( image );
if ( !indexWidget( index ) )
{
setIndexWidget( index, createActionWidget( mFilterModel->data( index, QgsAttributeTableModel::FeatureIdRole ).toLongLong() ) );
}
}
@@ -155,22 +155,20 @@ class GUI_EXPORT QgsAttributeTableView : public QTableView
void showHorizontalSortIndicator();
void actionTriggered();
void columnSizeChanged( int index, int oldWidth, int newWidth );
void onActionColumnItemPainted( const QModelIndex& index );

private:
void updateActionImage( QWidget* widget );
QWidget* createActionWidget( QgsFeatureId fid );

void selectRow( int row, bool anchor );
QgsAttributeTableModel* mMasterModel;
QgsAttributeTableFilterModel* mFilterModel;
QgsFeatureSelectionModel* mFeatureSelectionModel;
QgsIFeatureSelectionManager* mFeatureSelectionManager;
QgsAttributeTableDelegate* mTableDelegate;
QAbstractItemModel* mModel; // Most likely the filter model
QMenu *mActionPopup;
int mRowSectionAnchor;
QItemSelectionModel::SelectionFlag mCtrlDragSelectionFlag;
QScopedPointer<QWidget> mActionWidget;
};

#endif

0 comments on commit 3fcabc9

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