Android: Enable common arguments for SDK manager command

Task-number: QTCREATORBUG-18978
Change-Id: I9f3e2b16a77ff949268960d2b5c5aa1896fa3770
Reviewed-by: BogDan Vatra <bogdan@kdab.com>
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
This commit is contained in:
Vikas Pachdha
2017-09-27 15:26:59 +02:00
parent 476b133e91
commit c52ee5238b
7 changed files with 153 additions and 10 deletions

View File

@@ -87,6 +87,7 @@ namespace {
const QLatin1String SettingsGroup("AndroidConfigurations");
const QLatin1String SDKLocationKey("SDKLocation");
const QLatin1String SDKManagerToolArgsKey("SDKManagerToolArgs");
const QLatin1String NDKLocationKey("NDKLocation");
const QLatin1String OpenJDKLocationKey("OpenJDKLocation");
const QLatin1String KeystoreLocationKey("KeystoreLocation");
@@ -246,6 +247,7 @@ void AndroidConfig::load(const QSettings &settings)
// user settings
m_partitionSize = settings.value(PartitionSizeKey, 1024).toInt();
m_sdkLocation = FileName::fromString(settings.value(SDKLocationKey).toString());
m_sdkManagerToolArgs = settings.value(SDKManagerToolArgsKey).toStringList();
m_ndkLocation = FileName::fromString(settings.value(NDKLocationKey).toString());
m_openJDKLocation = FileName::fromString(settings.value(OpenJDKLocationKey).toString());
m_keystoreLocation = FileName::fromString(settings.value(KeystoreLocationKey).toString());
@@ -261,6 +263,7 @@ void AndroidConfig::load(const QSettings &settings)
&& settings.value(changeTimeStamp).toInt() != QFileInfo(sdkSettingsFileName()).lastModified().toMSecsSinceEpoch() / 1000) {
// persisten settings
m_sdkLocation = FileName::fromString(reader.restoreValue(SDKLocationKey, m_sdkLocation.toString()).toString());
m_sdkManagerToolArgs = reader.restoreValue(SDKManagerToolArgsKey, m_sdkManagerToolArgs).toStringList();
m_ndkLocation = FileName::fromString(reader.restoreValue(NDKLocationKey, m_ndkLocation.toString()).toString());
m_openJDKLocation = FileName::fromString(reader.restoreValue(OpenJDKLocationKey, m_openJDKLocation.toString()).toString());
m_keystoreLocation = FileName::fromString(reader.restoreValue(KeystoreLocationKey, m_keystoreLocation.toString()).toString());
@@ -283,6 +286,7 @@ void AndroidConfig::save(QSettings &settings) const
// user settings
settings.setValue(SDKLocationKey, m_sdkLocation.toString());
settings.setValue(SDKManagerToolArgsKey, m_sdkManagerToolArgs);
settings.setValue(NDKLocationKey, m_ndkLocation.toString());
settings.setValue(OpenJDKLocationKey, m_openJDKLocation.toString());
settings.setValue(KeystoreLocationKey, m_keystoreLocation.toString());
@@ -727,6 +731,17 @@ QVersionNumber AndroidConfig::buildToolsVersion() const
return maxVersion;
}
QStringList AndroidConfig::sdkManagerToolArgs() const
{
return m_sdkManagerToolArgs;
}
void AndroidConfig::setSdkManagerToolArgs(const QStringList &args)
{
m_sdkManagerToolArgs = args;
}
FileName AndroidConfig::ndkLocation() const
{
return m_ndkLocation;

View File

@@ -100,6 +100,8 @@ public:
void setSdkLocation(const Utils::FileName &sdkLocation);
QVersionNumber sdkToolsVersion() const;
QVersionNumber buildToolsVersion() const;
QStringList sdkManagerToolArgs() const;
void setSdkManagerToolArgs(const QStringList &args);
Utils::FileName ndkLocation() const;
QVersionNumber ndkVersion() const;
@@ -166,6 +168,7 @@ private:
void updateNdkInformation() const;
Utils::FileName m_sdkLocation;
QStringList m_sdkManagerToolArgs;
Utils::FileName m_ndkLocation;
Utils::FileName m_openJDKLocation;
Utils::FileName m_keystoreLocation;

View File

@@ -24,6 +24,7 @@
****************************************************************************/
#include "androidsdkmanager.h"
#include "androidconstants.h"
#include "androidmanager.h"
#include "androidtoolmanager.h"
@@ -31,7 +32,6 @@
#include "utils/qtcassert.h"
#include "utils/runextensions.h"
#include "utils/synchronousprocess.h"
#include "utils/environment.h"
#include <QFutureWatcher>
#include <QLoggingCategory>
@@ -52,6 +52,7 @@ const QVersionNumber sdkManagerIntroVersion(25, 3 ,0);
const char installLocationKey[] = "Installed Location:";
const char revisionKey[] = "Version:";
const char descriptionKey[] = "Description:";
const char commonArgsKey[] = "Common Arguments:";
const int sdkManagerCmdTimeoutS = 60;
const int sdkManagerOperationTimeoutS = 600;
@@ -178,6 +179,7 @@ public:
const AndroidSdkPackageList &allPackages(bool forceUpdate = false);
void refreshSdkPackages(bool forceReload = false);
void parseCommonArguments(QFutureInterface<QString> &fi);
void updateInstalled(SdkCmdFutureInterface &fi);
void update(SdkCmdFutureInterface &fi, const QStringList &install,
const QStringList &uninstall);
@@ -335,6 +337,11 @@ bool AndroidSdkManager::isBusy() const
return m_d->m_activeOperation && !m_d->m_activeOperation->isFinished();
}
QFuture<QString> AndroidSdkManager::availableArguments() const
{
return Utils::runAsync(&AndroidSdkManagerPrivate::parseCommonArguments, m_d.get());
}
QFuture<AndroidSdkManager::OperationOutput> AndroidSdkManager::updateAll()
{
if (isBusy()) {
@@ -663,7 +670,6 @@ AndroidSdkManagerPrivate::AndroidSdkManagerPrivate(AndroidSdkManager &sdkManager
m_sdkManager(sdkManager),
m_config(config)
{
}
AndroidSdkManagerPrivate::~AndroidSdkManagerPrivate()
@@ -709,8 +715,9 @@ void AndroidSdkManagerPrivate::reloadSdkPackages()
m_allPackages = Utils::transform(toolManager.availableSdkPlatforms(), toAndroidSdkPackages);
} else {
QString packageListing;
if (sdkManagerCommand(m_config.sdkManagerToolPath(), QStringList({"--list", "--verbose"}),
&packageListing)) {
QStringList args({"--list", "--verbose"});
args << m_config.sdkManagerToolArgs();
if (sdkManagerCommand(m_config.sdkManagerToolPath(), args, &packageListing)) {
SdkManagerOutputParser parser(m_allPackages);
parser.parsePackageListing(packageListing);
}
@@ -736,6 +743,7 @@ void AndroidSdkManagerPrivate::updateInstalled(SdkCmdFutureInterface &fi)
"Updating installed packages.");
fi.reportResult(result);
QStringList args("--update");
args << m_config.sdkManagerToolArgs();
if (!fi.isCanceled())
sdkManagerCommand(m_config.sdkManagerToolPath(), args, m_sdkManager, fi, result, 100);
else
@@ -785,13 +793,17 @@ void AndroidSdkManagerPrivate::update(SdkCmdFutureInterface &fi, const QStringLi
// Uninstall packages
for (const QString &sdkStylePath : uninstall) {
// Uninstall operations are not interptible. We don't want to leave half uninstalled.
if (doOperation(sdkStylePath, {"--uninstall", sdkStylePath}, false))
QStringList args;
args << "--uninstall" << sdkStylePath << m_config.sdkManagerToolArgs();
if (doOperation(sdkStylePath, args, false))
break;
}
// Install packages
for (const QString &sdkStylePath : install) {
if (doOperation(sdkStylePath, {sdkStylePath}, true))
QStringList args(sdkStylePath);
args << m_config.sdkManagerToolArgs();
if (doOperation(sdkStylePath, args, true))
break;
}
fi.setProgressValue(100);
@@ -805,6 +817,25 @@ void AndroidSdkManagerPrivate::addWatcher(const QFuture<AndroidSdkManager::Opera
m_activeOperation->setFuture(future);
}
void AndroidSdkManagerPrivate::parseCommonArguments(QFutureInterface<QString> &fi)
{
QString argumentDetails;
QString output;
sdkManagerCommand(m_config.sdkManagerToolPath(), QStringList("--help"), &output);
bool foundTag = false;
for (const QString& line : output.split('\n')) {
if (fi.isCanceled())
break;
if (foundTag)
argumentDetails.append(line + "\n");
else if (line.startsWith(commonArgsKey))
foundTag = true;
}
if (!fi.isCanceled())
fi.reportResult(argumentDetails);
}
void AndroidSdkManagerPrivate::clearPackages()
{
for (AndroidSdkPackage *p : m_allPackages)

View File

@@ -73,8 +73,9 @@ public:
AndroidSdkPackage::PackageState state
= AndroidSdkPackage::Installed);
void reloadPackages(bool forceReload = false);
bool isBusy() const;
QFuture<QString> availableArguments() const;
QFuture<OperationOutput> updateAll();
QFuture<OperationOutput> update(const QStringList &install, const QStringList &uninstall);

View File

@@ -26,13 +26,18 @@
#include "ui_androidsdkmanagerwidget.h"
#include "androidconfigurations.h"
#include "androidsdkmanager.h"
#include "androidsdkmodel.h"
#include "utils/runextensions.h"
#include "utils/outputformatter.h"
#include "utils/runextensions.h"
#include "utils/qtcassert.h"
#include "utils/utilsicons.h"
#include <QDialogButtonBox>
#include <QLabel>
#include <QLineEdit>
#include <QLoggingCategory>
#include <QMessageBox>
#include <QProcess>
@@ -47,6 +52,21 @@ namespace Internal {
using namespace std::placeholders;
class OptionsDialog : public QDialog
{
public:
OptionsDialog(AndroidSdkManager *sdkManager, const QStringList &args,
QWidget *parent = nullptr);
~OptionsDialog();
QStringList sdkManagerArguments() const;
private:
QPlainTextEdit *argumentDetailsEdit;
QLineEdit *argumentsEdit;
QFuture<QString> m_optionsFuture;
};
class PackageFilterModel : public QSortFilterProxyModel
{
public:
@@ -59,7 +79,7 @@ private:
AndroidSdkPackage::PackageState m_packageState = AndroidSdkPackage::AnyValidState;
};
AndroidSdkManagerWidget::AndroidSdkManagerWidget(const AndroidConfig &config,
AndroidSdkManagerWidget::AndroidSdkManagerWidget(AndroidConfig &config,
AndroidSdkManager *sdkManager, QWidget *parent) :
QWidget(parent),
m_androidConfig(config),
@@ -67,6 +87,7 @@ AndroidSdkManagerWidget::AndroidSdkManagerWidget(const AndroidConfig &config,
m_sdkModel(new AndroidSdkModel(m_sdkManager, this)),
m_ui(new Ui::AndroidSdkManagerWidget)
{
QTC_CHECK(sdkManager);
m_ui->setupUi(this);
m_ui->warningLabel->setElideMode(Qt::ElideRight);
m_ui->warningIconLabel->setPixmap(Utils::Icons::WARNING.pixmap());
@@ -128,6 +149,8 @@ AndroidSdkManagerWidget::AndroidSdkManagerWidget(const AndroidConfig &config,
&AndroidSdkManagerWidget::onCancel);
connect(m_ui->nativeSdkManagerButton, &QPushButton::clicked,
this, &AndroidSdkManagerWidget::onNativeSdkManager);
connect(m_ui->optionsButton, &QPushButton::clicked,
this, &AndroidSdkManagerWidget::onSdkManagerOptions);
}
AndroidSdkManagerWidget::~AndroidSdkManagerWidget()
@@ -147,6 +170,7 @@ void AndroidSdkManagerWidget::setSdkManagerControlsEnabled(bool enable)
m_ui->warningLabel->setVisible(!enable);
m_ui->packagesView->setEnabled(enable);
m_ui->updateInstalledButton->setEnabled(enable);
m_ui->optionsButton->setEnabled(enable);
}
void AndroidSdkManagerWidget::onApplyButton()
@@ -323,6 +347,18 @@ AndroidSdkManagerWidget::View AndroidSdkManagerWidget::currentView() const
return m_ui->viewStack->currentWidget() == m_ui->packagesStack ? PackageListing : Operations;
}
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);
}
}
}
PackageFilterModel::PackageFilterModel(AndroidSdkModel *sdkModel) :
QSortFilterProxyModel(sdkModel)
{
@@ -360,5 +396,54 @@ bool PackageFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sour
return showTopLevel || (packageState(srcIndex) & m_packageState);
}
OptionsDialog::OptionsDialog(AndroidSdkManager *sdkManager, const QStringList &args,
QWidget *parent) : QDialog(parent)
{
QTC_CHECK(sdkManager);
resize(800, 480);
setWindowTitle(tr("SDK Manager Arguments"));
argumentDetailsEdit = new QPlainTextEdit(this);
argumentDetailsEdit->setReadOnly(true);
auto populateOptions = [this](const QString& options) {
if (options.isEmpty()) {
argumentDetailsEdit->setPlainText(tr("Cannot load available arguments for "
"\"sdkmanager\" command."));
} else {
argumentDetailsEdit->setPlainText(options);
}
};
m_optionsFuture = sdkManager->availableArguments();
Utils::onResultReady(m_optionsFuture, populateOptions);
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);
argumentsEdit = new QLineEdit(this);
argumentsEdit->setText(args.join(" "));
auto gridLayout = new QGridLayout(this);
gridLayout->addWidget(new QLabel(tr("SDK manager arguments:"), this), 0, 0, 1, 1);
gridLayout->addWidget(argumentsEdit, 0, 1, 1, 1);
gridLayout->addWidget(new QLabel(tr("Available arguments:"), this), 1, 0, 1, 2);
gridLayout->addWidget(argumentDetailsEdit, 2, 0, 1, 2);
gridLayout->addWidget(dialogButtons, 3, 0, 1, 2);
}
OptionsDialog::~OptionsDialog()
{
m_optionsFuture.cancel();
m_optionsFuture.waitForFinished();
}
QStringList OptionsDialog::sdkManagerArguments() const
{
QString userInput = argumentsEdit->text().simplified();
return userInput.isEmpty() ? QStringList() : userInput.split(' ');
}
} // namespace Internal
} // namespace Android

View File

@@ -52,7 +52,7 @@ class AndroidSdkManagerWidget : public QWidget
};
public:
AndroidSdkManagerWidget(const AndroidConfig &config, AndroidSdkManager *sdkManager,
AndroidSdkManagerWidget(AndroidConfig &config, AndroidSdkManager *sdkManager,
QWidget *parent = nullptr);
~AndroidSdkManagerWidget();
@@ -68,6 +68,7 @@ private:
void onCancel();
void onNativeSdkManager();
void onOperationResult(int index);
void onSdkManagerOptions();
void addPackageFuture(const QFuture<AndroidSdkManager::OperationOutput> &future);
void notifyOperationFinished();
void packageFutureFinished();
@@ -75,7 +76,7 @@ private:
void switchView(View view);
View currentView() const;
const AndroidConfig &m_androidConfig;
AndroidConfig &m_androidConfig;
AndroidSdkManager *m_sdkManager = nullptr;
AndroidSdkModel *m_sdkModel = nullptr;
Ui::AndroidSdkManagerWidget *m_ui = nullptr;

View File

@@ -175,6 +175,13 @@
</layout>
</widget>
</item>
<item>
<widget class="QPushButton" name="optionsButton">
<property name="text">
<string>Advanced Options...</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">