From ba672d1334a308b82cd0047a7d5d4ad96ab5388a Mon Sep 17 00:00:00 2001 From: Assam Boudjelthia Date: Sun, 26 Sep 2021 16:57:59 +0300 Subject: [PATCH] Android: Do some refactoring for AvdDialog class Move some logic for avd creation to the AvdDialog, and some refactoring and simplification. Change-Id: Id65e586ab1c0e9e898a04f07d7707371f20da649 Reviewed-by: Alessandro Portale Reviewed-by: Qt CI Bot --- src/plugins/android/androiddevice.cpp | 54 +++-------- src/plugins/android/avddialog.cpp | 132 ++++++++++++++++---------- src/plugins/android/avddialog.h | 54 +++++------ 3 files changed, 116 insertions(+), 124 deletions(-) diff --git a/src/plugins/android/androiddevice.cpp b/src/plugins/android/androiddevice.cpp index 26f9a446e2b..38d6e09ad8b 100644 --- a/src/plugins/android/androiddevice.cpp +++ b/src/plugins/android/androiddevice.cpp @@ -604,50 +604,20 @@ AndroidDeviceFactory::AndroidDeviceFactory() 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; + AvdDialog dialog = AvdDialog(m_androidConfig, Core::ICore::dialogParent()); + if (dialog.exec() != QDialog::Accepted) + return ProjectExplorer::IDevice::Ptr(); + + const ProjectExplorer::IDevice::Ptr dev = dialog.device(); + const AndroidDevice *androidDev = static_cast(dev.data()); + if (androidDev) { + qCDebug(androidDeviceLog, "Created new Android AVD id \"%s\".", + qPrintable(androidDev->avdName())); + } else { + AndroidDeviceWidget::criticalDialog( + QObject::tr("The device info returned from AvdDialog is invalid.")); } - 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); } diff --git a/src/plugins/android/avddialog.cpp b/src/plugins/android/avddialog.cpp index 5f5a5cf6821..d3418f39ca8 100644 --- a/src/plugins/android/avddialog.cpp +++ b/src/plugins/android/avddialog.cpp @@ -26,6 +26,8 @@ #include "avddialog.h" #include "androidsdkmanager.h" #include "androidavdmanager.h" +#include "androiddevice.h" +#include "androidconstants.h" #include #include @@ -33,6 +35,7 @@ #include #include +#include #include #include #include @@ -46,29 +49,35 @@ namespace { static Q_LOGGING_CATEGORY(avdDialogLog, "qtc.android.avdDialog", QtWarningMsg) } -AvdDialog::AvdDialog(int minApiLevel, AndroidSdkManager *sdkManager, const QStringList &abis, - const AndroidConfig &config, QWidget *parent) : - QDialog(parent), - m_sdkManager(sdkManager), - m_minApiLevel(minApiLevel), - m_allowedNameChars(QLatin1String("[a-z|A-Z|0-9|._-]*")), - m_androidConfig(config) +AvdDialog::AvdDialog(const AndroidConfig &config, QWidget *parent) + : QDialog(parent), + m_sdkManager(m_androidConfig), + m_allowedNameChars(QLatin1String("[a-z|A-Z|0-9|._-]*")), + m_androidConfig(config) { - QTC_CHECK(m_sdkManager); m_avdDialog.setupUi(this); m_hideTipTimer.setInterval(2000); m_hideTipTimer.setSingleShot(true); - if (abis.isEmpty()) { - m_avdDialog.abiComboBox->addItems(QStringList({ - ProjectExplorer::Constants::ANDROID_ABI_X86, - ProjectExplorer::Constants::ANDROID_ABI_X86_64, - ProjectExplorer::Constants::ANDROID_ABI_ARMEABI_V7A, - ProjectExplorer::Constants::ANDROID_ABI_ARMEABI, - ProjectExplorer::Constants::ANDROID_ABI_ARM64_V8A})); - } else { - m_avdDialog.abiComboBox->addItems(abis); - } + connect(&m_hideTipTimer, &QTimer::timeout, this, &Utils::ToolTip::hide); + connect(m_avdDialog.deviceDefinitionTypeComboBox, + QOverload::of(&QComboBox::currentIndexChanged), + this, &AvdDialog::updateDeviceDefinitionComboBox); + connect(m_avdDialog.abiComboBox, + QOverload::of(&QComboBox::currentIndexChanged), + this, &AvdDialog::updateApiLevelComboBox); + + deviceTypeToStringMap.insert(AvdDialog::Phone, "Phone"); + deviceTypeToStringMap.insert(AvdDialog::Tablet, "Tablet"); + deviceTypeToStringMap.insert(AvdDialog::Automotive, "Automotive"); + deviceTypeToStringMap.insert(AvdDialog::TV, "TV"); + deviceTypeToStringMap.insert(AvdDialog::Wear, "Wear"); + + m_avdDialog.abiComboBox->addItems(QStringList({ + ProjectExplorer::Constants::ANDROID_ABI_X86, + ProjectExplorer::Constants::ANDROID_ABI_X86_64, + ProjectExplorer::Constants::ANDROID_ABI_ARMEABI_V7A, + ProjectExplorer::Constants::ANDROID_ABI_ARM64_V8A})); auto v = new QRegularExpressionValidator(m_allowedNameChars, this); m_avdDialog.nameLineEdit->setValidator(v); @@ -77,46 +86,70 @@ AvdDialog::AvdDialog(int minApiLevel, AndroidSdkManager *sdkManager, const QStri m_avdDialog.warningText->setType(Utils::InfoLabel::Warning); m_avdDialog.warningText->setElideMode(Qt::ElideNone); - connect(&m_hideTipTimer, &QTimer::timeout, this, []() { Utils::ToolTip::hide(); }); - parseDeviceDefinitionsList(); - for (const QString &type : DeviceTypeToStringMap) + for (const QString &type : deviceTypeToStringMap) m_avdDialog.deviceDefinitionTypeComboBox->addItem(type); - connect(m_avdDialog.deviceDefinitionTypeComboBox, - QOverload::of(&QComboBox::currentIndexChanged), - this, - &AvdDialog::updateDeviceDefinitionComboBox); - connect(m_avdDialog.abiComboBox, - QOverload::of(&QComboBox::currentIndexChanged), - this, &AvdDialog::updateApiLevelComboBox); - - m_avdDialog.deviceDefinitionTypeComboBox->setCurrentIndex(1); // Set Phone type as default index updateApiLevelComboBox(); } +int AvdDialog::exec() +{ + const int execResult = QDialog::exec(); + if (execResult == QDialog::Accepted) { + CreateAvdInfo result; + result.systemImage = systemImage(); + result.name = name(); + result.abi = abi(); + result.deviceDefinition = deviceDefinition(); + result.sdcardSize = sdcardSize(); + result.overwrite = m_avdDialog.overwriteCheckBox->isChecked(); + + const AndroidAvdManager avdManager = AndroidAvdManager(m_androidConfig); + QFutureWatcher createAvdFutureWatcher; + createAvdFutureWatcher.setFuture(avdManager.createAvd(result)); + + QEventLoop loop; + QObject::connect(&createAvdFutureWatcher, &QFutureWatcher::finished, + &loop, &QEventLoop::quit); + QObject::connect(&createAvdFutureWatcher, &QFutureWatcher::canceled, + &loop, &QEventLoop::quit); + loop.exec(QEventLoop::ExcludeUserInputEvents); + + const QFuture future = createAvdFutureWatcher.future(); + if (future.isResultReadyAt(0)) + m_createdAvdInfo = future.result(); + } + + return execResult; +} + bool AvdDialog::isValid() const { return !name().isEmpty() && systemImage() && systemImage()->isValid() && !abi().isEmpty(); } -CreateAvdInfo AvdDialog::gatherCreateAVDInfo(QWidget *parent, AndroidSdkManager *sdkManager, - const AndroidConfig &config, int minApiLevel, const QStringList &abis) +ProjectExplorer::IDevice::Ptr AvdDialog::device() const { - CreateAvdInfo result; - AvdDialog d(minApiLevel, sdkManager, abis, config, parent); - result.cancelled = (d.exec() != QDialog::Accepted); - if (result.cancelled || !d.isValid()) - return result; + AndroidDevice *dev = new AndroidDevice(); + const Utils::Id deviceId = AndroidDevice::idFromAvdInfo(m_createdAvdInfo); + using namespace ProjectExplorer; + dev->setupId(IDevice::AutoDetected, deviceId); + dev->setMachineType(IDevice::Emulator); + dev->setDisplayName(m_createdAvdInfo.name); + dev->setDeviceState(IDevice::DeviceConnected); + dev->setExtraData(Constants::AndroidAvdName, m_createdAvdInfo.name); + dev->setExtraData(Constants::AndroidCpuAbi, {m_createdAvdInfo.abi}); + if (!m_createdAvdInfo.systemImage) { + qCWarning(avdDialogLog) << "System image of the created AVD is nullptr"; + return IDevice::Ptr(); + } + dev->setExtraData(Constants::AndroidSdk, m_createdAvdInfo.systemImage->apiLevel()); + dev->setExtraData(Constants::AndroidAvdSdcard, QString("%1 MB") + .arg(m_createdAvdInfo.sdcardSize)); + dev->setExtraData(Constants::AndroidAvdDevice, m_createdAvdInfo.deviceDefinition); - result.systemImage = d.systemImage(); - result.name = d.name(); - result.abi = d.abi(); - result.deviceDefinition = d.deviceDefinition(); - result.sdcardSize = d.sdcardSize(); - result.overwrite = d.m_avdDialog.overwriteCheckBox->isChecked(); - - return result; + return IDevice::Ptr(dev); } AvdDialog::DeviceType AvdDialog::tagToDeviceType(const QString &type_tag) @@ -175,7 +208,7 @@ void AvdDialog::parseDeviceDefinitionsList() void AvdDialog::updateDeviceDefinitionComboBox() { - DeviceType curDeviceType = DeviceTypeToStringMap.key( + DeviceType curDeviceType = deviceTypeToStringMap.key( m_avdDialog.deviceDefinitionTypeComboBox->currentText()); m_avdDialog.deviceDefinitionComboBox->clear(); @@ -215,8 +248,8 @@ int AvdDialog::sdcardSize() const void AvdDialog::updateApiLevelComboBox() { - SystemImageList installedSystemImages = m_sdkManager->installedSystemImages(); - DeviceType curDeviceType = DeviceTypeToStringMap.key( + SystemImageList installedSystemImages = m_sdkManager.installedSystemImages(); + DeviceType curDeviceType = deviceTypeToStringMap.key( m_avdDialog.deviceDefinitionTypeComboBox->currentText()); QString selectedAbi = abi(); @@ -250,8 +283,7 @@ void AvdDialog::updateApiLevelComboBox() m_avdDialog.warningText->setVisible(true); m_avdDialog.warningText->setText( tr("Cannot create a new AVD. No suitable Android system image is installed.
" - "Install a system image of at least API version %1 from the SDK Manager tab.") - .arg(m_minApiLevel)); + "Install a system image for the intended Android version from the SDK Manager.")); m_avdDialog.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); } else if (filteredList.isEmpty()) { m_avdDialog.targetApiComboBox->setEnabled(false); diff --git a/src/plugins/android/avddialog.h b/src/plugins/android/avddialog.h index 9813cc813ba..3f95bed2130 100644 --- a/src/plugins/android/avddialog.h +++ b/src/plugins/android/avddialog.h @@ -41,21 +41,27 @@ class AvdDialog : public QDialog { Q_OBJECT public: - explicit AvdDialog(int minApiLevel, - AndroidSdkManager *sdkManager, - const QStringList &abis, - const AndroidConfig &config, - QWidget *parent = nullptr); + explicit AvdDialog(const AndroidConfig &config, QWidget *parent = nullptr); + int exec() override; - enum DeviceType { TV, Phone, Wear, Tablet, Automotive, PhoneOrTablet }; + enum DeviceType { Phone, Tablet, Automotive, TV, Wear, PhoneOrTablet }; - const QMap DeviceTypeToStringMap{ - {TV, "TV"}, - {Phone, "Phone"}, - {Wear, "Wear"}, - {Tablet, "Tablet"}, - {Automotive, "Automotive"} - }; + ProjectExplorer::IDevice::Ptr device() const; + + const SystemImage *systemImage() const; + QString name() const; + QString abi() const; + QString deviceDefinition() const; + int sdcardSize() const; + bool isValid() const; + +private: + void parseDeviceDefinitionsList(); + void updateDeviceDefinitionComboBox(); + void updateApiLevelComboBox(); + bool eventFilter(QObject *obj, QEvent *event) override; + + static AvdDialog::DeviceType tagToDeviceType(const QString &type_tag); struct DeviceDefinitionStruct { @@ -64,30 +70,14 @@ public: DeviceType deviceType; }; - const SystemImage *systemImage() const; - QString name() const; - QString abi() const; - QString deviceDefinition() const; - int sdcardSize() const; - bool isValid() const; - static AvdDialog::DeviceType tagToDeviceType(const QString &type_tag); - static CreateAvdInfo gatherCreateAVDInfo(QWidget *parent, AndroidSdkManager *sdkManager, - const AndroidConfig &config, - int minApiLevel = 0, const QStringList &abis = {}); - -private: - void parseDeviceDefinitionsList(); - void updateDeviceDefinitionComboBox(); - void updateApiLevelComboBox(); - bool eventFilter(QObject *obj, QEvent *event) override; - Ui::AddNewAVDDialog m_avdDialog; - AndroidSdkManager *m_sdkManager; - int m_minApiLevel; + AndroidSdkManager m_sdkManager; + CreateAvdInfo m_createdAvdInfo; QTimer m_hideTipTimer; QRegularExpression m_allowedNameChars; QList m_deviceDefinitionsList; AndroidConfig m_androidConfig; + QMap deviceTypeToStringMap; }; } }