summaryrefslogtreecommitdiffstats
path: root/src/libs/installer/componentmodel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/installer/componentmodel.cpp')
-rw-r--r--src/libs/installer/componentmodel.cpp81
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);