Android: inline addnewavddialog.ui

Change-Id: Ib90981f8fb60b637deb03da5466f7aaa49369104
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
hjk
2022-07-21 18:54:08 +02:00
parent b8a6d72137
commit a7636d8d5c
5 changed files with 138 additions and 248 deletions

View File

@@ -2,7 +2,6 @@ add_qtc_plugin(Android
DEPENDS QmlDebug Qt5::Xml LanguageServerProtocol DEPENDS QmlDebug Qt5::Xml LanguageServerProtocol
PLUGIN_DEPENDS Core Debugger ProjectExplorer QtSupport LanguageClient PLUGIN_DEPENDS Core Debugger ProjectExplorer QtSupport LanguageClient
SOURCES SOURCES
addnewavddialog.ui
android.qrc android.qrc
android_global.h android_global.h
androidtr.h androidtr.h

View File

@@ -1,179 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Android::Internal::AddNewAVDDialog</class>
<widget class="QDialog" name="Android::Internal::AddNewAVDDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
</rect>
</property>
<property name="windowTitle">
<string>Create new AVD</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="nameLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="abiLabel">
<property name="text">
<string>Architecture (ABI):</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="sdcardSizeLabel">
<property name="text">
<string>SD card size:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="targetApiLabel">
<property name="text">
<string>Target API:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="deviceDefinitionLabel">
<property name="text">
<string>Device definition:</string>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<widget class="QComboBox" name="abiComboBox"/>
</item>
<item row="5" column="1" colspan="2">
<widget class="QSpinBox" name="sdcardSizeSpinBox">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="suffix">
<string> MiB</string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>1000000</number>
</property>
<property name="value">
<number>512</number>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QLineEdit" name="nameLineEdit"/>
</item>
<item row="3" column="1" colspan="2">
<widget class="QComboBox" name="targetApiComboBox"/>
</item>
<item row="1" column="2">
<widget class="QComboBox" name="deviceDefinitionComboBox"/>
</item>
<item row="4" column="1" colspan="2">
<widget class="Utils::InfoLabel" name="warningText"/>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="deviceDefinitionTypeComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QCheckBox" name="overwriteCheckBox">
<property name="text">
<string>Overwrite existing AVD name</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Utils::InfoLabel</class>
<extends>QLabel</extends>
<header location="global">utils/infolabel.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Android::Internal::AddNewAVDDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>222</x>
<y>134</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>148</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Android::Internal::AddNewAVDDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>245</x>
<y>140</y>
</hint>
<hint type="destinationlabel">
<x>249</x>
<y>148</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -20,7 +20,6 @@ Project {
files: [ files: [
"android_global.h", "androidtr.h", "android_global.h", "androidtr.h",
"android.qrc", "android.qrc",
"addnewavddialog.ui",
"androidavdmanager.cpp", "androidavdmanager.cpp",
"androidavdmanager.h", "androidavdmanager.h",
"androidconfigurations.cpp", "androidconfigurations.cpp",

View File

@@ -24,30 +24,39 @@
****************************************************************************/ ****************************************************************************/
#include "avddialog.h" #include "avddialog.h"
#include "androidsdkmanager.h"
#include "androidavdmanager.h" #include "androidavdmanager.h"
#include "androiddevice.h"
#include "androidconstants.h" #include "androidconstants.h"
#include "androiddevice.h"
#include "androidsdkmanager.h"
#include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/projectexplorerconstants.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/infolabel.h>
#include <utils/layoutbuilder.h>
#include <utils/qtcassert.h>
#include <utils/tooltip/tooltip.h> #include <utils/tooltip/tooltip.h>
#include <utils/utilsicons.h> #include <utils/utilsicons.h>
#include <utils/qtcassert.h>
#include <QCheckBox>
#include <QComboBox>
#include <QDialogButtonBox>
#include <QFutureWatcher> #include <QFutureWatcher>
#include <QKeyEvent> #include <QKeyEvent>
#include <QMessageBox> #include <QLineEdit>
#include <QToolTip>
#include <QLoggingCategory> #include <QLoggingCategory>
#include <QMessageBox>
#include <QPushButton> #include <QPushButton>
#include <QSpinBox>
#include <QToolTip>
using namespace Android; using namespace Utils;
using namespace Android::Internal;
namespace Android::Internal {
namespace {
static Q_LOGGING_CATEGORY(avdDialogLog, "qtc.android.avdDialog", QtWarningMsg) static Q_LOGGING_CATEGORY(avdDialogLog, "qtc.android.avdDialog", QtWarningMsg)
}
AvdDialog::AvdDialog(const AndroidConfig &config, QWidget *parent) AvdDialog::AvdDialog(const AndroidConfig &config, QWidget *parent)
: QDialog(parent), : QDialog(parent),
@@ -55,38 +64,79 @@ AvdDialog::AvdDialog(const AndroidConfig &config, QWidget *parent)
m_androidConfig(config), m_androidConfig(config),
m_sdkManager(m_androidConfig) m_sdkManager(m_androidConfig)
{ {
m_avdDialog.setupUi(this); resize(800, 0);
m_hideTipTimer.setInterval(2000); setWindowTitle(tr("Create new AVD"));
m_hideTipTimer.setSingleShot(true);
connect(&m_hideTipTimer, &QTimer::timeout, this, &Utils::ToolTip::hide); m_abiComboBox = new QComboBox;
connect(m_avdDialog.deviceDefinitionTypeComboBox, &QComboBox::currentIndexChanged, m_abiComboBox->addItems({
this, &AvdDialog::updateDeviceDefinitionComboBox);
connect(m_avdDialog.abiComboBox, &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,
ProjectExplorer::Constants::ANDROID_ABI_X86_64, ProjectExplorer::Constants::ANDROID_ABI_X86_64,
ProjectExplorer::Constants::ANDROID_ABI_ARMEABI_V7A, ProjectExplorer::Constants::ANDROID_ABI_ARMEABI_V7A,
ProjectExplorer::Constants::ANDROID_ABI_ARM64_V8A})); ProjectExplorer::Constants::ANDROID_ABI_ARM64_V8A
});
auto v = new QRegularExpressionValidator(m_allowedNameChars, this); m_sdcardSizeSpinBox = new QSpinBox;
m_avdDialog.nameLineEdit->setValidator(v); m_sdcardSizeSpinBox->setSuffix(tr(" MiB"));
m_avdDialog.nameLineEdit->installEventFilter(this); m_sdcardSizeSpinBox->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
m_sdcardSizeSpinBox->setRange(0, 1000000);
m_sdcardSizeSpinBox->setValue(512);
m_avdDialog.warningText->setType(Utils::InfoLabel::Warning); m_nameLineEdit = new QLineEdit;
m_avdDialog.warningText->setElideMode(Qt::ElideNone); m_nameLineEdit->setValidator(new QRegularExpressionValidator(m_allowedNameChars, this));
m_nameLineEdit->installEventFilter(this);
m_targetApiComboBox = new QComboBox;
m_deviceDefinitionComboBox = new QComboBox;
m_warningText = new InfoLabel;
m_warningText->setType(InfoLabel::Warning);
m_warningText->setElideMode(Qt::ElideNone);
m_deviceDefinitionTypeComboBox = new QComboBox;
m_overwriteCheckBox = new QCheckBox(tr("Overwrite existing AVD name"));
m_buttonBox = new QDialogButtonBox(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
m_hideTipTimer.setInterval(2000);
m_hideTipTimer.setSingleShot(true);
using namespace Layouting;
const Break nl;
Column {
Form {
tr("Name:"), m_nameLineEdit, nl,
tr("Device definition:"),
Row { m_deviceDefinitionTypeComboBox, m_deviceDefinitionComboBox }, nl,
tr("Architecture (ABI):"), m_abiComboBox, nl,
tr("Target API:"), m_targetApiComboBox, nl,
QString(), m_warningText, nl,
tr("SD card size:"), m_sdcardSizeSpinBox, nl,
QString(), m_overwriteCheckBox,
},
Stretch(),
m_buttonBox
}.attachTo(this);
connect(&m_hideTipTimer, &QTimer::timeout, this, &Utils::ToolTip::hide);
connect(m_deviceDefinitionTypeComboBox, &QComboBox::currentIndexChanged,
this, &AvdDialog::updateDeviceDefinitionComboBox);
connect(m_abiComboBox, &QComboBox::currentIndexChanged,
this, &AvdDialog::updateApiLevelComboBox);
connect(m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
m_deviceTypeToStringMap.insert(AvdDialog::Phone, "Phone");
m_deviceTypeToStringMap.insert(AvdDialog::Tablet, "Tablet");
m_deviceTypeToStringMap.insert(AvdDialog::Automotive, "Automotive");
m_deviceTypeToStringMap.insert(AvdDialog::TV, "TV");
m_deviceTypeToStringMap.insert(AvdDialog::Wear, "Wear");
parseDeviceDefinitionsList(); parseDeviceDefinitionsList();
for (const QString &type : deviceTypeToStringMap) for (const QString &type : m_deviceTypeToStringMap)
m_avdDialog.deviceDefinitionTypeComboBox->addItem(type); m_deviceDefinitionTypeComboBox->addItem(type);
updateApiLevelComboBox(); updateApiLevelComboBox();
} }
@@ -101,7 +151,7 @@ int AvdDialog::exec()
result.abi = abi(); result.abi = abi();
result.deviceDefinition = deviceDefinition(); result.deviceDefinition = deviceDefinition();
result.sdcardSize = sdcardSize(); result.sdcardSize = sdcardSize();
result.overwrite = m_avdDialog.overwriteCheckBox->isChecked(); result.overwrite = m_overwriteCheckBox->isChecked();
const AndroidAvdManager avdManager = AndroidAvdManager(m_androidConfig); const AndroidAvdManager avdManager = AndroidAvdManager(m_androidConfig);
QFutureWatcher<CreateAvdInfo> createAvdFutureWatcher; QFutureWatcher<CreateAvdInfo> createAvdFutureWatcher;
@@ -204,49 +254,49 @@ void AvdDialog::parseDeviceDefinitionsList()
void AvdDialog::updateDeviceDefinitionComboBox() void AvdDialog::updateDeviceDefinitionComboBox()
{ {
DeviceType curDeviceType = deviceTypeToStringMap.key( DeviceType curDeviceType = m_deviceTypeToStringMap.key(
m_avdDialog.deviceDefinitionTypeComboBox->currentText()); m_deviceDefinitionTypeComboBox->currentText());
m_avdDialog.deviceDefinitionComboBox->clear(); m_deviceDefinitionComboBox->clear();
for (const DeviceDefinitionStruct &item : qAsConst(m_deviceDefinitionsList)) { for (const DeviceDefinitionStruct &item : qAsConst(m_deviceDefinitionsList)) {
if (item.deviceType == curDeviceType) if (item.deviceType == curDeviceType)
m_avdDialog.deviceDefinitionComboBox->addItem(item.name_id); m_deviceDefinitionComboBox->addItem(item.name_id);
} }
m_avdDialog.deviceDefinitionComboBox->addItem("Custom"); m_deviceDefinitionComboBox->addItem("Custom");
updateApiLevelComboBox(); updateApiLevelComboBox();
} }
const SystemImage* AvdDialog::systemImage() const const SystemImage* AvdDialog::systemImage() const
{ {
return m_avdDialog.targetApiComboBox->currentData().value<SystemImage*>(); return m_targetApiComboBox->currentData().value<SystemImage*>();
} }
QString AvdDialog::name() const QString AvdDialog::name() const
{ {
return m_avdDialog.nameLineEdit->text(); return m_nameLineEdit->text();
} }
QString AvdDialog::abi() const QString AvdDialog::abi() const
{ {
return m_avdDialog.abiComboBox->currentText(); return m_abiComboBox->currentText();
} }
QString AvdDialog::deviceDefinition() const QString AvdDialog::deviceDefinition() const
{ {
return m_avdDialog.deviceDefinitionComboBox->currentText(); return m_deviceDefinitionComboBox->currentText();
} }
int AvdDialog::sdcardSize() const int AvdDialog::sdcardSize() const
{ {
return m_avdDialog.sdcardSizeSpinBox->value(); return m_sdcardSizeSpinBox->value();
} }
void AvdDialog::updateApiLevelComboBox() void AvdDialog::updateApiLevelComboBox()
{ {
SystemImageList installedSystemImages = m_sdkManager.installedSystemImages(); SystemImageList installedSystemImages = m_sdkManager.installedSystemImages();
DeviceType curDeviceType = deviceTypeToStringMap.key( DeviceType curDeviceType = m_deviceTypeToStringMap.key(
m_avdDialog.deviceDefinitionTypeComboBox->currentText()); m_deviceDefinitionTypeComboBox->currentText());
QString selectedAbi = abi(); QString selectedAbi = abi();
auto hasAbi = [selectedAbi](const SystemImage *image) { auto hasAbi = [selectedAbi](const SystemImage *image) {
@@ -261,49 +311,49 @@ void AvdDialog::updateApiLevelComboBox()
return image && deviceType == curDeviceType && hasAbi(image); return image && deviceType == curDeviceType && hasAbi(image);
}); });
m_avdDialog.targetApiComboBox->clear(); m_targetApiComboBox->clear();
for (SystemImage *image : qAsConst(filteredList)) { for (SystemImage *image : qAsConst(filteredList)) {
QString imageString = "android-" % QString::number(image->apiLevel()); QString imageString = "android-" % QString::number(image->apiLevel());
const QStringList imageSplits = image->sdkStylePath().split(';'); const QStringList imageSplits = image->sdkStylePath().split(';');
if (imageSplits.size() == 4) if (imageSplits.size() == 4)
imageString += QStringLiteral(" (%1)").arg(imageSplits.at(2)); imageString += QStringLiteral(" (%1)").arg(imageSplits.at(2));
m_avdDialog.targetApiComboBox->addItem(imageString, m_targetApiComboBox->addItem(imageString,
QVariant::fromValue<SystemImage *>(image)); QVariant::fromValue<SystemImage *>(image));
m_avdDialog.targetApiComboBox->setItemData(m_avdDialog.targetApiComboBox->count() - 1, m_targetApiComboBox->setItemData(m_targetApiComboBox->count() - 1,
image->descriptionText(), image->descriptionText(),
Qt::ToolTipRole); Qt::ToolTipRole);
} }
if (installedSystemImages.isEmpty()) { if (installedSystemImages.isEmpty()) {
m_avdDialog.targetApiComboBox->setEnabled(false); m_targetApiComboBox->setEnabled(false);
m_avdDialog.warningText->setVisible(true); m_warningText->setVisible(true);
m_avdDialog.warningText->setText( m_warningText->setText(
tr("Cannot create a new AVD. No suitable Android system image is installed.<br/>" tr("Cannot create a new AVD. No suitable Android system image is installed.<br/>"
"Install a system image for the intended Android version from the SDK Manager.")); "Install a system image for the intended Android version from the SDK Manager."));
m_avdDialog.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
} else if (filteredList.isEmpty()) { } else if (filteredList.isEmpty()) {
m_avdDialog.targetApiComboBox->setEnabled(false); m_targetApiComboBox->setEnabled(false);
m_avdDialog.warningText->setVisible(true); m_warningText->setVisible(true);
m_avdDialog.warningText->setText(tr("Cannot create an AVD for ABI %1.<br/>Install a system " m_warningText->setText(tr("Cannot create an AVD for ABI %1.<br/>Install a system "
"image for it from the SDK Manager tab first.") "image for it from the SDK Manager tab first.")
.arg(abi())); .arg(abi()));
m_avdDialog.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
} else { } else {
m_avdDialog.warningText->setVisible(false); m_warningText->setVisible(false);
m_avdDialog.targetApiComboBox->setEnabled(true); m_targetApiComboBox->setEnabled(true);
m_avdDialog.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
} }
} }
bool AvdDialog::eventFilter(QObject *obj, QEvent *event) bool AvdDialog::eventFilter(QObject *obj, QEvent *event)
{ {
if (obj == m_avdDialog.nameLineEdit && event->type() == QEvent::KeyPress) { if (obj == m_nameLineEdit && event->type() == QEvent::KeyPress) {
auto ke = static_cast<QKeyEvent *>(event); auto ke = static_cast<QKeyEvent *>(event);
const QString key = ke->text(); const QString key = ke->text();
if (!key.isEmpty() && !m_allowedNameChars.match(key).hasMatch()) { if (!key.isEmpty() && !m_allowedNameChars.match(key).hasMatch()) {
QPoint position = m_avdDialog.nameLineEdit->parentWidget()->mapToGlobal(m_avdDialog.nameLineEdit->geometry().bottomLeft()); QPoint position = m_nameLineEdit->parentWidget()->mapToGlobal(m_nameLineEdit->geometry().bottomLeft());
position -= Utils::ToolTip::offsetFromPosition(); position -= Utils::ToolTip::offsetFromPosition();
Utils::ToolTip::show(position, tr("Allowed characters are: a-z A-Z 0-9 and . _ -"), m_avdDialog.nameLineEdit); Utils::ToolTip::show(position, tr("Allowed characters are: a-z A-Z 0-9 and . _ -"), m_nameLineEdit);
m_hideTipTimer.start(); m_hideTipTimer.start();
} else { } else {
m_hideTipTimer.stop(); m_hideTipTimer.stop();
@@ -312,3 +362,5 @@ bool AvdDialog::eventFilter(QObject *obj, QEvent *event)
} }
return QDialog::eventFilter(obj, event); return QDialog::eventFilter(obj, event);
} }
} // Android::Internal

View File

@@ -25,12 +25,21 @@
#pragma once #pragma once
#include "androidconfigurations.h" #include "androidconfigurations.h"
#include "ui_addnewavddialog.h"
#include "androidconfigurations.h" #include "androidconfigurations.h"
#include <QDialog> #include <QDialog>
#include <QTimer> #include <QTimer>
QT_BEGIN_NAMESPACE
class QComboBox;
class QCheckBox;
class QDialogButtonBox;
class QLineEdit;
class QSpinBox;
QT_END_NAMESPACE
namespace Utils { class InfoLabel; }
namespace Android { namespace Android {
class AndroidConfig; class AndroidConfig;
class SdkPlatform; class SdkPlatform;
@@ -70,14 +79,24 @@ private:
DeviceType deviceType; DeviceType deviceType;
}; };
Ui::AddNewAVDDialog m_avdDialog;
CreateAvdInfo m_createdAvdInfo; CreateAvdInfo m_createdAvdInfo;
QTimer m_hideTipTimer; QTimer m_hideTipTimer;
QRegularExpression m_allowedNameChars; QRegularExpression m_allowedNameChars;
QList<DeviceDefinitionStruct> m_deviceDefinitionsList; QList<DeviceDefinitionStruct> m_deviceDefinitionsList;
const AndroidConfig &m_androidConfig; const AndroidConfig &m_androidConfig;
AndroidSdkManager m_sdkManager; AndroidSdkManager m_sdkManager;
QMap<AvdDialog::DeviceType, QString> deviceTypeToStringMap; QMap<AvdDialog::DeviceType, QString> m_deviceTypeToStringMap;
QComboBox *m_abiComboBox;
QSpinBox *m_sdcardSizeSpinBox;
QLineEdit *m_nameLineEdit;
QComboBox *m_targetApiComboBox;
QComboBox *m_deviceDefinitionComboBox;
Utils::InfoLabel *m_warningText;
QComboBox *m_deviceDefinitionTypeComboBox;
QCheckBox *m_overwriteCheckBox;
QDialogButtonBox *m_buttonBox;
}; };
}
} } // Internal
} // Android