diff options
author | Daniel Teske <daniel.teske@digia.com> | 2014-03-24 16:31:28 +0100 |
---|---|---|
committer | Daniel Teske <daniel.teske@digia.com> | 2014-04-01 16:24:45 +0200 |
commit | a087b3cd7f9b4ed2e5ec96ce8b0c74432db57568 (patch) | |
tree | 51c78f96d0294af3f4ac5131d98422ebd51ed65a | |
parent | 7e4502d67633da3a3850b9f973d682843a625123 (diff) | |
download | qt-creator-a087b3cd7f9b4ed2e5ec96ce8b0c74432db57568.tar.gz |
Android: Rework Create AVD dialog
Filter the list of api levels to only show those that can be created.
Change-Id: I7aaaa58324ca44176e39982cda29d746011fa346
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>
-rw-r--r-- | src/plugins/android/addnewavddialog.ui | 77 | ||||
-rw-r--r-- | src/plugins/android/android.pro | 6 | ||||
-rw-r--r-- | src/plugins/android/androidconfigurations.cpp | 96 | ||||
-rw-r--r-- | src/plugins/android/androidconfigurations.h | 20 | ||||
-rw-r--r-- | src/plugins/android/androiddeployqtstep.cpp | 4 | ||||
-rw-r--r-- | src/plugins/android/androiddeployqtwidget.cpp | 2 | ||||
-rw-r--r-- | src/plugins/android/androidmanager.cpp | 2 | ||||
-rw-r--r-- | src/plugins/android/androidpackagecreationwidget.cpp | 2 | ||||
-rw-r--r-- | src/plugins/android/avddialog.cpp | 115 | ||||
-rw-r--r-- | src/plugins/android/avddialog.h | 62 |
10 files changed, 302 insertions, 84 deletions
diff --git a/src/plugins/android/addnewavddialog.ui b/src/plugins/android/addnewavddialog.ui index c73cc37ca8..f06986fa4c 100644 --- a/src/plugins/android/addnewavddialog.ui +++ b/src/plugins/android/addnewavddialog.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>250</width> - <height>161</height> + <width>336</width> + <height>183</height> </rect> </property> <property name="windowTitle"> @@ -16,27 +16,67 @@ <layout class="QVBoxLayout" name="verticalLayout"> <item> <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Name:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="nameLineEdit"/> + </item> <item row="1" column="0"> - <widget class="QLabel" name="label_2"> + <widget class="QLabel" name="label_4"> <property name="text"> - <string>Target API:</string> + <string>ABI:</string> </property> <property name="alignment"> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> </property> </widget> </item> - <item row="0" column="0"> - <widget class="QLabel" name="label"> + <item row="1" column="1"> + <widget class="QComboBox" name="abiComboBox"/> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_2"> <property name="text"> - <string>Name:</string> + <string>Target API:</string> </property> <property name="alignment"> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> </property> </widget> </item> - <item row="3" column="0"> + <item row="2" column="1"> + <widget class="QComboBox" name="targetComboBox"/> + </item> + <item row="3" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="warningIcon"> + <property name="text"> + <string/> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="warningText"> + <property name="text"> + <string/> + </property> + </widget> + </item> + </layout> + </item> + <item row="4" column="0"> <widget class="QLabel" name="label_3"> <property name="text"> <string>SD card size:</string> @@ -46,10 +86,7 @@ </property> </widget> </item> - <item row="0" column="1"> - <widget class="QLineEdit" name="nameLineEdit"/> - </item> - <item row="3" column="1"> + <item row="4" column="1"> <widget class="QSpinBox" name="sizeSpinBox"> <property name="alignment"> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> @@ -68,22 +105,6 @@ </property> </widget> </item> - <item row="1" column="1"> - <widget class="QComboBox" name="targetComboBox"/> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_4"> - <property name="text"> - <string>ABI:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QComboBox" name="abiComboBox"/> - </item> </layout> </item> <item> diff --git a/src/plugins/android/android.pro b/src/plugins/android/android.pro index 18e26ce087..cee247a474 100644 --- a/src/plugins/android/android.pro +++ b/src/plugins/android/android.pro @@ -55,7 +55,8 @@ HEADERS += \ javaindenter.h \ javaautocompleter.h \ javacompletionassistprovider.h \ - javafilewizard.h + javafilewizard.h \ + avddialog.h SOURCES += \ androidconfigurations.cpp \ @@ -105,7 +106,8 @@ SOURCES += \ javaindenter.cpp \ javaautocompleter.cpp \ javacompletionassistprovider.cpp \ - javafilewizard.cpp + javafilewizard.cpp \ + avddialog.cpp FORMS += \ androidsettingswidget.ui \ diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp index 73b1b8d0a3..43db4ae413 100644 --- a/src/plugins/android/androidconfigurations.cpp +++ b/src/plugins/android/androidconfigurations.cpp @@ -32,9 +32,9 @@ #include "androidtoolchain.h" #include "androiddevice.h" #include "androidgdbserverkitinformation.h" -#include "ui_addnewavddialog.h" #include "androidqtversion.h" #include "androiddevicedialog.h" +#include "avddialog.h" #include <coreplugin/icore.h> #include <coreplugin/messagemanager.h> @@ -60,6 +60,7 @@ #include <QFileInfo> #include <QDirIterator> #include <QMetaObject> +#include <QApplication> #include <QStringListModel> #include <QMessageBox> @@ -260,6 +261,15 @@ void AndroidConfig::updateNdkInformation() const m_NdkInformationUpToDate = true; } +bool AndroidConfig::sortSdkPlatformByApiLevel(const SdkPlatform &a, const SdkPlatform &b) +{ + if (a.apiLevel != b.apiLevel) + return a.apiLevel > b.apiLevel; + if (a.name != b.name) + return a.name < b.name; + return false; +} + void AndroidConfig::updateAvailableSdkPlatforms() const { if (m_availableSdkPlatformsUpToDate) @@ -273,26 +283,47 @@ void AndroidConfig::updateAvailableSdkPlatforms() const proc.terminate(); return; } + + SdkPlatform platform; while (proc.canReadLine()) { const QString line = QString::fromLocal8Bit(proc.readLine().trimmed()); - int index = line.indexOf(QLatin1String("\"android-")); - if (index == -1) - continue; - QString androidTarget = line.mid(index + 1, line.length() - index - 2); - int apiLevel = androidTarget.mid(androidTarget.lastIndexOf(QLatin1Char('-')) + 1).toInt(); - QVector<int>::iterator it = qLowerBound(m_availableSdkPlatforms.begin(), m_availableSdkPlatforms.end(), apiLevel, qGreater<int>()); - m_availableSdkPlatforms.insert(it, apiLevel); + if (line.startsWith(QLatin1String("id:")) && line.contains(QLatin1String("android-"))) { + int index = line.indexOf(QLatin1String("\"android-")); + if (index == -1) + continue; + QString androidTarget = line.mid(index + 1, line.length() - index - 2); + platform.apiLevel = androidTarget.mid(androidTarget.lastIndexOf(QLatin1Char('-')) + 1).toInt(); + } else if (line.startsWith(QLatin1String("Name:"))) { + platform.name = line.mid(6); + } else if (line.startsWith(QLatin1String("ABIs"))) { + platform.abis = line.mid(6).trimmed().split(QLatin1String(", ")); + } else if (line.startsWith(QLatin1String("---")) || line.startsWith(QLatin1String("==="))) { + if (platform.apiLevel == -1) + continue; + auto it = qLowerBound(m_availableSdkPlatforms.begin(), m_availableSdkPlatforms.end(), + platform, sortSdkPlatformByApiLevel); + m_availableSdkPlatforms.insert(it, platform); + platform = SdkPlatform(); + } } m_availableSdkPlatformsUpToDate = true; } -QStringList AndroidConfig::sdkTargets(int minApiLevel) const +QStringList AndroidConfig::apiLevelNamesFor(const QList<SdkPlatform> &platforms) +{ + QStringList results; + foreach (const SdkPlatform &platform, platforms) + results << QLatin1String("android-") + QString::number(platform.apiLevel); + return results; +} + +QList<SdkPlatform> AndroidConfig::sdkTargets(int minApiLevel) const { updateAvailableSdkPlatforms(); - QStringList result; + QList<SdkPlatform> result; for (int i = 0; i < m_availableSdkPlatforms.size(); ++i) { - if (m_availableSdkPlatforms.at(i) >= minApiLevel) - result << QLatin1String("android-") + QString::number(m_availableSdkPlatforms.at(i)); + if (m_availableSdkPlatforms.at(i).apiLevel >= minApiLevel) + result << m_availableSdkPlatforms.at(i); else break; } @@ -450,39 +481,12 @@ QVector<AndroidDeviceInfo> AndroidConfig::connectedDevices(QString *error) const QString AndroidConfig::createAVD(QWidget *parent, int minApiLevel, QString targetArch) const { - QDialog d(parent); - Ui::AddNewAVDDialog avdDialog; - avdDialog.setupUi(&d); - // NOTE: adb list targets does actually include information on which abis are supported per apilevel - // we aren't using that information here - avdDialog.targetComboBox->addItems(sdkTargets(minApiLevel)); - - if (targetArch.isEmpty()) - avdDialog.abiComboBox->addItems(QStringList() - << QLatin1String("armeabi-v7a") - << QLatin1String("armeabi") - << QLatin1String("x86") - << QLatin1String("mips")); - else - avdDialog.abiComboBox->addItems(QStringList(targetArch)); - - if (!avdDialog.targetComboBox->count()) { - QMessageBox::critical(parent, QApplication::translate("AndroidConfig", "Error Creating AVD"), - QApplication::translate("AndroidConfig", "Cannot create a new AVD. No sufficiently recent Android SDK available.\n" - "Please install an SDK of at least API version %1."). - arg(minApiLevel)); - return QString(); - } - - QRegExp rx(QLatin1String("\\S+")); - QRegExpValidator v(rx, 0); - avdDialog.nameLineEdit->setValidator(&v); - if (d.exec() != QDialog::Accepted) + AvdDialog d(minApiLevel, targetArch, this, parent); + if (d.exec() != QDialog::Accepted || !d.isValid()) return QString(); QString error; - QString avd = createAVD(avdDialog.targetComboBox->currentText(), avdDialog.nameLineEdit->text(), - avdDialog.abiComboBox->currentText(), avdDialog.sizeSpinBox->value(), - &error); + QString avd = createAVD(d.target(), d.name(), d.abi(), d.sdcardSize(), &error); + if (!error.isEmpty()) { QMessageBox::critical(parent, QApplication::translate("AndroidConfig", "Error Creating AVD"), error); @@ -787,12 +791,12 @@ QStringList AndroidConfig::getAbis(const QString &device) const return result; } -QString AndroidConfig::highestAndroidSdk() const +SdkPlatform AndroidConfig::highestAndroidSdk() const { updateAvailableSdkPlatforms(); if (m_availableSdkPlatforms.isEmpty()) - return QString(); - return QLatin1String("android-") + QString::number(m_availableSdkPlatforms.first()); + return SdkPlatform(); + return m_availableSdkPlatforms.first(); } QString AndroidConfig::bestNdkPlatformMatch(const QString &targetAPI) const diff --git a/src/plugins/android/androidconfigurations.h b/src/plugins/android/androidconfigurations.h index 4578a39a92..fd35944737 100644 --- a/src/plugins/android/androidconfigurations.h +++ b/src/plugins/android/androidconfigurations.h @@ -65,6 +65,17 @@ struct AndroidDeviceInfo static QStringList adbSelector(const QString &serialNumber); }; +class SdkPlatform +{ +public: + SdkPlatform() + : apiLevel(-1) + {} + int apiLevel; + QString name; + QStringList abis; +}; + class AndroidConfig { public: @@ -73,7 +84,8 @@ public: void load(const QSettings &settings); void save(QSettings &settings) const; - QStringList sdkTargets(int minApiLevel = 0) const; + static QStringList apiLevelNamesFor(const QList<SdkPlatform> &platforms); + QList<SdkPlatform> sdkTargets(int minApiLevel = 0) const; Utils::FileName sdkLocation() const; void setSdkLocation(const Utils::FileName &sdkLocation); @@ -137,8 +149,7 @@ public: bool waitForBooted(const QString &serialNumber, const QFutureInterface<bool> &fi) const; bool isConnected(const QString &serialNumber) const; - QString highestAndroidSdk() const; - + SdkPlatform highestAndroidSdk() const; private: Utils::FileName toolPath(ProjectExplorer::Abi::Architecture architecture, const QString &ndkToolChainVersion) const; Utils::FileName openJDKBinPath() const; @@ -160,7 +171,8 @@ private: //caches mutable bool m_availableSdkPlatformsUpToDate; - mutable QVector<int> m_availableSdkPlatforms; + mutable QVector<SdkPlatform> m_availableSdkPlatforms; + static bool sortSdkPlatformByApiLevel(const SdkPlatform &a, const SdkPlatform &b); mutable bool m_NdkInformationUpToDate; mutable QString m_toolchainHost; diff --git a/src/plugins/android/androiddeployqtstep.cpp b/src/plugins/android/androiddeployqtstep.cpp index 7335f5b69e..55465111d3 100644 --- a/src/plugins/android/androiddeployqtstep.cpp +++ b/src/plugins/android/androiddeployqtstep.cpp @@ -160,7 +160,9 @@ void AndroidDeployQtStep::ctor() m_verbose = false; // will be overwriten by settings if the user choose something different - m_buildTargetSdk = AndroidConfigurations::currentConfig().highestAndroidSdk(); + SdkPlatform sdk = AndroidConfigurations::currentConfig().highestAndroidSdk(); + if (sdk.apiLevel > 0) + m_buildTargetSdk = QLatin1String("android-") + QString::number(sdk.apiLevel); connect(project(), SIGNAL(proFilesEvaluated()), this, SLOT(updateInputFile())); diff --git a/src/plugins/android/androiddeployqtwidget.cpp b/src/plugins/android/androiddeployqtwidget.cpp index 371588c398..86f0537e5c 100644 --- a/src/plugins/android/androiddeployqtwidget.cpp +++ b/src/plugins/android/androiddeployqtwidget.cpp @@ -63,7 +63,7 @@ AndroidDeployQtWidget::AndroidDeployQtWidget(AndroidDeployQtStep *step) // Target sdk combobox int minApiLevel = 9; - QStringList targets = AndroidConfigurations::currentConfig().sdkTargets(minApiLevel); + QStringList targets = AndroidConfig::apiLevelNamesFor(AndroidConfigurations::currentConfig().sdkTargets(minApiLevel)); m_ui->targetSDKComboBox->addItems(targets); m_ui->targetSDKComboBox->setCurrentIndex(targets.indexOf(step->buildTargetSdk())); diff --git a/src/plugins/android/androidmanager.cpp b/src/plugins/android/androidmanager.cpp index 3c5e1397db..68c76e2ed0 100644 --- a/src/plugins/android/androidmanager.cpp +++ b/src/plugins/android/androidmanager.cpp @@ -613,7 +613,7 @@ bool AndroidManager::createAndroidTemplatesIfNecessary(ProjectExplorer::Target * if (qt->qtVersion() >= QtSupport::QtVersionNumber(5, 0, 0)) minApiLevel = 9; - QStringList sdks = AndroidConfigurations::currentConfig().sdkTargets(minApiLevel); + QStringList sdks = AndroidConfig::apiLevelNamesFor(AndroidConfigurations::currentConfig().sdkTargets(minApiLevel)); if (sdks.isEmpty()) { raiseError(tr("No Qt for Android SDKs were found.\nPlease install at least one SDK.")); return false; diff --git a/src/plugins/android/androidpackagecreationwidget.cpp b/src/plugins/android/androidpackagecreationwidget.cpp index 543a8872d8..7dfebc7e3a 100644 --- a/src/plugins/android/androidpackagecreationwidget.cpp +++ b/src/plugins/android/androidpackagecreationwidget.cpp @@ -232,7 +232,7 @@ void AndroidPackageCreationWidget::updateAndroidProjectInfo() if (qt->qtVersion() >= QtSupport::QtVersionNumber(5, 0, 0)) minApiLevel = 9; - QStringList targets = AndroidConfigurations::currentConfig().sdkTargets(minApiLevel); + QStringList targets = AndroidConfig::apiLevelNamesFor(AndroidConfigurations::currentConfig().sdkTargets(minApiLevel)); m_ui->targetSDKComboBox->addItems(targets); m_ui->targetSDKComboBox->setCurrentIndex(targets.indexOf(AndroidManager::buildTargetSDK(target))); diff --git a/src/plugins/android/avddialog.cpp b/src/plugins/android/avddialog.cpp new file mode 100644 index 0000000000..9922e63aac --- /dev/null +++ b/src/plugins/android/avddialog.cpp @@ -0,0 +1,115 @@ +/************************************************************************** +** +** Copyright (c) 2014 BogDan Vatra <bog_dan_ro@yahoo.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "avddialog.h" +#include "androidconfigurations.h" + +#include <QMessageBox> + +using namespace Android; +using namespace Android::Internal; + +AvdDialog::AvdDialog(int minApiLevel, const QString &targetArch, const AndroidConfig *config, QWidget *parent) : + QDialog(parent), m_config(config), m_minApiLevel(minApiLevel) +{ + m_avdDialog.setupUi(this); + + if (targetArch.isEmpty()) + m_avdDialog.abiComboBox->addItems(QStringList() + << QLatin1String("armeabi-v7a") + << QLatin1String("armeabi") + << QLatin1String("x86") + << QLatin1String("mips")); + else + m_avdDialog.abiComboBox->addItems(QStringList(targetArch)); + + QRegExp rx(QLatin1String("\\S+")); + QRegExpValidator v(rx, 0); + m_avdDialog.nameLineEdit->setValidator(&v); + m_avdDialog.warningIcon->setPixmap(QPixmap(QLatin1String(":/projectexplorer/images/compile_warning.png"))); + + updateApiLevelComboBox(); + + connect(m_avdDialog.abiComboBox, SIGNAL(currentIndexChanged(int)), + this, SLOT(updateApiLevelComboBox())); +} + +bool AvdDialog::isValid() const +{ + return !name().isEmpty() && !target().isEmpty() && !abi().isEmpty(); +} + +QString AvdDialog::target() const +{ + return m_avdDialog.targetComboBox->currentText(); +} + +QString AvdDialog::name() const +{ + return m_avdDialog.nameLineEdit->text(); +} + +QString AvdDialog::abi() const +{ + return m_avdDialog.abiComboBox->currentText(); +} + +int AvdDialog::sdcardSize() const +{ + return m_avdDialog.sizeSpinBox->value(); +} + +void AvdDialog::updateApiLevelComboBox() +{ + QList<SdkPlatform> filteredList; + QList<SdkPlatform> platforms = m_config->sdkTargets(m_minApiLevel); + foreach (const SdkPlatform &platform, platforms) { + if (platform.abis.contains(abi())) + filteredList << platform; + } + + m_avdDialog.targetComboBox->clear(); + m_avdDialog.targetComboBox->addItems(AndroidConfig::apiLevelNamesFor(filteredList)); + + if (platforms.isEmpty()) { + m_avdDialog.warningIcon->setVisible(true); + m_avdDialog.warningText->setVisible(true); + m_avdDialog.warningText->setText(tr("Cannot create a new AVD. No sufficiently recent Android SDK available.\n" + "Please install an SDK of at least API version %1.") + .arg(m_minApiLevel)); + } else if (filteredList.isEmpty()) { + m_avdDialog.warningIcon->setVisible(true); + m_avdDialog.warningText->setVisible(true); + m_avdDialog.warningText->setText(tr("Cannot create a AVD for ABI %1. Please install a image for it.") + .arg(abi())); + } else { + m_avdDialog.warningIcon->setVisible(false); + m_avdDialog.warningText->setVisible(false); + } +} diff --git a/src/plugins/android/avddialog.h b/src/plugins/android/avddialog.h new file mode 100644 index 0000000000..d0aefc2221 --- /dev/null +++ b/src/plugins/android/avddialog.h @@ -0,0 +1,62 @@ +/************************************************************************** +** +** Copyright (c) 2014 BogDan Vatra <bog_dan_ro@yahoo.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef AVDDIALOG_H +#define AVDDIALOG_H + +#include "ui_addnewavddialog.h" +#include <QDialog> + +namespace Android { +namespace Internal { +class AndroidConfig; + +class AvdDialog : public QDialog +{ + Q_OBJECT +public: + explicit AvdDialog(int minApiLevel, const QString &targetArch, + const AndroidConfig *config, QWidget *parent = 0); + + QString target() const; + QString name() const; + QString abi() const; + int sdcardSize() const; + bool isValid() const; +private slots: + void updateApiLevelComboBox(); +private: + Ui::AddNewAVDDialog m_avdDialog; + const AndroidConfig *m_config; + int m_minApiLevel; +}; +} +} + +#endif // AVDDIALOG_H |