2022-08-19 15:59:36 +02:00
|
|
|
// Copyright (C) 2017 The Qt Company Ltd.
|
2022-12-21 10:12:09 +01:00
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
2022-07-22 10:32:08 +02:00
|
|
|
|
2017-09-18 13:48:00 +02:00
|
|
|
#include "androidconfigurations.h"
|
2017-09-27 15:26:59 +02:00
|
|
|
#include "androidsdkmanager.h"
|
2022-10-06 17:53:35 +02:00
|
|
|
#include "androidsdkmanagerwidget.h"
|
2017-09-18 13:48:00 +02:00
|
|
|
#include "androidsdkmodel.h"
|
2022-10-06 17:53:35 +02:00
|
|
|
#include "androidtr.h"
|
2017-09-18 13:48:00 +02:00
|
|
|
|
2020-07-31 17:41:28 +02:00
|
|
|
#include <app/app_version.h>
|
2022-07-22 10:32:08 +02:00
|
|
|
|
2023-05-03 15:05:47 +02:00
|
|
|
#include <utils/async.h>
|
2022-07-22 10:32:08 +02:00
|
|
|
#include <utils/layoutbuilder.h>
|
2019-01-08 16:05:57 +01:00
|
|
|
#include <utils/outputformatter.h>
|
|
|
|
|
#include <utils/qtcassert.h>
|
|
|
|
|
#include <utils/utilsicons.h>
|
2017-09-18 13:48:00 +02:00
|
|
|
|
2023-01-17 10:42:10 +01:00
|
|
|
#include <QAbstractButton>
|
2017-09-27 15:26:59 +02:00
|
|
|
#include <QDialogButtonBox>
|
2022-11-18 08:46:13 +01:00
|
|
|
#include <QGridLayout>
|
2017-09-27 15:26:59 +02:00
|
|
|
#include <QLabel>
|
|
|
|
|
#include <QLineEdit>
|
2017-09-18 13:48:00 +02:00
|
|
|
#include <QLoggingCategory>
|
|
|
|
|
#include <QMessageBox>
|
|
|
|
|
#include <QSortFilterProxyModel>
|
|
|
|
|
|
2022-07-22 10:32:08 +02:00
|
|
|
using namespace Utils;
|
|
|
|
|
using namespace std::placeholders;
|
2017-09-18 13:48:00 +02:00
|
|
|
|
2022-07-22 10:32:08 +02:00
|
|
|
namespace Android::Internal {
|
2017-09-18 13:48:00 +02:00
|
|
|
|
2022-07-22 10:32:08 +02:00
|
|
|
static Q_LOGGING_CATEGORY(androidSdkMgrUiLog, "qtc.android.sdkManagerUi", QtWarningMsg)
|
2017-09-18 13:48:00 +02:00
|
|
|
|
|
|
|
|
class PackageFilterModel : public QSortFilterProxyModel
|
|
|
|
|
{
|
|
|
|
|
public:
|
2022-07-22 10:32:08 +02:00
|
|
|
PackageFilterModel(AndroidSdkModel *sdkModel);
|
2017-09-18 13:48:00 +02:00
|
|
|
|
|
|
|
|
void setAcceptedPackageState(AndroidSdkPackage::PackageState state);
|
2021-09-13 04:20:29 +03:00
|
|
|
void setAcceptedSearchPackage(const QString &text);
|
2017-09-18 13:48:00 +02:00
|
|
|
bool filterAcceptsRow(int source_row, const QModelIndex &sourceParent) const override;
|
|
|
|
|
|
|
|
|
|
private:
|
2022-07-22 10:32:08 +02:00
|
|
|
AndroidSdkPackage::PackageState m_packageState = AndroidSdkPackage::AnyValidState;
|
2021-09-13 04:20:29 +03:00
|
|
|
QString m_searchText;
|
2017-09-18 13:48:00 +02:00
|
|
|
};
|
|
|
|
|
|
2017-09-27 15:26:59 +02:00
|
|
|
AndroidSdkManagerWidget::AndroidSdkManagerWidget(AndroidConfig &config,
|
2017-09-18 13:48:00 +02:00
|
|
|
AndroidSdkManager *sdkManager, QWidget *parent) :
|
2022-03-06 03:06:59 +02:00
|
|
|
QDialog(parent),
|
2017-09-18 13:48:00 +02:00
|
|
|
m_androidConfig(config),
|
|
|
|
|
m_sdkManager(sdkManager),
|
2022-07-22 10:32:08 +02:00
|
|
|
m_sdkModel(new AndroidSdkModel(m_androidConfig, m_sdkManager, this))
|
2017-09-18 13:48:00 +02:00
|
|
|
{
|
2017-09-27 15:26:59 +02:00
|
|
|
QTC_CHECK(sdkManager);
|
2022-07-22 10:32:08 +02:00
|
|
|
|
2022-10-06 17:53:35 +02:00
|
|
|
setWindowTitle(Tr::tr("Android SDK Manager"));
|
2022-07-22 10:32:08 +02:00
|
|
|
resize(664, 396);
|
2022-03-06 03:06:59 +02:00
|
|
|
setModal(true);
|
2017-09-18 13:48:00 +02:00
|
|
|
|
2022-07-22 10:32:08 +02:00
|
|
|
m_packagesStack = new QWidget;
|
|
|
|
|
|
|
|
|
|
auto packagesView = new QTreeView(m_packagesStack);
|
|
|
|
|
packagesView->setIndentation(20);
|
|
|
|
|
packagesView->header()->setCascadingSectionResizes(false);
|
|
|
|
|
|
2022-10-06 17:53:35 +02:00
|
|
|
auto updateInstalledButton = new QPushButton(Tr::tr("Update Installed"));
|
2022-07-22 10:32:08 +02:00
|
|
|
|
|
|
|
|
auto channelCheckbox = new QComboBox;
|
2022-10-06 17:53:35 +02:00
|
|
|
channelCheckbox->addItem(Tr::tr("Default"));
|
|
|
|
|
channelCheckbox->addItem(Tr::tr("Stable"));
|
|
|
|
|
channelCheckbox->addItem(Tr::tr("Beta"));
|
|
|
|
|
channelCheckbox->addItem(Tr::tr("Dev"));
|
|
|
|
|
channelCheckbox->addItem(Tr::tr("Canary"));
|
2022-07-22 10:32:08 +02:00
|
|
|
|
2022-10-06 17:53:35 +02:00
|
|
|
auto obsoleteCheckBox = new QCheckBox(Tr::tr("Include obsolete"));
|
2022-07-22 10:32:08 +02:00
|
|
|
|
2022-10-06 17:53:35 +02:00
|
|
|
auto showAvailableRadio = new QRadioButton(Tr::tr("Available"));
|
|
|
|
|
auto showInstalledRadio = new QRadioButton(Tr::tr("Installed"));
|
|
|
|
|
auto showAllRadio = new QRadioButton(Tr::tr("All"));
|
2022-07-22 10:32:08 +02:00
|
|
|
showAllRadio->setChecked(true);
|
|
|
|
|
|
2022-10-06 17:53:35 +02:00
|
|
|
auto optionsButton = new QPushButton(Tr::tr("Advanced Options..."));
|
2017-09-18 13:48:00 +02:00
|
|
|
|
2022-07-22 10:32:08 +02:00
|
|
|
auto searchField = new FancyLineEdit(m_packagesStack);
|
|
|
|
|
searchField->setPlaceholderText("Filter");
|
|
|
|
|
|
2022-10-06 17:53:35 +02:00
|
|
|
auto expandCheck = new QCheckBox(Tr::tr("Expand All"));
|
2022-07-22 10:32:08 +02:00
|
|
|
|
|
|
|
|
m_outputStack = new QWidget;
|
|
|
|
|
m_operationProgress = new QProgressBar(m_outputStack);
|
|
|
|
|
|
|
|
|
|
m_outputEdit = new QPlainTextEdit(m_outputStack);
|
|
|
|
|
m_outputEdit->setReadOnly(true);
|
|
|
|
|
|
2022-10-06 17:53:35 +02:00
|
|
|
m_sdkLicenseLabel = new QLabel(Tr::tr("Do you want to accept the Android SDK license?"));
|
2022-07-22 10:32:08 +02:00
|
|
|
m_sdkLicenseLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
|
|
|
|
|
m_sdkLicenseLabel->hide();
|
|
|
|
|
|
|
|
|
|
m_sdkLicenseButtonBox = new QDialogButtonBox(m_outputStack);
|
|
|
|
|
m_sdkLicenseButtonBox->setEnabled(false);
|
|
|
|
|
m_sdkLicenseButtonBox->setStandardButtons(QDialogButtonBox::No|QDialogButtonBox::Yes);
|
|
|
|
|
m_sdkLicenseButtonBox->hide();
|
|
|
|
|
|
|
|
|
|
m_buttonBox = new QDialogButtonBox(this);
|
2023-01-05 12:25:44 +01:00
|
|
|
m_buttonBox->setStandardButtons(QDialogButtonBox::Apply | QDialogButtonBox::Cancel);
|
|
|
|
|
m_buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
|
2022-07-22 10:32:08 +02:00
|
|
|
|
|
|
|
|
m_viewStack = new QStackedWidget(this);
|
|
|
|
|
m_viewStack->addWidget(m_packagesStack);
|
|
|
|
|
m_viewStack->addWidget(m_outputStack);
|
|
|
|
|
m_viewStack->setCurrentWidget(m_packagesStack);
|
|
|
|
|
|
|
|
|
|
m_formatter = new OutputFormatter;
|
|
|
|
|
m_formatter->setPlainTextEdit(m_outputEdit);
|
|
|
|
|
|
|
|
|
|
auto proxyModel = new PackageFilterModel(m_sdkModel);
|
|
|
|
|
packagesView->setModel(proxyModel);
|
|
|
|
|
packagesView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
|
|
|
|
packagesView->header()->setSectionResizeMode(AndroidSdkModel::packageNameColumn,
|
|
|
|
|
QHeaderView::Stretch);
|
|
|
|
|
packagesView->header()->setStretchLastSection(false);
|
|
|
|
|
|
|
|
|
|
using namespace Layouting;
|
|
|
|
|
Grid {
|
|
|
|
|
searchField, expandCheck, br,
|
|
|
|
|
|
|
|
|
|
Span(2, packagesView),
|
|
|
|
|
Column {
|
|
|
|
|
updateInstalledButton,
|
|
|
|
|
st,
|
|
|
|
|
Group {
|
2022-10-06 17:53:35 +02:00
|
|
|
title(Tr::tr("Show Packages")),
|
2022-07-22 10:32:08 +02:00
|
|
|
Column {
|
2022-10-06 17:53:35 +02:00
|
|
|
Row { Tr::tr("Channel:"), channelCheckbox },
|
2022-07-22 10:32:08 +02:00
|
|
|
obsoleteCheckBox,
|
2022-08-29 17:38:41 +02:00
|
|
|
hr,
|
2022-07-22 10:32:08 +02:00
|
|
|
showAvailableRadio,
|
|
|
|
|
showInstalledRadio,
|
|
|
|
|
showAllRadio,
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
optionsButton
|
|
|
|
|
}
|
2022-11-22 18:15:16 +01:00
|
|
|
}.attachTo(m_packagesStack, WithoutMargins);
|
2022-07-22 10:32:08 +02:00
|
|
|
|
|
|
|
|
Column {
|
|
|
|
|
m_outputEdit,
|
|
|
|
|
Row { m_sdkLicenseLabel, m_sdkLicenseButtonBox },
|
|
|
|
|
m_operationProgress,
|
2022-11-22 18:15:16 +01:00
|
|
|
}.attachTo(m_outputStack, WithoutMargins);
|
2022-07-22 10:32:08 +02:00
|
|
|
|
|
|
|
|
Column {
|
|
|
|
|
m_viewStack,
|
|
|
|
|
m_buttonBox
|
|
|
|
|
}.attachTo(this);
|
|
|
|
|
|
2023-01-05 12:25:44 +01:00
|
|
|
connect(m_sdkModel, &AndroidSdkModel::dataChanged, this, [this] {
|
2022-07-22 10:32:08 +02:00
|
|
|
if (m_viewStack->currentWidget() == m_packagesStack)
|
2023-01-05 12:25:44 +01:00
|
|
|
m_buttonBox->button(QDialogButtonBox::Apply)
|
|
|
|
|
->setEnabled(!m_sdkModel->userSelection().isEmpty());
|
2017-09-18 13:48:00 +02:00
|
|
|
});
|
|
|
|
|
|
2022-07-22 10:32:08 +02:00
|
|
|
connect(m_sdkModel, &AndroidSdkModel::modelAboutToBeReset, this,
|
2023-01-05 12:25:44 +01:00
|
|
|
[this, expandCheck] {
|
|
|
|
|
m_buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
|
2022-07-22 10:32:08 +02:00
|
|
|
expandCheck->setChecked(false);
|
2017-09-18 13:48:00 +02:00
|
|
|
cancelPendingOperations();
|
|
|
|
|
switchView(PackageListing);
|
|
|
|
|
});
|
|
|
|
|
|
2022-07-26 11:26:51 +02:00
|
|
|
connect(expandCheck, &QCheckBox::stateChanged, this, [packagesView](int state) {
|
|
|
|
|
if (state == Qt::Checked)
|
|
|
|
|
packagesView->expandAll();
|
|
|
|
|
else
|
|
|
|
|
packagesView->collapseAll();
|
2017-09-18 13:48:00 +02:00
|
|
|
});
|
2022-07-22 10:32:08 +02:00
|
|
|
connect(updateInstalledButton, &QPushButton::clicked,
|
2017-09-18 13:48:00 +02:00
|
|
|
this, &AndroidSdkManagerWidget::onUpdatePackages);
|
2022-07-22 10:32:08 +02:00
|
|
|
connect(showAllRadio, &QRadioButton::toggled, this, [this, proxyModel](bool checked) {
|
2017-09-18 13:48:00 +02:00
|
|
|
if (checked) {
|
|
|
|
|
proxyModel->setAcceptedPackageState(AndroidSdkPackage::AnyValidState);
|
|
|
|
|
m_sdkModel->resetSelection();
|
|
|
|
|
}
|
|
|
|
|
});
|
2022-07-22 10:32:08 +02:00
|
|
|
connect(showInstalledRadio, &QRadioButton::toggled,
|
2022-07-19 22:51:32 +02:00
|
|
|
this, [this, proxyModel](bool checked) {
|
2017-09-18 13:48:00 +02:00
|
|
|
if (checked) {
|
|
|
|
|
proxyModel->setAcceptedPackageState(AndroidSdkPackage::Installed);
|
|
|
|
|
m_sdkModel->resetSelection();
|
|
|
|
|
}
|
|
|
|
|
});
|
2022-07-22 10:32:08 +02:00
|
|
|
connect(showAvailableRadio, &QRadioButton::toggled, this, [this, proxyModel](bool checked) {
|
2017-09-18 13:48:00 +02:00
|
|
|
if (checked) {
|
|
|
|
|
proxyModel->setAcceptedPackageState(AndroidSdkPackage::Available);
|
|
|
|
|
m_sdkModel->resetSelection();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2022-07-22 10:32:08 +02:00
|
|
|
connect(searchField, &QLineEdit::textChanged,
|
|
|
|
|
this, [this, proxyModel, expandCheck](const QString &text) {
|
2021-09-13 04:20:29 +03:00
|
|
|
proxyModel->setAcceptedSearchPackage(text);
|
|
|
|
|
m_sdkModel->resetSelection();
|
|
|
|
|
// It is more convenient to expand the view with the results
|
2022-07-22 10:32:08 +02:00
|
|
|
expandCheck->setChecked(!text.isEmpty());
|
2021-09-13 04:20:29 +03:00
|
|
|
});
|
|
|
|
|
|
2023-01-05 12:25:44 +01:00
|
|
|
connect(m_buttonBox->button(QDialogButtonBox::Apply), &QAbstractButton::clicked, this, [this] {
|
|
|
|
|
onApplyButton();
|
|
|
|
|
});
|
|
|
|
|
connect(m_buttonBox, &QDialogButtonBox::rejected, this, &AndroidSdkManagerWidget::onCancel);
|
|
|
|
|
|
2022-07-22 10:32:08 +02:00
|
|
|
connect(optionsButton, &QPushButton::clicked,
|
2017-09-27 15:26:59 +02:00
|
|
|
this, &AndroidSdkManagerWidget::onSdkManagerOptions);
|
2022-07-22 10:32:08 +02:00
|
|
|
connect(m_sdkLicenseButtonBox, &QDialogButtonBox::accepted, this, [this] {
|
2017-10-07 23:22:29 +02:00
|
|
|
m_sdkManager->acceptSdkLicense(true);
|
2022-07-22 10:32:08 +02:00
|
|
|
m_sdkLicenseButtonBox->setEnabled(false); // Wait for next license to enable controls
|
2017-10-07 23:22:29 +02:00
|
|
|
});
|
2022-07-22 10:32:08 +02:00
|
|
|
connect(m_sdkLicenseButtonBox, &QDialogButtonBox::rejected, this, [this] {
|
2017-10-07 23:22:29 +02:00
|
|
|
m_sdkManager->acceptSdkLicense(false);
|
2022-07-22 10:32:08 +02:00
|
|
|
m_sdkLicenseButtonBox->setEnabled(false); // Wait for next license to enable controls
|
2017-10-07 23:22:29 +02:00
|
|
|
});
|
2021-09-14 20:12:56 +03:00
|
|
|
|
2022-07-22 10:32:08 +02:00
|
|
|
connect(obsoleteCheckBox, &QCheckBox::stateChanged, this, [this](int state) {
|
2021-09-14 20:12:56 +03:00
|
|
|
const QString obsoleteArg = "--include_obsolete";
|
|
|
|
|
QStringList args = m_androidConfig.sdkManagerToolArgs();
|
|
|
|
|
if (state == Qt::Checked && !args.contains(obsoleteArg)) {
|
|
|
|
|
args.append(obsoleteArg);
|
|
|
|
|
m_androidConfig.setSdkManagerToolArgs(args);
|
|
|
|
|
} else if (state == Qt::Unchecked && args.contains(obsoleteArg)) {
|
|
|
|
|
args.removeAll(obsoleteArg);
|
|
|
|
|
m_androidConfig.setSdkManagerToolArgs(args);
|
|
|
|
|
}
|
|
|
|
|
m_sdkManager->reloadPackages(true);
|
|
|
|
|
});
|
|
|
|
|
|
2022-07-22 10:32:08 +02:00
|
|
|
connect(channelCheckbox, &QComboBox::currentIndexChanged, this, [this](int index) {
|
2021-09-14 20:12:56 +03:00
|
|
|
QStringList args = m_androidConfig.sdkManagerToolArgs();
|
|
|
|
|
QString existingArg;
|
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
|
|
|
const QString arg = "--channel=" + QString::number(i);
|
|
|
|
|
if (args.contains(arg)) {
|
|
|
|
|
existingArg = arg;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (index == 0 && !existingArg.isEmpty()) {
|
|
|
|
|
args.removeAll(existingArg);
|
|
|
|
|
m_androidConfig.setSdkManagerToolArgs(args);
|
|
|
|
|
} else if (index > 0) {
|
|
|
|
|
// Add 1 to account for Stable (second item) being channel 0
|
|
|
|
|
const QString channelArg = "--channel=" + QString::number(index - 1);
|
|
|
|
|
if (existingArg != channelArg) {
|
|
|
|
|
if (!existingArg.isEmpty()) {
|
|
|
|
|
args.removeAll(existingArg);
|
|
|
|
|
m_androidConfig.setSdkManagerToolArgs(args);
|
|
|
|
|
}
|
|
|
|
|
args.append(channelArg);
|
|
|
|
|
m_androidConfig.setSdkManagerToolArgs(args);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
m_sdkManager->reloadPackages(true);
|
|
|
|
|
});
|
2017-09-18 13:48:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AndroidSdkManagerWidget::~AndroidSdkManagerWidget()
|
|
|
|
|
{
|
|
|
|
|
if (m_currentOperation)
|
|
|
|
|
delete m_currentOperation;
|
|
|
|
|
cancelPendingOperations();
|
|
|
|
|
delete m_formatter;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-26 19:06:17 +02:00
|
|
|
void AndroidSdkManagerWidget::installEssentials()
|
2017-09-26 11:24:16 +02:00
|
|
|
{
|
|
|
|
|
m_sdkModel->selectMissingEssentials();
|
2020-05-18 18:03:50 +03:00
|
|
|
if (!m_sdkModel->missingEssentials().isEmpty()) {
|
|
|
|
|
QMessageBox::warning(this,
|
2022-10-06 17:53:35 +02:00
|
|
|
Tr::tr("Android SDK Changes"),
|
|
|
|
|
Tr::tr("%1 cannot find the following essential packages: \"%2\".\n"
|
|
|
|
|
"Install them manually after the current operation is done.\n")
|
|
|
|
|
.arg(Core::Constants::IDE_DISPLAY_NAME)
|
|
|
|
|
.arg(m_sdkModel->missingEssentials().join("\", \"")));
|
2020-05-18 18:03:50 +03:00
|
|
|
}
|
2022-10-06 17:53:35 +02:00
|
|
|
onApplyButton(Tr::tr("Android SDK installation is missing necessary packages. "
|
2022-03-26 19:06:17 +02:00
|
|
|
"Do you want to install the missing packages?"));
|
2017-09-26 11:24:16 +02:00
|
|
|
}
|
|
|
|
|
|
2017-10-07 23:22:29 +02:00
|
|
|
void AndroidSdkManagerWidget::beginLicenseCheck()
|
|
|
|
|
{
|
2022-10-06 17:53:35 +02:00
|
|
|
m_formatter->appendMessage(Tr::tr("Checking pending licenses...\n"), NormalMessageFormat);
|
|
|
|
|
m_formatter->appendMessage(Tr::tr("The installation of Android SDK packages may fail if the "
|
|
|
|
|
"respective licenses are not accepted.\n"),
|
2022-07-22 10:32:08 +02:00
|
|
|
LogMessageFormat);
|
2017-10-07 23:22:29 +02:00
|
|
|
addPackageFuture(m_sdkManager->checkPendingLicenses());
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-30 11:37:39 +02:00
|
|
|
void AndroidSdkManagerWidget::onApplyButton(const QString &extraMessage)
|
2017-09-18 13:48:00 +02:00
|
|
|
{
|
2017-10-07 23:22:29 +02:00
|
|
|
QTC_ASSERT(m_currentView == PackageListing, return);
|
2017-09-18 13:48:00 +02:00
|
|
|
|
|
|
|
|
if (m_sdkManager->isBusy()) {
|
2022-10-06 17:53:35 +02:00
|
|
|
m_formatter->appendMessage(Tr::tr("\nSDK Manager is busy."), StdErrFormat);
|
2017-09-18 13:48:00 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const QList<const AndroidSdkPackage *> packagesToUpdate = m_sdkModel->userSelection();
|
|
|
|
|
if (packagesToUpdate.isEmpty())
|
|
|
|
|
return;
|
|
|
|
|
|
2017-10-07 23:22:29 +02:00
|
|
|
QStringList installPackages, uninstallPackages;
|
2017-09-18 13:48:00 +02:00
|
|
|
for (auto package : packagesToUpdate) {
|
|
|
|
|
QString str = QString(" %1").arg(package->descriptionText());
|
2017-10-07 23:22:29 +02:00
|
|
|
if (package->state() == AndroidSdkPackage::Installed)
|
2017-09-18 13:48:00 +02:00
|
|
|
uninstallPackages << str;
|
2017-10-07 23:22:29 +02:00
|
|
|
else
|
2017-09-18 13:48:00 +02:00
|
|
|
installPackages << str;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-06 17:53:35 +02:00
|
|
|
QString message = Tr::tr("%n Android SDK packages shall be updated.", "", packagesToUpdate.count());
|
2022-01-30 11:37:39 +02:00
|
|
|
if (!extraMessage.isEmpty())
|
|
|
|
|
message.prepend(extraMessage + "\n\n");
|
2022-10-06 17:53:35 +02:00
|
|
|
QMessageBox messageDlg(QMessageBox::Information, Tr::tr("Android SDK Changes"),
|
2022-01-30 11:37:39 +02:00
|
|
|
message, QMessageBox::Ok | QMessageBox::Cancel, this);
|
2017-09-18 13:48:00 +02:00
|
|
|
|
|
|
|
|
QString details;
|
|
|
|
|
if (!uninstallPackages.isEmpty())
|
2022-10-06 17:53:35 +02:00
|
|
|
details = Tr::tr("[Packages to be uninstalled:]\n").append(uninstallPackages.join("\n"));
|
2017-09-18 13:48:00 +02:00
|
|
|
|
|
|
|
|
if (!installPackages.isEmpty()) {
|
|
|
|
|
if (!uninstallPackages.isEmpty())
|
|
|
|
|
details.append("\n\n");
|
|
|
|
|
details.append("[Packages to be installed:]\n").append(installPackages.join("\n"));
|
|
|
|
|
}
|
|
|
|
|
messageDlg.setDetailedText(details);
|
|
|
|
|
if (messageDlg.exec() == QMessageBox::Cancel)
|
|
|
|
|
return;
|
|
|
|
|
|
2022-03-06 03:06:59 +02:00
|
|
|
// Open the SDK Manager dialog after accepting to continue with the installation
|
|
|
|
|
show();
|
|
|
|
|
|
2017-09-18 13:48:00 +02:00
|
|
|
switchView(Operations);
|
2017-10-07 23:22:29 +02:00
|
|
|
m_pendingCommand = AndroidSdkManager::UpdatePackage;
|
|
|
|
|
// User agreed with the selection. Check for licenses.
|
|
|
|
|
if (!installPackages.isEmpty()) {
|
|
|
|
|
// Pending license affects installtion only.
|
|
|
|
|
beginLicenseCheck();
|
|
|
|
|
} else {
|
|
|
|
|
// Uninstall only. Go Ahead.
|
|
|
|
|
beginExecution();
|
|
|
|
|
}
|
2017-09-18 13:48:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidSdkManagerWidget::onUpdatePackages()
|
|
|
|
|
{
|
|
|
|
|
if (m_sdkManager->isBusy()) {
|
2022-10-06 17:53:35 +02:00
|
|
|
m_formatter->appendMessage(Tr::tr("\nSDK Manager is busy."), StdErrFormat);
|
2017-09-18 13:48:00 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
switchView(Operations);
|
2017-10-07 23:22:29 +02:00
|
|
|
m_pendingCommand = AndroidSdkManager::UpdateAll;
|
|
|
|
|
beginLicenseCheck();
|
2017-09-18 13:48:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidSdkManagerWidget::onCancel()
|
|
|
|
|
{
|
|
|
|
|
cancelPendingOperations();
|
2023-01-05 12:25:44 +01:00
|
|
|
close();
|
2017-09-18 13:48:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidSdkManagerWidget::onOperationResult(int index)
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(m_currentOperation, return);
|
|
|
|
|
AndroidSdkManager::OperationOutput result = m_currentOperation->resultAt(index);
|
2017-10-07 23:22:29 +02:00
|
|
|
if (result.type == AndroidSdkManager::LicenseWorkflow) {
|
|
|
|
|
// Show license controls and enable to user input.
|
2022-07-22 10:32:08 +02:00
|
|
|
m_sdkLicenseLabel->setVisible(true);
|
|
|
|
|
m_sdkLicenseButtonBox->setVisible(true);
|
|
|
|
|
m_sdkLicenseButtonBox->setEnabled(true);
|
|
|
|
|
m_sdkLicenseButtonBox->button(QDialogButtonBox::No)->setDefault(true);
|
2017-10-07 23:22:29 +02:00
|
|
|
}
|
|
|
|
|
auto breakLine = [](const QString &line) { return line.endsWith("\n") ? line : line + "\n";};
|
|
|
|
|
if (!result.stdError.isEmpty() && result.type != AndroidSdkManager::LicenseCheck)
|
2022-07-22 10:32:08 +02:00
|
|
|
m_formatter->appendMessage(breakLine(result.stdError), StdErrFormat);
|
2017-10-07 23:22:29 +02:00
|
|
|
if (!result.stdOutput.isEmpty() && result.type != AndroidSdkManager::LicenseCheck)
|
2022-07-22 10:32:08 +02:00
|
|
|
m_formatter->appendMessage(breakLine(result.stdOutput), StdOutFormat);
|
|
|
|
|
m_outputEdit->ensureCursorVisible();
|
2017-10-07 23:22:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidSdkManagerWidget::onLicenseCheckResult(const AndroidSdkManager::OperationOutput& output)
|
|
|
|
|
{
|
|
|
|
|
if (output.success) {
|
|
|
|
|
// No assertion was found. Looks like all license are accepted. Go Ahead.
|
|
|
|
|
runPendingCommand();
|
|
|
|
|
} else {
|
2022-01-30 11:37:39 +02:00
|
|
|
// Run license workflow.
|
|
|
|
|
beginLicenseWorkflow();
|
2017-10-07 23:22:29 +02:00
|
|
|
}
|
2017-09-18 13:48:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidSdkManagerWidget::addPackageFuture(const QFuture<AndroidSdkManager::OperationOutput>
|
|
|
|
|
&future)
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(!m_currentOperation, return);
|
|
|
|
|
if (!future.isFinished() || !future.isCanceled()) {
|
|
|
|
|
m_currentOperation = new QFutureWatcher<AndroidSdkManager::OperationOutput>;
|
2022-07-19 22:51:32 +02:00
|
|
|
connect(m_currentOperation, &QFutureWatcherBase::resultReadyAt,
|
2017-09-18 13:48:00 +02:00
|
|
|
this, &AndroidSdkManagerWidget::onOperationResult);
|
2022-07-19 22:51:32 +02:00
|
|
|
connect(m_currentOperation, &QFutureWatcherBase::finished,
|
2017-09-18 13:48:00 +02:00
|
|
|
this, &AndroidSdkManagerWidget::packageFutureFinished);
|
2022-07-19 22:51:32 +02:00
|
|
|
connect(m_currentOperation, &QFutureWatcherBase::progressValueChanged,
|
|
|
|
|
this, [this](int value) {
|
2022-07-22 10:32:08 +02:00
|
|
|
m_operationProgress->setValue(value);
|
2017-09-18 13:48:00 +02:00
|
|
|
});
|
2017-10-12 10:03:13 +02:00
|
|
|
m_currentOperation->setFuture(future);
|
2017-09-18 13:48:00 +02:00
|
|
|
} else {
|
|
|
|
|
qCDebug(androidSdkMgrUiLog) << "Operation canceled/finished before adding to the queue";
|
|
|
|
|
if (m_sdkManager->isBusy()) {
|
2022-10-06 17:53:35 +02:00
|
|
|
m_formatter->appendMessage(Tr::tr("SDK Manager is busy. Operation cancelled."),
|
2022-07-22 10:32:08 +02:00
|
|
|
StdErrFormat);
|
2017-09-18 13:48:00 +02:00
|
|
|
}
|
|
|
|
|
notifyOperationFinished();
|
2017-10-07 23:22:29 +02:00
|
|
|
switchView(PackageListing);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidSdkManagerWidget::beginExecution()
|
|
|
|
|
{
|
|
|
|
|
const QList<const AndroidSdkPackage *> packagesToUpdate = m_sdkModel->userSelection();
|
|
|
|
|
if (packagesToUpdate.isEmpty()) {
|
|
|
|
|
switchView(PackageListing);
|
|
|
|
|
return;
|
2017-09-18 13:48:00 +02:00
|
|
|
}
|
2017-10-07 23:22:29 +02:00
|
|
|
|
|
|
|
|
QStringList installSdkPaths, uninstallSdkPaths;
|
|
|
|
|
for (auto package : packagesToUpdate) {
|
|
|
|
|
if (package->state() == AndroidSdkPackage::Installed)
|
|
|
|
|
uninstallSdkPaths << package->sdkStylePath();
|
|
|
|
|
else
|
|
|
|
|
installSdkPaths << package->sdkStylePath();
|
|
|
|
|
}
|
2022-10-06 17:53:35 +02:00
|
|
|
m_formatter->appendMessage(Tr::tr("Installing/Uninstalling selected packages...\n"),
|
2022-07-22 10:32:08 +02:00
|
|
|
NormalMessageFormat);
|
2022-10-06 17:53:35 +02:00
|
|
|
m_formatter->appendMessage(Tr::tr("Closing the %1 dialog will cancel the running and scheduled SDK "
|
2022-07-22 10:32:08 +02:00
|
|
|
"operations.\n").arg(HostOsInfo::isMacHost() ?
|
2022-10-06 17:53:35 +02:00
|
|
|
Tr::tr("preferences") : Tr::tr("options")),
|
2022-07-22 10:32:08 +02:00
|
|
|
LogMessageFormat);
|
2017-10-07 23:22:29 +02:00
|
|
|
|
|
|
|
|
addPackageFuture(m_sdkManager->update(installSdkPaths, uninstallSdkPaths));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidSdkManagerWidget::beginUpdate()
|
|
|
|
|
{
|
2022-10-06 17:53:35 +02:00
|
|
|
m_formatter->appendMessage(Tr::tr("Updating installed packages...\n"), NormalMessageFormat);
|
|
|
|
|
m_formatter->appendMessage(Tr::tr("Closing the %1 dialog will cancel the running and scheduled SDK "
|
2022-07-22 10:32:08 +02:00
|
|
|
"operations.\n").arg(HostOsInfo::isMacHost() ?
|
2022-10-06 17:53:35 +02:00
|
|
|
Tr::tr("preferences") : Tr::tr("options")),
|
2022-07-22 10:32:08 +02:00
|
|
|
LogMessageFormat);
|
2017-10-07 23:22:29 +02:00
|
|
|
addPackageFuture(m_sdkManager->updateAll());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidSdkManagerWidget::beginLicenseWorkflow()
|
|
|
|
|
{
|
|
|
|
|
switchView(LicenseWorkflow);
|
|
|
|
|
addPackageFuture(m_sdkManager->runLicenseCommand());
|
2017-09-18 13:48:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidSdkManagerWidget::notifyOperationFinished()
|
|
|
|
|
{
|
|
|
|
|
if (!m_currentOperation || m_currentOperation->isFinished()) {
|
2022-10-06 17:53:35 +02:00
|
|
|
QMessageBox::information(this, Tr::tr("Android SDK Changes"),
|
|
|
|
|
Tr::tr("Android SDK operations finished."), QMessageBox::Ok);
|
2022-07-22 10:32:08 +02:00
|
|
|
m_operationProgress->setValue(0);
|
2022-03-06 03:06:59 +02:00
|
|
|
// Once the update/install is done, let's hide the dialog.
|
|
|
|
|
hide();
|
2017-09-18 13:48:00 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidSdkManagerWidget::packageFutureFinished()
|
|
|
|
|
{
|
2017-10-07 23:22:29 +02:00
|
|
|
QTC_ASSERT (m_currentOperation, return);
|
|
|
|
|
|
|
|
|
|
bool continueWorkflow = true;
|
|
|
|
|
if (m_currentOperation->isCanceled()) {
|
2022-10-06 17:53:35 +02:00
|
|
|
m_formatter->appendMessage(Tr::tr("Operation cancelled.\n"), StdErrFormat);
|
2017-10-07 23:22:29 +02:00
|
|
|
continueWorkflow = false;
|
2017-09-18 13:48:00 +02:00
|
|
|
}
|
2022-07-22 10:32:08 +02:00
|
|
|
m_operationProgress->setValue(100);
|
2017-10-07 23:22:29 +02:00
|
|
|
int resultCount = m_currentOperation->future().resultCount();
|
|
|
|
|
if (continueWorkflow && resultCount > 0) {
|
|
|
|
|
AndroidSdkManager::OperationOutput output = m_currentOperation->resultAt(resultCount -1);
|
|
|
|
|
AndroidSdkManager::CommandType type = output.type;
|
|
|
|
|
m_currentOperation->deleteLater();
|
|
|
|
|
m_currentOperation = nullptr;
|
|
|
|
|
switch (type) {
|
|
|
|
|
case AndroidSdkManager::LicenseCheck:
|
|
|
|
|
onLicenseCheckResult(output);
|
|
|
|
|
break;
|
|
|
|
|
case AndroidSdkManager::LicenseWorkflow:
|
2022-07-22 10:32:08 +02:00
|
|
|
m_sdkLicenseButtonBox->hide();
|
|
|
|
|
m_sdkLicenseLabel->hide();
|
2017-10-07 23:22:29 +02:00
|
|
|
runPendingCommand();
|
|
|
|
|
break;
|
|
|
|
|
case AndroidSdkManager::UpdateAll:
|
|
|
|
|
case AndroidSdkManager::UpdatePackage:
|
|
|
|
|
notifyOperationFinished();
|
|
|
|
|
switchView(PackageListing);
|
|
|
|
|
m_sdkManager->reloadPackages(true);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
m_currentOperation->deleteLater();
|
|
|
|
|
m_currentOperation = nullptr;
|
|
|
|
|
switchView(PackageListing);
|
|
|
|
|
m_sdkManager->reloadPackages(true);
|
|
|
|
|
}
|
2017-09-18 13:48:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidSdkManagerWidget::cancelPendingOperations()
|
|
|
|
|
{
|
|
|
|
|
if (!m_sdkManager->isBusy()) {
|
2022-10-06 17:53:35 +02:00
|
|
|
m_formatter->appendMessage(Tr::tr("\nNo pending operations to cancel...\n"),
|
2022-07-22 10:32:08 +02:00
|
|
|
NormalMessageFormat);
|
2017-10-07 23:22:29 +02:00
|
|
|
switchView(PackageListing);
|
2017-09-18 13:48:00 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2022-10-06 17:53:35 +02:00
|
|
|
m_formatter->appendMessage(Tr::tr("\nCancelling pending operations...\n"),
|
2022-07-22 10:32:08 +02:00
|
|
|
NormalMessageFormat);
|
2017-09-18 13:48:00 +02:00
|
|
|
m_sdkManager->cancelOperatons();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidSdkManagerWidget::switchView(AndroidSdkManagerWidget::View view)
|
|
|
|
|
{
|
2020-03-18 09:53:07 +01:00
|
|
|
if (m_currentView == PackageListing)
|
2017-10-07 23:22:29 +02:00
|
|
|
m_formatter->clear();
|
|
|
|
|
m_currentView = view;
|
2022-03-06 03:06:59 +02:00
|
|
|
if (m_currentView == PackageListing) {
|
|
|
|
|
// We need the buttonBox only in the main listing view, as the license and update
|
|
|
|
|
// views already have a cancel button.
|
2023-01-05 12:25:44 +01:00
|
|
|
m_buttonBox->button(QDialogButtonBox::Apply)->setVisible(true);
|
2017-10-07 23:22:29 +02:00
|
|
|
emit updatingSdkFinished();
|
2022-03-06 03:06:59 +02:00
|
|
|
} else {
|
2023-01-05 12:25:44 +01:00
|
|
|
m_buttonBox->button(QDialogButtonBox::Apply)->setVisible(false);
|
2017-10-07 23:22:29 +02:00
|
|
|
emit updatingSdk();
|
2022-03-06 03:06:59 +02:00
|
|
|
}
|
2017-10-07 23:22:29 +02:00
|
|
|
|
2020-03-24 06:54:15 +01:00
|
|
|
if (m_currentView == LicenseWorkflow)
|
|
|
|
|
emit licenseWorkflowStarted();
|
|
|
|
|
|
2022-07-22 10:32:08 +02:00
|
|
|
m_operationProgress->setValue(0);
|
|
|
|
|
m_viewStack->setCurrentWidget(m_currentView == PackageListing ?
|
|
|
|
|
m_packagesStack : m_outputStack);
|
2017-09-18 13:48:00 +02:00
|
|
|
}
|
|
|
|
|
|
2017-10-07 23:22:29 +02:00
|
|
|
void AndroidSdkManagerWidget::runPendingCommand()
|
2017-09-18 13:48:00 +02:00
|
|
|
{
|
2017-10-07 23:22:29 +02:00
|
|
|
if (m_pendingCommand == AndroidSdkManager::UpdatePackage)
|
|
|
|
|
beginExecution(); // License workflow can only start when updating packages.
|
|
|
|
|
else if (m_pendingCommand == AndroidSdkManager::UpdateAll)
|
|
|
|
|
beginUpdate();
|
|
|
|
|
else
|
|
|
|
|
QTC_ASSERT(false, qCDebug(androidSdkMgrUiLog) << "Unexpected state: No pending command.");
|
2017-09-18 13:48:00 +02:00
|
|
|
}
|
|
|
|
|
|
2017-09-27 15:26:59 +02:00
|
|
|
void AndroidSdkManagerWidget::onSdkManagerOptions()
|
|
|
|
|
{
|
|
|
|
|
OptionsDialog dlg(m_sdkManager, m_androidConfig.sdkManagerToolArgs(), this);
|
|
|
|
|
if (dlg.exec() == QDialog::Accepted) {
|
|
|
|
|
QStringList arguments = dlg.sdkManagerArguments();
|
|
|
|
|
if (arguments != m_androidConfig.sdkManagerToolArgs()) {
|
|
|
|
|
m_androidConfig.setSdkManagerToolArgs(arguments);
|
|
|
|
|
m_sdkManager->reloadPackages(true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-18 13:48:00 +02:00
|
|
|
PackageFilterModel::PackageFilterModel(AndroidSdkModel *sdkModel) :
|
|
|
|
|
QSortFilterProxyModel(sdkModel)
|
|
|
|
|
{
|
|
|
|
|
setSourceModel(sdkModel);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PackageFilterModel::setAcceptedPackageState(AndroidSdkPackage::PackageState state)
|
|
|
|
|
{
|
|
|
|
|
m_packageState = state;
|
|
|
|
|
invalidateFilter();
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-13 04:20:29 +03:00
|
|
|
void PackageFilterModel::setAcceptedSearchPackage(const QString &name)
|
|
|
|
|
{
|
|
|
|
|
m_searchText = name;
|
|
|
|
|
invalidateFilter();
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-18 13:48:00 +02:00
|
|
|
bool PackageFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
|
|
|
|
{
|
|
|
|
|
QModelIndex srcIndex = sourceModel()->index(sourceRow, 0, sourceParent);
|
|
|
|
|
if (!srcIndex.isValid())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
auto packageState = [](const QModelIndex& i) {
|
|
|
|
|
return (AndroidSdkPackage::PackageState)i.data(AndroidSdkModel::PackageStateRole).toInt();
|
|
|
|
|
};
|
|
|
|
|
|
2021-09-13 04:20:29 +03:00
|
|
|
auto packageFound = [this](const QModelIndex& i) {
|
|
|
|
|
return i.data(AndroidSdkModel::packageNameColumn).toString()
|
|
|
|
|
.contains(m_searchText, Qt::CaseInsensitive);
|
|
|
|
|
};
|
|
|
|
|
|
2017-09-18 13:48:00 +02:00
|
|
|
bool showTopLevel = false;
|
|
|
|
|
if (!sourceParent.isValid()) {
|
|
|
|
|
// Top Level items
|
|
|
|
|
for (int row = 0; row < sourceModel()->rowCount(srcIndex); ++row) {
|
|
|
|
|
QModelIndex childIndex = sourceModel()->index(row, 0, srcIndex);
|
2021-09-13 04:20:29 +03:00
|
|
|
if ((m_packageState & packageState(childIndex) && packageFound(childIndex))) {
|
2017-09-18 13:48:00 +02:00
|
|
|
showTopLevel = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-06 14:55:47 +02:00
|
|
|
return showTopLevel || ((packageState(srcIndex) & m_packageState) && packageFound(srcIndex));
|
2017-09-18 13:48:00 +02:00
|
|
|
}
|
|
|
|
|
|
2017-09-27 15:26:59 +02:00
|
|
|
OptionsDialog::OptionsDialog(AndroidSdkManager *sdkManager, const QStringList &args,
|
|
|
|
|
QWidget *parent) : QDialog(parent)
|
|
|
|
|
{
|
|
|
|
|
QTC_CHECK(sdkManager);
|
|
|
|
|
resize(800, 480);
|
2022-10-06 17:53:35 +02:00
|
|
|
setWindowTitle(Tr::tr("SDK Manager Arguments"));
|
2017-09-27 15:26:59 +02:00
|
|
|
|
2022-07-22 10:32:08 +02:00
|
|
|
m_argumentDetailsEdit = new QPlainTextEdit(this);
|
|
|
|
|
m_argumentDetailsEdit->setReadOnly(true);
|
2017-09-27 15:26:59 +02:00
|
|
|
|
|
|
|
|
auto populateOptions = [this](const QString& options) {
|
|
|
|
|
if (options.isEmpty()) {
|
2022-10-06 17:53:35 +02:00
|
|
|
m_argumentDetailsEdit->setPlainText(Tr::tr("Cannot load available arguments for "
|
|
|
|
|
"\"sdkmanager\" command."));
|
2017-09-27 15:26:59 +02:00
|
|
|
} else {
|
2022-07-22 10:32:08 +02:00
|
|
|
m_argumentDetailsEdit->setPlainText(options);
|
2017-09-27 15:26:59 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
m_optionsFuture = sdkManager->availableArguments();
|
2023-04-06 18:27:10 +02:00
|
|
|
Utils::onResultReady(m_optionsFuture, this, populateOptions);
|
2017-09-27 15:26:59 +02:00
|
|
|
|
|
|
|
|
auto dialogButtons = new QDialogButtonBox(this);
|
|
|
|
|
dialogButtons->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
|
|
|
|
|
connect(dialogButtons, &QDialogButtonBox::accepted, this, &OptionsDialog::accept);
|
|
|
|
|
connect(dialogButtons, &QDialogButtonBox::rejected, this, &OptionsDialog::reject);
|
|
|
|
|
|
2022-07-22 10:32:08 +02:00
|
|
|
m_argumentsEdit = new QLineEdit(this);
|
|
|
|
|
m_argumentsEdit->setText(args.join(" "));
|
2017-09-27 15:26:59 +02:00
|
|
|
|
|
|
|
|
auto gridLayout = new QGridLayout(this);
|
2022-10-06 17:53:35 +02:00
|
|
|
gridLayout->addWidget(new QLabel(Tr::tr("SDK manager arguments:"), this), 0, 0, 1, 1);
|
2022-07-22 10:32:08 +02:00
|
|
|
gridLayout->addWidget(m_argumentsEdit, 0, 1, 1, 1);
|
2022-10-06 17:53:35 +02:00
|
|
|
gridLayout->addWidget(new QLabel(Tr::tr("Available arguments:"), this), 1, 0, 1, 2);
|
2022-07-22 10:32:08 +02:00
|
|
|
gridLayout->addWidget(m_argumentDetailsEdit, 2, 0, 1, 2);
|
2017-09-27 15:26:59 +02:00
|
|
|
gridLayout->addWidget(dialogButtons, 3, 0, 1, 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OptionsDialog::~OptionsDialog()
|
|
|
|
|
{
|
|
|
|
|
m_optionsFuture.cancel();
|
|
|
|
|
m_optionsFuture.waitForFinished();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QStringList OptionsDialog::sdkManagerArguments() const
|
|
|
|
|
{
|
2022-07-22 10:32:08 +02:00
|
|
|
QString userInput = m_argumentsEdit->text().simplified();
|
2017-09-27 15:26:59 +02:00
|
|
|
return userInput.isEmpty() ? QStringList() : userInput.split(' ');
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-22 10:32:08 +02:00
|
|
|
} // Android::Internal
|