From e860871d2a6984a89f443928dfee5dbfa84d40cf Mon Sep 17 00:00:00 2001 From: Assam Boudjelthia Date: Sat, 11 Sep 2021 18:38:13 +0300 Subject: [PATCH] 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 Reviewed-by: Alessandro Portale --- src/plugins/android/androidconfigurations.h | 1 + src/plugins/android/androiddevice.cpp | 195 ++++++++++++++++- src/plugins/android/androiddevice.h | 13 ++ src/plugins/android/androidsettingswidget.cpp | 201 ------------------ src/plugins/android/androidsettingswidget.ui | 136 ------------ src/plugins/android/avddialog.cpp | 3 +- 6 files changed, 208 insertions(+), 341 deletions(-) diff --git a/src/plugins/android/androidconfigurations.h b/src/plugins/android/androidconfigurations.h index 6e5978a58eb..09f7ac85f1d 100644 --- a/src/plugins/android/androidconfigurations.h +++ b/src/plugins/android/androidconfigurations.h @@ -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 diff --git a/src/plugins/android/androiddevice.cpp b/src/plugins/android/androiddevice.cpp index 9a276ce6f71..26f9a446e2b 100644 --- a/src/plugins/android/androiddevice.cpp +++ b/src/plugins/android/androiddevice.cpp @@ -31,16 +31,24 @@ #include "androidconstants.h" #include "androidmanager.h" #include "androidsignaloperation.h" +#include "avddialog.h" + +#include #include #include #include +#include #include #include +#include #include +#include #include +#include +#include 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(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(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 pair; + pair.first = device; + pair.second = false; + if (m_avdManager.removeAvd(name)) + pair.second = true; + return pair; + })); +} + +void AndroidDeviceManager::handleAvdRemoved() +{ + const QPair 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 " + "(Help Web Page):").arg(helpUrl)); + dialog.setTextValue(m_androidConfig.emulatorArgs().join(' ')); + + if (auto label = dialog.findChild()) { + 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 createAvdFutureWatcher; + createAvdFutureWatcher.setFuture(avdManager.createAvd(info)); + + QEventLoop loop; + QObject::connect(&createAvdFutureWatcher, &QFutureWatcher::finished, + &loop, &QEventLoop::quit); + QObject::connect(&createAvdFutureWatcher, &QFutureWatcher::canceled, + &loop, &QEventLoop::quit); + loop.exec(QEventLoop::ExcludeUserInputEvents); + + QFuture 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 diff --git a/src/plugins/android/androiddevice.h b/src/plugins/android/androiddevice.h index 7f90122fc5a..5e6fabb43b6 100644 --- a/src/plugins/android/androiddevice.h +++ b/src/plugins/android/androiddevice.h @@ -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 m_avdsFutureWatcher; QFutureWatcher> m_devicesFutureWatcher; + QFutureWatcher> m_removeAvdFutureWatcher; QTimer m_devicesUpdaterTimer; + AndroidAvdManager m_avdManager; AndroidConfig m_androidConfig; }; diff --git a/src/plugins/android/androidsettingswidget.cpp b/src/plugins/android/androidsettingswidget.cpp index 7e3b51ca130..d67c53a9637 100644 --- a/src/plugins/android/androidsettingswidget.cpp +++ b/src/plugins/android/androidsettingswidget.cpp @@ -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 @@ -76,22 +74,8 @@ namespace Android { namespace Internal { class AndroidSdkManagerWidget; -class AndroidAvdManager; class SummaryWidget; -class AvdModel final : public ListModel -{ - 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 m_futureWatcher; - QFutureWatcher 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 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 (Help Web Page):").arg(helpUrl)); - dialog.setTextValue(m_androidConfig.emulatorArgs().join(' ')); - - if (auto label = dialog.findChild()) { - 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(); diff --git a/src/plugins/android/androidsettingswidget.ui b/src/plugins/android/androidsettingswidget.ui index 0a1cb22af31..6ad64eb2cac 100644 --- a/src/plugins/android/androidsettingswidget.ui +++ b/src/plugins/android/androidsettingswidget.ui @@ -269,142 +269,6 @@ 0 - - - AVD Manager - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - - Qt::ElideMiddle - - - false - - - false - - - - - - - - - false - - - - 0 - 0 - - - - Start... - - - - - - - Refresh List - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 0 - 8 - - - - - - - - - 0 - 0 - - - - Add... - - - - - - - false - - - - 0 - 0 - - - - Remove - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Advanced Options... - - - - - - - SDK Manager diff --git a/src/plugins/android/avddialog.cpp b/src/plugins/android/avddialog.cpp index dd3224701d2..5f5a5cf6821 100644 --- a/src/plugins/android/avddialog.cpp +++ b/src/plugins/android/avddialog.cpp @@ -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();