QQuickTableView: Expose internal model changes via the model property
If the delegate changes the model, those changes need to be visible in the "model" property of the view. To this end, use QQmlTableInstanceModel's model variant instead of the assigned one once it has been synchronized. The inner change signaling from the delegates to the view will be added in a separate change. Pick-to: 6.10 Task-number: QTBUG-139941 Change-Id: I1296fa2c886dad063b6b39defef56cb7faf1e943 Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
This commit is contained in:
parent
7105eb6d0d
commit
a5ad373e6e
|
@ -452,7 +452,7 @@ QVariant QQmlTableInstanceModel::model() const
|
|||
return m_adaptorModel.model();
|
||||
}
|
||||
|
||||
void QQmlTableInstanceModel::setModel(const QVariant &model)
|
||||
void QQmlTableInstanceModel::forceSetModel(const QVariant &model)
|
||||
{
|
||||
// Pooled items are still accessible/alive for the application, and
|
||||
// needs to stay in sync with the model. So we need to drain the pool
|
||||
|
@ -469,6 +469,16 @@ void QQmlTableInstanceModel::setModel(const QVariant &model)
|
|||
}
|
||||
}
|
||||
|
||||
void QQmlTableInstanceModel::setModel(const QVariant &model)
|
||||
{
|
||||
if (m_adaptorModel.model() == model)
|
||||
return;
|
||||
|
||||
forceSetModel(model);
|
||||
|
||||
emit modelChanged();
|
||||
}
|
||||
|
||||
void QQmlTableInstanceModel::dataChangedCallback(const QModelIndex &begin, const QModelIndex &end, const QVector<int> &roles)
|
||||
{
|
||||
// This function is called when model data has changed. In that case, we tell the adaptor model
|
||||
|
@ -494,8 +504,11 @@ void QQmlTableInstanceModel::modelAboutToBeResetCallback()
|
|||
auto const aim = abstractItemModel();
|
||||
auto oldRoleNames = aim->roleNames();
|
||||
QObject::connect(aim, &QAbstractItemModel::modelReset, this, [this, aim, oldRoleNames](){
|
||||
if (oldRoleNames != aim->roleNames())
|
||||
setModel(model());
|
||||
if (oldRoleNames != aim->roleNames()) {
|
||||
// We refresh the model, but without sending any signals. The actual model object
|
||||
// stays the same after all.
|
||||
forceSetModel(model());
|
||||
}
|
||||
}, Qt::SingleShotConnection);
|
||||
}
|
||||
|
||||
|
|
|
@ -102,6 +102,9 @@ public:
|
|||
|
||||
QQmlDelegateModelItem *getModelItem(int index);
|
||||
|
||||
signals:
|
||||
void modelChanged();
|
||||
|
||||
private:
|
||||
enum DestructionMode {
|
||||
Deferred,
|
||||
|
@ -129,6 +132,7 @@ private:
|
|||
|
||||
void dataChangedCallback(const QModelIndex &begin, const QModelIndex &end, const QVector<int> &roles);
|
||||
void modelAboutToBeResetCallback();
|
||||
void forceSetModel(const QVariant &model);
|
||||
|
||||
static bool isDoneIncubating(QQmlDelegateModelItem *modelItem);
|
||||
static void deleteModelItemLater(QQmlDelegateModelItem *modelItem);
|
||||
|
|
|
@ -4573,12 +4573,17 @@ void QQuickTableViewPrivate::syncDelegateModelAccess()
|
|||
|
||||
QVariant QQuickTableViewPrivate::modelImpl() const
|
||||
{
|
||||
return assignedModel;
|
||||
if (needsModelSynchronization)
|
||||
return assignedModel;
|
||||
if (tableModel)
|
||||
return tableModel->model();
|
||||
return QVariant::fromValue(model);
|
||||
}
|
||||
|
||||
void QQuickTableViewPrivate::setModelImpl(const QVariant &newModel)
|
||||
{
|
||||
assignedModel = newModel;
|
||||
needsModelSynchronization = true;
|
||||
scheduleRebuildTable(QQuickTableViewPrivate::RebuildOption::All);
|
||||
emit q_func()->modelChanged();
|
||||
}
|
||||
|
@ -4612,6 +4617,7 @@ void QQuickTableViewPrivate::syncModel()
|
|||
tableModel->setModel(assignedModel);
|
||||
}
|
||||
|
||||
needsModelSynchronization = false;
|
||||
connectToModel();
|
||||
}
|
||||
|
||||
|
@ -4748,6 +4754,11 @@ void QQuickTableViewPrivate::connectToModel()
|
|||
} else {
|
||||
QObjectPrivate::connect(model, &QQmlInstanceModel::modelUpdated, this, &QQuickTableViewPrivate::modelUpdated);
|
||||
}
|
||||
|
||||
if (tableModel) {
|
||||
QObject::connect(tableModel, &QQmlTableInstanceModel::modelChanged,
|
||||
q, &QQuickTableView::modelChanged);
|
||||
}
|
||||
}
|
||||
|
||||
void QQuickTableViewPrivate::disconnectFromModel()
|
||||
|
@ -4774,6 +4785,11 @@ void QQuickTableViewPrivate::disconnectFromModel()
|
|||
} else {
|
||||
QObjectPrivate::disconnect(model, &QQmlInstanceModel::modelUpdated, this, &QQuickTableViewPrivate::modelUpdated);
|
||||
}
|
||||
|
||||
if (tableModel) {
|
||||
QObject::disconnect(tableModel, &QQmlTableInstanceModel::modelChanged,
|
||||
q, &QQuickTableView::modelChanged);
|
||||
}
|
||||
}
|
||||
|
||||
void QQuickTableViewPrivate::modelUpdated(const QQmlChangeSet &changeSet, bool reset)
|
||||
|
|
|
@ -427,6 +427,7 @@ public:
|
|||
QItemSelectionModel::SelectionFlag selectionFlag = QItemSelectionModel::NoUpdate;
|
||||
std::function<void(CallBackFlag)> selectableCallbackFunction;
|
||||
bool inSelectionModelUpdate = false;
|
||||
bool needsModelSynchronization = false;
|
||||
|
||||
int assignedPositionViewAtRowAfterRebuild = 0;
|
||||
int assignedPositionViewAtColumnAfterRebuild = 0;
|
||||
|
|
|
@ -68,6 +68,19 @@ Item {
|
|||
property int y: 12
|
||||
}
|
||||
|
||||
function aAt0() : real {
|
||||
switch (modelIndex) {
|
||||
case Model.Singular:
|
||||
case Model.List:
|
||||
return model.get(0).a
|
||||
case Model.Array:
|
||||
return model[0].a
|
||||
case Model.Object:
|
||||
return model.a
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
property int modelIndex: Model.None
|
||||
property int delegateIndex: Delegate.None
|
||||
|
||||
|
|
|
@ -8382,6 +8382,18 @@ void tst_QQuickTableView::delegateModelAccess()
|
|||
? access != QQmlDelegateModel::ReadOnly
|
||||
: access == QQmlDelegateModel::ReadWrite;
|
||||
|
||||
const bool writeShouldPropagate =
|
||||
|
||||
// If we've explicitly asked for the model to be written, it is
|
||||
(access == QQmlDelegateModel::ReadWrite) ||
|
||||
|
||||
// If it's a QAIM or an object, it's implicitly written
|
||||
(modelKind != Model::Kind::Array) ||
|
||||
|
||||
// When writing through the model object from a typed delegate,
|
||||
// (like with DelegateModel).
|
||||
(access == QQmlDelegateModel::Qt5ReadWrite && delegateKind == Delegate::Typed);
|
||||
|
||||
double expected = 11;
|
||||
|
||||
QCOMPARE(delegate->property("immediateX").toDouble(), expected);
|
||||
|
@ -8394,6 +8406,10 @@ void tst_QQuickTableView::delegateModelAccess()
|
|||
QCOMPARE(delegate->property("immediateX").toDouble(), expected);
|
||||
QCOMPARE(delegate->property("modelX").toDouble(), expected);
|
||||
|
||||
double aAt0 = -1;
|
||||
QMetaObject::invokeMethod(tableView, "aAt0", Q_RETURN_ARG(double, aAt0));
|
||||
QCOMPARE(aAt0, writeShouldPropagate ? expected : 11);
|
||||
|
||||
if (immediateWritable)
|
||||
expected = 1;
|
||||
|
||||
|
@ -8404,6 +8420,10 @@ void tst_QQuickTableView::delegateModelAccess()
|
|||
delegateKind == Delegate::Untyped ? expected : 1);
|
||||
|
||||
QCOMPARE(delegate->property("modelX").toDouble(), expected);
|
||||
|
||||
aAt0 = -1;
|
||||
QMetaObject::invokeMethod(tableView, "aAt0", Q_RETURN_ARG(double, aAt0));
|
||||
QCOMPARE(aAt0, writeShouldPropagate ? expected : 11);
|
||||
}
|
||||
|
||||
void tst_QQuickTableView::checkVisualRowColumnAfterReorder()
|
||||
|
|
Loading…
Reference in New Issue