diff options
author | Arttu Tarkiainen <arttu.tarkiainen@qt.io> | 2023-01-10 16:16:41 +0200 |
---|---|---|
committer | Arttu Tarkiainen <arttu.tarkiainen@qt.io> | 2023-02-08 16:37:22 +0200 |
commit | 399c010235bdb9079005930e125f301f53153808 (patch) | |
tree | aeb0bea9d6530930ccf60a6e26bab3652e8a5647 /src/libs | |
parent | 3ef3edd5206552dd037774594901780a4c817687 (diff) |
Add common base class for the installer calculator classes
As the classes already share similar features and public API, it would
make sense to inherit a common abstract class to define the interface.
Change-Id: I7ed278b1b049b7ec12c4401e55fdf39306b0ab85
Reviewed-by: Katja Marttila <katja.marttila@qt.io>
Diffstat (limited to 'src/libs')
-rw-r--r-- | src/libs/installer/calculatorbase.cpp | 76 | ||||
-rw-r--r-- | src/libs/installer/calculatorbase.h | 84 | ||||
-rw-r--r-- | src/libs/installer/installer.pro | 2 | ||||
-rw-r--r-- | src/libs/installer/installercalculator.cpp | 84 | ||||
-rw-r--r-- | src/libs/installer/installercalculator.h | 40 | ||||
-rw-r--r-- | src/libs/installer/packagemanagercore.cpp | 24 | ||||
-rw-r--r-- | src/libs/installer/packagemanagercore_p.cpp | 14 | ||||
-rw-r--r-- | src/libs/installer/uninstallercalculator.cpp | 85 | ||||
-rw-r--r-- | src/libs/installer/uninstallercalculator.h | 36 |
9 files changed, 261 insertions, 184 deletions
diff --git a/src/libs/installer/calculatorbase.cpp b/src/libs/installer/calculatorbase.cpp new file mode 100644 index 000000000..4f1732677 --- /dev/null +++ b/src/libs/installer/calculatorbase.cpp @@ -0,0 +1,76 @@ +/************************************************************************** +** +** Copyright (C) 2023 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#include "calculatorbase.h" + +#include "component.h" + +namespace QInstaller { + +CalculatorBase::CalculatorBase(PackageManagerCore *core) + : m_core(core) +{ +} + +CalculatorBase::~CalculatorBase() +{ +} + +void CalculatorBase::insertResolution(Component *component, const Resolution resolutionType + , const QString &referencedComponent) +{ + // Keep the first reason + if (m_componentNameResolutionHash.contains(component->name())) + return; + + m_componentNameResolutionHash.insert(component->name(), + QPair<Resolution, QString>(resolutionType, referencedComponent)); +} + +QList<Component *> CalculatorBase::resolvedComponents() const +{ + return m_resolvedComponents; +} + +CalculatorBase::Resolution CalculatorBase::resolutionType(Component *component) const +{ + return m_componentNameResolutionHash.value(component->name()).first; +} + +QString CalculatorBase::error() const +{ + return m_errorString; +} + +QString CalculatorBase::referencedComponent(Component *component) const +{ + return m_componentNameResolutionHash.value(component->name()).second; +} + +} // namespace QInstaller + diff --git a/src/libs/installer/calculatorbase.h b/src/libs/installer/calculatorbase.h new file mode 100644 index 000000000..baf51c5b4 --- /dev/null +++ b/src/libs/installer/calculatorbase.h @@ -0,0 +1,84 @@ +/************************************************************************** +** +** Copyright (C) 2023 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#ifndef CALCULATORBASE_H +#define CALCULATORBASE_H + +#include "installer_global.h" + +#include <QList> +#include <QString> +#include <QMetaEnum> + +namespace QInstaller { + +class Component; +class PackageManagerCore; + +class INSTALLER_EXPORT CalculatorBase +{ +public: + enum class Resolution { + Selected = 0, // "Selected Component(s) without Dependencies" / "Deselected Component(s)" + Replaced, // "Component(s) replaced by other components" + VirtualDependent, // "No dependencies to virtual component" + Dependent, // "Added as dependency for %1." / "Removed as dependency component is removed" + Automatic, // "Component(s) added as automatic dependencies" / "Removed as autodependency component is removed" + Resolved // "Component(s) that have resolved Dependencies" + }; + + CalculatorBase(PackageManagerCore *core); + virtual ~CalculatorBase() = 0; + + virtual bool solve(const QList<Component *> &components) = 0; + void insertResolution(Component *component, const Resolution resolutionType, + const QString &referencedComponent = QString()); + + QList<Component *> resolvedComponents() const; + virtual QString resolutionText(Component *component) const = 0; + Resolution resolutionType(Component *component) const; + + QString error() const; + +protected: + virtual bool solveComponent(Component *component, const QString &version = QString()) = 0; + QString referencedComponent(Component *component) const; + +protected: + PackageManagerCore *m_core; + QString m_errorString; + + QList<Component *> m_resolvedComponents; + QHash<QString, QPair<Resolution, QString> > m_componentNameResolutionHash; +}; + +} // namespace QInstaller + +Q_DECLARE_METATYPE(QInstaller::CalculatorBase::Resolution) + +#endif // CALCULATORBASE_H diff --git a/src/libs/installer/installer.pro b/src/libs/installer/installer.pro index 0de80b064..5a58968ee 100644 --- a/src/libs/installer/installer.pro +++ b/src/libs/installer/installer.pro @@ -46,6 +46,7 @@ greaterThan(QT_MAJOR_VERSION, 5):QT += core5compat HEADERS += packagemanagercore.h \ aspectratiolabel.h \ + calculatorbase.h \ componentsortfilterproxymodel.h \ concurrentoperationrunner.h \ genericdatacache.h \ @@ -149,6 +150,7 @@ SOURCES += packagemanagercore.cpp \ abstractarchive.cpp \ archivefactory.cpp \ aspectratiolabel.cpp \ + calculatorbase.cpp \ concurrentoperationrunner.cpp \ directoryguard.cpp \ fileguard.cpp \ diff --git a/src/libs/installer/installercalculator.cpp b/src/libs/installer/installercalculator.cpp index 77989e3f8..105e99fd8 100644 --- a/src/libs/installer/installercalculator.cpp +++ b/src/libs/installer/installercalculator.cpp @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2022 The Qt Company Ltd. +** Copyright (C) 2023 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -42,48 +42,38 @@ namespace QInstaller { */ InstallerCalculator::InstallerCalculator(PackageManagerCore *core, const AutoDependencyHash &autoDependencyComponentHash) - : m_core(core) + : CalculatorBase(core) , m_autoDependencyComponentHash(autoDependencyComponentHash) { } -InstallerCalculator::InstallReasonType InstallerCalculator::installReasonType(const Component *c) const +InstallerCalculator::~InstallerCalculator() { - return m_toInstallComponentIdReasonHash.value(c->name(), - qMakePair(InstallerCalculator::Selected, QString())).first; } -QString InstallerCalculator::installReason(const Component *component) const +QString InstallerCalculator::resolutionText(Component *component) const { - InstallerCalculator::InstallReasonType reason = installReasonType(component); + const Resolution reason = resolutionType(component); switch (reason) { - case Automatic: + case Resolution::Automatic: return QCoreApplication::translate("InstallerCalculator", "Components added as automatic dependencies:"); - case Dependent: + case Resolution::Dependent: return QCoreApplication::translate("InstallerCalculator", "Components added as " - "dependency for \"%1\":").arg(installReasonReferencedComponent(component)); - case Resolved: + "dependency for \"%1\":").arg(referencedComponent(component)); + case Resolution::Resolved: return QCoreApplication::translate("InstallerCalculator", "Components that have resolved dependencies:"); - case Selected: + case Resolution::Selected: return QCoreApplication::translate("InstallerCalculator", "Selected components without dependencies:"); + default: + Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid install resolution detected!"); } return QString(); } -QList<Component*> InstallerCalculator::orderedComponentsToInstall() const -{ - return m_orderedComponentsToInstall; -} - -QString InstallerCalculator::componentsToInstallError() const -{ - return m_componentsToInstallError; -} - -bool InstallerCalculator::appendComponentsToInstall(const QList<Component *> &components) +bool InstallerCalculator::solve(const QList<Component *> &components) { if (components.isEmpty()) return true; @@ -95,54 +85,38 @@ bool InstallerCalculator::appendComponentsToInstall(const QList<Component *> &co if (m_toInstallComponentIds.contains(component->name())) { const QString errorMessage = recursionError(component); qCWarning(QInstaller::lcInstallerInstallLog).noquote() << errorMessage; - m_componentsToInstallError.append(errorMessage); + m_errorString.append(errorMessage); Q_ASSERT_X(!m_toInstallComponentIds.contains(component->name()), Q_FUNC_INFO, qPrintable(errorMessage)); return false; } if (component->currentDependencies().isEmpty()) - realAppendToInstallComponents(component); + addComponentForInstall(component); else notAppendedComponents.append(component); } for (Component *component : qAsConst(notAppendedComponents)) { - if (!appendComponentToInstall(component)) + if (!solveComponent(component)) return false; } // All regular dependencies are resolved. Now we are looking for auto depend on components. QSet<Component *> foundAutoDependOnList = autodependencyComponents(); - if (!foundAutoDependOnList.isEmpty()) - return appendComponentsToInstall(foundAutoDependOnList.values()); - return true; -} + return solve(foundAutoDependOnList.values()); -QString InstallerCalculator::installReasonReferencedComponent(const Component *component) const -{ - return m_toInstallComponentIdReasonHash.value(component->name(), - qMakePair(InstallerCalculator::Selected, QString())).second; -} - -void InstallerCalculator::insertInstallReason(Component *component, - InstallReasonType installReason, const QString &referencedComponentName) -{ - // keep the first reason - if (m_toInstallComponentIdReasonHash.contains(component->name())) - return; - m_toInstallComponentIdReasonHash.insert(component->name(), - qMakePair(installReason, referencedComponentName)); + return true; } -void InstallerCalculator::realAppendToInstallComponents(Component *component, const QString &version) +void InstallerCalculator::addComponentForInstall(Component *component, const QString &version) { if (!m_componentsForAutodepencencyCheck.contains(component)) m_componentsForAutodepencencyCheck.append(component); if (!component->isInstalled(version) || (m_core->isUpdater() && component->isUpdateAvailable())) { - m_orderedComponentsToInstall.append(component); + m_resolvedComponents.append(component); m_toInstallComponentIds.insert(component->name()); } } @@ -150,10 +124,10 @@ void InstallerCalculator::realAppendToInstallComponents(Component *component, co QString InstallerCalculator::recursionError(Component *component) const { return QCoreApplication::translate("InstallerCalculator", "Recursion detected, component \"%1\" " - "already added with reason: \"%2\"").arg(component->name(), installReason(component)); + "already added with reason: \"%2\"").arg(component->name(), resolutionText(component)); } -bool InstallerCalculator::appendComponentToInstall(Component *component, const QString &version) +bool InstallerCalculator::solveComponent(Component *component, const QString &version) { const QStringList dependenciesList = component->currentDependencies(); QString requiredDependencyVersion = version; @@ -166,7 +140,7 @@ bool InstallerCalculator::appendComponentToInstall(Component *component, const Q "Cannot find missing dependency \"%1\" for \"%2\".").arg(dependencyComponentName, component->name()); qCWarning(QInstaller::lcInstallerInstallLog).noquote() << errorMessage; - m_componentsToInstallError.append(errorMessage); + m_errorString.append(errorMessage); if (component->packageManagerCore()->settings().allowUnstableComponents()) { component->setUnstable(Component::UnstableError::MissingDependency, errorMessage); continue; @@ -204,24 +178,24 @@ bool InstallerCalculator::appendComponentToInstall(Component *component, const Q if (m_visitedComponents.value(component).contains(dependencyComponent)) { const QString errorMessage = recursionError(component); qCWarning(QInstaller::lcInstallerInstallLog).noquote() << errorMessage; - m_componentsToInstallError = errorMessage; + m_errorString = errorMessage; Q_ASSERT_X(!m_visitedComponents.value(component).contains(dependencyComponent), Q_FUNC_INFO, qPrintable(errorMessage)); return false; } m_visitedComponents[component].insert(dependencyComponent); // add needed dependency components to the next run - insertInstallReason(dependencyComponent, InstallerCalculator::Dependent, + insertResolution(dependencyComponent, Resolution::Dependent, component->name()); - if (!appendComponentToInstall(dependencyComponent, requiredDependencyVersion)) + if (!solveComponent(dependencyComponent, requiredDependencyVersion)) return false; } } if (!m_toInstallComponentIds.contains(component->name())) { - realAppendToInstallComponents(component, requiredDependencyVersion); - insertInstallReason(component, InstallerCalculator::Resolved); + addComponentForInstall(component, requiredDependencyVersion); + insertResolution(component, Resolution::Resolved); } return true; } @@ -253,7 +227,7 @@ QSet<Component *> InstallerCalculator::autodependencyComponents() // are other autodependencies as well if (autoDependComponent->isAutoDependOn(m_toInstallComponentIds)) { foundAutoDependOnList.insert(autoDependComponent); - insertInstallReason(autoDependComponent, InstallerCalculator::Automatic); + insertResolution(autoDependComponent, Resolution::Automatic); } } } diff --git a/src/libs/installer/installercalculator.h b/src/libs/installer/installercalculator.h index 422de439c..339dbeffd 100644 --- a/src/libs/installer/installercalculator.h +++ b/src/libs/installer/installercalculator.h @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2022 The Qt Company Ltd. +** Copyright (C) 2023 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -30,6 +30,7 @@ #include "installer_global.h" #include "qinstallerglobal.h" +#include "calculatorbase.h" #include <QHash> #include <QList> @@ -41,51 +42,30 @@ namespace QInstaller { class Component; class PackageManagerCore; -class INSTALLER_EXPORT InstallerCalculator +class INSTALLER_EXPORT InstallerCalculator : public CalculatorBase { public: InstallerCalculator(PackageManagerCore *core, const AutoDependencyHash &autoDependencyComponentHash); + ~InstallerCalculator(); - enum InstallReasonType - { - Selected, // "Selected Component(s) without Dependencies" - Automatic, // "Component(s) added as automatic dependencies" - Dependent, // "Added as dependency for %1." - Resolved // "Component(s) that have resolved Dependencies" - }; - - 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 solve(const QList<Component *> &components) override; + QString resolutionText(Component *component) const override; private: - QString installReasonReferencedComponent(const Component *component) const; - 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()); + bool solveComponent(Component *component, const QString &version = QString()) override; + + void addComponentForInstall(Component *component, 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; QSet<QString> m_toInstallComponentIds; //for faster lookups - QString m_componentsToInstallError; - //calculate installation order variables - QList<Component*> m_orderedComponentsToInstall; - //we can't use this reason hash as component id hash, because some reasons are ready before - //the component is added - QHash<QString, QPair<InstallReasonType, QString> > m_toInstallComponentIdReasonHash; //Helper hash for quicker search for autodependency components AutoDependencyHash m_autoDependencyComponentHash; }; -} - +} // namespace QInstaller #endif // INSTALLERCALCULATOR_H diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp index d5758438d..ebefafab6 100644 --- a/src/libs/installer/packagemanagercore.cpp +++ b/src/libs/installer/packagemanagercore.cpp @@ -2199,7 +2199,7 @@ bool PackageManagerCore::calculateComponentsToInstall() const const QList<Component*> selectedComponentsToInstall = componentsMarkedForInstallation(); const bool componentsToInstallCalculated = - d->installerCalculator()->appendComponentsToInstall(selectedComponentsToInstall); + d->installerCalculator()->solve(selectedComponentsToInstall); emit finishedCalculateComponentsToInstall(); return componentsToInstallCalculated; @@ -2210,7 +2210,7 @@ bool PackageManagerCore::calculateComponentsToInstall() const */ QList<Component*> PackageManagerCore::orderedComponentsToInstall() const { - return d->installerCalculator()->orderedComponentsToInstall(); + return d->installerCalculator()->resolvedComponents(); } /*! @@ -2287,15 +2287,15 @@ bool PackageManagerCore::calculateComponentsToUninstall() const emit aboutCalculateComponentsToUninstall(); d->clearUninstallerCalculator(); - const QList<Component *> componentsToInstallList = d->installerCalculator()->orderedComponentsToInstall(); + const QList<Component *> componentsToInstallList = d->installerCalculator()->resolvedComponents(); QList<Component *> selectedComponentsToUninstall; foreach (Component* component, components(PackageManagerCore::ComponentType::Replacements)) { // Uninstall the component if replacement is selected for install or update QPair<Component*, Component*> comp = d->componentsToReplace().value(component->name()); - if (comp.first && d->m_installerCalculator->orderedComponentsToInstall().contains(comp.first)) { - d->uninstallerCalculator()->insertUninstallReason(component, - UninstallerCalculator::Replaced, comp.first->name()); + if (comp.first && d->m_installerCalculator->resolvedComponents().contains(comp.first)) { + d->uninstallerCalculator()->insertResolution(component, + CalculatorBase::Resolution::Replaced, comp.first->name()); selectedComponentsToUninstall.append(comp.second); } } @@ -2304,7 +2304,7 @@ bool PackageManagerCore::calculateComponentsToUninstall() const selectedComponentsToUninstall.append(component); } const bool componentsToUninstallCalculated = - d->uninstallerCalculator()->appendComponentsToUninstall(selectedComponentsToUninstall); + d->uninstallerCalculator()->solve(selectedComponentsToUninstall); emit finishedCalculateComponentsToUninstall(); return componentsToUninstallCalculated; @@ -2319,7 +2319,7 @@ bool PackageManagerCore::calculateComponentsToUninstall() const */ QList<Component *> PackageManagerCore::componentsToUninstall() const { - return d->uninstallerCalculator()->componentsToUninstall().values(); + return d->uninstallerCalculator()->resolvedComponents(); } /*! @@ -2327,7 +2327,7 @@ QList<Component *> PackageManagerCore::componentsToUninstall() const */ QString PackageManagerCore::componentsToInstallError() const { - return d->installerCalculator()->componentsToInstallError(); + return d->installerCalculator()->error(); } /*! @@ -2335,7 +2335,7 @@ QString PackageManagerCore::componentsToInstallError() const */ QString PackageManagerCore::componentsToUninstallError() const { - return d->uninstallerCalculator()->componentsToUninstallError(); + return d->uninstallerCalculator()->error(); } /*! @@ -2349,7 +2349,7 @@ QString PackageManagerCore::componentsToUninstallError() const */ QString PackageManagerCore::installReason(Component *component) const { - return d->installerCalculator()->installReason(component); + return d->installerCalculator()->resolutionText(component); } /*! @@ -2365,7 +2365,7 @@ QString PackageManagerCore::installReason(Component *component) const */ QString PackageManagerCore::uninstallReason(Component *component) const { - return d->uninstallerCalculator()->uninstallReason(component); + return d->uninstallerCalculator()->resolutionText(component); } /*! diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp index 7313a2761..a4e5b185d 100644 --- a/src/libs/installer/packagemanagercore_p.cpp +++ b/src/libs/installer/packagemanagercore_p.cpp @@ -401,10 +401,10 @@ bool PackageManagerCorePrivate::buildComponentTree(QHash<QString, Component*> &c component->setCheckState(Qt::Checked); clearInstallerCalculator(); - if (installerCalculator()->appendComponentsToInstall(components.values()) == false) { - setStatus(PackageManagerCore::Failure, installerCalculator()->componentsToInstallError()); + if (installerCalculator()->solve(components.values()) == false) { + setStatus(PackageManagerCore::Failure, installerCalculator()->error()); MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(), QLatin1String("Error"), - tr("Unresolved dependencies"), installerCalculator()->componentsToInstallError()); + tr("Unresolved dependencies"), installerCalculator()->error()); return false; } @@ -1932,7 +1932,7 @@ bool PackageManagerCorePrivate::runPackageUpdater() // There is a replacement, but the replacement is not scheduled for update, keep it as well. if (m_componentsToReplaceUpdaterMode.contains(name) - && !m_installerCalculator->orderedComponentsToInstall().contains(m_componentsToReplaceUpdaterMode.value(name).first)) { + && !m_installerCalculator->resolvedComponents().contains(m_componentsToReplaceUpdaterMode.value(name).first)) { nonRevertedOperations.append(operation); continue; } @@ -2935,9 +2935,9 @@ void PackageManagerCorePrivate::updateComponentCheckedState() ? ComponentModelHelper::KeepInstalled : ComponentModelHelper::KeepUninstalled); } - for (Component *component : uninstallerCalculator()->componentsToUninstall()) + for (Component *component : uninstallerCalculator()->resolvedComponents()) component->setInstallAction(ComponentModelHelper::Uninstall); - for (Component *component : installerCalculator()->orderedComponentsToInstall()) + for (Component *component : installerCalculator()->resolvedComponents()) component->setInstallAction(ComponentModelHelper::Install); } @@ -3062,7 +3062,7 @@ bool PackageManagerCorePrivate::calculateComponentsAndRun() qCDebug(QInstaller::lcInstallerInstallLog) << "Installation canceled."; } else if (componentsOk && acceptLicenseAgreements()) { try { - loadComponentScripts(installerCalculator()->orderedComponentsToInstall(), true); + loadComponentScripts(installerCalculator()->resolvedComponents(), true); } catch (const Error &error) { qCWarning(QInstaller::lcInstallerInstallLog) << error.message(); return false; diff --git a/src/libs/installer/uninstallercalculator.cpp b/src/libs/installer/uninstallercalculator.cpp index ebfc52efe..de753f71a 100644 --- a/src/libs/installer/uninstallercalculator.cpp +++ b/src/libs/installer/uninstallercalculator.cpp @@ -44,25 +44,21 @@ UninstallerCalculator::UninstallerCalculator(PackageManagerCore *core , const AutoDependencyHash &autoDependencyComponentHash , const LocalDependencyHash &localDependencyComponentHash , const QStringList &localVirtualComponents) - : m_core(core) + : CalculatorBase(core) , m_autoDependencyComponentHash(autoDependencyComponentHash) , m_localDependencyComponentHash(localDependencyComponentHash) , m_localVirtualComponents(localVirtualComponents) { } -QSet<Component *> UninstallerCalculator::componentsToUninstall() const +UninstallerCalculator::~UninstallerCalculator() { - return m_componentsToUninstall; } -QString UninstallerCalculator::componentsToUninstallError() const +bool UninstallerCalculator::solveComponent(Component *component, const QString &version) { - return m_componentsToUninstallError; -} + Q_UNUSED(version) -bool UninstallerCalculator::appendComponentToUninstall(Component *component) -{ if (!component) return true; @@ -76,7 +72,7 @@ bool UninstallerCalculator::appendComponentToUninstall(Component *component) if (!depComponent || !depComponent->isInstalled()) continue; - if (m_componentsToUninstall.contains(depComponent) + if (m_resolvedComponents.contains(depComponent) || m_core->orderedComponentsToInstall().contains(depComponent)) { // Component is already selected for uninstall or update continue; @@ -86,28 +82,28 @@ bool UninstallerCalculator::appendComponentToUninstall(Component *component) const QString errorMessage = QCoreApplication::translate("InstallerCalculator", "Impossible dependency resolution detected. Forced install component \"%1\" would be uninstalled " "because its dependency \"%2\" is marked for uninstallation with reason: \"%3\".") - .arg(depComponent->name(), component->name(), uninstallReason(component)); + .arg(depComponent->name(), component->name(), resolutionText(component)); qCWarning(QInstaller::lcInstallerInstallLog).noquote() << errorMessage; - m_componentsToUninstallError.append(errorMessage); + m_errorString.append(errorMessage); return false; } // Resolve also all cascading dependencies - if (!appendComponentToUninstall(depComponent)) + if (!solveComponent(depComponent)) return false; - insertUninstallReason(depComponent, UninstallerCalculator::Dependent, component->name()); + insertResolution(depComponent, Resolution::Dependent, component->name()); } } - m_componentsToUninstall.insert(component); + m_resolvedComponents.append(component); return true; } -bool UninstallerCalculator::appendComponentsToUninstall(const QList<Component*> &components) +bool UninstallerCalculator::solve(const QList<Component*> &components) { foreach (Component *component, components) { - if (!appendComponentToUninstall(component)) + if (!solveComponent(component)) return false; } @@ -122,8 +118,8 @@ bool 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 (!m_componentsToUninstall.contains(autoDepComponent)) { - insertUninstallReason(autoDepComponent, UninstallerCalculator::AutoDependent, component->name()); + if (!m_resolvedComponents.contains(autoDepComponent)) { + insertResolution(autoDepComponent, Resolution::Automatic, component->name()); autoDepComponent->setInstallAction(ComponentModelHelper::AutodependUninstallation); autoDependOnList.append(autoDepComponent); } @@ -132,56 +128,38 @@ bool UninstallerCalculator::appendComponentsToUninstall(const QList<Component*> } if (!autoDependOnList.isEmpty()) - appendComponentsToUninstall(autoDependOnList); + solve(autoDependOnList); else appendVirtualComponentsToUninstall(); return true; } -void UninstallerCalculator::insertUninstallReason(Component *component, const UninstallReasonType uninstallReason, - const QString &referencedComponentName) -{ - // keep the first reason - if (m_toUninstallComponentIdReasonHash.contains(component->name())) - return; - m_toUninstallComponentIdReasonHash.insert(component->name(), - qMakePair(uninstallReason, referencedComponentName)); -} - -QString UninstallerCalculator::uninstallReason(Component *component) const +QString UninstallerCalculator::resolutionText(Component *component) const { - UninstallerCalculator::UninstallReasonType reason = uninstallReasonType(component); + Resolution reason = resolutionType(component); switch (reason) { - case Selected: + case Resolution::Selected: return QCoreApplication::translate("UninstallerCalculator", "Deselected Components:"); - case Replaced: + case Resolution::Replaced: return QCoreApplication::translate("UninstallerCalculator", "Components replaced " - "by \"%1\":").arg(uninstallReasonReferencedComponent(component)); - case VirtualDependent: + "by \"%1\":").arg(referencedComponent(component)); + case Resolution::VirtualDependent: return QCoreApplication::translate("UninstallerCalculator", "Removing virtual components without existing dependencies:"); - case Dependent: + case Resolution::Dependent: return QCoreApplication::translate("UninstallerCalculator", "Components " - "dependency \"%1\" removed:").arg(uninstallReasonReferencedComponent(component)); - case AutoDependent: + "dependency \"%1\" removed:").arg(referencedComponent(component)); + case Resolution::Automatic: return QCoreApplication::translate("UninstallerCalculator", "Components " - "autodependency \"%1\" removed:").arg(uninstallReasonReferencedComponent(component)); + "autodependency \"%1\" removed:").arg(referencedComponent(component)); + default: + Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid uninstall resolution detected!"); } return QString(); } -UninstallerCalculator::UninstallReasonType UninstallerCalculator::uninstallReasonType(Component *c) const -{ - return m_toUninstallComponentIdReasonHash.value(c->name()).first; -} - -QString UninstallerCalculator::uninstallReasonReferencedComponent(Component *component) const -{ - return m_toUninstallComponentIdReasonHash.value(component->name()).second; -} - void UninstallerCalculator::appendVirtualComponentsToUninstall() { QList<Component*> unneededVirtualList; @@ -191,20 +169,20 @@ void UninstallerCalculator::appendVirtualComponentsToUninstall() if (!virtualComponent) continue; - if (virtualComponent->isInstalled() && !m_componentsToUninstall.contains(virtualComponent)) { + if (virtualComponent->isInstalled() && !m_resolvedComponents.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); - insertUninstallReason(virtualComponent, UninstallerCalculator::VirtualDependent); + insertResolution(virtualComponent, Resolution::VirtualDependent); } } } if (!unneededVirtualList.isEmpty()) - appendComponentsToUninstall(unneededVirtualList); + solve(unneededVirtualList); } bool UninstallerCalculator::isRequiredVirtualPackage(Component *component) @@ -212,10 +190,11 @@ bool UninstallerCalculator::isRequiredVirtualPackage(Component *component) const QStringList localInstallDependents = m_core->localDependenciesToComponent(component); for (const QString &dependent : localInstallDependents) { Component *comp = m_core->componentByName(dependent); - if (!m_componentsToUninstall.contains(comp)) { + if (!m_resolvedComponents.contains(comp)) { return true; } } return m_core->isDependencyForRequestedComponent(component); } + } // namespace QInstaller diff --git a/src/libs/installer/uninstallercalculator.h b/src/libs/installer/uninstallercalculator.h index b764042aa..24979a9bb 100644 --- a/src/libs/installer/uninstallercalculator.h +++ b/src/libs/installer/uninstallercalculator.h @@ -30,6 +30,7 @@ #include "installer_global.h" #include "qinstallerglobal.h" +#include "calculatorbase.h" #include <QHash> #include <QList> @@ -41,49 +42,30 @@ namespace QInstaller { class Component; class PackageManagerCore; -class INSTALLER_EXPORT UninstallerCalculator +class INSTALLER_EXPORT UninstallerCalculator : public CalculatorBase { public: - enum UninstallReasonType - { - Selected, // "Deselected Component(s)" - Replaced, // "Component(s) replaced by other components" - VirtualDependent, // "No dependencies to virtual component" - Dependent, // "Removed as dependency component is removed" - AutoDependent // "Removed as autodependency component is removed" - }; - UninstallerCalculator(PackageManagerCore *core, const AutoDependencyHash &autoDependencyComponentHash, const LocalDependencyHash &localDependencyComponentHash, const QStringList &localVirtualComponents); + ~UninstallerCalculator(); - QSet<Component*> componentsToUninstall() const; - QString componentsToUninstallError() const; - - bool 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; + bool solve(const QList<Component*> &components) override; + QString resolutionText(Component *component) const override; private: - QString uninstallReasonReferencedComponent(Component *component) const; + bool solveComponent(Component *component, const QString &version = QString()) override; + bool isRequiredVirtualPackage(Component *component); - bool appendComponentToUninstall(Component *component); void appendVirtualComponentsToUninstall(); - QString m_componentsToUninstallError; - QSet<Component *> m_componentsToUninstall; - PackageManagerCore *m_core; - QHash<QString, QPair<UninstallReasonType, QString> > m_toUninstallComponentIdReasonHash; +private: AutoDependencyHash m_autoDependencyComponentHash; LocalDependencyHash m_localDependencyComponentHash; QStringList m_localVirtualComponents; }; -} - +} // namespace QInstaller #endif // UNINSTALLERCALCULATOR_H |