forked from qt-creator/qt-creator
Move AVD Manager from Android Settings to Device Settings
Move AVD management and creation to Qt Creator's DeviceManager facilities. This allows AVDs to be created from the Devices settings page and their details and control/action buttons for starting/stopping, etc. are added there as well. This makes the process similar to other device types that Qt Creator supports, to get a similar experience. Task-number: QTCREATORBUG-23991 Change-Id: I16c52b3cc73035e0ee12fd54ae9dad4595c8cda5 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
@@ -70,6 +70,7 @@ public:
|
||||
int sdcardSize = 0;
|
||||
QString error; // only used in the return value of createAVD
|
||||
bool overwrite = false;
|
||||
bool cancelled = false;
|
||||
};
|
||||
|
||||
struct SdkForQtVersions
|
||||
|
@@ -31,16 +31,24 @@
|
||||
#include "androidconstants.h"
|
||||
#include "androidmanager.h"
|
||||
#include "androidsignaloperation.h"
|
||||
#include "avddialog.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
#include <projectexplorer/devicesupport/devicemanager.h>
|
||||
#include <projectexplorer/devicesupport/idevicewidget.h>
|
||||
#include <projectexplorer/runconfiguration.h>
|
||||
|
||||
#include <utils/qtcprocess.h>
|
||||
#include <utils/runextensions.h>
|
||||
#include <utils/url.h>
|
||||
|
||||
#include <QEventLoop>
|
||||
#include <QFormLayout>
|
||||
#include <QInputDialog>
|
||||
#include <QLoggingCategory>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
@@ -60,6 +68,9 @@ public:
|
||||
AndroidDeviceWidget(const ProjectExplorer::IDevice::Ptr &device);
|
||||
|
||||
void updateDeviceFromUi() final {}
|
||||
static QString dialogTitle();
|
||||
static bool criticalDialog(const QString &error);
|
||||
static bool questionDialog(const QString &question);
|
||||
};
|
||||
|
||||
AndroidDeviceWidget::AndroidDeviceWidget(const IDevice::Ptr &device)
|
||||
@@ -98,6 +109,38 @@ AndroidDeviceWidget::AndroidDeviceWidget(const IDevice::Ptr &device)
|
||||
}
|
||||
}
|
||||
|
||||
QString AndroidDeviceWidget::dialogTitle()
|
||||
{
|
||||
return tr("Android Device Manager");
|
||||
}
|
||||
|
||||
bool AndroidDeviceWidget::criticalDialog(const QString &error)
|
||||
{
|
||||
qCDebug(androidDeviceLog) << error;
|
||||
QMessageBox box(Core::ICore::dialogParent());
|
||||
box.QDialog::setWindowTitle(dialogTitle());
|
||||
box.setText(error);
|
||||
box.setIcon(QMessageBox::Critical);
|
||||
box.setWindowFlag(Qt::WindowTitleHint);
|
||||
return box.exec();
|
||||
}
|
||||
|
||||
bool AndroidDeviceWidget::questionDialog(const QString &question)
|
||||
{
|
||||
QMessageBox box(Core::ICore::dialogParent());
|
||||
box.QDialog::setWindowTitle(dialogTitle());
|
||||
box.setText(question);
|
||||
box.setIcon(QMessageBox::Question);
|
||||
QPushButton *YesButton = box.addButton(QMessageBox::Yes);
|
||||
box.addButton(QMessageBox::No);
|
||||
box.setWindowFlag(Qt::WindowTitleHint);
|
||||
box.exec();
|
||||
|
||||
if (box.clickedButton() == YesButton)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
AndroidDevice::AndroidDevice()
|
||||
{
|
||||
setupId(IDevice::AutoDetected, Constants::ANDROID_DEVICE_ID);
|
||||
@@ -111,6 +154,20 @@ AndroidDevice::AndroidDevice()
|
||||
addDeviceAction({tr("Refresh"), [](const IDevice::Ptr &device, QWidget *parent) {
|
||||
AndroidDeviceManager::instance()->updateDevicesListOnce();
|
||||
}});
|
||||
|
||||
addDeviceAction({tr("Start AVD"), [](const IDevice::Ptr &device, QWidget *parent) {
|
||||
if (device->machineType() == IDevice::Emulator)
|
||||
AndroidDeviceManager::instance()->startAvd(device);
|
||||
}});
|
||||
|
||||
addDeviceAction({tr("Erase AVD"), [](const IDevice::Ptr &device, QWidget *parent) {
|
||||
if (device->machineType() == IDevice::Emulator)
|
||||
AndroidDeviceManager::instance()->eraseAvd(device);
|
||||
}});
|
||||
|
||||
addDeviceAction({tr("AVD Arguments"), [](const IDevice::Ptr &device, QWidget *parent) {
|
||||
AndroidDeviceManager::instance()->setEmulatorArguments();
|
||||
}});
|
||||
}
|
||||
|
||||
IDevice::Ptr AndroidDevice::create()
|
||||
@@ -350,6 +407,81 @@ void AndroidDeviceManager::updateDevicesListOnce()
|
||||
}
|
||||
}
|
||||
|
||||
void AndroidDeviceManager::startAvd(const ProjectExplorer::IDevice::Ptr &device)
|
||||
{
|
||||
const AndroidDevice *androidDev = static_cast<const AndroidDevice *>(device.data());
|
||||
const QString name = androidDev->avdName();
|
||||
qCDebug(androidDeviceLog, "Starting Android AVD id \"%s\".", qPrintable(name));
|
||||
Utils::runAsync([this, name, device]() {
|
||||
const QString serialNumber = m_avdManager.startAvd(name);
|
||||
// Mark the AVD as ReadyToUse once we know it's started
|
||||
if (!serialNumber.isEmpty()) {
|
||||
DeviceManager *const devMgr = DeviceManager::instance();
|
||||
devMgr->setDeviceState(device->id(), IDevice::DeviceReadyToUse);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void AndroidDeviceManager::eraseAvd(const IDevice::Ptr &device)
|
||||
{
|
||||
if (device.isNull())
|
||||
return;
|
||||
|
||||
if (device->machineType() == IDevice::Hardware)
|
||||
return;
|
||||
|
||||
const QString name = static_cast<const AndroidDevice *>(device.data())->avdName();
|
||||
const QString question = tr("Erase the Android AVD \"%1\"?\nThis cannot be undone.").arg(name);
|
||||
if (!AndroidDeviceWidget::questionDialog(question))
|
||||
return;
|
||||
|
||||
qCDebug(androidDeviceLog) << QString("Erasing Android AVD \"%1\" from the system.").arg(name);
|
||||
m_removeAvdFutureWatcher.setFuture(Utils::runAsync([this, name, device]() {
|
||||
QPair<IDevice::ConstPtr, bool> pair;
|
||||
pair.first = device;
|
||||
pair.second = false;
|
||||
if (m_avdManager.removeAvd(name))
|
||||
pair.second = true;
|
||||
return pair;
|
||||
}));
|
||||
}
|
||||
|
||||
void AndroidDeviceManager::handleAvdRemoved()
|
||||
{
|
||||
const QPair<IDevice::ConstPtr, bool> result = m_removeAvdFutureWatcher.result();
|
||||
const QString name = result.first->displayName();
|
||||
if (result.second) {
|
||||
qCDebug(androidDeviceLog, "Android AVD id \"%s\" removed from the system.", qPrintable(name));
|
||||
// Remove the device from QtC after it's been removed using avdmanager.
|
||||
DeviceManager::instance()->removeDevice(result.first->id());
|
||||
} else {
|
||||
AndroidDeviceWidget::criticalDialog(QObject::tr("An error occurred while removing the "
|
||||
"Android AVD \"%1\" using avdmanager tool.").arg(name));
|
||||
}
|
||||
}
|
||||
|
||||
void AndroidDeviceManager::setEmulatorArguments()
|
||||
{
|
||||
const QString helpUrl =
|
||||
"https://developer.android.com/studio/run/emulator-commandline#startup-options";
|
||||
|
||||
QInputDialog dialog(Core::ICore::dialogParent());
|
||||
dialog.setWindowTitle(tr("Emulator Command-line Startup Options"));
|
||||
dialog.setLabelText(tr("Emulator command-line startup options "
|
||||
"(<a href=\"%1\">Help Web Page</a>):").arg(helpUrl));
|
||||
dialog.setTextValue(m_androidConfig.emulatorArgs().join(' '));
|
||||
|
||||
if (auto label = dialog.findChild<QLabel*>()) {
|
||||
label->setOpenExternalLinks(true);
|
||||
label->setMinimumWidth(500);
|
||||
}
|
||||
|
||||
if (dialog.exec() != QDialog::Accepted)
|
||||
return;
|
||||
|
||||
m_androidConfig.setEmulatorArgs(Utils::ProcessArgs::splitArgs(dialog.textValue()));
|
||||
}
|
||||
|
||||
void AndroidDeviceManager::setupDevicesWatcher()
|
||||
{
|
||||
// The call to avdmanager is always slower than the call to adb devices,
|
||||
@@ -443,23 +575,80 @@ AndroidDeviceManager *AndroidDeviceManager::instance()
|
||||
}
|
||||
|
||||
AndroidDeviceManager::AndroidDeviceManager(QObject *parent)
|
||||
: QObject(parent), m_androidConfig(AndroidConfigurations::currentConfig())
|
||||
: QObject(parent),
|
||||
m_androidConfig(AndroidConfigurations::currentConfig()),
|
||||
m_avdManager(m_androidConfig)
|
||||
{
|
||||
connect(qApp, &QCoreApplication::aboutToQuit, this, [this]() {
|
||||
m_devicesUpdaterTimer.stop();
|
||||
m_avdsFutureWatcher.waitForFinished();
|
||||
m_devicesFutureWatcher.waitForFinished();
|
||||
m_removeAvdFutureWatcher.waitForFinished();
|
||||
});
|
||||
|
||||
connect(&m_removeAvdFutureWatcher, &QFutureWatcherBase::finished,
|
||||
this, &AndroidDeviceManager::handleAvdRemoved);
|
||||
}
|
||||
|
||||
// Factory
|
||||
AndroidDeviceFactory::AndroidDeviceFactory()
|
||||
: ProjectExplorer::IDeviceFactory(Constants::ANDROID_DEVICE_TYPE)
|
||||
: ProjectExplorer::IDeviceFactory(Constants::ANDROID_DEVICE_TYPE),
|
||||
m_androidConfig(AndroidConfigurations::currentConfig())
|
||||
{
|
||||
setDisplayName(AndroidDevice::tr("Android Device"));
|
||||
setDisplayName(AndroidDevice::tr("Android Virtual Device"));
|
||||
setCombinedIcon(":/android/images/androiddevicesmall.png",
|
||||
":/android/images/androiddevice.png");
|
||||
setConstructionFunction(&AndroidDevice::create);
|
||||
setCanCreate(m_androidConfig.sdkToolsOk());
|
||||
}
|
||||
|
||||
IDevice::Ptr AndroidDeviceFactory::create() const
|
||||
{
|
||||
AndroidSdkManager sdkManager = AndroidSdkManager(m_androidConfig);
|
||||
const CreateAvdInfo info = AvdDialog::gatherCreateAVDInfo(Core::ICore::dialogParent(),
|
||||
&sdkManager, m_androidConfig);
|
||||
if (!info.isValid()) {
|
||||
if (!info.cancelled) {
|
||||
AndroidDeviceWidget::criticalDialog(
|
||||
QObject::tr("The returned device info is invalid."));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const AndroidAvdManager avdManager = AndroidAvdManager(m_androidConfig);
|
||||
QFutureWatcher<CreateAvdInfo> createAvdFutureWatcher;
|
||||
createAvdFutureWatcher.setFuture(avdManager.createAvd(info));
|
||||
|
||||
QEventLoop loop;
|
||||
QObject::connect(&createAvdFutureWatcher, &QFutureWatcher<CreateAvdInfo>::finished,
|
||||
&loop, &QEventLoop::quit);
|
||||
QObject::connect(&createAvdFutureWatcher, &QFutureWatcher<CreateAvdInfo>::canceled,
|
||||
&loop, &QEventLoop::quit);
|
||||
loop.exec(QEventLoop::ExcludeUserInputEvents);
|
||||
|
||||
QFuture<CreateAvdInfo> future = createAvdFutureWatcher.future();
|
||||
if (!(future.isResultReadyAt(0) && future.result().isValid())) {
|
||||
AndroidDeviceWidget::criticalDialog(QObject::tr("The device info returned by "
|
||||
"avdmanager tool is invalid for the device name \"%1\".").arg(info.name));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const CreateAvdInfo newAvdInfo = createAvdFutureWatcher.result();
|
||||
|
||||
AndroidDevice *dev = new AndroidDevice();
|
||||
const Utils::Id deviceId = AndroidDevice::idFromAvdInfo(newAvdInfo);
|
||||
dev->setupId(IDevice::AutoDetected, deviceId);
|
||||
dev->setMachineType(IDevice::Emulator);
|
||||
dev->setDisplayName(newAvdInfo.name);
|
||||
dev->setDeviceState(IDevice::DeviceConnected);
|
||||
dev->setExtraData(Constants::AndroidAvdName, newAvdInfo.name);
|
||||
dev->setExtraData(Constants::AndroidCpuAbi, {newAvdInfo.abi});
|
||||
dev->setExtraData(Constants::AndroidSdk, newAvdInfo.systemImage->apiLevel());
|
||||
dev->setExtraData(Constants::AndroidAvdSdcard, QString("%1 MB").arg(newAvdInfo.sdcardSize));
|
||||
dev->setExtraData(Constants::AndroidAvdDevice, newAvdInfo.deviceDefinition);
|
||||
|
||||
qCDebug(androidDeviceLog, "Created new Android AVD id \"%s\".", qPrintable(newAvdInfo.name));
|
||||
return IDevice::Ptr(dev);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -26,6 +26,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "androidavdmanager.h"
|
||||
#include "androidconfigurations.h"
|
||||
#include "androiddeviceinfo.h"
|
||||
|
||||
@@ -84,6 +85,10 @@ class AndroidDeviceFactory final : public ProjectExplorer::IDeviceFactory
|
||||
{
|
||||
public:
|
||||
AndroidDeviceFactory();
|
||||
ProjectExplorer::IDevice::Ptr create() const override;
|
||||
|
||||
private:
|
||||
AndroidConfig m_androidConfig;
|
||||
};
|
||||
|
||||
class AndroidDeviceManager : public QObject
|
||||
@@ -94,13 +99,21 @@ public:
|
||||
void updateDevicesList();
|
||||
void updateDevicesListOnce();
|
||||
|
||||
void startAvd(const ProjectExplorer::IDevice::Ptr &device);
|
||||
void eraseAvd(const ProjectExplorer::IDevice::Ptr &device);
|
||||
|
||||
void setEmulatorArguments();
|
||||
|
||||
private:
|
||||
AndroidDeviceManager(QObject *parent = nullptr);
|
||||
void devicesListUpdated();
|
||||
void handleAvdRemoved();
|
||||
|
||||
QFutureWatcher<AndroidDeviceInfoList> m_avdsFutureWatcher;
|
||||
QFutureWatcher<QVector<AndroidDeviceInfo>> m_devicesFutureWatcher;
|
||||
QFutureWatcher<QPair<ProjectExplorer::IDevice::ConstPtr, bool>> m_removeAvdFutureWatcher;
|
||||
QTimer m_devicesUpdaterTimer;
|
||||
AndroidAvdManager m_avdManager;
|
||||
AndroidConfig m_androidConfig;
|
||||
};
|
||||
|
||||
|
@@ -27,14 +27,12 @@
|
||||
|
||||
#include "ui_androidsettingswidget.h"
|
||||
|
||||
#include "androidavdmanager.h"
|
||||
#include "androidconfigurations.h"
|
||||
#include "androidconstants.h"
|
||||
#include "androidsdkdownloader.h"
|
||||
#include "androidsdkmanager.h"
|
||||
#include "androidsdkmanagerwidget.h"
|
||||
#include "androidtoolchain.h"
|
||||
#include "avddialog.h"
|
||||
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
|
||||
@@ -76,22 +74,8 @@ namespace Android {
|
||||
namespace Internal {
|
||||
|
||||
class AndroidSdkManagerWidget;
|
||||
class AndroidAvdManager;
|
||||
class SummaryWidget;
|
||||
|
||||
class AvdModel final : public ListModel<AndroidDeviceInfo>
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Android::Internal::AvdModel)
|
||||
|
||||
public:
|
||||
AvdModel();
|
||||
|
||||
QVariant itemData(const AndroidDeviceInfo &info, int column, int role) const final;
|
||||
|
||||
QString avdName(const QModelIndex &index) const;
|
||||
QModelIndex indexForAvdName(const QString &avdName) const;
|
||||
};
|
||||
|
||||
class AndroidSettingsWidget final : public Core::IOptionsPageWidget
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Android::Internal::AndroidSettingsWidget)
|
||||
@@ -114,20 +98,9 @@ private:
|
||||
void openNDKDownloadUrl();
|
||||
void openOpenJDKDownloadUrl();
|
||||
void downloadOpenSslRepo(const bool silent = false);
|
||||
void addAVD();
|
||||
void avdAdded();
|
||||
void removeAVD();
|
||||
void startAVD();
|
||||
void avdActivated(const QModelIndex &);
|
||||
void editEmulatorArgsAVD();
|
||||
void createKitToggled();
|
||||
|
||||
void updateUI();
|
||||
void updateAvds();
|
||||
|
||||
void startUpdateAvd();
|
||||
void enableAvdControls();
|
||||
void disableAvdControls();
|
||||
|
||||
void downloadSdk();
|
||||
void addCustomNdkItem();
|
||||
@@ -136,12 +109,7 @@ private:
|
||||
Ui_AndroidSettingsWidget m_ui;
|
||||
AndroidSdkManagerWidget *m_sdkManagerWidget = nullptr;
|
||||
AndroidConfig m_androidConfig{AndroidConfigurations::currentConfig()};
|
||||
AvdModel m_AVDModel;
|
||||
QFutureWatcher<CreateAvdInfo> m_futureWatcher;
|
||||
|
||||
QFutureWatcher<AndroidDeviceInfoList> m_virtualDevicesWatcher;
|
||||
QString m_lastAddedAvd;
|
||||
AndroidAvdManager m_avdManager{m_androidConfig};
|
||||
AndroidSdkManager m_sdkManager{m_androidConfig};
|
||||
AndroidSdkDownloader m_sdkDownloader;
|
||||
bool m_isInitialReloadDone = false;
|
||||
@@ -253,44 +221,6 @@ private:
|
||||
QMap<int, RowData> m_validationData;
|
||||
};
|
||||
|
||||
QModelIndex AvdModel::indexForAvdName(const QString &avdName) const
|
||||
{
|
||||
return findIndex([avdName](const AndroidDeviceInfo &info) { return info.avdname == avdName; });
|
||||
}
|
||||
|
||||
QString AvdModel::avdName(const QModelIndex &index) const
|
||||
{
|
||||
return dataAt(index.row()).avdname;
|
||||
}
|
||||
|
||||
QVariant AvdModel::itemData(const AndroidDeviceInfo &info, int column, int role) const
|
||||
{
|
||||
if (role != Qt::DisplayRole)
|
||||
return {};
|
||||
|
||||
switch (column) {
|
||||
case 0:
|
||||
return info.avdname;
|
||||
case 1:
|
||||
return info.sdk;
|
||||
case 2:
|
||||
return info.cpuAbi.isEmpty() ? QVariant() : QVariant(info.cpuAbi.first());
|
||||
case 3:
|
||||
return info.avdDevice.isEmpty() ? QVariant("Custom") : info.avdDevice;
|
||||
case 4:
|
||||
return info.avdTarget;
|
||||
case 5:
|
||||
return info.avdSdcardSize;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
AvdModel::AvdModel()
|
||||
{
|
||||
//: AVD - Android Virtual Device
|
||||
setHeader({tr("AVD Name"), tr("API"), tr("CPU/ABI"), tr("Device Type"), tr("Target"), tr("SD-card Size")});
|
||||
}
|
||||
|
||||
void AndroidSettingsWidget::showEvent(QShowEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
@@ -432,11 +362,6 @@ AndroidSettingsWidget::AndroidSettingsWidget()
|
||||
m_ui.openSslPathChooser->setFilePath(m_androidConfig.openSslLocation());
|
||||
|
||||
m_ui.CreateKitCheckBox->setChecked(m_androidConfig.automaticKitCreation());
|
||||
m_ui.AVDTableView->setModel(&m_AVDModel);
|
||||
m_ui.AVDTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
for (int column : {1, 2, 5})
|
||||
m_ui.AVDTableView->horizontalHeader()->setSectionResizeMode(
|
||||
column, QHeaderView::ResizeToContents);
|
||||
|
||||
const QIcon downloadIcon = Icons::ONLINE.icon();
|
||||
m_ui.downloadSDKToolButton->setIcon(downloadIcon);
|
||||
@@ -475,24 +400,6 @@ AndroidSettingsWidget::AndroidSettingsWidget()
|
||||
|
||||
connect(m_ui.openSslPathChooser, &PathChooser::rawPathChanged,
|
||||
this, &AndroidSettingsWidget::validateOpenSsl);
|
||||
connect(&m_virtualDevicesWatcher, &QFutureWatcherBase::finished,
|
||||
this, &AndroidSettingsWidget::updateAvds);
|
||||
connect(m_ui.AVDRefreshPushButton, &QAbstractButton::clicked,
|
||||
this, &AndroidSettingsWidget::startUpdateAvd);
|
||||
connect(&m_futureWatcher, &QFutureWatcherBase::finished,
|
||||
this, &AndroidSettingsWidget::avdAdded);
|
||||
connect(m_ui.AVDAddPushButton, &QAbstractButton::clicked,
|
||||
this, &AndroidSettingsWidget::addAVD);
|
||||
connect(m_ui.AVDRemovePushButton, &QAbstractButton::clicked,
|
||||
this, &AndroidSettingsWidget::removeAVD);
|
||||
connect(m_ui.AVDStartPushButton, &QAbstractButton::clicked,
|
||||
this, &AndroidSettingsWidget::startAVD);
|
||||
connect(m_ui.AVDTableView, &QAbstractItemView::activated,
|
||||
this, &AndroidSettingsWidget::avdActivated);
|
||||
connect(m_ui.AVDTableView, &QAbstractItemView::clicked,
|
||||
this, &AndroidSettingsWidget::avdActivated);
|
||||
connect(m_ui.AVDAdvancedOptionsPushButton, &QAbstractButton::clicked,
|
||||
this, &AndroidSettingsWidget::editEmulatorArgsAVD);
|
||||
connect(m_ui.CreateKitCheckBox, &QAbstractButton::toggled,
|
||||
this, &AndroidSettingsWidget::createKitToggled);
|
||||
connect(m_ui.downloadNDKToolButton, &QAbstractButton::clicked,
|
||||
@@ -530,38 +437,6 @@ AndroidSettingsWidget::~AndroidSettingsWidget()
|
||||
{
|
||||
// Deleting m_sdkManagerWidget will cancel all ongoing and pending sdkmanager operations.
|
||||
delete m_sdkManagerWidget;
|
||||
m_futureWatcher.waitForFinished();
|
||||
}
|
||||
|
||||
void AndroidSettingsWidget::disableAvdControls()
|
||||
{
|
||||
m_ui.AVDAddPushButton->setEnabled(false);
|
||||
m_ui.AVDTableView->setEnabled(false);
|
||||
m_ui.AVDRemovePushButton->setEnabled(false);
|
||||
m_ui.AVDStartPushButton->setEnabled(false);
|
||||
}
|
||||
|
||||
void AndroidSettingsWidget::enableAvdControls()
|
||||
{
|
||||
m_ui.AVDTableView->setEnabled(true);
|
||||
m_ui.AVDAddPushButton->setEnabled(true);
|
||||
avdActivated(m_ui.AVDTableView->currentIndex());
|
||||
}
|
||||
|
||||
void AndroidSettingsWidget::startUpdateAvd()
|
||||
{
|
||||
disableAvdControls();
|
||||
m_virtualDevicesWatcher.setFuture(m_avdManager.avdList());
|
||||
}
|
||||
|
||||
void AndroidSettingsWidget::updateAvds()
|
||||
{
|
||||
m_AVDModel.setAllData(m_virtualDevicesWatcher.result());
|
||||
if (!m_lastAddedAvd.isEmpty()) {
|
||||
m_ui.AVDTableView->setCurrentIndex(m_AVDModel.indexForAvdName(m_lastAddedAvd));
|
||||
m_lastAddedAvd.clear();
|
||||
}
|
||||
enableAvdControls();
|
||||
}
|
||||
|
||||
void AndroidSettingsWidget::validateJdk()
|
||||
@@ -648,7 +523,6 @@ void AndroidSettingsWidget::validateSdk()
|
||||
}
|
||||
}
|
||||
|
||||
startUpdateAvd();
|
||||
updateNdkList();
|
||||
updateUI();
|
||||
}
|
||||
@@ -754,80 +628,6 @@ void AndroidSettingsWidget::downloadOpenSslRepo(const bool silent)
|
||||
gitCloner->start();
|
||||
}
|
||||
|
||||
void AndroidSettingsWidget::addAVD()
|
||||
{
|
||||
disableAvdControls();
|
||||
CreateAvdInfo info = AvdDialog::gatherCreateAVDInfo(this, &m_sdkManager, m_androidConfig);
|
||||
|
||||
if (!info.isValid()) {
|
||||
enableAvdControls();
|
||||
return;
|
||||
}
|
||||
|
||||
m_futureWatcher.setFuture(m_avdManager.createAvd(info));
|
||||
}
|
||||
|
||||
void AndroidSettingsWidget::avdAdded()
|
||||
{
|
||||
CreateAvdInfo info = m_futureWatcher.result();
|
||||
if (!info.error.isEmpty()) {
|
||||
enableAvdControls();
|
||||
QMessageBox::critical(this, QApplication::translate("AndroidConfig", "Error Creating AVD"), info.error);
|
||||
return;
|
||||
}
|
||||
|
||||
startUpdateAvd();
|
||||
m_lastAddedAvd = info.name;
|
||||
}
|
||||
|
||||
void AndroidSettingsWidget::removeAVD()
|
||||
{
|
||||
disableAvdControls();
|
||||
QString avdName = m_AVDModel.avdName(m_ui.AVDTableView->currentIndex());
|
||||
if (QMessageBox::question(this, tr("Remove Android Virtual Device"),
|
||||
tr("Remove device \"%1\"? This cannot be undone.").arg(avdName),
|
||||
QMessageBox::Yes | QMessageBox::No)
|
||||
== QMessageBox::No) {
|
||||
enableAvdControls();
|
||||
return;
|
||||
}
|
||||
|
||||
m_avdManager.removeAvd(avdName);
|
||||
startUpdateAvd();
|
||||
}
|
||||
|
||||
void AndroidSettingsWidget::startAVD()
|
||||
{
|
||||
m_avdManager.startAvdAsync(m_AVDModel.avdName(m_ui.AVDTableView->currentIndex()));
|
||||
}
|
||||
|
||||
void AndroidSettingsWidget::avdActivated(const QModelIndex &index)
|
||||
{
|
||||
m_ui.AVDRemovePushButton->setEnabled(index.isValid());
|
||||
m_ui.AVDStartPushButton->setEnabled(index.isValid());
|
||||
}
|
||||
|
||||
void AndroidSettingsWidget::editEmulatorArgsAVD()
|
||||
{
|
||||
const QString helpUrl =
|
||||
"https://developer.android.com/studio/run/emulator-commandline#startup-options";
|
||||
|
||||
QInputDialog dialog(this);
|
||||
dialog.setWindowTitle(tr("Emulator Command-line Startup Options"));
|
||||
dialog.setLabelText(tr("Emulator command-line startup options (<a href=\"%1\">Help Web Page</a>):").arg(helpUrl));
|
||||
dialog.setTextValue(m_androidConfig.emulatorArgs().join(' '));
|
||||
|
||||
if (auto label = dialog.findChild<QLabel*>()) {
|
||||
label->setOpenExternalLinks(true);
|
||||
label->setMinimumWidth(500);
|
||||
}
|
||||
|
||||
if (dialog.exec() != QDialog::Accepted)
|
||||
return;
|
||||
|
||||
m_androidConfig.setEmulatorArgs(ProcessArgs::splitArgs(dialog.textValue()));
|
||||
}
|
||||
|
||||
void AndroidSettingsWidget::createKitToggled()
|
||||
{
|
||||
m_androidConfig.setAutomaticKitCreation(m_ui.CreateKitCheckBox->isChecked());
|
||||
@@ -840,7 +640,6 @@ void AndroidSettingsWidget::updateUI()
|
||||
const bool androidSetupOk = m_androidSummary->allRowsOk();
|
||||
const bool openSslOk = m_openSslSummary->allRowsOk();
|
||||
|
||||
m_ui.avdManagerTab->setEnabled(javaSetupOk && androidSetupOk);
|
||||
m_ui.sdkManagerTab->setEnabled(sdkToolsOk);
|
||||
|
||||
const QListWidgetItem *currentItem = m_ui.ndkListWidget->currentItem();
|
||||
|
@@ -269,142 +269,6 @@
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="avdManagerTab">
|
||||
<attribute name="title">
|
||||
<string>AVD Manager</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTableView" name="AVDTableView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="textElideMode">
|
||||
<enum>Qt::ElideMiddle</enum>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderHighlightSections">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QPushButton" name="AVDStartPushButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Start...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="AVDRefreshPushButton">
|
||||
<property name="text">
|
||||
<string>Refresh List</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>8</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="AVDAddPushButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="AVDRemovePushButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="AVDAdvancedOptionsPushButton">
|
||||
<property name="text">
|
||||
<string>Advanced Options...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="sdkManagerTab">
|
||||
<attribute name="title">
|
||||
<string>SDK Manager</string>
|
||||
|
@@ -105,7 +105,8 @@ CreateAvdInfo AvdDialog::gatherCreateAVDInfo(QWidget *parent, AndroidSdkManager
|
||||
{
|
||||
CreateAvdInfo result;
|
||||
AvdDialog d(minApiLevel, sdkManager, abis, config, parent);
|
||||
if (d.exec() != QDialog::Accepted || !d.isValid())
|
||||
result.cancelled = (d.exec() != QDialog::Accepted);
|
||||
if (result.cancelled || !d.isValid())
|
||||
return result;
|
||||
|
||||
result.systemImage = d.systemImage();
|
||||
|
Reference in New Issue
Block a user