Android: Decouple missing packages logic from UI

There is no need to modify UI selection in order to
execute installation / deinstallation.

Change-Id: I205477e5ff0e7b07bfbcd6b5f8f985fcb180884e
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
Jarek Kobus
2024-04-18 15:57:25 +02:00
parent 3a4784ea6c
commit a204bd2304
7 changed files with 82 additions and 97 deletions

View File

@@ -215,6 +215,32 @@ const AndroidSdkPackageList &AndroidSdkManager::allSdkPackages()
return m_d->allPackages(); return m_d->allPackages();
} }
QStringList AndroidSdkManager::notFoundEssentialSdkPackages()
{
QStringList essentials = androidConfig().allEssentials();
const AndroidSdkPackageList &packages = allSdkPackages();
for (AndroidSdkPackage *package : packages) {
essentials.removeOne(package->sdkStylePath());
if (essentials.isEmpty())
return {};
}
return essentials;
}
QStringList AndroidSdkManager::missingEssentialSdkPackages()
{
const QStringList essentials = androidConfig().allEssentials();
const AndroidSdkPackageList &packages = allSdkPackages();
QStringList missingPackages;
for (AndroidSdkPackage *package : packages) {
if (essentials.contains(package->sdkStylePath())
&& package->state() != AndroidSdkPackage::Installed) {
missingPackages.append(package->sdkStylePath());
}
}
return missingPackages;
}
AndroidSdkPackageList AndroidSdkManager::installedSdkPackages() AndroidSdkPackageList AndroidSdkManager::installedSdkPackages()
{ {
return m_d->filteredPackages(AndroidSdkPackage::Installed, AndroidSdkPackage::AnyValidType); return m_d->filteredPackages(AndroidSdkPackage::Installed, AndroidSdkPackage::AnyValidType);

View File

@@ -52,6 +52,8 @@ public:
SdkPlatformList installedSdkPlatforms(); SdkPlatformList installedSdkPlatforms();
const AndroidSdkPackageList &allSdkPackages(); const AndroidSdkPackageList &allSdkPackages();
QStringList notFoundEssentialSdkPackages();
QStringList missingEssentialSdkPackages();
AndroidSdkPackageList installedSdkPackages(); AndroidSdkPackageList installedSdkPackages();
SystemImageList installedSystemImages(); SystemImageList installedSystemImages();
NdkList installedNdkPackages(); NdkList installedNdkPackages();

View File

@@ -159,7 +159,7 @@ AndroidSdkManagerWidget::AndroidSdkManagerWidget(AndroidSdkManager *sdkManager,
connect(m_sdkModel, &AndroidSdkModel::dataChanged, this, [this] { connect(m_sdkModel, &AndroidSdkModel::dataChanged, this, [this] {
if (m_viewStack->currentWidget() == m_packagesStack) if (m_viewStack->currentWidget() == m_packagesStack)
m_buttonBox->button(QDialogButtonBox::Apply) m_buttonBox->button(QDialogButtonBox::Apply)
->setEnabled(!m_sdkModel->userSelection().isEmpty()); ->setEnabled(m_sdkModel->installationChange().count());
}); });
connect(m_sdkModel, &AndroidSdkModel::modelAboutToBeReset, this, connect(m_sdkModel, &AndroidSdkModel::modelAboutToBeReset, this,
@@ -206,9 +206,8 @@ AndroidSdkManagerWidget::AndroidSdkManagerWidget(AndroidSdkManager *sdkManager,
expandCheck->setChecked(!text.isEmpty()); expandCheck->setChecked(!text.isEmpty());
}); });
connect(m_buttonBox->button(QDialogButtonBox::Apply), &QAbstractButton::clicked, this, [this] { connect(m_buttonBox->button(QDialogButtonBox::Apply), &QAbstractButton::clicked,
onApplyButton(); this, &AndroidSdkManagerWidget::onApplyButton);
});
connect(m_buttonBox, &QDialogButtonBox::rejected, this, &AndroidSdkManagerWidget::onCancel); connect(m_buttonBox, &QDialogButtonBox::rejected, this, &AndroidSdkManagerWidget::onCancel);
connect(optionsButton, &QPushButton::clicked, connect(optionsButton, &QPushButton::clicked,
@@ -273,19 +272,20 @@ AndroidSdkManagerWidget::~AndroidSdkManagerWidget()
delete m_formatter; delete m_formatter;
} }
void AndroidSdkManagerWidget::installEssentials() void AndroidSdkManagerWidget::installMissingEssentials()
{ {
const QStringList missingEssentials = m_sdkModel->selectMissingEssentials(); const QStringList notFoundEssentials = m_sdkManager->notFoundEssentialSdkPackages();
if (!missingEssentials.isEmpty()) { if (!notFoundEssentials.isEmpty()) {
QMessageBox::warning(Core::ICore::dialogParent(), QMessageBox::warning(Core::ICore::dialogParent(),
Tr::tr("Android SDK Changes"), Tr::tr("Android SDK Changes"),
Tr::tr("%1 cannot find the following essential packages: \"%2\".\n" Tr::tr("%1 cannot find the following essential packages: \"%2\".\n"
"Install them manually after the current operation is done.\n") "Install them manually after the current operation is done.\n")
.arg(QGuiApplication::applicationDisplayName(), .arg(QGuiApplication::applicationDisplayName(),
missingEssentials.join("\", \""))); notFoundEssentials.join("\", \"")));
} }
onApplyButton(Tr::tr("Android SDK installation is missing necessary packages. " applyInstallationChange({m_sdkManager->missingEssentialSdkPackages()},
"Do you want to install the missing packages?")); Tr::tr("Android SDK installation is missing necessary packages. "
"Do you want to install the missing packages?"));
} }
void AndroidSdkManagerWidget::beginLicenseCheck() void AndroidSdkManagerWidget::beginLicenseCheck()
@@ -298,45 +298,39 @@ void AndroidSdkManagerWidget::beginLicenseCheck()
addPackageFuture(m_sdkManager->checkPendingLicenses()); addPackageFuture(m_sdkManager->checkPendingLicenses());
} }
void AndroidSdkManagerWidget::onApplyButton(const QString &extraMessage) void AndroidSdkManagerWidget::applyInstallationChange(const InstallationChange &change,
const QString &extraMessage)
{ {
QTC_ASSERT(m_currentView == PackageListing, return); m_installationChange = change;
if (m_sdkManager->isBusy()) { if (m_sdkManager->isBusy()) {
m_formatter->appendMessage("\n" + Tr::tr("SDK Manager is busy."), StdErrFormat); m_formatter->appendMessage("\n" + Tr::tr("SDK Manager is busy."), StdErrFormat);
return; return;
} }
const QList<const AndroidSdkPackage *> packagesToUpdate = m_sdkModel->userSelection(); if (m_installationChange.count() == 0)
if (packagesToUpdate.isEmpty())
return; return;
QStringList installPackages, uninstallPackages; QString message = Tr::tr("%n Android SDK packages shall be updated.", "", change.count());
for (auto package : packagesToUpdate) {
QString str = QString(" %1").arg(package->descriptionText());
if (package->state() == AndroidSdkPackage::Installed)
uninstallPackages << str;
else
installPackages << str;
}
QString message = Tr::tr("%n Android SDK packages shall be updated.", "", packagesToUpdate.count());
if (!extraMessage.isEmpty()) if (!extraMessage.isEmpty())
message.prepend(extraMessage + "\n\n"); message.prepend(extraMessage + "\n\n");
QMessageBox messageDlg(QMessageBox::Information,
Tr::tr("Android SDK Changes"), QMessageBox messageDlg(QMessageBox::Information, Tr::tr("Android SDK Changes"),
message, message, QMessageBox::Ok | QMessageBox::Cancel,
QMessageBox::Ok | QMessageBox::Cancel,
Core::ICore::dialogParent()); Core::ICore::dialogParent());
QString details; QString details;
if (!uninstallPackages.isEmpty()) if (!change.toUninstall.isEmpty()) {
details = Tr::tr("[Packages to be uninstalled:]\n").append(uninstallPackages.join("\n")); QStringList toUninstall = {Tr::tr("[Packages to be uninstalled:]")};
toUninstall += change.toUninstall;
if (!installPackages.isEmpty()) { details += toUninstall.join("\n ");
if (!uninstallPackages.isEmpty()) }
if (!change.toInstall.isEmpty()) {
if (!change.toUninstall.isEmpty())
details.append("\n\n"); details.append("\n\n");
details.append("[Packages to be installed:]\n").append(installPackages.join("\n")); QStringList toInstall = {Tr::tr("[Packages to be installed:]")};
toInstall += change.toInstall;
details += toInstall.join("\n ");
} }
messageDlg.setDetailedText(details); messageDlg.setDetailedText(details);
if (messageDlg.exec() == QMessageBox::Cancel) if (messageDlg.exec() == QMessageBox::Cancel)
@@ -348,7 +342,7 @@ void AndroidSdkManagerWidget::onApplyButton(const QString &extraMessage)
switchView(Operations); switchView(Operations);
m_pendingCommand = AndroidSdkManager::UpdatePackage; m_pendingCommand = AndroidSdkManager::UpdatePackage;
// User agreed with the selection. Check for licenses. // User agreed with the selection. Check for licenses.
if (!installPackages.isEmpty()) { if (!change.toInstall.isEmpty()) {
// Pending license affects installtion only. // Pending license affects installtion only.
beginLicenseCheck(); beginLicenseCheck();
} else { } else {
@@ -357,6 +351,12 @@ void AndroidSdkManagerWidget::onApplyButton(const QString &extraMessage)
} }
} }
void AndroidSdkManagerWidget::onApplyButton()
{
QTC_ASSERT(m_currentView == PackageListing, return);
applyInstallationChange(m_sdkModel->installationChange());
}
void AndroidSdkManagerWidget::onUpdatePackages() void AndroidSdkManagerWidget::onUpdatePackages()
{ {
if (m_sdkManager->isBusy()) { if (m_sdkManager->isBusy()) {
@@ -432,19 +432,11 @@ void AndroidSdkManagerWidget::addPackageFuture(const QFuture<AndroidSdkManager::
void AndroidSdkManagerWidget::beginExecution() void AndroidSdkManagerWidget::beginExecution()
{ {
const QList<const AndroidSdkPackage *> packagesToUpdate = m_sdkModel->userSelection(); if (m_installationChange.count() == 0) {
if (packagesToUpdate.isEmpty()) {
switchView(PackageListing); switchView(PackageListing);
return; return;
} }
QStringList installSdkPaths, uninstallSdkPaths;
for (auto package : packagesToUpdate) {
if (package->state() == AndroidSdkPackage::Installed)
uninstallSdkPaths << package->sdkStylePath();
else
installSdkPaths << package->sdkStylePath();
}
m_formatter->appendMessage(Tr::tr("Installing/Uninstalling selected packages...\n"), m_formatter->appendMessage(Tr::tr("Installing/Uninstalling selected packages...\n"),
NormalMessageFormat); NormalMessageFormat);
m_formatter->appendMessage(Tr::tr("Closing the %1 dialog will cancel the running and scheduled SDK " m_formatter->appendMessage(Tr::tr("Closing the %1 dialog will cancel the running and scheduled SDK "
@@ -452,7 +444,8 @@ void AndroidSdkManagerWidget::beginExecution()
Tr::tr("preferences") : Tr::tr("options")), Tr::tr("preferences") : Tr::tr("options")),
LogMessageFormat); LogMessageFormat);
addPackageFuture(m_sdkManager->update({installSdkPaths, uninstallSdkPaths})); addPackageFuture(m_sdkManager->update(m_installationChange));
m_installationChange = {};
} }
void AndroidSdkManagerWidget::beginUpdate() void AndroidSdkManagerWidget::beginUpdate()

View File

@@ -70,10 +70,11 @@ public:
AndroidSdkManagerWidget(AndroidSdkManager *sdkManager, QWidget *parent = nullptr); AndroidSdkManagerWidget(AndroidSdkManager *sdkManager, QWidget *parent = nullptr);
~AndroidSdkManagerWidget() override; ~AndroidSdkManagerWidget() override;
void installEssentials(); void installMissingEssentials();
private: private:
void onApplyButton(const QString &extraMessage = {}); void applyInstallationChange(const InstallationChange &change, const QString &extraMessage = {});
void onApplyButton();
void onUpdatePackages(); void onUpdatePackages();
void onCancel(); void onCancel();
void onOperationResult(int index); void onOperationResult(int index);
@@ -97,6 +98,7 @@ private:
Utils::OutputFormatter *m_formatter = nullptr; Utils::OutputFormatter *m_formatter = nullptr;
QFutureWatcher<AndroidSdkManager::OperationOutput> *m_currentOperation = nullptr; QFutureWatcher<AndroidSdkManager::OperationOutput> *m_currentOperation = nullptr;
InstallationChange m_installationChange;
QStackedWidget *m_viewStack; QStackedWidget *m_viewStack;
QWidget *m_packagesStack; QWidget *m_packagesStack;
QWidget *m_outputStack; QWidget *m_outputStack;

View File

@@ -11,11 +11,6 @@
#include <utils/utilsicons.h> #include <utils/utilsicons.h>
#include <QIcon> #include <QIcon>
#include <QLoggingCategory>
namespace {
static Q_LOGGING_CATEGORY(androidSdkModelLog, "qtc.android.sdkmodel", QtWarningMsg)
}
namespace Android { namespace Android {
namespace Internal { namespace Internal {
@@ -258,51 +253,19 @@ bool AndroidSdkModel::setData(const QModelIndex &index, const QVariant &value, i
return false; return false;
} }
QStringList AndroidSdkModel::selectMissingEssentials() InstallationChange AndroidSdkModel::installationChange() const
{ {
resetSelection(); if (m_changeState.isEmpty())
QStringList pendingPkgs(androidConfig().allEssentials()); return {};
auto addTool = [this](QList<const AndroidSdkPackage *>::const_iterator itr) {
if ((*itr)->installedLocation().isEmpty()) {
m_changeState << *itr;
auto i = index(std::distance(m_tools.cbegin(), itr), 0, index(0, 0));
emit dataChanged(i, i, {Qt::CheckStateRole});
}
};
for (auto tool = m_tools.cbegin(); tool != m_tools.cend(); ++tool) {
if (!pendingPkgs.contains((*tool)->sdkStylePath()))
continue;
addTool(tool); InstallationChange change;
pendingPkgs.removeOne((*tool)->sdkStylePath()); for (const AndroidSdkPackage *package : m_changeState) {
if (package->state() == AndroidSdkPackage::Installed)
if (pendingPkgs.isEmpty()) change.toUninstall << package->sdkStylePath();
break; else
change.toInstall << package->sdkStylePath();
} }
return change;
// Select SDK platform
for (const SdkPlatform *platform : std::as_const(m_sdkPlatforms)) {
if (!platform->installedLocation().isEmpty()) {
pendingPkgs.removeOne(platform->sdkStylePath());
} else if (pendingPkgs.contains(platform->sdkStylePath()) &&
platform->installedLocation().isEmpty()) {
auto i = index(0, 0, index(1, 0));
m_changeState << platform;
emit dataChanged(i, i, {Qt::CheckStateRole});
pendingPkgs.removeOne(platform->sdkStylePath());
}
if (pendingPkgs.isEmpty())
break;
}
if (!pendingPkgs.isEmpty())
qCDebug(androidSdkModelLog) << "Couldn't find some essential packages:" << pendingPkgs;
return pendingPkgs;
}
QList<const AndroidSdkPackage *> AndroidSdkModel::userSelection() const
{
return Utils::toList(m_changeState);
} }
void AndroidSdkModel::resetSelection() void AndroidSdkModel::resetSelection()

View File

@@ -41,9 +41,8 @@ public:
Qt::ItemFlags flags(const QModelIndex &index) const override; Qt::ItemFlags flags(const QModelIndex &index) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override; bool setData(const QModelIndex &index, const QVariant &value, int role) override;
QStringList selectMissingEssentials();
QList<const AndroidSdkPackage *> userSelection() const;
void resetSelection(); void resetSelection();
InstallationChange installationChange() const;
private: private:
void clearContainers(); void clearContainers();

View File

@@ -669,7 +669,7 @@ void AndroidSettingsWidget::validateSdk()
AllEssentialsInstalledRow}); AllEssentialsInstalledRow});
androidConfig().setSdkFullyConfigured(sdkToolsOk && componentsOk); androidConfig().setSdkFullyConfigured(sdkToolsOk && componentsOk);
if (sdkToolsOk && !componentsOk) if (sdkToolsOk && !componentsOk)
m_sdkManagerWidget->installEssentials(); m_sdkManagerWidget->installMissingEssentials();
updateNdkList(); updateNdkList();
updateUI(); updateUI();