diff options
Diffstat (limited to 'src/libs/installer/componentmodel.cpp')
-rw-r--r-- | src/libs/installer/componentmodel.cpp | 81 |
1 files changed, 47 insertions, 34 deletions
diff --git a/src/libs/installer/componentmodel.cpp b/src/libs/installer/componentmodel.cpp index e60ba92ae..1e8dd1ff7 100644 --- a/src/libs/installer/componentmodel.cpp +++ b/src/libs/installer/componentmodel.cpp @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2022 The Qt Company Ltd. +** Copyright (C) 2024 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -47,6 +47,8 @@ namespace QInstaller { This enum value holds the checked state of the components available for installation. + \value Empty + The model does not contain any components. \value AllChecked All components are checked. \value AllUnchecked @@ -58,14 +60,7 @@ namespace QInstaller { */ /*! - \fn void QInstaller::ComponentModel::componentsCheckStateChanged(const QList<QModelIndex> &indexes) - - This signal is emitted whenever the checked state of components are changed. The \a indexes value - indicates the QModelIndexes representation of the components as seen from the model. -*/ - -/*! - \fn void QInstaller::ComponentModel::modelCheckStateChanged(QInstaller::ComponentModel::ModelState state) + \fn void QInstaller::ComponentModel::checkStateChanged(QInstaller::ComponentModel::ModelState state) This signal is emitted whenever the checked state of a model is changed after all state calculations have taken place. The \a state is a combination of \c ModelStateFlag values @@ -221,7 +216,10 @@ QVariant ComponentModel::data(const QModelIndex &index, int role) const return component->data(Qt::UserRole + index.column()); } if (role == Qt::CheckStateRole) { - if (!component->isCheckable() || !component->autoDependencies().isEmpty() || component->isUnstable()) + if (!component->isCheckable() || component->isUnstable()) + return QVariant(); + + if (!m_core->isUpdater() && !component->autoDependencies().isEmpty()) return QVariant(); } if (role == ComponentModelHelper::ExpandedByDefault) { @@ -238,7 +236,6 @@ QVariant ComponentModel::data(const QModelIndex &index, int role) const /*! Sets the \a role data for the item at \a index to \a value. Returns true if successful; otherwise returns false. The dataChanged() signal is emitted if the data was successfully set. - The componentsCheckStateChanged() signal is emitted in addition if the checked state of the item is set. */ bool ComponentModel::setData(const QModelIndex &index, const QVariant &value, int role) { @@ -260,13 +257,10 @@ bool ComponentModel::setData(const QModelIndex &index, const QVariant &value, in const Qt::CheckState oldValue = component->checkState(); newValue = (oldValue == Qt::Checked) ? Qt::Unchecked : Qt::Checked; } - const QList<QModelIndex> changed = updateCheckedState(nodes << component, newValue); - foreach (const QModelIndex &changedIndex, changed) { + const QSet<QModelIndex> changed = updateCheckedState(nodes << component, newValue); + foreach (const QModelIndex &changedIndex, changed) emit dataChanged(changedIndex, changedIndex); - } - updateModelState(); - if (changed.count() > 0) - emit componentsCheckStateChanged(changed); + updateAndEmitModelState(); // update the internal state } else { component->setData(value, role); emit dataChanged(index, index); @@ -341,6 +335,22 @@ QSet<Component *> ComponentModel::uncheckable() const return m_uncheckable; } +bool ComponentModel::componentsSelected() const +{ + if (m_core->isInstaller() || m_core->isUpdater()) + return checked().count(); + + if (checkedState().testFlag(ComponentModel::DefaultChecked) == false) + return true; + + const QSet<Component *> uncheckables = uncheckable(); + for (auto &component : uncheckables) { + if (component->forcedInstallation() && !component->isInstalled()) + return true; // allow installation for new forced components + } + return false; +} + /*! Returns a pointer to the PackageManagerCore this model belongs to. */ @@ -400,7 +410,7 @@ void ComponentModel::reset(QList<Component *> rootComponents) m_uncheckable.clear(); m_indexByNameCache.clear(); m_rootComponentList.clear(); - m_modelState = DefaultChecked; + m_modelState = !rootComponents.isEmpty() ? DefaultChecked : Empty; // Initialize these with an empty set for every possible state, cause we compare the hashes later in // updateAndEmitModelState(). The comparison than might lead to wrong results if one of the checked @@ -446,8 +456,7 @@ void ComponentModel::setCheckedState(QInstaller::ComponentModel::ModelStateFlag default: break; } - updateModelState(); - emit modelCheckStateChanged(m_modelState); + updateAndEmitModelState(); // update the internal state } @@ -485,12 +494,15 @@ void ComponentModel::postModelReset() } m_currentCheckedState = m_initialCheckedState; - updateModelState(); // update the internal state - emit modelCheckStateChanged(m_modelState); + updateAndEmitModelState(); // update the internal state } -void ComponentModel::updateModelState() +void ComponentModel::updateAndEmitModelState() { + if (m_rootComponentList.isEmpty()) { + m_modelState = ComponentModel::Empty; + return; + } m_modelState = ComponentModel::DefaultChecked; if (m_initialCheckedState != m_currentCheckedState) m_modelState = ComponentModel::PartiallyChecked; @@ -504,6 +516,8 @@ void ComponentModel::updateModelState() m_modelState |= ComponentModel::AllChecked; m_modelState &= ~ComponentModel::PartiallyChecked; } + + emit checkStateChanged(m_modelState); } void ComponentModel::collectComponents(Component *const component, const QModelIndex &parent) const @@ -547,7 +561,7 @@ static Qt::CheckState verifyPartiallyChecked(Component *component) } // namespace ComponentModelPrivate -QList<QModelIndex> ComponentModel::updateCheckedState(const ComponentSet &components, const Qt::CheckState state) +QSet<QModelIndex> ComponentModel::updateCheckedState(const ComponentSet &components, const Qt::CheckState state) { // get all parent nodes for the components we're going to update QMultiMap<QString, Component *> sortedNodesMap; @@ -558,20 +572,22 @@ QList<QModelIndex> ComponentModel::updateCheckedState(const ComponentSet &compon } } - QList<QModelIndex> changed; + QSet<QModelIndex> changed; const ComponentList sortedNodes = sortedNodesMap.values(); // we can start in descending order to check node and tri-state nodes properly for (int i = sortedNodes.count(); i > 0; i--) { Component * const node = sortedNodes.at(i - 1); - bool checkable = true; - if (node->value(scCheckable, scTrue).toLower() == scFalse) { - checkable = false; - } + if (!node->isEnabled() || node->isUnstable()) + continue; - if ((!node->isCheckable() && checkable) || !node->isEnabled() || !node->autoDependencies().isEmpty() || node->isUnstable()) + //Do not let forced installations to be uninstalled + if (!m_core->isUpdater() && node->forcedInstallation() && (node->checkState() != Qt::Unchecked)) continue; + if (!m_core->isUpdater() && !node->autoDependencies().isEmpty()) + continue; + Qt::CheckState newState = state; const Qt::CheckState recentState = node->checkState(); if (node->isTristate()) @@ -580,10 +596,7 @@ QList<QModelIndex> ComponentModel::updateCheckedState(const ComponentSet &compon continue; node->setCheckState(newState); - QModelIndex index = indexFromComponentName(node->treeName()); - //Prepend to the list so that install order is correct (parent first) - if (!changed.contains(index)) - changed.prepend(indexFromComponentName(node->treeName())); + changed.insert(indexFromComponentName(node->treeName())); m_currentCheckedState[Qt::Checked].remove(node); m_currentCheckedState[Qt::Unchecked].remove(node); |