diff options
author | Katja Marttila <katja.marttila@qt.io> | 2022-03-18 14:13:24 +0200 |
---|---|---|
committer | Katja Marttila <katja.marttila@qt.io> | 2022-03-24 09:15:33 +0200 |
commit | ac1637b8976d7d85ac42f308c4be6de97dcf86cb (patch) | |
tree | 601dc434e0d8ae225758c2603fe4992a3b83418f | |
parent | 449afefe542d3411de4bdacd068c1116ec10779c (diff) |
Add install reason why component is uninstalled
In details view uninstallable and installable components are listed. For
installable components a reason is shown why the component is installed.
Added similar kind of message for uninstallable components as well.
Task-number: QTIFW-2581
Change-Id: Idbf31200793a6c89a4ed4a6fc115f49889b5f9b5
Reviewed-by: Arttu Tarkiainen <arttu.tarkiainen@qt.io>
-rw-r--r-- | src/libs/installer/packagemanagercore.cpp | 34 | ||||
-rw-r--r-- | src/libs/installer/packagemanagercore.h | 1 | ||||
-rw-r--r-- | src/libs/installer/packagemanagercore_p.cpp | 2 | ||||
-rw-r--r-- | src/libs/installer/uninstallercalculator.cpp | 53 | ||||
-rw-r--r-- | src/libs/installer/uninstallercalculator.h | 16 | ||||
-rw-r--r-- | tests/auto/installer/solver/tst_solver.cpp | 26 |
6 files changed, 119 insertions, 13 deletions
diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp index 918b01ad6..363609a92 100644 --- a/src/libs/installer/packagemanagercore.cpp +++ b/src/libs/installer/packagemanagercore.cpp @@ -2107,7 +2107,6 @@ QList<Component*> PackageManagerCore::orderedComponentsToInstall() const bool PackageManagerCore::calculateComponents(QString *displayString) { QString htmlOutput; - QString lastInstallReason; if (!calculateComponentsToUninstall() || !calculateComponentsToInstall()) { htmlOutput.append(QString::fromLatin1("<h2><font color=\"red\">%1</font></h2><ul>") @@ -2125,13 +2124,24 @@ bool PackageManagerCore::calculateComponents(QString *displayString) QList<Component*> componentsToRemove = componentsToUninstall(); if (!componentsToRemove.isEmpty()) { + QMap<QString, QStringList> orderedUninstallReasons; htmlOutput.append(QString::fromLatin1("<h3>%1</h3><ul>").arg(tr("Components about to " - "be removed."))); - foreach (Component *component, componentsToRemove) - htmlOutput.append(QString::fromLatin1("<li> %1 </li>").arg(component->name())); + "be removed:"))); + foreach (Component *component, componentsToRemove) { + const QString reason = uninstallReason(component); + QStringList value = orderedUninstallReasons.value(reason); + orderedUninstallReasons.insert(reason, value << component->name()); + } + for (auto &reason : orderedUninstallReasons.keys()) { + htmlOutput.append(QString::fromLatin1("<h4>%1</h4><ul>").arg(reason)); + foreach (const QString componentName, orderedUninstallReasons.value(reason)) + htmlOutput.append(QString::fromLatin1("<li> %1 </li>").arg(componentName)); + htmlOutput.append(QLatin1String("</ul>")); + } htmlOutput.append(QLatin1String("</ul>")); } + QString lastInstallReason; foreach (Component *component, orderedComponentsToInstall()) { const QString reason = installReason(component); if (lastInstallReason != reason) { @@ -2201,6 +2211,22 @@ QString PackageManagerCore::installReason(Component *component) const } /*! + Returns the reason why \a component needs to be uninstalled: + + \list + \li The component was scheduled for uninstallation. + \li The component was replaced by another component. + \li The component is virtual and its dependencies are uninstalled. + \li The components dependencies are uninstalled. + \li The components autodependencies are uninstalled. + \endlist +*/ +QString PackageManagerCore::uninstallReason(Component *component) const +{ + return d->uninstallerCalculator()->uninstallReason(component); +} + +/*! Returns a list of components that depend on \a _component. The list can be empty. diff --git a/src/libs/installer/packagemanagercore.h b/src/libs/installer/packagemanagercore.h index 012c57d58..523661797 100644 --- a/src/libs/installer/packagemanagercore.h +++ b/src/libs/installer/packagemanagercore.h @@ -240,6 +240,7 @@ public: QString componentsToInstallError() const; QString installReason(Component *component) const; + QString uninstallReason(Component *component) const; QList<Component*> dependees(const Component *component) const; QList<Component*> installDependants(const Component *component) const; diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp index 4aaa27cfd..464a68109 100644 --- a/src/libs/installer/packagemanagercore_p.cpp +++ b/src/libs/installer/packagemanagercore_p.cpp @@ -2792,6 +2792,8 @@ void PackageManagerCorePrivate::calculateUninstallComponents() QPair<Component*, Component*> comp = componentsToReplace().value(component->name()); if (comp.first) { if (comp.first->isSelectedForInstallation() || comp.first->updateRequested()) { + uninstallerCalculator()->insertUninstallReason(component, + UninstallerCalculator::Replaced, comp.first->name()); selectedComponentsToUninstall.append(comp.second); } } diff --git a/src/libs/installer/uninstallercalculator.cpp b/src/libs/installer/uninstallercalculator.cpp index 7d5ce9e2a..a8c47e523 100644 --- a/src/libs/installer/uninstallercalculator.cpp +++ b/src/libs/installer/uninstallercalculator.cpp @@ -66,8 +66,10 @@ void UninstallerCalculator::appendComponentToUninstall(Component *component) QSet<Component *> dependees = QSet<Component *>(dependeesList.begin(), dependeesList.end()).subtract(m_componentsToUninstall); - foreach (Component *dependee, dependees) + foreach (Component *dependee, dependees) { appendComponentToUninstall(dependee); + insertUninstallReason(dependee, UninstallerCalculator::Dependent, component->name()); + } m_componentsToUninstall.insert(component); } @@ -119,6 +121,7 @@ void UninstallerCalculator::appendComponentsToUninstall(const QList<Component*> // A component requested auto uninstallation, keep it to resolve their dependencies as well. if (!autoDependencies.isEmpty()) { autoDependOnList.append(component); + insertUninstallReason(component, UninstallerCalculator::AutoDependent, autoDependencies.join(QLatin1String(", "))); component->setInstallAction(ComponentModelHelper::AutodependUninstallation); } } @@ -130,6 +133,50 @@ void UninstallerCalculator::appendComponentsToUninstall(const QList<Component*> appendVirtualComponentsToUninstall(); } +void UninstallerCalculator::insertUninstallReason(Component *component, 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 +{ + UninstallerCalculator::UninstallReasonType reason = uninstallReasonType(component); + switch (reason) { + case Selected: + return QCoreApplication::translate("UninstallerCalculator", + "Deselected Components:"); + case Replaced: + return QCoreApplication::translate("UninstallerCalculator", "Components replaced " + "by \"%1\":").arg(uninstallReasonReferencedComponent(component)); + case VirtualDependent: + return QCoreApplication::translate("UninstallerCalculator", + "Removing virtual components without existing dependencies:"); + case Dependent: + return QCoreApplication::translate("UninstallerCalculator", "Components " + "dependency \"%1\" removed:").arg(uninstallReasonReferencedComponent(component)); + case AutoDependent: + return QCoreApplication::translate("UninstallerCalculator", "Components " + "autodependency \"%1\" removed:").arg(uninstallReasonReferencedComponent(component)); + } + 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; @@ -148,8 +195,10 @@ void UninstallerCalculator::appendVirtualComponentsToUninstall() break; } } - if (!required) + if (!required) { unneededVirtualList.append(component); + insertUninstallReason(component, UninstallerCalculator::VirtualDependent); + } } } diff --git a/src/libs/installer/uninstallercalculator.h b/src/libs/installer/uninstallercalculator.h index fb7035d4e..c20616e93 100644 --- a/src/libs/installer/uninstallercalculator.h +++ b/src/libs/installer/uninstallercalculator.h @@ -43,11 +43,26 @@ class PackageManagerCore; class INSTALLER_EXPORT UninstallerCalculator { 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(const QList<Component *> &installedComponents, PackageManagerCore *core); QSet<Component*> componentsToUninstall() const; void appendComponentsToUninstall(const QList<Component*> &components); + void insertUninstallReason(Component *component, + UninstallReasonType installReasonType, + const QString &referencedComponentName = QString()); + QString uninstallReason(Component *component) const; + UninstallerCalculator::UninstallReasonType uninstallReasonType(Component *c) const; + QString uninstallReasonReferencedComponent(Component *component) const; private: @@ -57,6 +72,7 @@ private: 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 2f4e17855..5e499da2d 100644 --- a/tests/auto/installer/solver/tst_solver.cpp +++ b/tests/auto/installer/solver/tst_solver.cpp @@ -39,6 +39,9 @@ using namespace QInstaller; typedef QMap<Component *, QStringList> ComponentToStringList; +typedef QList<QPair<Component *, UninstallerCalculator::UninstallReasonType>> UninstallReasonList; + +Q_DECLARE_METATYPE(UninstallReasonList) class Data { public: @@ -218,7 +221,6 @@ private slots: << (QList<Component *>() << componentA) << (QList<Component *>()); } - } void unresolvedDependencyVersion() @@ -242,7 +244,9 @@ private slots: QTest::addColumn<QList<Component *> >("selectedToUninstall"); QTest::addColumn<QList<Component *> >("installedComponents"); QTest::addColumn<QSet<Component *> >("expectedResult"); + QTest::addColumn<UninstallReasonList >("uninstallReasons"); + UninstallReasonList uninstallReasonList; PackageManagerCore *core = new PackageManagerCore(); core->setPackageManager(); NamedComponent *componentA = new NamedComponent(core, QLatin1String("A")); @@ -259,11 +263,15 @@ private slots: componentB->setInstalled(); componentAB->setInstalled(); + uninstallReasonList.append(qMakePair(componentAB, UninstallerCalculator::Selected)); + uninstallReasonList.append(qMakePair(componentB, UninstallerCalculator::Dependent)); QTest::newRow("Uninstaller resolved") << core << (QList<Component *>() << componentAB) << (QList<Component *>() << componentA << componentB) - << (QSet<Component *>() << componentAB << componentB); + << (QSet<Component *>() << componentAB << componentB) + << (uninstallReasonList); + uninstallReasonList.clear(); core = new PackageManagerCore(); core->setPackageManager(); NamedComponent *compA = new NamedComponent(core, QLatin1String("A")); @@ -277,10 +285,13 @@ private slots: compA->setInstalled(); compB->setInstalled(); + uninstallReasonList.append(qMakePair(compA, UninstallerCalculator::Selected)); + uninstallReasonList.append(qMakePair(compB, UninstallerCalculator::Dependent)); QTest::newRow("Cascade dependencies") << core << (QList<Component *>() << compA) << (QList<Component *>() << compB) - << (QSet<Component *>() << compA << compB); + << (QSet<Component *>() << compA << compB) + << (uninstallReasonList); } void resolveUninstaller() @@ -289,17 +300,19 @@ private slots: QFETCH(QList<Component *> , selectedToUninstall); QFETCH(QList<Component *> , installedComponents); QFETCH(QSet<Component *> , expectedResult); - + QFETCH(UninstallReasonList, uninstallReasons); UninstallerCalculator calc(installedComponents, core); calc.appendComponentsToUninstall(selectedToUninstall); QSet<Component *> result = calc.componentsToUninstall(); - + for (auto pair : uninstallReasons) { + UninstallerCalculator::UninstallReasonType type = calc.uninstallReasonType(pair.first); + QCOMPARE(pair.second, type); + } QCOMPARE(result.count(), expectedResult.count()); QCOMPARE(result, expectedResult); delete core; } - void checkComponent_data() { QTest::addColumn<QList<Component *> >("componentsToCheck"); @@ -342,7 +355,6 @@ private slots: QTest::newRow("AutoDepend and dependency") << (QList<Component *>() << componentC << componentD << componentE) << result; - } void checkComponent() |