QQmlDelegateModel: Refresh the view when a column is added at 0

It can happen that a model reports n>0 rows but columns=0 (See
QConcatenateTablesProxyModel). In those cases we would render glitchy
items until the elements are marked as dirty.

Pick-to: 6.2
Change-Id: I615c9cacbb1b6f9dee3898b03476605e5ac39d0a
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
Aleix Pol 2021-09-23 03:43:04 +02:00 committed by Aleix Pol Gonzalez
parent 5cee9766bb
commit ec9251efb9
4 changed files with 86 additions and 0 deletions

View File

@ -389,6 +389,12 @@ void QQmlDelegateModelPrivate::connectToAbstractItemModel()
q, QQmlDelegateModel, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
qmlobject_connect(aim, QAbstractItemModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
q, QQmlDelegateModel, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)));
qmlobject_connect(aim, QAbstractItemModel, SIGNAL(columnsInserted(QModelIndex,int,int)),
q, QQmlDelegateModel, SLOT(_q_columnsInserted(QModelIndex,int,int)));
qmlobject_connect(aim, QAbstractItemModel, SIGNAL(columnsRemoved(QModelIndex,int,int)),
q, QQmlDelegateModel, SLOT(_q_columnsRemoved(QModelIndex,int,int)));
qmlobject_connect(aim, QAbstractItemModel, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)),
q, QQmlDelegateModel, SLOT(_q_columnsMoved(QModelIndex,int,int,QModelIndex,int)));
qmlobject_connect(aim, QAbstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
q, QQmlDelegateModel, SLOT(_q_dataChanged(QModelIndex,QModelIndex,QVector<int>)));
qmlobject_connect(aim, QAbstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
@ -413,6 +419,12 @@ void QQmlDelegateModelPrivate::disconnectFromAbstractItemModel()
q, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)));
QObject::disconnect(aim, SIGNAL(rowsRemoved(QModelIndex,int,int)),
q, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
QObject::disconnect(aim, SIGNAL(columnsInserted(QModelIndex,int,int)), q,
SLOT(_q_columnsInserted(QModelIndex,int,int)));
QObject::disconnect(aim, SIGNAL(columnsRemoved(QModelIndex,int,int)), q,
SLOT(_q_columnsRemoved(QModelIndex,int,int)));
QObject::disconnect(aim, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)), q,
SLOT(_q_columnsMoved(QModelIndex,int,int,QModelIndex,int)));
QObject::disconnect(aim, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
q, SLOT(_q_dataChanged(QModelIndex,QModelIndex,QVector<int>)));
QObject::disconnect(aim, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
@ -1970,6 +1982,38 @@ void QQmlDelegateModel::_q_rowsMoved(
}
}
void QQmlDelegateModel::_q_columnsInserted(const QModelIndex &parent, int begin, int end)
{
Q_D(QQmlDelegateModel);
Q_UNUSED(end);
if (parent == d->m_adaptorModel.rootIndex && begin == 0) {
// mark all items as changed
_q_itemsChanged(0, d->m_count, QVector<int>());
}
}
void QQmlDelegateModel::_q_columnsRemoved(const QModelIndex &parent, int begin, int end)
{
Q_D(QQmlDelegateModel);
Q_UNUSED(end);
if (parent == d->m_adaptorModel.rootIndex && begin == 0) {
// mark all items as changed
_q_itemsChanged(0, d->m_count, QVector<int>());
}
}
void QQmlDelegateModel::_q_columnsMoved(const QModelIndex &parent, int start, int end,
const QModelIndex &destination, int column)
{
Q_D(QQmlDelegateModel);
Q_UNUSED(end);
if ((parent == d->m_adaptorModel.rootIndex && start == 0)
|| (destination == d->m_adaptorModel.rootIndex && column == 0)) {
// mark all items as changed
_q_itemsChanged(0, d->m_count, QVector<int>());
}
}
void QQmlDelegateModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end, const QVector<int> &roles)
{
Q_D(QQmlDelegateModel);

View File

@ -152,6 +152,9 @@ private Q_SLOTS:
void _q_itemsMoved(int from, int to, int count);
void _q_modelReset();
void _q_rowsInserted(const QModelIndex &,int,int);
void _q_columnsInserted(const QModelIndex &, int, int);
void _q_columnsRemoved(const QModelIndex &, int, int);
void _q_columnsMoved(const QModelIndex &, int, int, const QModelIndex &, int);
void _q_rowsAboutToBeRemoved(const QModelIndex &parent, int begin, int end);
void _q_rowsRemoved(const QModelIndex &,int,int);
void _q_rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int);

View File

@ -0,0 +1,11 @@
import QtQuick 2.8
ListView {
id: root
width: 200
height: 200
delegate: Text {
text: display
}
}

View File

@ -27,11 +27,14 @@
****************************************************************************/
#include <QtTest/qtest.h>
#include <QtCore/QConcatenateTablesProxyModel>
#include <QtGui/QStandardItemModel>
#include <QtQml/qqmlcomponent.h>
#include <QtQmlModels/private/qqmldelegatemodel_p.h>
#include <QtQuick/qquickview.h>
#include <QtQuick/qquickitem.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtTest/QSignalSpy>
class tst_QQmlDelegateModel : public QQmlDataTest
{
@ -46,6 +49,7 @@ private slots:
void qtbug_86017();
void filterOnGroup_removeWhenCompleted();
void contextAccessedByHandler();
void redrawUponColumnChange();
};
class AbstractItemModel : public QAbstractItemModel
@ -175,6 +179,30 @@ void tst_QQmlDelegateModel::contextAccessedByHandler()
QVERIFY(root->property("works").toBool());
}
void tst_QQmlDelegateModel::redrawUponColumnChange()
{
QStandardItemModel m1;
m1.appendRow({
new QStandardItem("Banana"),
new QStandardItem("Coconut"),
});
QQuickView view(testFileUrl("redrawUponColumnChange.qml"));
QCOMPARE(view.status(), QQuickView::Ready);
view.show();
QQuickItem *root = view.rootObject();
root->setProperty("model", QVariant::fromValue<QObject *>(&m1));
QObject *item = root->property("currentItem").value<QObject *>();
QVERIFY(item);
QCOMPARE(item->property("text").toString(), "Banana");
QVERIFY(root);
m1.removeColumn(0);
QCOMPARE(item->property("text").toString(), "Coconut");
}
QTEST_MAIN(tst_QQmlDelegateModel)
#include "tst_qqmldelegatemodel.moc"