Skip to content

Commit 3fcabc9

Browse files
committed
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
1 parent 6d1e554 commit 3fcabc9

File tree

5 files changed

+24
-44
lines changed

5 files changed

+24
-44
lines changed

python/gui/attributetable/qgsattributetabledelegate.sip

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,14 @@ class QgsAttributeTableDelegate : QItemDelegate
4040

4141
void setFeatureSelectionModel( QgsFeatureSelectionModel* featureSelectionModel );
4242

43+
signals:
4344
/**
44-
* Set an image that represents an action widget
45+
* Is emitted when an action column item is painted.
46+
* The consumer of this signal can initialize the index widget.
47+
*
48+
* @note This signal is emitted repeatedly whenever the item is being painted.
49+
* It is the consumers responsibility to check if initialization has already
50+
* happened before.
4551
*/
46-
void setActionWidgetImage( const QImage& image );
52+
void actionColumnItemPainted( const QModelIndex& index ) const;
4753
};

src/gui/attributetable/qgsattributetabledelegate.cpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -118,20 +118,13 @@ void QgsAttributeTableDelegate::setFeatureSelectionModel( QgsFeatureSelectionMod
118118
mFeatureSelectionModel = featureSelectionModel;
119119
}
120120

121-
void QgsAttributeTableDelegate::setActionWidgetImage( const QImage& image )
122-
{
123-
mActionWidgetImage = image;
124-
}
125-
126-
127121
void QgsAttributeTableDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
128122
{
129123
QgsAttributeTableFilterModel::ColumnType columnType = static_cast<QgsAttributeTableFilterModel::ColumnType>( index.model()->data( index, QgsAttributeTableFilterModel::TypeRole ).toInt() );
130124

131125
if ( columnType == QgsAttributeTableFilterModel::ColumnTypeActionButton )
132126
{
133-
QRect r = option.rect.adjusted( -1, 0, 0, 0 );
134-
painter->drawImage( r.x(), r.y(), mActionWidgetImage );
127+
emit actionColumnItemPainted( index );
135128
}
136129
else
137130
{

src/gui/attributetable/qgsattributetabledelegate.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,15 +77,20 @@ class GUI_EXPORT QgsAttributeTableDelegate : public QItemDelegate
7777

7878
void setFeatureSelectionModel( QgsFeatureSelectionModel* featureSelectionModel );
7979

80+
signals:
8081
/**
81-
* Set an image that represents an action widget
82+
* Is emitted when an action column item is painted.
83+
* The consumer of this signal can initialize the index widget.
84+
*
85+
* @note This signal is emitted repeatedly whenever the item is being painted.
86+
* It is the consumers responsibility to check if initialization has already
87+
* happened before.
8288
*/
83-
void setActionWidgetImage( const QImage& image );
89+
void actionColumnItemPainted( const QModelIndex& index ) const;
8490

8591
private:
8692
QgsVectorLayer* mLayer;
8793
QgsFeatureSelectionModel* mFeatureSelectionModel;
88-
QImage mActionWidgetImage;
8994
};
9095

9196
#endif //QGSATTRIBUTETABLEDELEGATE_H

src/gui/attributetable/qgsattributetableview.cpp

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,12 @@
3535

3636
QgsAttributeTableView::QgsAttributeTableView( QWidget *parent )
3737
: QTableView( parent )
38-
, mMasterModel( nullptr )
3938
, mFilterModel( nullptr )
4039
, mFeatureSelectionModel( nullptr )
4140
, mFeatureSelectionManager( nullptr )
42-
, mModel( nullptr )
4341
, mActionPopup( nullptr )
4442
, mRowSectionAnchor( 0 )
4543
, mCtrlDragSelectionFlag( QItemSelectionModel::Select )
46-
, mActionWidget( nullptr )
4744
{
4845
QSettings settings;
4946
restoreGeometry( settings.value( "/BetterAttributeTable/geometry" ).toByteArray() );
@@ -52,8 +49,6 @@ QgsAttributeTableView::QgsAttributeTableView( QWidget *parent )
5249
horizontalHeader()->setHighlightSections( false );
5350

5451
// We need mouse move events to create the action button on hover
55-
setMouseTracking( true );
56-
5752
mTableDelegate = new QgsAttributeTableDelegate( this );
5853
setItemDelegate( mTableDelegate );
5954

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

126122
delete mFeatureSelectionModel;
@@ -138,10 +134,6 @@ void QgsAttributeTableView::setModel( QgsAttributeTableFilterModel* filterModel
138134
mTableDelegate->setFeatureSelectionModel( mFeatureSelectionModel );
139135
connect( mFeatureSelectionModel, SIGNAL( requestRepaint( QModelIndexList ) ), this, SLOT( repaintRequested( QModelIndexList ) ) );
140136
connect( mFeatureSelectionModel, SIGNAL( requestRepaint() ), this, SLOT( repaintRequested() ) );
141-
142-
mActionWidget.reset( createActionWidget( 0 ) );
143-
mActionWidget->setVisible( false );
144-
updateActionImage( mActionWidget.data() );
145137
}
146138
}
147139

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

239231
void QgsAttributeTableView::mouseMoveEvent( QMouseEvent *event )
240232
{
241-
QModelIndex index = indexAt( event->pos() );
242-
if ( index.data( QgsAttributeTableFilterModel::TypeRole ) == QgsAttributeTableFilterModel::ColumnTypeActionButton )
243-
{
244-
Q_ASSERT( index.isValid() );
245-
246-
if ( !indexWidget( index ) )
247-
setIndexWidget( index, createActionWidget( mFilterModel->data( index, QgsAttributeTableModel::FeatureIdRole ).toLongLong() ) );
248-
}
249-
250233
setSelectionMode( QAbstractItemView::NoSelection );
251234
QTableView::mouseMoveEvent( event );
252235
setSelectionMode( QAbstractItemView::ExtendedSelection );
@@ -396,18 +379,13 @@ void QgsAttributeTableView::actionTriggered()
396379
void QgsAttributeTableView::columnSizeChanged( int index, int oldWidth, int newWidth )
397380
{
398381
Q_UNUSED( oldWidth )
399-
if ( mFilterModel->actionColumnIndex() == index )
400-
{
401-
mActionWidget->resize( newWidth, mActionWidget->height() );
402-
updateActionImage( mActionWidget.data() );
403-
}
404382
emit columnResized( index, newWidth );
405383
}
406384

407-
void QgsAttributeTableView::updateActionImage( QWidget* widget )
385+
void QgsAttributeTableView::onActionColumnItemPainted( const QModelIndex& index )
408386
{
409-
QImage image( widget->size(), QImage::Format_ARGB32_Premultiplied );
410-
QPainter painter( &image );
411-
widget->render( &painter );
412-
mTableDelegate->setActionWidgetImage( image );
387+
if ( !indexWidget( index ) )
388+
{
389+
setIndexWidget( index, createActionWidget( mFilterModel->data( index, QgsAttributeTableModel::FeatureIdRole ).toLongLong() ) );
390+
}
413391
}

src/gui/attributetable/qgsattributetableview.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,22 +155,20 @@ class GUI_EXPORT QgsAttributeTableView : public QTableView
155155
void showHorizontalSortIndicator();
156156
void actionTriggered();
157157
void columnSizeChanged( int index, int oldWidth, int newWidth );
158+
void onActionColumnItemPainted( const QModelIndex& index );
158159

159160
private:
160161
void updateActionImage( QWidget* widget );
161162
QWidget* createActionWidget( QgsFeatureId fid );
162163

163164
void selectRow( int row, bool anchor );
164-
QgsAttributeTableModel* mMasterModel;
165165
QgsAttributeTableFilterModel* mFilterModel;
166166
QgsFeatureSelectionModel* mFeatureSelectionModel;
167167
QgsIFeatureSelectionManager* mFeatureSelectionManager;
168168
QgsAttributeTableDelegate* mTableDelegate;
169-
QAbstractItemModel* mModel; // Most likely the filter model
170169
QMenu *mActionPopup;
171170
int mRowSectionAnchor;
172171
QItemSelectionModel::SelectionFlag mCtrlDragSelectionFlag;
173-
QScopedPointer<QWidget> mActionWidget;
174172
};
175173

176174
#endif

0 commit comments

Comments
 (0)