Skip to content

Commit

Permalink
QAbstractItemView: don't calc update rect when there are to many indexes
Browse files Browse the repository at this point in the history
With 8de62d3 we try to avoid a complete
repaint by checking if the changed indexes are inside the visible rect.
This works fine when the amount of indexes to check is small but fails
otherwise. Therefore add a configurable, upper bound for this check.

Fixes: QTBUG-124173
Change-Id: I1aedd2cbe6e2d0090a640c8a1cf1cdb69f5b002a
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
  • Loading branch information
chehrlic committed Aug 10, 2024
1 parent c234700 commit ff33981
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 1 deletion.
39 changes: 38 additions & 1 deletion src/widgets/itemviews/qabstractitemview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ QAbstractItemViewPrivate::QAbstractItemViewPrivate()
delayedPendingLayout(true),
moveCursorUpdatedView(false),
verticalScrollModeSet(false),
horizontalScrollModeSet(false)
horizontalScrollModeSet(false),
updateThreshold(200)
{
keyboardInputTime.invalidate();
}
Expand Down Expand Up @@ -3203,6 +3204,37 @@ int QAbstractItemView::sizeHintForColumn(int column) const
return width;
}

/*!
\property QAbstractItemView::updateThreshold
\since 6.9
This property holds the amount of changed indexes to directly trigger
a full update of the view inside dataChanged().
The algorithm inside dataChanged() tries to minimize a full update of the
view by calculating if the changed indexes are visible or not. For very
large models, with a lot of large changes, this might take longer than the
actual update so it's counter-productive. This property gives the ability
to control the algorithm to skip the check and directly trigger a full
update when the amount of changed indexes exceeds the given value.
The default value is 200.
\sa dataChanged()
*/
uint32_t QAbstractItemView::updateThreshold() const
{
Q_D(const QAbstractItemView);
return d->updateThreshold;
}

void QAbstractItemView::setUpdateThreshold(uint32_t threshold)
{
Q_D(QAbstractItemView);
if (d->updateThreshold == threshold)
return;
d->updateThreshold = threshold;
}

/*!
Opens a persistent editor on the item at the given \a index.
If no editor exists, the delegate will create a new editor.
Expand Down Expand Up @@ -3397,6 +3429,11 @@ void QAbstractItemView::dataChanged(const QModelIndex &topLeft, const QModelInde
topLeft.row() > bottomRight.row() ||
topLeft.column() > bottomRight.column()) {
// invalid parameter - call update() to redraw all
Q_ASSERT(false);
d->viewport->update();
} else if ((bottomRight.row() - topLeft.row() + 1ULL) *
(bottomRight.column() - topLeft.column() + 1ULL) > d->updateThreshold) {
// too many indices to check - force full update
d->viewport->update();
} else {
const QRect updateRect = d->intersectedRect(d->viewport->rect(), topLeft, bottomRight);
Expand Down
5 changes: 5 additions & 0 deletions src/widgets/itemviews/qabstractitemview.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ class Q_WIDGETS_EXPORT QAbstractItemView : public QAbstractScrollArea
RESET resetVerticalScrollMode)
Q_PROPERTY(ScrollMode horizontalScrollMode READ horizontalScrollMode
WRITE setHorizontalScrollMode RESET resetHorizontalScrollMode)
Q_PROPERTY(uint32_t updateThreshold READ updateThreshold
WRITE setUpdateThreshold)

public:
enum SelectionMode {
Expand Down Expand Up @@ -177,6 +179,9 @@ class Q_WIDGETS_EXPORT QAbstractItemView : public QAbstractScrollArea
virtual int sizeHintForRow(int row) const;
virtual int sizeHintForColumn(int column) const;

uint32_t updateThreshold() const;
void setUpdateThreshold(uint32_t threshold);

void openPersistentEditor(const QModelIndex &index);
void closePersistentEditor(const QModelIndex &index);
bool isPersistentEditorOpen(const QModelIndex &index) const;
Expand Down
2 changes: 2 additions & 0 deletions src/widgets/itemviews/qabstractitemview_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,8 @@ class Q_AUTOTEST_EXPORT QAbstractItemViewPrivate : public QAbstractScrollAreaPri
bool verticalScrollModeSet;
bool horizontalScrollModeSet;

uint32_t updateThreshold;

virtual QRect visualRect(const QModelIndex &index) const { return q_func()->visualRect(index); }

std::array<QMetaObject::Connection, 14> modelConnections;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,10 @@ void tst_QAbstractItemView::getSetCheck()
QCOMPARE(20, obj1->autoScrollMargin());
obj1->setAutoScrollMargin(16);
QCOMPARE(16, obj1->autoScrollMargin());

QCOMPARE(200U, obj1->updateThreshold());
obj1->setUpdateThreshold(4711);
QCOMPARE(4711U, obj1->updateThreshold());
}

void tst_QAbstractItemView::cleanup()
Expand Down

0 comments on commit ff33981

Please sign in to comment.