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.cpp126
1 files changed, 63 insertions, 63 deletions
diff --git a/src/libs/installer/componentmodel.cpp b/src/libs/installer/componentmodel.cpp
index aab487b45..1e8dd1ff7 100644
--- a/src/libs/installer/componentmodel.cpp
+++ b/src/libs/installer/componentmodel.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 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,13 +60,6 @@ namespace QInstaller {
*/
/*!
- \fn void QInstaller::ComponentModel::checkStateChanged(const QModelIndex &index)
-
- This signal is emitted whenever the checked state of a component is changed. The \a index value
- indicates the QModelIndex representation of the component as seen from the model.
-*/
-
-/*!
\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
@@ -101,7 +96,6 @@ ComponentModel::ComponentModel(int columns, PackageManagerCore *core)
, m_modelState(DefaultChecked)
{
m_headerData.insert(0, columns, QVariant());
- connect(this, &QAbstractItemModel::modelReset, this, &ComponentModel::slotModelReset);
}
/*!
@@ -222,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) {
@@ -239,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 checkStateChanged() signals are emitted in addition if the checked state of the item is set.
*/
bool ComponentModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
@@ -253,17 +249,17 @@ bool ComponentModel::setData(const QModelIndex &index, const QVariant &value, in
if (role == Qt::CheckStateRole) {
if (index.column() != 0)
return false;
- ComponentSet nodes = component->childItems().toSet();
+
+ const QList<Component*> childItems = component->childItems();
+ ComponentSet nodes(childItems.begin(), childItems.end());
Qt::CheckState newValue = Qt::CheckState(value.toInt());
if (newValue == Qt::PartiallyChecked) {
const Qt::CheckState oldValue = component->checkState();
newValue = (oldValue == Qt::Checked) ? Qt::Unchecked : Qt::Checked;
}
- QSet<QModelIndex> changed = updateCheckedState(nodes << component, newValue);
- foreach (const QModelIndex &index, changed) {
- emit dataChanged(index, index);
- emit checkStateChanged(index);
- }
+ const QSet<QModelIndex> changed = updateCheckedState(nodes << component, newValue);
+ foreach (const QModelIndex &changedIndex, changed)
+ emit dataChanged(changedIndex, changedIndex);
updateAndEmitModelState(); // update the internal state
} else {
component->setData(value, role);
@@ -339,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.
*/
@@ -385,20 +397,20 @@ Component *ComponentModel::componentFromIndex(const QModelIndex &index) const
// -- public slots
/*!
- Sets \a rootComponents to be the list of currently shown components.
+ Resets model and sets \a rootComponents to be the list of currently shown components.
The model is repopulated and the individual component's checked state is used to show the check
mark in front of the visual component representation. The modelAboutToBeReset() and
modelReset() signals are emitted.
*/
-void ComponentModel::setRootComponents(QList<QInstaller::Component*> rootComponents)
+void ComponentModel::reset(QList<Component *> rootComponents)
{
beginResetModel();
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
@@ -417,49 +429,49 @@ void ComponentModel::setRootComponents(QList<QInstaller::Component*> rootCompone
m_rootComponentList.append(component);
}
endResetModel();
+ postModelReset();
}
/*!
Sets the checked state of every component in the model to be \a state.
The ComponentModel::PartiallyChecked flag is ignored by this function. Note that components
- are not changed if they are not checkable. The dataChanged() and checkStateChanged() signals
- are emitted.
+ are not changed if they are not checkable. The modelCheckStateChanged() signal
+ is emitted.
*/
void ComponentModel::setCheckedState(QInstaller::ComponentModel::ModelStateFlag state)
{
- QSet<QModelIndex> changed;
switch (state) {
case AllChecked:
- changed = updateCheckedState(m_currentCheckedState[Qt::Unchecked], Qt::Checked);
+ updateCheckedState(m_currentCheckedState[Qt::Unchecked], Qt::Checked);
break;
case AllUnchecked:
- changed = updateCheckedState(m_currentCheckedState[Qt::Checked], Qt::Unchecked);
+ updateCheckedState(m_currentCheckedState[Qt::Checked], Qt::Unchecked);
break;
case DefaultChecked:
// record all changes, to be able to update the UI properly
- changed = updateCheckedState(m_currentCheckedState[Qt::Checked], Qt::Unchecked);
- changed += updateCheckedState(m_initialCheckedState[Qt::Checked], Qt::Checked);
+ updateCheckedState(m_currentCheckedState[Qt::Checked], Qt::Unchecked);
+ updateCheckedState(m_initialCheckedState[Qt::Checked], Qt::Checked);
break;
default:
break;
}
-
- if (changed.isEmpty())
- return;
-
- // notify about changes done to the model
- foreach (const QModelIndex &index, changed) {
- emit dataChanged(index, index);
- emit checkStateChanged(index);
- }
updateAndEmitModelState(); // update the internal state
}
// -- private slots
-void ComponentModel::slotModelReset()
+void ComponentModel::onVirtualStateChanged()
+{
+ // If the virtual state of a component changes, force a reset of the component model.
+ reset(m_core->components(PackageManagerCore::ComponentType::Root));
+}
+
+
+// -- private
+
+void ComponentModel::postModelReset()
{
ComponentList components = m_rootComponentList;
if (!m_core->isUpdater()) {
@@ -485,17 +497,12 @@ 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()
{
+ if (m_rootComponentList.isEmpty()) {
+ m_modelState = ComponentModel::Empty;
+ return;
+ }
m_modelState = ComponentModel::DefaultChecked;
if (m_initialCheckedState != m_currentCheckedState)
m_modelState = ComponentModel::PartiallyChecked;
@@ -511,15 +518,6 @@ void ComponentModel::updateAndEmitModelState()
}
emit checkStateChanged(m_modelState);
-
- foreach (const Component *component, m_rootComponentList) {
- emit dataChanged(indexFromComponentName(component->treeName()),
- indexFromComponentName(component->treeName()));
- QList<Component *> children = component->childItems();
- foreach (const Component *child, children)
- emit dataChanged(indexFromComponentName(child->treeName()),
- indexFromComponentName(child->treeName()));
- }
}
void ComponentModel::collectComponents(Component *const component, const QModelIndex &parent) const
@@ -563,13 +561,13 @@ static Qt::CheckState verifyPartiallyChecked(Component *component)
} // namespace ComponentModelPrivate
-QSet<QModelIndex> ComponentModel::updateCheckedState(const ComponentSet &components, 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
- QMap<QString, Component *> sortedNodesMap;
+ QMultiMap<QString, Component *> sortedNodesMap;
foreach (Component *component, components) {
while (component && !sortedNodesMap.values(component->treeName()).contains(component)) {
- sortedNodesMap.insertMulti(component->treeName(), component);
+ sortedNodesMap.insert(component->treeName(), component);
component = component->parentComponent();
}
}
@@ -580,14 +578,16 @@ QSet<QModelIndex> ComponentModel::updateCheckedState(const ComponentSet &compone
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())