diff options
author | Arttu Tarkiainen <arttu.tarkiainen@qt.io> | 2021-09-23 16:40:50 +0300 |
---|---|---|
committer | Arttu Tarkiainen <arttu.tarkiainen@qt.io> | 2021-10-28 07:11:49 +0000 |
commit | f64011e117e759754f7b4f2885f9bf335a6596ff (patch) | |
tree | f811214fcdbe6f5b666c92c7195a1c06fbffead8 /src/libs/installer | |
parent | 270c5dfd9b6c86bec8eaf34d0a2c3d3b945ed5e5 (diff) |
ComponentModel: Fix segfaults on reset when used with a proxy model
Resetting the model is split into two parts - 'ComponentModel
::setRootComponents' updates the root item list and emits
'QAbstractItemModel::modelReset' which was connected to a private
slot of the class that updates the component check state and then
emits 'QAbstractItemModel::dataChanged' for each component index.
The issue was that these could be emitted before the proxy model's
private slot that catches the source model reset and performs
invalidation had been invoked, causing the proxy model's slot
reacting to source model data changes to refer previously retrieved
source model indexes, which now had invalid information.
Fix by moving the post-reset operations to non-slot function
'ComponentModel::postModelReset()' which is called after the
'QAbstractItemModel::modelReset' is emitted, so that any directly
connected slots get invoked first.
Task-number: QTIFW-1404
Change-Id: If4d55110c93658689787484d0e8a8eb6b6da685d
Reviewed-by: Katja Marttila <katja.marttila@qt.io>
Diffstat (limited to 'src/libs/installer')
-rw-r--r-- | src/libs/installer/componentmodel.cpp | 22 | ||||
-rw-r--r-- | src/libs/installer/componentmodel.h | 4 |
2 files changed, 13 insertions, 13 deletions
diff --git a/src/libs/installer/componentmodel.cpp b/src/libs/installer/componentmodel.cpp index 642828ad7..aeaa0b2fc 100644 --- a/src/libs/installer/componentmodel.cpp +++ b/src/libs/installer/componentmodel.cpp @@ -101,7 +101,6 @@ ComponentModel::ComponentModel(int columns, PackageManagerCore *core) , m_modelState(DefaultChecked) { m_headerData.insert(0, columns, QVariant()); - connect(this, &QAbstractItemModel::modelReset, this, &ComponentModel::slotModelReset); } /*! @@ -417,6 +416,7 @@ void ComponentModel::setRootComponents(QList<QInstaller::Component*> rootCompone m_rootComponentList.append(component); } endResetModel(); + postModelReset(); } /*! @@ -459,7 +459,16 @@ void ComponentModel::setCheckedState(QInstaller::ComponentModel::ModelStateFlag // -- private slots -void ComponentModel::slotModelReset() +void ComponentModel::onVirtualStateChanged() +{ + // If the virtual state of a component changes, force a reset of the component model. + setRootComponents(m_core->components(PackageManagerCore::ComponentType::Root)); +} + + +// -- private + +void ComponentModel::postModelReset() { ComponentList components = m_rootComponentList; if (!m_core->isUpdater()) { @@ -485,15 +494,6 @@ void ComponentModel::slotModelReset() updateAndEmitModelState(); // update the internal state } -void ComponentModel::onVirtualStateChanged() -{ - // If the virtual state of a component changes, force a reset of the component model. - setRootComponents(m_core->components(PackageManagerCore::ComponentType::Root)); -} - - -// -- private - void ComponentModel::updateAndEmitModelState() { m_modelState = ComponentModel::DefaultChecked; diff --git a/src/libs/installer/componentmodel.h b/src/libs/installer/componentmodel.h index 8a9fbf884..e5cd2c57d 100644 --- a/src/libs/installer/componentmodel.h +++ b/src/libs/installer/componentmodel.h @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -94,10 +94,10 @@ Q_SIGNALS: void checkStateChanged(QInstaller::ComponentModel::ModelState state); private Q_SLOTS: - void slotModelReset(); void onVirtualStateChanged(); private: + void postModelReset(); void updateAndEmitModelState(); void collectComponents(Component *const component, const QModelIndex &parent) const; QSet<QModelIndex> updateCheckedState(const ComponentSet &components, Qt::CheckState state); |