diff options
-rw-r--r-- | src/libs/installer/componentmodel.cpp | 38 | ||||
-rw-r--r-- | src/libs/installer/componentmodel.h | 7 | ||||
-rw-r--r-- | src/libs/installer/componentselectionpage_p.cpp | 14 | ||||
-rw-r--r-- | src/libs/installer/installercalculator.cpp | 201 | ||||
-rw-r--r-- | src/libs/installer/installercalculator.h | 27 | ||||
-rw-r--r-- | src/libs/installer/packagemanagercore.cpp | 66 | ||||
-rw-r--r-- | src/libs/installer/packagemanagercore.h | 1 | ||||
-rw-r--r-- | src/libs/installer/packagemanagercore_p.cpp | 17 | ||||
-rw-r--r-- | src/libs/installer/packagemanagercore_p.h | 1 | ||||
-rw-r--r-- | src/libs/installer/uninstallercalculator.cpp | 83 | ||||
-rw-r--r-- | src/libs/installer/uninstallercalculator.h | 14 | ||||
-rw-r--r-- | tests/auto/installer/solver/tst_solver.cpp | 6 |
12 files changed, 128 insertions, 347 deletions
diff --git a/src/libs/installer/componentmodel.cpp b/src/libs/installer/componentmodel.cpp index e60ba92ae..ef662b309 100644 --- a/src/libs/installer/componentmodel.cpp +++ b/src/libs/installer/componentmodel.cpp @@ -58,14 +58,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 @@ -238,7 +231,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 +252,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); @@ -446,8 +435,7 @@ void ComponentModel::setCheckedState(QInstaller::ComponentModel::ModelStateFlag default: break; } - updateModelState(); - emit modelCheckStateChanged(m_modelState); + updateAndEmitModelState(); // update the internal state } @@ -485,11 +473,10 @@ 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() { m_modelState = ComponentModel::DefaultChecked; if (m_initialCheckedState != m_currentCheckedState) @@ -504,6 +491,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 +536,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,7 +547,7 @@ 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--) { @@ -580,10 +569,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); diff --git a/src/libs/installer/componentmodel.h b/src/libs/installer/componentmodel.h index f9fbae47a..26cd888a3 100644 --- a/src/libs/installer/componentmodel.h +++ b/src/libs/installer/componentmodel.h @@ -90,17 +90,16 @@ public Q_SLOTS: void setCheckedState(QInstaller::ComponentModel::ModelStateFlag state); Q_SIGNALS: - void componentsCheckStateChanged(const QList<QModelIndex> &indexes); - void modelCheckStateChanged(QInstaller::ComponentModel::ModelState state); + void checkStateChanged(QInstaller::ComponentModel::ModelState state); private Q_SLOTS: void onVirtualStateChanged(); private: void postModelReset(); - void updateModelState(); + void updateAndEmitModelState(); void collectComponents(Component *const component, const QModelIndex &parent) const; - QList<QModelIndex> updateCheckedState(const ComponentSet &components, const Qt::CheckState state); + QSet<QModelIndex> updateCheckedState(const ComponentSet &components, const Qt::CheckState state); private: PackageManagerCore *m_core; diff --git a/src/libs/installer/componentselectionpage_p.cpp b/src/libs/installer/componentselectionpage_p.cpp index 0dcdc2de9..292b28e67 100644 --- a/src/libs/installer/componentselectionpage_p.cpp +++ b/src/libs/installer/componentselectionpage_p.cpp @@ -185,16 +185,10 @@ ComponentSelectionPagePrivate::ComponentSelectionPagePrivate(ComponentSelectionP m_stackedLayout->addWidget(progressStackedWidget); m_stackedLayout->setCurrentIndex(0); - connect(m_allModel, &ComponentModel::modelCheckStateChanged, - this, &ComponentSelectionPagePrivate::onModelStateChanged); - connect(m_updaterModel, &ComponentModel::modelCheckStateChanged, - this, &ComponentSelectionPagePrivate::onModelStateChanged); - - connect(m_allModel, &ComponentModel::componentsCheckStateChanged, this, - [=]() { onModelStateChanged(m_allModel->checkedState());}); - - connect(m_updaterModel, &ComponentModel::componentsCheckStateChanged, this, - [=]() { onModelStateChanged(m_allModel->checkedState());}); + connect(m_allModel, &ComponentModel::checkStateChanged, + this, &ComponentSelectionPagePrivate::onModelStateChanged); + connect(m_updaterModel, &ComponentModel::checkStateChanged, + this, &ComponentSelectionPagePrivate::onModelStateChanged); connect(m_core, SIGNAL(metaJobProgress(int)), this, SLOT(onProgressChanged(int))); connect(m_core, SIGNAL(metaJobInfoMessage(QString)), this, SLOT(setMessage(QString))); diff --git a/src/libs/installer/installercalculator.cpp b/src/libs/installer/installercalculator.cpp index 48c90621b..4eb65f1ad 100644 --- a/src/libs/installer/installercalculator.cpp +++ b/src/libs/installer/installercalculator.cpp @@ -49,7 +49,8 @@ InstallerCalculator::InstallerCalculator(PackageManagerCore *core, const AutoDep InstallerCalculator::InstallReasonType InstallerCalculator::installReasonType(const Component *c) const { - return m_toInstallComponentIdReasonHash.value(c->name()).first; + return m_toInstallComponentIdReasonHash.value(c->name(), + qMakePair(InstallerCalculator::Selected, QString())).first; } QString InstallerCalculator::installReason(const Component *component) const @@ -82,103 +83,77 @@ QString InstallerCalculator::componentsToInstallError() const return m_componentsToInstallError; } -bool InstallerCalculator::appendComponentsToInstall(const QList<Component *> &components, bool modelReset, const bool revertFromInstall) +bool InstallerCalculator::appendComponentsToInstall(const QList<Component *> &components) { if (components.isEmpty()) return true; QList<Component*> notAppendedComponents; // for example components with unresolved dependencies - foreach (Component *component, components) { + for (Component *component : qAsConst(components)){ if (!component) continue; - // When model has been reseted, there should not be components with the same name if (m_toInstallComponentIds.contains(component->name())) { - if (modelReset) { - const QString errorMessage = recursionError(component); - qCWarning(QInstaller::lcInstallerInstallLog).noquote() << errorMessage; - m_componentsToInstallError.append(errorMessage); - Q_ASSERT_X(!m_toInstallComponentIds.contains(component->name()), Q_FUNC_INFO, - qPrintable(errorMessage)); - return false; - } - if (!revertFromInstall && !modelReset) { - // We can end up here if component is already added as dependency and - // user explicitly selects it to install. Increase the references to - // know when the component should be removed from install - const QStringList dependenciesList = component->currentDependencies(); - for (const QString &dependencyComponentName : dependenciesList) - calculateComponentDependencyReferences(dependencyComponentName, component); - continue; - } + const QString errorMessage = recursionError(component); + qCWarning(QInstaller::lcInstallerInstallLog).noquote() << errorMessage; + m_componentsToInstallError.append(errorMessage); + Q_ASSERT_X(!m_toInstallComponentIds.contains(component->name()), Q_FUNC_INFO, + qPrintable(errorMessage)); + return false; } if (component->currentDependencies().isEmpty()) - realAppendToInstallComponents(component, QString(), revertFromInstall); + realAppendToInstallComponents(component); else notAppendedComponents.append(component); } - foreach (Component *component, notAppendedComponents) { - if (!appendComponentToInstall(component, QString(), revertFromInstall)) + for (Component *component : qAsConst(notAppendedComponents)) { + if (!appendComponentToInstall(component)) return false; } // All regular dependencies are resolved. Now we are looking for auto depend on components. - QSet<Component *> foundAutoDependOnList = autodependencyComponents(revertFromInstall); + QSet<Component *> foundAutoDependOnList = autodependencyComponents(); if (!foundAutoDependOnList.isEmpty()) - return appendComponentsToInstall(foundAutoDependOnList.values(), modelReset, revertFromInstall); - + return appendComponentsToInstall(foundAutoDependOnList.values()); return true; } -bool InstallerCalculator::removeComponentsFromInstall(const QList<Component *> &components) -{ - return appendComponentsToInstall(components, false, true); -} - QString InstallerCalculator::installReasonReferencedComponent(const Component *component) const { - const QString componentName = component->name(); - if (m_referenceCount.contains(componentName)) - return m_referenceCount.value(componentName).first(); - return m_toInstallComponentIdReasonHash.value(componentName, - qMakePair(InstallerCalculator::Selected, QString())).second; + return m_toInstallComponentIdReasonHash.value(component->name(), + qMakePair(InstallerCalculator::Selected, QString())).second; } -void InstallerCalculator::insertInstallReason(const Component *component, - const InstallReasonType installReason, const QString &referencedComponentName, const bool revertFromInstall) +void InstallerCalculator::insertInstallReason(Component *component, + InstallReasonType installReason, const QString &referencedComponentName) { - if (revertFromInstall && m_toInstallComponentIdReasonHash.contains(component->name())) { - m_toInstallComponentIdReasonHash.remove(component->name()); - } else if (!m_toInstallComponentIdReasonHash.contains(component->name())) { - m_toInstallComponentIdReasonHash.insert(component->name(), - qMakePair(installReason, referencedComponentName)); - } + // keep the first reason + if (m_toInstallComponentIdReasonHash.contains(component->name())) + return; + m_toInstallComponentIdReasonHash.insert(component->name(), + qMakePair(installReason, referencedComponentName)); } -void InstallerCalculator::realAppendToInstallComponents(Component *component, const QString &version, const bool revertFromInstall) +void InstallerCalculator::realAppendToInstallComponents(Component *component, const QString &version) { if (!m_componentsForAutodepencencyCheck.contains(component)) m_componentsForAutodepencencyCheck.append(component); - if (revertFromInstall) { - if (m_toInstallComponentIds.contains(component->name())) { - // Component is no longer added as dependency and is not explicitly selected for install by user - if (m_referenceCount.value(component->name()).isEmpty() && !component->isSelected()) { - m_toInstallComponentIds.remove(component->name()); - m_orderedComponentsToInstall.removeAll(component); - } - } - } else { - if (!component->isInstalled(version) - || (m_core->isUpdater() && component->isUpdateAvailable())) { - m_toInstallComponentIds.insert(component->name()); - m_orderedComponentsToInstall.append(component); - } + + if (!component->isInstalled(version) || (m_core->isUpdater() && component->isUpdateAvailable())) { + m_orderedComponentsToInstall.append(component); + m_toInstallComponentIds.insert(component->name()); } } -bool InstallerCalculator::appendComponentToInstall(Component *component, const QString &version, bool revertFromInstall) +QString InstallerCalculator::recursionError(Component *component) const +{ + return QCoreApplication::translate("InstallerCalculator", "Recursion detected, component \"%1\" " + "already added with reason: \"%2\"").arg(component->name(), installReason(component)); +} + +bool InstallerCalculator::appendComponentToInstall(Component *component, const QString &version) { const QStringList dependenciesList = component->currentDependencies(); QString requiredDependencyVersion = version; @@ -199,8 +174,6 @@ bool InstallerCalculator::appendComponentToInstall(Component *component, const Q return false; } } - if (revertFromInstall && dependencyComponent->forcedInstallation()) - continue; //Check if component requires higher version than what might be already installed bool isUpdateRequired = false; QString requiredName; @@ -219,72 +192,39 @@ bool InstallerCalculator::appendComponentToInstall(Component *component, const Q requiredDependencyVersion = requiredVersion; } } - - // Component can be requested for install by several component (as a dependency). - // Keep the reference count to a dependency component, so we know when component - // needs to be removed from install. Do not increase the reference count when - // the dependency is also autodependency as the component is removed anyway only - // when there are no references to the dependency. - if (revertFromInstall) { - if (m_toInstallComponentIds.contains(dependencyComponentName) - && m_referenceCount.contains(dependencyComponentName)) { - if (!component->autoDependencies().contains(dependencyComponentName)) { - QStringList &value = m_referenceCount[dependencyComponentName]; - if (value.contains(component->name())) { - value.removeOne(component->name()); - if (value.isEmpty()) - m_referenceCount.remove(dependencyComponentName); - } - } - } - insertInstallReason(dependencyComponent, InstallerCalculator::Dependent, - component->name(), true); - if (!appendComponentToInstall(dependencyComponent, requiredDependencyVersion, revertFromInstall)) + //Check dependencies only if + //- Dependency is not installed or update requested, nor newer version of dependency component required + //- And dependency component is not already added for install + //- And component is not already added for install, then dependencies are already resolved + if (((!dependencyComponent->isInstalled() || dependencyComponent->updateRequested()) + || isUpdateRequired) && (!m_toInstallComponentIds.contains(dependencyComponent->name()) + && !m_toInstallComponentIds.contains(component->name()))) { + if (m_visitedComponents.value(component).contains(dependencyComponent)) { + const QString errorMessage = recursionError(component); + qCWarning(QInstaller::lcInstallerInstallLog).noquote() << errorMessage; + m_componentsToInstallError = errorMessage; + Q_ASSERT_X(!m_visitedComponents.value(component).contains(dependencyComponent), + Q_FUNC_INFO, qPrintable(errorMessage)); return false; - m_visitedComponents.remove(component); - } else { - //Check dependencies only if - //- Dependency is not installed or update requested, nor newer version of dependency component required - //- And dependency component is not already added for install - //- And component is not already added for install, then dependencies are already resolved - if (((!dependencyComponent->isInstalled() || dependencyComponent->updateRequested()) - || isUpdateRequired) && (!m_toInstallComponentIds.contains(dependencyComponent->name()) - && !m_toInstallComponentIds.contains(component->name()))) { - if (m_visitedComponents.value(component).contains(dependencyComponent)) { - const QString errorMessage = recursionError(component); - qCWarning(QInstaller::lcInstallerInstallLog).noquote() << errorMessage; - m_componentsToInstallError = errorMessage; - Q_ASSERT_X(!m_visitedComponents.value(component).contains(dependencyComponent), - Q_FUNC_INFO, qPrintable(errorMessage)); - return false; - } - m_visitedComponents[component].insert(dependencyComponent); } - if (!component->autoDependencies().contains(dependencyComponentName)) - m_referenceCount[dependencyComponentName] << component->name(); + m_visitedComponents[component].insert(dependencyComponent); + // add needed dependency components to the next run + insertInstallReason(dependencyComponent, InstallerCalculator::Dependent, + component->name()); - insertInstallReason(dependencyComponent, InstallerCalculator::Dependent, component->name()); - if (!appendComponentToInstall(dependencyComponent, requiredDependencyVersion, revertFromInstall)) + if (!appendComponentToInstall(dependencyComponent, requiredDependencyVersion)) return false; } } - if (!revertFromInstall && !m_toInstallComponentIds.contains(component->name())) { - realAppendToInstallComponents(component, requiredDependencyVersion, revertFromInstall); + + if (!m_toInstallComponentIds.contains(component->name())) { + realAppendToInstallComponents(component, requiredDependencyVersion); insertInstallReason(component, InstallerCalculator::Resolved); } - if (revertFromInstall && m_toInstallComponentIds.contains(component->name())) { - realAppendToInstallComponents(component, requiredDependencyVersion, revertFromInstall); - } return true; } -QString InstallerCalculator::recursionError(const Component *component) const -{ - return QCoreApplication::translate("InstallerCalculator", "Recursion detected, component \"%1\" " - "already added with reason: \"%2\"").arg(component->name(), installReason(component)); -} - -QSet<Component *> InstallerCalculator::autodependencyComponents(const bool revertFromInstall) +QSet<Component *> InstallerCalculator::autodependencyComponents() { // All regular dependencies are resolved. Now we are looking for auto depend on components. // m_componentsForAutodepencencyCheck is a list of recently calculated components to be installed @@ -293,13 +233,12 @@ QSet<Component *> InstallerCalculator::autodependencyComponents(const bool rever QSet<Component *> foundAutoDependOnList; for (const Component *component : qAsConst(m_componentsForAutodepencencyCheck)) { if (!m_autoDependencyComponentHash.contains(component->name()) - || (!revertFromInstall && m_core->isUpdater() && !component->updateRequested())) + || (m_core->isUpdater() && !component->updateRequested())) continue; for (const QString& autoDependency : m_autoDependencyComponentHash.value(component->name())) { // If a components is already installed or is scheduled for installation, no need to check // for auto depend installation. - if ((!revertFromInstall && m_toInstallComponentIds.contains(autoDependency)) - || (revertFromInstall && !m_toInstallComponentIds.contains(autoDependency))) { + if (m_toInstallComponentIds.contains(autoDependency)) { continue; } Component *autoDependComponent = m_core->componentByName(autoDependency); @@ -314,10 +253,6 @@ QSet<Component *> InstallerCalculator::autodependencyComponents(const bool rever foundAutoDependOnList.insert(autoDependComponent); insertInstallReason(autoDependComponent, InstallerCalculator::Automatic); } - } else if (revertFromInstall - && m_toInstallComponentIds.contains(autoDependComponent->name()) - && !m_toInstallComponentIds.contains(component->name())) { - foundAutoDependOnList.insert(autoDependComponent); } } } @@ -325,20 +260,4 @@ QSet<Component *> InstallerCalculator::autodependencyComponents(const bool rever return foundAutoDependOnList; } -void InstallerCalculator::calculateComponentDependencyReferences(const QString dependencyComponentName, const Component *component) -{ - Component *dependencyComponent = m_core->componentByName(dependencyComponentName); - if (!dependencyComponent || component->autoDependencies().contains(dependencyComponentName)) - return; - QStringList value = m_referenceCount.value(dependencyComponentName, QStringList()); - value << component->name(); - m_referenceCount.insert(dependencyComponentName, value); - - const QStringList dependenciesList = dependencyComponent->currentDependencies(); - for (const QString &depComponentName : dependenciesList) { - Component *dependencyComponent = m_core->componentByName(depComponentName); - calculateComponentDependencyReferences(depComponentName, dependencyComponent); - } -} - } // namespace QInstaller diff --git a/src/libs/installer/installercalculator.h b/src/libs/installer/installercalculator.h index c2fa8761c..422de439c 100644 --- a/src/libs/installer/installercalculator.h +++ b/src/libs/installer/installercalculator.h @@ -39,6 +39,7 @@ namespace QInstaller { class Component; +class PackageManagerCore; class INSTALLER_EXPORT InstallerCalculator { @@ -53,33 +54,27 @@ public: Resolved // "Component(s) that have resolved Dependencies" }; - InstallReasonType installReasonType(const Component *c) const; + InstallReasonType installReasonType(const Component *component) const; QString installReason(const Component *component) const; QList<Component*> orderedComponentsToInstall() const; QString componentsToInstallError() const; - - bool appendComponentsToInstall(const QList<Component*> &components, bool modelReset = false, const bool revertFromInstall = false); - bool removeComponentsFromInstall(const QList<Component*> &components); + bool appendComponentsToInstall(const QList<Component*> &components); private: QString installReasonReferencedComponent(const Component *component) const; - void insertInstallReason(const Component *component, - const InstallReasonType installReason, - const QString &referencedComponentName = QString(), - const bool revertFromInstall = false); - void realAppendToInstallComponents(Component *component, const QString &version, const bool revertFromInstall); - bool appendComponentToInstall(Component *component, const QString &version, const bool revertFromInstall); - QString recursionError(const Component *component) const; - QSet<Component *> autodependencyComponents(const bool revertFromInstall); - void calculateComponentDependencyReferences(const QString dependencyComponentName, const Component *component); + void insertInstallReason(Component *component, + InstallReasonType installReasonType, + const QString &referencedComponentName = QString()); + void realAppendToInstallComponents(Component *component, const QString &version = QString()); + bool appendComponentToInstall(Component *components, const QString &version = QString()); + QSet<Component *> autodependencyComponents(); + QString recursionError(Component *component) const; private: PackageManagerCore *m_core; QHash<Component*, QSet<Component*> > m_visitedComponents; QList<const Component*> m_componentsForAutodepencencyCheck; - //for faster lookups. - QSet<QString> m_toInstallComponentIds; - QHash<QString, QStringList> m_referenceCount; + QSet<QString> m_toInstallComponentIds; //for faster lookups QString m_componentsToInstallError; //calculate installation order variables QList<Component*> m_orderedComponentsToInstall; diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp index 0788387a2..c866f1112 100644 --- a/src/libs/installer/packagemanagercore.cpp +++ b/src/libs/installer/packagemanagercore.cpp @@ -611,7 +611,7 @@ void PackageManagerCore::componentsToInstallNeedsRecalculation() QList<Component*> selectedComponentsToInstall = componentsMarkedForInstallation(); d->m_componentsToInstallCalculated = - d->installerCalculator()->appendComponentsToInstall(selectedComponentsToInstall, true); + d->installerCalculator()->appendComponentsToInstall(selectedComponentsToInstall); d->calculateUninstallComponents(); d->updateComponentCheckedState(); @@ -622,66 +622,6 @@ void PackageManagerCore::componentsToInstallNeedsRecalculation() } /*! - Calculates components to install based on user selection. \a indexes - contains list of model indexes user has selected for install, dependencies - and autodependencies are resolved later. - */ -void PackageManagerCore::calculateUserSelectedComponentsToInstall(const QList<QModelIndex> &indexes) -{ - QList<Component*> componentsToInstall; - QList<Component*> componentsToUnInstall; - ComponentModel *model = isUpdater() ? updaterComponentModel() : defaultComponentModel(); - for (QModelIndex index : indexes) { - Component *installComponent = model->componentFromIndex(index); - // 1. Component is selected for install - if (installComponent->isSelected() && !installComponent->isInstalled()) { - componentsToInstall.append(installComponent); - // Check if component has replacements that needs to be removed - const QList<Component*> replacedComponents = d->replacedComponentsByName(installComponent->name()); - for (Component *replacedComponent : replacedComponents) { - componentsToUnInstall.append(replacedComponent); - d->uninstallerCalculator()->insertUninstallReason(replacedComponent, - UninstallerCalculator::UninstallReasonType::Replaced); - } - } - // 2. Component is reselected for install (tapping checkbox off/on) - else if (installComponent->isSelected() && installComponent->isInstalled() - && !d->installerCalculator()->orderedComponentsToInstall().contains(installComponent)) { - componentsToInstall.append(installComponent); - } - // 3. Component is selected for uninstall - else if (!isUpdater() && !installComponent->isSelected() && installComponent->isInstalled()) { - componentsToUnInstall.append(installComponent); - } - // 4. Component is reselected for uninstall (tapping checkbox on/off) - else if (!installComponent->isSelected() - && d->installerCalculator()->orderedComponentsToInstall().contains(installComponent)) { - componentsToUnInstall.append(installComponent); - // Check if component has replacements that needs to be readded - componentsToInstall.append(d->replacedComponentsByName(installComponent->name())); - } - } - - d->installerCalculator()->removeComponentsFromInstall(componentsToUnInstall); - d->m_componentsToInstallCalculated - = d->installerCalculator()->appendComponentsToInstall(componentsToInstall, false); - if (!isUpdater()) { - d->uninstallerCalculator()->appendComponentsToUninstall(componentsToUnInstall, false); - } - d->uninstallerCalculator()->removeComponentsFromUnInstall(componentsToInstall); - if (componentsToUnInstall.isEmpty() && !componentsToInstall.isEmpty()) { - // There are no new components to be uninstalled but there - // are new components to be installed which might have virtual - // dependences to components which are already selected for uninstall. - // We need to remove those components from uninstall. - d->uninstallerCalculator()->appendVirtualComponentsToUninstall(true); - } - - d->updateComponentCheckedState(); -} - - -/*! Forces a recalculation of components to install. \sa {installer::clearComponentsToInstallCalculated}{installer.clearComponentsToInstallCalculated} */ @@ -4576,10 +4516,8 @@ ComponentModel *PackageManagerCore::componentModel(PackageManagerCore *core, con ComponentModel::tr("Release Date")); model->setHeaderData(ComponentModelHelper::UncompressedSizeColumn, Qt::Horizontal, ComponentModel::tr("Size")); - connect(model, &ComponentModel::modelCheckStateChanged, + connect(model, &ComponentModel::checkStateChanged, this, &PackageManagerCore::componentsToInstallNeedsRecalculation); - connect(model, &ComponentModel::componentsCheckStateChanged, - this, &PackageManagerCore::calculateUserSelectedComponentsToInstall); return model; } diff --git a/src/libs/installer/packagemanagercore.h b/src/libs/installer/packagemanagercore.h index 911c4b480..26fa8e086 100644 --- a/src/libs/installer/packagemanagercore.h +++ b/src/libs/installer/packagemanagercore.h @@ -361,7 +361,6 @@ public Q_SLOTS: void setCompleteUninstallation(bool complete); void cancelMetaInfoJob(); void componentsToInstallNeedsRecalculation(); - void calculateUserSelectedComponentsToInstall(const QList<QModelIndex> &indexes); void clearComponentsToInstallCalculated(); Q_SIGNALS: diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp index 6eb589086..129c35d46 100644 --- a/src/libs/installer/packagemanagercore_p.cpp +++ b/src/libs/installer/packagemanagercore_p.cpp @@ -542,21 +542,6 @@ QHash<QString, QStringList> &PackageManagerCorePrivate::componentReplaces() return m_componentReplaces; } -QList<Component*> PackageManagerCorePrivate::replacedComponentsByName(const QString &name) -{ - // Creates a list of components which are replaced by component 'name' - QList<Component*> replacedComponents; - if (m_componentReplaces.contains(name)) { - for (const QString &replacedComponentName : m_componentReplaces.value(name)) { - Component *replacedComponent = m_core->componentByName(replacedComponentName, - m_core->components(PackageManagerCore::ComponentType::All)); - if (replacedComponent) - replacedComponents.append(replacedComponent); - } - } - return replacedComponents; -} - void PackageManagerCorePrivate::clearInstallerCalculator() { delete m_installerCalculator; @@ -591,7 +576,7 @@ UninstallerCalculator *PackageManagerCorePrivate::uninstallerCalculator() const } } - pmcp->m_uninstallerCalculator = new UninstallerCalculator(installedComponents, m_core, + pmcp->m_uninstallerCalculator = new UninstallerCalculator(m_core, pmcp->m_autoDependencyComponentHash, pmcp->m_localDependencyComponentHash, pmcp->m_localVirtualComponents); } return m_uninstallerCalculator; diff --git a/src/libs/installer/packagemanagercore_p.h b/src/libs/installer/packagemanagercore_p.h index a42033ff6..56cf48d25 100644 --- a/src/libs/installer/packagemanagercore_p.h +++ b/src/libs/installer/packagemanagercore_p.h @@ -119,7 +119,6 @@ public: QList<Component*> &replacementDependencyComponents(); QHash<QString, QPair<Component*, Component*> > &componentsToReplace(); QHash<QString, QStringList > &componentReplaces(); - QList<Component*> replacedComponentsByName(const QString &name); void clearInstallerCalculator(); InstallerCalculator *installerCalculator() const; diff --git a/src/libs/installer/uninstallercalculator.cpp b/src/libs/installer/uninstallercalculator.cpp index 36d769207..4c07d81e3 100644 --- a/src/libs/installer/uninstallercalculator.cpp +++ b/src/libs/installer/uninstallercalculator.cpp @@ -30,9 +30,6 @@ #include "component.h" #include "packagemanagercore.h" -#include "globals.h" - -#include <QDebug> namespace QInstaller { @@ -42,13 +39,11 @@ namespace QInstaller { \internal */ -UninstallerCalculator::UninstallerCalculator(const QList<Component *> &installedComponents - , PackageManagerCore *core +UninstallerCalculator::UninstallerCalculator(PackageManagerCore *core , const AutoDependencyHash &autoDependencyComponentHash , const LocalDependencyHash &localDependencyComponentHash , const QStringList &localVirtualComponents) - : m_installedComponents(installedComponents) - , m_core(core) + : m_core(core) , m_autoDependencyComponentHash(autoDependencyComponentHash) , m_localDependencyComponentHash(localDependencyComponentHash) , m_localVirtualComponents(localVirtualComponents) @@ -60,7 +55,7 @@ QSet<Component *> UninstallerCalculator::componentsToUninstall() const return m_componentsToUninstall; } -void UninstallerCalculator::appendComponentToUninstall(Component *component, const bool reverse) +void UninstallerCalculator::appendComponentToUninstall(Component *component) { if (!component) return; @@ -75,28 +70,20 @@ void UninstallerCalculator::appendComponentToUninstall(Component *component, con if (!depComponent) continue; if (depComponent->isInstalled() && !m_componentsToUninstall.contains(depComponent)) { - appendComponentToUninstall(depComponent, reverse); + appendComponentToUninstall(depComponent); insertUninstallReason(depComponent, UninstallerCalculator::Dependent, component->name()); - } else if (reverse && depComponent->isVirtual()) { - // Remove from uninstall only hidden components, user - // can select other dependencies manually - appendComponentToUninstall(depComponent, true); } } } - if (reverse) { - m_componentsToUninstall.remove(component); - } else { - m_componentsToUninstall.insert(component); - } + + m_componentsToUninstall.insert(component); } -void UninstallerCalculator::appendComponentsToUninstall(const QList<Component*> &components, const bool reverse) +void UninstallerCalculator::appendComponentsToUninstall(const QList<Component*> &components) { - if (components.isEmpty()) - return; foreach (Component *component, components) - appendComponentToUninstall(component, reverse); + appendComponentToUninstall(component); + QList<Component*> autoDependOnList; // All regular dependees are resolved. Now we are looking for auto depend on components. for (Component *component : components) { @@ -108,9 +95,7 @@ void UninstallerCalculator::appendComponentsToUninstall(const QList<Component*> Component *autoDepComponent = m_core->componentByName(autoDependencyComponent); if (autoDepComponent && autoDepComponent->isInstalled()) { // A component requested auto uninstallation, keep it to resolve their dependencies as well. - if (reverse) { - autoDependOnList.append(autoDepComponent); - } else if (!m_componentsToUninstall.contains(autoDepComponent)) { + if (!m_componentsToUninstall.contains(autoDepComponent)) { insertUninstallReason(autoDepComponent, UninstallerCalculator::AutoDependent, component->name()); autoDepComponent->setInstallAction(ComponentModelHelper::AutodependUninstallation); autoDependOnList.append(autoDepComponent); @@ -118,15 +103,11 @@ void UninstallerCalculator::appendComponentsToUninstall(const QList<Component*> } } } + if (!autoDependOnList.isEmpty()) - appendComponentsToUninstall(autoDependOnList, reverse); + appendComponentsToUninstall(autoDependOnList); else - appendVirtualComponentsToUninstall(reverse); -} - -void UninstallerCalculator::removeComponentsFromUnInstall(const QList<Component*> &components) -{ - appendComponentsToUninstall(components, true); + appendVirtualComponentsToUninstall(); } void UninstallerCalculator::insertUninstallReason(Component *component, const UninstallReasonType uninstallReason, @@ -172,38 +153,30 @@ QString UninstallerCalculator::uninstallReasonReferencedComponent(Component *com return m_toUninstallComponentIdReasonHash.value(component->name()).second; } -void UninstallerCalculator::appendVirtualComponentsToUninstall(const bool reverse) +void UninstallerCalculator::appendVirtualComponentsToUninstall() { QList<Component*> unneededVirtualList; - // Check for virtual components without dependees - if (reverse) { - for (Component *reverseFromUninstall : qAsConst(m_virtualComponentsForReverse)) { - if (m_componentsToUninstall.contains(reverseFromUninstall) && (isRequiredVirtualPackage(reverseFromUninstall))) - unneededVirtualList.append(reverseFromUninstall); - } - } else { - for (const QString &componentName : qAsConst(m_localVirtualComponents)) { - Component *virtualComponent = m_core->componentByName(componentName, m_core->components(PackageManagerCore::ComponentType::All)); - if (!virtualComponent) - continue; + for (const QString &componentName : qAsConst(m_localVirtualComponents)) { + Component *virtualComponent = m_core->componentByName(componentName, m_core->components(PackageManagerCore::ComponentType::All)); + if (!virtualComponent) + continue; - if (virtualComponent->isInstalled() && !m_componentsToUninstall.contains(virtualComponent)) { - // Components with auto dependencies were handled in the previous step - if (!virtualComponent->autoDependencies().isEmpty() || virtualComponent->forcedInstallation()) - continue; + if (virtualComponent->isInstalled() && !m_componentsToUninstall.contains(virtualComponent)) { + // Components with auto dependencies were handled in the previous step + if (!virtualComponent->autoDependencies().isEmpty() || virtualComponent->forcedInstallation()) + continue; - if (!isRequiredVirtualPackage(virtualComponent)) { - unneededVirtualList.append(virtualComponent); - m_virtualComponentsForReverse.append(virtualComponent); - insertUninstallReason(virtualComponent, UninstallerCalculator::VirtualDependent); - } - } + if (!isRequiredVirtualPackage(virtualComponent)) { + unneededVirtualList.append(virtualComponent); + m_virtualComponentsForReverse.append(virtualComponent); + insertUninstallReason(virtualComponent, UninstallerCalculator::VirtualDependent); + } } } if (!unneededVirtualList.isEmpty()) - appendComponentsToUninstall(unneededVirtualList, reverse); + appendComponentsToUninstall(unneededVirtualList); } bool UninstallerCalculator::isRequiredVirtualPackage(Component *component) diff --git a/src/libs/installer/uninstallercalculator.h b/src/libs/installer/uninstallercalculator.h index 57f2f926a..74207e005 100644 --- a/src/libs/installer/uninstallercalculator.h +++ b/src/libs/installer/uninstallercalculator.h @@ -53,28 +53,26 @@ public: AutoDependent // "Removed as autodependency component is removed" }; - UninstallerCalculator(const QList<Component *> &installedComponents, PackageManagerCore *core, + UninstallerCalculator(PackageManagerCore *core, const AutoDependencyHash &autoDependencyComponentHash, const LocalDependencyHash &localDependencyComponentHash, const QStringList &localVirtualComponents); QSet<Component*> componentsToUninstall() const; - void appendComponentsToUninstall(const QList<Component*> &components, const bool reverse = false); - void removeComponentsFromUnInstall(const QList<Component*> &components); + void appendComponentsToUninstall(const QList<Component*> &components); void insertUninstallReason(Component *component, const UninstallReasonType uninstallReason, const QString &referencedComponentName = QString()); QString uninstallReason(Component *component) const; UninstallerCalculator::UninstallReasonType uninstallReasonType(Component *c) const; - QString uninstallReasonReferencedComponent(Component *component) const; - bool isRequiredVirtualPackage(Component *component); - void appendVirtualComponentsToUninstall(const bool reverse); private: - void appendComponentToUninstall(Component *component, const bool reverse); + QString uninstallReasonReferencedComponent(Component *component) const; + bool isRequiredVirtualPackage(Component *component); + void appendComponentToUninstall(Component *component); + void appendVirtualComponentsToUninstall(); - QList<Component *> m_installedComponents; QSet<Component *> m_componentsToUninstall; PackageManagerCore *m_core; QHash<QString, QPair<UninstallReasonType, QString> > m_toUninstallComponentIdReasonHash; diff --git a/tests/auto/installer/solver/tst_solver.cpp b/tests/auto/installer/solver/tst_solver.cpp index bdfc4d3df..ee05cc7f4 100644 --- a/tests/auto/installer/solver/tst_solver.cpp +++ b/tests/auto/installer/solver/tst_solver.cpp @@ -248,7 +248,6 @@ private slots: { QTest::addColumn<PackageManagerCore *>("core"); QTest::addColumn<QList<Component *> >("selectedToUninstall"); - QTest::addColumn<QList<Component *> >("installedComponents"); QTest::addColumn<QSet<Component *> >("expectedResult"); QTest::addColumn<UninstallReasonList >("uninstallReasons"); QTest::addColumn<LocalDependencyHash >("dependencyHash"); @@ -277,7 +276,6 @@ private slots: uninstallReasonList.append(qMakePair(componentB, UninstallerCalculator::Dependent)); QTest::newRow("Uninstaller resolved") << core << (QList<Component *>() << componentAB) - << (QList<Component *>() << componentA << componentB) << (QSet<Component *>() << componentAB << componentB) << uninstallReasonList << dependencyComponentHash; @@ -303,7 +301,6 @@ private slots: uninstallReasonList.append(qMakePair(compB, UninstallerCalculator::Dependent)); QTest::newRow("Cascade dependencies") << core << (QList<Component *>() << compA) - << (QList<Component *>() << compB) << (QSet<Component *>() << compA << compB) << (uninstallReasonList) << dependencyComponentHash; @@ -313,12 +310,11 @@ private slots: { QFETCH(PackageManagerCore *, core); QFETCH(QList<Component *> , selectedToUninstall); - QFETCH(QList<Component *> , installedComponents); QFETCH(QSet<Component *> , expectedResult); QFETCH(UninstallReasonList, uninstallReasons); QFETCH(LocalDependencyHash, dependencyHash); - UninstallerCalculator calc(installedComponents, core, QHash<QString, QStringList>(), dependencyHash, QStringList()); + UninstallerCalculator calc(core, QHash<QString, QStringList>(), dependencyHash, QStringList()); calc.appendComponentsToUninstall(selectedToUninstall); QSet<Component *> result = calc.componentsToUninstall(); for (auto pair : uninstallReasons) { |