forked from qt-creator/qt-creator
Android: Fix blocking the ui on adding an avd
Task-number: QTCREATORBUG-10601 Change-Id: I3d1fef8a44f434f7eb484f538863c436b4e3a21c Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>
This commit is contained in:
@@ -61,6 +61,7 @@
|
||||
#include <QDirIterator>
|
||||
#include <QMetaObject>
|
||||
#include <QApplication>
|
||||
#include <QtConcurrentRun>
|
||||
|
||||
#include <QStringListModel>
|
||||
#include <QMessageBox>
|
||||
@@ -501,34 +502,41 @@ QVector<AndroidDeviceInfo> AndroidConfig::connectedDevices(QString *error) const
|
||||
return devices;
|
||||
}
|
||||
|
||||
QString AndroidConfig::createAVD(QWidget *parent, int minApiLevel, QString targetArch) const
|
||||
AndroidConfig::CreateAvdInfo AndroidConfig::gatherCreateAVDInfo(QWidget *parent, int minApiLevel, QString targetArch) const
|
||||
{
|
||||
CreateAvdInfo result;
|
||||
AvdDialog d(minApiLevel, targetArch, this, parent);
|
||||
if (d.exec() != QDialog::Accepted || !d.isValid())
|
||||
return QString();
|
||||
QString error;
|
||||
QString avd = createAVD(d.target(), d.name(), d.abi(), d.sdcardSize(), &error);
|
||||
return result;
|
||||
|
||||
if (!error.isEmpty()) {
|
||||
QMessageBox::critical(parent, QApplication::translate("AndroidConfig", "Error Creating AVD"),
|
||||
error);
|
||||
}
|
||||
|
||||
return avd;
|
||||
result.target = d.target();
|
||||
result.name = d.name();
|
||||
result.abi = d.abi();
|
||||
result.sdcardSize = d.sdcardSize();
|
||||
return result;
|
||||
}
|
||||
|
||||
QString AndroidConfig::createAVD(const QString &target, const QString &name, const QString &abi, int sdcardSize, QString *error) const
|
||||
QFuture<AndroidConfig::CreateAvdInfo> AndroidConfig::createAVD(CreateAvdInfo info) const
|
||||
{
|
||||
return QtConcurrent::run(&AndroidConfig::createAVDImpl, info, androidToolPath(), androidToolEnvironment());
|
||||
}
|
||||
|
||||
AndroidConfig::CreateAvdInfo AndroidConfig::createAVDImpl(CreateAvdInfo info, Utils::FileName androidToolPath, Utils::Environment env)
|
||||
{
|
||||
QProcess proc;
|
||||
proc.setProcessEnvironment(androidToolEnvironment().toProcessEnvironment());
|
||||
proc.start(androidToolPath().toString(),
|
||||
QStringList() << QLatin1String("create") << QLatin1String("avd")
|
||||
<< QLatin1String("-t") << target
|
||||
<< QLatin1String("-n") << name
|
||||
<< QLatin1String("-b") << abi
|
||||
<< QLatin1String("-c") << QString::fromLatin1("%1M").arg(sdcardSize));
|
||||
if (!proc.waitForStarted())
|
||||
return QString();
|
||||
proc.setProcessEnvironment(env.toProcessEnvironment());
|
||||
QStringList arguments;
|
||||
arguments << QLatin1String("create") << QLatin1String("avd")
|
||||
<< QLatin1String("-t") << info.target
|
||||
<< QLatin1String("-n") << info.name
|
||||
<< QLatin1String("-b") << info.abi
|
||||
<< QLatin1String("-c") << QString::fromLatin1("%1M").arg(info.sdcardSize);
|
||||
proc.start(androidToolPath.toString(), arguments);
|
||||
if (!proc.waitForStarted()) {
|
||||
info.error = QApplication::translate("AndroidConfig", "Could not start process \"%1 %2\"")
|
||||
.arg(androidToolPath.toString(), arguments.join(QLatin1String(" ")));
|
||||
return info;
|
||||
}
|
||||
|
||||
proc.write(QByteArray("yes\n")); // yes to "Do you wish to create a custom hardware profile"
|
||||
|
||||
@@ -558,11 +566,10 @@ QString AndroidConfig::createAVD(const QString &target, const QString &name, con
|
||||
// The exit code is always 0, so we need to check stderr
|
||||
// For now assume that any output at all indicates a error
|
||||
if (!errorOutput.isEmpty()) {
|
||||
*error = errorOutput;
|
||||
return QString();
|
||||
info.error = errorOutput;
|
||||
}
|
||||
|
||||
return name;
|
||||
return info;
|
||||
}
|
||||
|
||||
bool AndroidConfig::removeAVD(const QString &name) const
|
||||
|
||||
@@ -127,9 +127,18 @@ public:
|
||||
Utils::FileName stripPath(ProjectExplorer::Abi::Architecture architecture, const QString &ndkToolChainVersion) const;
|
||||
Utils::FileName readelfPath(ProjectExplorer::Abi::Architecture architecture, const QString &ndkToolChainVersion) const;
|
||||
|
||||
class CreateAvdInfo
|
||||
{
|
||||
public:
|
||||
QString target;
|
||||
QString name;
|
||||
QString abi;
|
||||
int sdcardSize;
|
||||
QString error; // only used in the return value of createAVD
|
||||
};
|
||||
|
||||
QString createAVD(QWidget *parent, int minApiLevel = 0, QString targetArch = QString()) const;
|
||||
QString createAVD(const QString &target, const QString &name, const QString &abi, int sdcardSize, QString *error) const;
|
||||
CreateAvdInfo gatherCreateAVDInfo(QWidget *parent, int minApiLevel = 0, QString targetArch = QString()) const;
|
||||
QFuture<CreateAvdInfo> createAVD(CreateAvdInfo info) const;
|
||||
bool removeAVD(const QString &name) const;
|
||||
|
||||
QVector<AndroidDeviceInfo> connectedDevices(QString *error = 0) const;
|
||||
@@ -151,6 +160,8 @@ public:
|
||||
|
||||
SdkPlatform highestAndroidSdk() const;
|
||||
private:
|
||||
static CreateAvdInfo createAVDImpl(CreateAvdInfo info, Utils::FileName androidToolPath, Utils::Environment env);
|
||||
|
||||
Utils::FileName toolPath(ProjectExplorer::Abi::Architecture architecture, const QString &ndkToolChainVersion) const;
|
||||
Utils::FileName openJDKBinPath() const;
|
||||
int getSDKVersion(const QString &device) const;
|
||||
|
||||
@@ -31,9 +31,11 @@
|
||||
#include "androidmanager.h"
|
||||
#include "ui_androiddevicedialog.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QPainter>
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QToolTip>
|
||||
#include <QtConcurrentRun>
|
||||
|
||||
using namespace Android;
|
||||
using namespace Android::Internal;
|
||||
@@ -413,12 +415,16 @@ AndroidDeviceDialog::AndroidDeviceDialog(int apiLevel, const QString &abi, QWidg
|
||||
connect(m_ui->createAVDButton, SIGNAL(clicked()),
|
||||
this, SLOT(createAvd()));
|
||||
|
||||
connect(&m_futureWatcher, SIGNAL(finished()),
|
||||
this, SLOT(avdAdded()));
|
||||
|
||||
refreshDeviceList();
|
||||
}
|
||||
|
||||
AndroidDeviceDialog::~AndroidDeviceDialog()
|
||||
{
|
||||
delete m_ui;
|
||||
m_futureWatcher.waitForFinished();
|
||||
}
|
||||
|
||||
AndroidDeviceInfo AndroidDeviceDialog::device()
|
||||
@@ -472,11 +478,28 @@ void AndroidDeviceDialog::refreshDeviceList()
|
||||
|
||||
void AndroidDeviceDialog::createAvd()
|
||||
{
|
||||
QString avd = AndroidConfigurations::currentConfig().createAVD(this, m_apiLevel, m_abi);
|
||||
if (avd.isEmpty())
|
||||
m_ui->createAVDButton->setEnabled(false);
|
||||
AndroidConfig::CreateAvdInfo info = AndroidConfigurations::currentConfig().gatherCreateAVDInfo(this, m_apiLevel, m_abi);
|
||||
|
||||
if (info.target.isEmpty()) {
|
||||
m_ui->createAVDButton->setEnabled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
m_futureWatcher.setFuture(AndroidConfigurations::currentConfig().createAVD(info));
|
||||
}
|
||||
|
||||
void AndroidDeviceDialog::avdAdded()
|
||||
{
|
||||
m_ui->createAVDButton->setEnabled(true);
|
||||
AndroidConfig::CreateAvdInfo info = m_futureWatcher.result();
|
||||
if (!info.error.isEmpty()) {
|
||||
QMessageBox::critical(this, QApplication::translate("AndroidConfig", "Error Creating AVD"), info.error);
|
||||
return;
|
||||
}
|
||||
|
||||
refreshDeviceList();
|
||||
QModelIndex index = m_model->indexFor(avd);
|
||||
QModelIndex index = m_model->indexFor(info.name);
|
||||
m_ui->deviceView->setCurrentIndex(index);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
#include <QVector>
|
||||
#include <QDialog>
|
||||
#include <QFutureWatcher>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QModelIndex;
|
||||
@@ -63,11 +64,13 @@ private slots:
|
||||
void createAvd();
|
||||
void clickedOnView(const QModelIndex &idx);
|
||||
void showHelp();
|
||||
void avdAdded();
|
||||
private:
|
||||
AndroidDeviceModel *m_model;
|
||||
Ui::AndroidDeviceDialog *m_ui;
|
||||
int m_apiLevel;
|
||||
QString m_abi;
|
||||
QFutureWatcher<AndroidConfig::CreateAvdInfo> m_futureWatcher;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
#include <QMessageBox>
|
||||
#include <QModelIndex>
|
||||
#include <QtCore/QUrl>
|
||||
#include <QtConcurrentRun>
|
||||
|
||||
namespace Android {
|
||||
namespace Internal {
|
||||
@@ -64,6 +65,15 @@ void AvdModel::setAvdList(const QVector<AndroidDeviceInfo> &list)
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QModelIndex AvdModel::indexForAvdName(const QString &avdName) const
|
||||
{
|
||||
for (int i = 0; i < m_list.size(); ++i) {
|
||||
if (m_list.at(i).serialNumber == avdName)
|
||||
return index(i, 0);
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QString AvdModel::avdName(const QModelIndex &index) const
|
||||
{
|
||||
return m_list.at(index.row()).serialNumber;
|
||||
@@ -144,11 +154,15 @@ AndroidSettingsWidget::AndroidSettingsWidget(QWidget *parent)
|
||||
|
||||
check(All);
|
||||
applyToUi(All);
|
||||
|
||||
connect(&m_futureWatcher, SIGNAL(finished()),
|
||||
this, SLOT(avdAdded()));
|
||||
}
|
||||
|
||||
AndroidSettingsWidget::~AndroidSettingsWidget()
|
||||
{
|
||||
delete m_ui;
|
||||
m_futureWatcher.waitForFinished();
|
||||
}
|
||||
|
||||
void AndroidSettingsWidget::check(AndroidSettingsWidget::Mode mode)
|
||||
@@ -468,9 +482,28 @@ void AndroidSettingsWidget::openOpenJDKDownloadUrl()
|
||||
|
||||
void AndroidSettingsWidget::addAVD()
|
||||
{
|
||||
m_androidConfig.createAVD(this);
|
||||
m_ui->AVDAddPushButton->setEnabled(false);
|
||||
AndroidConfig::CreateAvdInfo info = m_androidConfig.gatherCreateAVDInfo(this);
|
||||
|
||||
if (info.target.isEmpty()) {
|
||||
m_ui->AVDAddPushButton->setEnabled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
m_futureWatcher.setFuture(m_androidConfig.createAVD(info));
|
||||
}
|
||||
|
||||
void AndroidSettingsWidget::avdAdded()
|
||||
{
|
||||
m_ui->AVDAddPushButton->setEnabled(true);
|
||||
AndroidConfig::CreateAvdInfo info = m_futureWatcher.result();
|
||||
if (!info.error.isEmpty()) {
|
||||
QMessageBox::critical(this, QApplication::translate("AndroidConfig", "Error Creating AVD"), info.error);
|
||||
return;
|
||||
}
|
||||
|
||||
m_AVDModel.setAvdList(m_androidConfig.androidVirtualDevices());
|
||||
avdActivated(m_ui->AVDTableView->currentIndex());
|
||||
m_ui->AVDTableView->setCurrentIndex(m_AVDModel.indexForAvdName(info.name));
|
||||
}
|
||||
|
||||
void AndroidSettingsWidget::removeAVD()
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <QString>
|
||||
#include <QWidget>
|
||||
#include <QAbstractTableModel>
|
||||
#include <QFutureWatcher>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class Ui_AndroidSettingsWidget;
|
||||
@@ -50,6 +51,7 @@ class AvdModel: public QAbstractTableModel
|
||||
public:
|
||||
void setAvdList(const QVector<AndroidDeviceInfo> &list);
|
||||
QString avdName(const QModelIndex &index) const;
|
||||
QModelIndex indexForAvdName(const QString &avdName) const;
|
||||
|
||||
protected:
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||
@@ -86,6 +88,7 @@ private slots:
|
||||
void openAntDownloadUrl();
|
||||
void openOpenJDKDownloadUrl();
|
||||
void addAVD();
|
||||
void avdAdded();
|
||||
void removeAVD();
|
||||
void startAVD();
|
||||
void avdActivated(QModelIndex);
|
||||
@@ -111,6 +114,7 @@ private:
|
||||
Ui_AndroidSettingsWidget *m_ui;
|
||||
AndroidConfig m_androidConfig;
|
||||
AvdModel m_AVDModel;
|
||||
QFutureWatcher<AndroidConfig::CreateAvdInfo> m_futureWatcher;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
Reference in New Issue
Block a user