forked from qt-creator/qt-creator
Android: Implement device selection dialog
Change-Id: I1f4f3065a09837414429bbfc68110ada85ea174a Reviewed-by: BogDan Vatra <bogdan@kde.org>
This commit is contained in:
@@ -41,7 +41,8 @@ HEADERS += \
|
||||
androidmanifesteditorfactory.h \
|
||||
androidmanifesteditor.h \
|
||||
androidmanifesteditorwidget.h \
|
||||
androidmanifestdocument.h
|
||||
androidmanifestdocument.h \
|
||||
androiddevicedialog.h
|
||||
|
||||
SOURCES += \
|
||||
androidconfigurations.cpp \
|
||||
@@ -77,14 +78,16 @@ SOURCES += \
|
||||
androidmanifesteditorfactory.cpp \
|
||||
androidmanifesteditor.cpp \
|
||||
androidmanifesteditorwidget.cpp \
|
||||
androidmanifestdocument.cpp
|
||||
androidmanifestdocument.cpp \
|
||||
androiddevicedialog.cpp
|
||||
|
||||
FORMS += \
|
||||
androidsettingswidget.ui \
|
||||
androidpackagecreationwidget.ui \
|
||||
androiddeploystepwidget.ui \
|
||||
addnewavddialog.ui \
|
||||
androidcreatekeystorecertificate.ui
|
||||
androidcreatekeystorecertificate.ui \
|
||||
androiddevicedialog.ui
|
||||
|
||||
exists(../../shared/qbs/qbs.pro) {
|
||||
HEADERS += \
|
||||
|
||||
@@ -38,6 +38,9 @@ QtcPlugin {
|
||||
"androidcreatekeystorecertificate.ui",
|
||||
"androiddebugsupport.cpp",
|
||||
"androiddebugsupport.h",
|
||||
"androiddevicedialog.cpp",
|
||||
"androiddevicedialog.h",
|
||||
"androiddevicedialog.ui",
|
||||
"androiddeployconfiguration.cpp",
|
||||
"androiddeployconfiguration.h",
|
||||
"androiddeploystep.cpp",
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "androidgdbserverkitinformation.h"
|
||||
#include "ui_addnewavddialog.h"
|
||||
#include "androidqtversion.h"
|
||||
#include "androiddevicedialog.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <utils/hostosinfo.h>
|
||||
@@ -42,6 +43,7 @@
|
||||
#include <projectexplorer/kitinformation.h>
|
||||
#include <projectexplorer/devicesupport/devicemanager.h>
|
||||
#include <projectexplorer/toolchainmanager.h>
|
||||
#include <projectexplorer/session.h>
|
||||
#include <debugger/debuggerkitinformation.h>
|
||||
#include <qtsupport/baseqtversion.h>
|
||||
#include <qtsupport/qtkitinformation.h>
|
||||
@@ -76,6 +78,7 @@ namespace {
|
||||
const QLatin1String KeystoreLocationKey("KeystoreLocation");
|
||||
const QLatin1String AutomaticKitCreationKey("AutomatiKitCreation");
|
||||
const QLatin1String MakeExtraSearchDirectory("MakeExtraSearchDirectory");
|
||||
const QLatin1String DefaultDevice("DefaultDevice");
|
||||
const QLatin1String PartitionSizeKey("PartitionSize");
|
||||
const QLatin1String ToolchainHostKey("ToolchainHost");
|
||||
const QLatin1String ArmToolchainPrefix("arm-linux-androideabi");
|
||||
@@ -99,12 +102,11 @@ namespace {
|
||||
{
|
||||
if (dev1.serialNumber.contains(QLatin1String("????")) == dev2.serialNumber.contains(QLatin1String("????")))
|
||||
return !dev1.serialNumber.contains(QLatin1String("????"));
|
||||
bool dev1IsEmulator = dev1.serialNumber.startsWith(QLatin1String("emulator"));
|
||||
bool dev2IsEmulator = dev2.serialNumber.startsWith(QLatin1String("emulator"));
|
||||
if (dev1IsEmulator != dev2IsEmulator)
|
||||
return !dev1IsEmulator;
|
||||
if (dev1.type != dev2.type)
|
||||
return dev1.type == AndroidDeviceInfo::Hardware;
|
||||
if (dev1.sdk != dev2.sdk)
|
||||
return dev1.sdk < dev2.sdk;
|
||||
|
||||
return dev1.serialNumber < dev2.serialNumber;
|
||||
}
|
||||
}
|
||||
@@ -380,38 +382,53 @@ FileName AndroidConfigurations::zipalignPath() const
|
||||
return path.appendPath(QLatin1String("tools/zipalign" QTC_HOST_EXE_SUFFIX));
|
||||
}
|
||||
|
||||
QString AndroidConfigurations::getDeployDeviceSerialNumber(int *apiLevel, const QString &abi, QString *error) const
|
||||
AndroidDeviceInfo AndroidConfigurations::showDeviceDialog(ProjectExplorer::Project *project, int apiLevel, const QString &abi)
|
||||
{
|
||||
QVector<AndroidDeviceInfo> devices = connectedDevices(error);
|
||||
QString serialNumber = defaultDevice(project, abi);
|
||||
if (!serialNumber.isEmpty()) {
|
||||
// search for that device
|
||||
foreach (const AndroidDeviceInfo &info, AndroidConfigurations::instance().connectedDevices())
|
||||
if (info.serialNumber == serialNumber
|
||||
&& info.sdk >= apiLevel)
|
||||
return info;
|
||||
|
||||
foreach (AndroidDeviceInfo device, devices) {
|
||||
if (device.unauthorized) {
|
||||
if (error) {
|
||||
*error += tr("Skipping %1: Unauthorized. Please check the confirmation dialog on your device..").arg(device.serialNumber);
|
||||
*error += QLatin1Char('\n');
|
||||
}
|
||||
} else if (!device.cpuAbi.contains(abi)) {
|
||||
if (error) {
|
||||
*error += tr("Skipping %1: ABI is incompatible, device supports ABIs: %2.")
|
||||
.arg(getProductModel(device.serialNumber))
|
||||
.arg(device.cpuAbi.join(QLatin1String(" ")));
|
||||
*error += QLatin1Char('\n');
|
||||
}
|
||||
} else if (device.sdk < *apiLevel) {
|
||||
if (error) {
|
||||
*error += tr("Skipping %1: API Level of device is: %2.")
|
||||
.arg(getProductModel(device.serialNumber))
|
||||
.arg(device.sdk);
|
||||
*error += QLatin1Char('\n');
|
||||
}
|
||||
} else {
|
||||
if (error)
|
||||
error->clear(); // no errors if we found a device
|
||||
*apiLevel = device.sdk;
|
||||
return device.serialNumber;
|
||||
}
|
||||
foreach (const AndroidDeviceInfo &info, AndroidConfigurations::instance().androidVirtualDevices())
|
||||
if (info.serialNumber == serialNumber
|
||||
&& info.sdk >= apiLevel)
|
||||
return info;
|
||||
}
|
||||
return QString();
|
||||
|
||||
AndroidDeviceDialog dialog(apiLevel, abi);
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
AndroidDeviceInfo info = dialog.device();
|
||||
if (dialog.saveDeviceSelection()) {
|
||||
if (!info.serialNumber.isEmpty())
|
||||
AndroidConfigurations::instance().setDefaultDevice(project, abi, info.serialNumber);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
return AndroidDeviceInfo();
|
||||
}
|
||||
|
||||
void AndroidConfigurations::clearDefaultDevices(ProjectExplorer::Project *project)
|
||||
{
|
||||
if (m_defaultDeviceForAbi.contains(project))
|
||||
m_defaultDeviceForAbi.remove(project);
|
||||
}
|
||||
|
||||
void AndroidConfigurations::setDefaultDevice(ProjectExplorer::Project *project, const QString &abi, const QString &serialNumber)
|
||||
{
|
||||
m_defaultDeviceForAbi[project][abi] = serialNumber;
|
||||
}
|
||||
|
||||
QString AndroidConfigurations::defaultDevice(Project *project, const QString &abi) const
|
||||
{
|
||||
if (!m_defaultDeviceForAbi.contains(project))
|
||||
return QString();
|
||||
const QMap<QString, QString> &map = m_defaultDeviceForAbi.value(project);
|
||||
if (!map.contains(abi))
|
||||
return QString();
|
||||
return map.value(abi);
|
||||
}
|
||||
|
||||
QVector<AndroidDeviceInfo> AndroidConfigurations::connectedDevices(QString *error) const
|
||||
@@ -435,6 +452,7 @@ QVector<AndroidDeviceInfo> AndroidConfigurations::connectedDevices(QString *erro
|
||||
const QString deviceType = QString::fromLatin1(device.mid(device.indexOf('\t'))).trimmed();
|
||||
AndroidDeviceInfo dev;
|
||||
dev.serialNumber = serialNo;
|
||||
dev.type = serialNo.startsWith(QLatin1String("emulator")) ? AndroidDeviceInfo::Emulator : AndroidDeviceInfo::Hardware;
|
||||
dev.sdk = getSDKVersion(dev.serialNumber);
|
||||
dev.cpuAbi = getAbis(dev.serialNumber);
|
||||
dev.unauthorized = (deviceType == QLatin1String("unauthorized"));
|
||||
@@ -546,6 +564,7 @@ QVector<AndroidDeviceInfo> AndroidConfigurations::androidVirtualDevices() const
|
||||
if (dev.cpuAbi == QStringList(QLatin1String("armeabi-v7a")))
|
||||
dev.cpuAbi << QLatin1String("armeabi");
|
||||
dev.unauthorized = false;
|
||||
dev.type = AndroidDeviceInfo::Emulator;
|
||||
devices.push_back(dev);
|
||||
}
|
||||
qSort(devices.begin(), devices.end(), androidDevicesLessThan);
|
||||
@@ -553,19 +572,6 @@ QVector<AndroidDeviceInfo> AndroidConfigurations::androidVirtualDevices() const
|
||||
return devices;
|
||||
}
|
||||
|
||||
QString AndroidConfigurations::findAvd(int *apiLevel, const QString &cpuAbi)
|
||||
{
|
||||
QVector<AndroidDeviceInfo> devices = androidVirtualDevices();
|
||||
foreach (const AndroidDeviceInfo &device, devices) {
|
||||
// take first emulator how supports this package
|
||||
if (device.sdk >= *apiLevel && device.cpuAbi.contains(cpuAbi)) {
|
||||
*apiLevel = device.sdk;
|
||||
return device.serialNumber;
|
||||
}
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString AndroidConfigurations::startAVD(const QString &name, int apiLevel, QString cpuAbi) const
|
||||
{
|
||||
if (startAVDAsync(name))
|
||||
@@ -643,6 +649,8 @@ int AndroidConfigurations::getSDKVersion(const QString &device) const
|
||||
//!
|
||||
QString AndroidConfigurations::getProductModel(const QString &device) const
|
||||
{
|
||||
if (m_serialNumberToDeviceName.contains(device))
|
||||
return m_serialNumberToDeviceName.value(device);
|
||||
// workaround for '????????????' serial numbers
|
||||
QStringList arguments = AndroidDeviceInfo::adbSelector(device);
|
||||
arguments << QLatin1String("shell") << QLatin1String("getprop")
|
||||
@@ -657,6 +665,8 @@ QString AndroidConfigurations::getProductModel(const QString &device) const
|
||||
QString model = QString::fromLocal8Bit(adbProc.readAll().trimmed());
|
||||
if (model.isEmpty())
|
||||
return device;
|
||||
if (!device.startsWith(QLatin1String("????")))
|
||||
m_serialNumberToDeviceName.insert(device, model);
|
||||
return model;
|
||||
}
|
||||
|
||||
@@ -856,6 +866,9 @@ AndroidConfigurations::AndroidConfigurations(QObject *parent)
|
||||
{
|
||||
load();
|
||||
updateAvailablePlatforms();
|
||||
|
||||
connect(ProjectExplorer::SessionManager::instance(), SIGNAL(projectRemoved(ProjectExplorer::Project*)),
|
||||
this, SLOT(clearDefaultDevices(ProjectExplorer::Project*)));
|
||||
}
|
||||
|
||||
void AndroidConfigurations::load()
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QVector>
|
||||
#include <QHash>
|
||||
#include <QMap>
|
||||
#include <projectexplorer/abi.h>
|
||||
#include <utils/fileutils.h>
|
||||
|
||||
@@ -41,6 +43,8 @@ QT_BEGIN_NAMESPACE
|
||||
class QSettings;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace ProjectExplorer { class Project; }
|
||||
|
||||
namespace Android {
|
||||
namespace Internal {
|
||||
|
||||
@@ -68,6 +72,8 @@ struct AndroidDeviceInfo
|
||||
QStringList cpuAbi;
|
||||
int sdk;
|
||||
bool unauthorized;
|
||||
enum AndroidDeviceType { Hardware, Emulator };
|
||||
AndroidDeviceType type;
|
||||
|
||||
static QStringList adbSelector(const QString &serialNumber);
|
||||
};
|
||||
@@ -93,13 +99,11 @@ public:
|
||||
Utils::FileName zipalignPath() const;
|
||||
Utils::FileName stripPath(ProjectExplorer::Abi::Architecture architecture, const QString &ndkToolChainVersion) const;
|
||||
Utils::FileName readelfPath(ProjectExplorer::Abi::Architecture architecture, const QString &ndkToolChainVersion) const;
|
||||
QString getDeployDeviceSerialNumber(int *apiLevel, const QString &abi, QString *error = 0) const;
|
||||
QString createAVD(int minApiLevel = 0, QString targetArch = QString()) const;
|
||||
QString createAVD(const QString &target, const QString &name, const QString &abi, int sdcardSize) const;
|
||||
bool removeAVD(const QString &name) const;
|
||||
QVector<AndroidDeviceInfo> connectedDevices(QString *error = 0) const;
|
||||
QVector<AndroidDeviceInfo> androidVirtualDevices() const;
|
||||
QString findAvd(int *apiLevel, const QString &cpuAbi);
|
||||
QString startAVD(const QString &name, int apiLevel, QString cpuAbi) const;
|
||||
bool startAVDAsync(const QString &avdName) const;
|
||||
QString waitForAvd(int apiLevel, const QString &cpuAbi) const;
|
||||
@@ -117,6 +121,12 @@ public:
|
||||
QString getProductModel(const QString &device) const;
|
||||
bool hasFinishedBooting(const QString &device) const;
|
||||
|
||||
AndroidDeviceInfo showDeviceDialog(ProjectExplorer::Project *project, int apiLevel, const QString &abi);
|
||||
void setDefaultDevice(ProjectExplorer::Project *project, const QString &abi, const QString &serialNumber); // serial number or avd name
|
||||
QString defaultDevice(ProjectExplorer::Project *project, const QString &abi) const; // serial number or avd name
|
||||
public slots:
|
||||
void clearDefaultDevices(ProjectExplorer::Project *project);
|
||||
|
||||
signals:
|
||||
void updated();
|
||||
|
||||
@@ -140,6 +150,9 @@ private:
|
||||
static AndroidConfigurations *m_instance;
|
||||
AndroidConfig m_config;
|
||||
QVector<int> m_availablePlatforms;
|
||||
mutable QHash<QString, QString> m_serialNumberToDeviceName;
|
||||
|
||||
QMap<ProjectExplorer::Project *, QMap<QString, QString> > m_defaultDeviceForAbi;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "androidrunconfiguration.h"
|
||||
#include "androidmanager.h"
|
||||
#include "androidtoolchain.h"
|
||||
#include "androiddevicedialog.h"
|
||||
|
||||
#include <coreplugin/messagemanager.h>
|
||||
#include <projectexplorer/buildconfiguration.h>
|
||||
@@ -102,31 +103,15 @@ bool AndroidDeployStep::init()
|
||||
m_deviceAPILevel = AndroidManager::minimumSDK(target());
|
||||
m_targetArch = AndroidManager::targetArch(target());
|
||||
|
||||
if (m_deviceAPILevel == 0) // minimum api level is unset
|
||||
writeOutput(tr("Please wait, searching for a suitable device for target: ABI:%2").arg(m_targetArch));
|
||||
else
|
||||
writeOutput(tr("Please wait, searching for a suitable device for target: API %1, ABI:%2").arg(m_deviceAPILevel).arg(m_targetArch));
|
||||
|
||||
QString error;
|
||||
m_deviceSerialNumber = AndroidConfigurations::instance().getDeployDeviceSerialNumber(&m_deviceAPILevel, m_targetArch, &error);
|
||||
if (!error.isEmpty())
|
||||
writeOutput(error);
|
||||
|
||||
m_avdName.clear();
|
||||
if (m_deviceSerialNumber.isEmpty()) {
|
||||
writeOutput(tr("Falling back to Android virtual machine device."));
|
||||
m_avdName = AndroidConfigurations::instance().findAvd(&m_deviceAPILevel, m_targetArch);
|
||||
if (m_avdName.isEmpty())
|
||||
m_avdName = AndroidConfigurations::instance().createAVD(m_deviceAPILevel, m_targetArch);
|
||||
if (m_avdName.isEmpty()) // user canceled
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_deviceSerialNumber.isEmpty() && m_avdName.isEmpty()) {
|
||||
m_deviceSerialNumber.clear();
|
||||
raiseError(tr("Cannot deploy: no devices or emulators found for your package."));
|
||||
AndroidDeviceInfo info = AndroidConfigurations::instance().showDeviceDialog(project(), m_deviceAPILevel, m_targetArch);
|
||||
if (info.serialNumber.isEmpty()) // aborted
|
||||
return false;
|
||||
}
|
||||
|
||||
m_deviceAPILevel = info.sdk;
|
||||
m_deviceSerialNumber = info.serialNumber;
|
||||
|
||||
if (info.type == AndroidDeviceInfo::Emulator)
|
||||
m_avdName = m_deviceSerialNumber;
|
||||
|
||||
QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target()->kit());
|
||||
if (!version)
|
||||
@@ -212,20 +197,20 @@ void AndroidDeployStep::cleanLibsOnDevice()
|
||||
{
|
||||
const QString targetArch = AndroidManager::targetArch(target());
|
||||
int deviceAPILevel = AndroidManager::minimumSDK(target());
|
||||
QString deviceSerialNumber = AndroidConfigurations::instance().getDeployDeviceSerialNumber(&deviceAPILevel, targetArch);
|
||||
if (deviceSerialNumber.isEmpty()) {
|
||||
QString avdName = AndroidConfigurations::instance().findAvd(&deviceAPILevel, targetArch);
|
||||
if (avdName.isEmpty()) {
|
||||
// No avd found, don't create one just error out
|
||||
MessageManager::write(tr("Could not find a device."));
|
||||
return;
|
||||
}
|
||||
deviceSerialNumber = AndroidConfigurations::instance().startAVD(avdName, deviceAPILevel, targetArch);
|
||||
}
|
||||
if (!deviceSerialNumber.length()) {
|
||||
MessageManager::write(tr("Could not run adb. No device found."));
|
||||
|
||||
AndroidDeviceInfo info = AndroidConfigurations::instance().showDeviceDialog(project(), m_deviceAPILevel, m_targetArch);
|
||||
if (info.serialNumber.isEmpty()) // aborted
|
||||
return;
|
||||
|
||||
deviceAPILevel = info.sdk;
|
||||
QString deviceSerialNumber = info.serialNumber;
|
||||
|
||||
if (info.type == AndroidDeviceInfo::Emulator) {
|
||||
deviceSerialNumber = AndroidConfigurations::instance().startAVD(deviceSerialNumber, deviceAPILevel, targetArch);
|
||||
if (deviceSerialNumber.isEmpty())
|
||||
MessageManager::write(tr("Starting android virtual device failed."));
|
||||
}
|
||||
|
||||
QProcess *process = new QProcess(this);
|
||||
QStringList arguments = AndroidDeviceInfo::adbSelector(deviceSerialNumber);
|
||||
arguments << QLatin1String("shell") << QLatin1String("rm") << QLatin1String("-r") << QLatin1String("/data/local/tmp/qt");
|
||||
@@ -268,18 +253,17 @@ void AndroidDeployStep::installQASIPackage(const QString &packagePath)
|
||||
{
|
||||
const QString targetArch = AndroidManager::targetArch(target());
|
||||
int deviceAPILevel = AndroidManager::minimumSDK(target());
|
||||
QString deviceSerialNumber = AndroidConfigurations::instance().getDeployDeviceSerialNumber(&deviceAPILevel, targetArch);
|
||||
if (deviceSerialNumber.isEmpty()) {
|
||||
QString avdName = AndroidConfigurations::instance().findAvd(&deviceAPILevel, targetArch);
|
||||
if (avdName.isEmpty()) {
|
||||
MessageManager::write(tr("No device found."));
|
||||
return;
|
||||
}
|
||||
deviceSerialNumber = AndroidConfigurations::instance().startAVD(avdName, deviceAPILevel, targetArch);
|
||||
}
|
||||
if (!deviceSerialNumber.length()) {
|
||||
MessageManager::write(tr("Could not run adb. No device found."));
|
||||
|
||||
AndroidDeviceInfo info = AndroidConfigurations::instance().showDeviceDialog(project(), m_deviceAPILevel, m_targetArch);
|
||||
if (info.serialNumber.isEmpty()) // aborted
|
||||
return;
|
||||
|
||||
deviceAPILevel = info.sdk;
|
||||
QString deviceSerialNumber = info.serialNumber;
|
||||
if (info.type == AndroidDeviceInfo::Emulator) {
|
||||
deviceSerialNumber = AndroidConfigurations::instance().startAVD(deviceSerialNumber, deviceAPILevel, targetArch);
|
||||
if (deviceSerialNumber.isEmpty())
|
||||
MessageManager::write(tr("Starting android virtual device failed."));
|
||||
}
|
||||
|
||||
QProcess *process = new QProcess(this);
|
||||
|
||||
@@ -55,6 +55,7 @@ AndroidDeployStepWidget::AndroidDeployStepWidget(AndroidDeployStep *step) :
|
||||
|
||||
connect(ui->chooseButton, SIGNAL(clicked()), SLOT(setQASIPackagePath()));
|
||||
connect(ui->cleanLibsPushButton, SIGNAL(clicked()), SLOT(cleanLibsOnDevice()));
|
||||
connect(ui->resetDefaultDevices, SIGNAL(clicked()), SLOT(resetDefaultDevices()));
|
||||
|
||||
connect(m_step, SIGNAL(deployOptionsChanged()),
|
||||
this, SLOT(deployOptionsChanged()));
|
||||
@@ -125,5 +126,10 @@ void AndroidDeployStepWidget::cleanLibsOnDevice()
|
||||
m_step->cleanLibsOnDevice();
|
||||
}
|
||||
|
||||
void AndroidDeployStepWidget::resetDefaultDevices()
|
||||
{
|
||||
AndroidConfigurations::instance().clearDefaultDevices(m_step->project());
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Qt4ProjectManager
|
||||
|
||||
@@ -55,6 +55,7 @@ private slots:
|
||||
|
||||
void setQASIPackagePath();
|
||||
void cleanLibsOnDevice();
|
||||
void resetDefaultDevices();
|
||||
|
||||
void deployOptionsChanged();
|
||||
private:
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>678</width>
|
||||
<width>682</width>
|
||||
<height>155</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -69,21 +69,21 @@ The APK will not be usable on any other device.</string>
|
||||
<string>Advanced Actions</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<item row="1" column="0">
|
||||
<widget class="QPushButton" name="cleanLibsPushButton">
|
||||
<property name="text">
|
||||
<string>Clean Temporary Libraries Directory on Device</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item row="2" column="0">
|
||||
<widget class="QPushButton" name="chooseButton">
|
||||
<property name="text">
|
||||
<string>Install Ministro from APK</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item row="3" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
@@ -96,6 +96,13 @@ The APK will not be usable on any other device.</string>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="resetDefaultDevices">
|
||||
<property name="text">
|
||||
<string>Reset Default Devices</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
472
src/plugins/android/androiddevicedialog.cpp
Normal file
472
src/plugins/android/androiddevicedialog.cpp
Normal file
@@ -0,0 +1,472 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** 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 "androiddevicedialog.h"
|
||||
#include "androidmanager.h"
|
||||
#include "ui_androiddevicedialog.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
using namespace Android;
|
||||
using namespace Android::Internal;
|
||||
|
||||
namespace Android {
|
||||
namespace Internal {
|
||||
|
||||
// yeah, writing tree models is fun!
|
||||
class AndroidDeviceModelNode
|
||||
{
|
||||
public:
|
||||
AndroidDeviceModelNode(AndroidDeviceModelNode *parent, const AndroidDeviceInfo &info, const QString &incompatibleReason = QString())
|
||||
: m_parent(parent), m_info(info), m_incompatibleReason(incompatibleReason)
|
||||
{
|
||||
if (m_parent)
|
||||
m_parent->m_children.append(this);
|
||||
}
|
||||
|
||||
AndroidDeviceModelNode(AndroidDeviceModelNode *parent, const QString &displayName)
|
||||
: m_parent(parent), m_displayName(displayName)
|
||||
{
|
||||
if (m_parent)
|
||||
m_parent->m_children.append(this);
|
||||
}
|
||||
|
||||
~AndroidDeviceModelNode()
|
||||
{
|
||||
if (m_parent)
|
||||
m_parent->m_children.removeOne(this);
|
||||
QList<AndroidDeviceModelNode *> children = m_children;
|
||||
qDeleteAll(children);
|
||||
}
|
||||
|
||||
AndroidDeviceModelNode *parent() const
|
||||
{
|
||||
return m_parent;
|
||||
}
|
||||
|
||||
QList<AndroidDeviceModelNode *> children() const
|
||||
{
|
||||
return m_children;
|
||||
}
|
||||
|
||||
AndroidDeviceInfo deviceInfo() const
|
||||
{
|
||||
return m_info;
|
||||
}
|
||||
|
||||
QString displayName() const
|
||||
{
|
||||
return m_displayName;
|
||||
}
|
||||
|
||||
QString incompatibleReason() const
|
||||
{
|
||||
return m_incompatibleReason;
|
||||
}
|
||||
|
||||
private:
|
||||
AndroidDeviceModelNode *m_parent;
|
||||
AndroidDeviceInfo m_info;
|
||||
QString m_incompatibleReason;
|
||||
QString m_displayName;
|
||||
QList<AndroidDeviceModelNode *> m_children;
|
||||
};
|
||||
|
||||
class AndroidDeviceModelDelegate : public QStyledItemDelegate
|
||||
{
|
||||
public:
|
||||
AndroidDeviceModelDelegate(QObject * parent = 0)
|
||||
: QStyledItemDelegate(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
~AndroidDeviceModelDelegate()
|
||||
{
|
||||
}
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
QStyleOptionViewItemV4 opt = option;
|
||||
initStyleOption(&opt, index);
|
||||
painter->save();
|
||||
|
||||
AndroidDeviceModelNode *node = static_cast<AndroidDeviceModelNode *>(index.internalPointer());
|
||||
AndroidDeviceInfo device = node->deviceInfo();
|
||||
|
||||
painter->setPen(Qt::NoPen);
|
||||
|
||||
// Paint Background
|
||||
QPalette palette = opt.palette; // we always draw enabled
|
||||
palette.setCurrentColorGroup(QPalette::Active);
|
||||
bool selected = opt.state & QStyle::State_Selected;
|
||||
QColor backgroundColor = selected ? palette.highlight().color()
|
||||
: palette.background().color();
|
||||
painter->setBrush(backgroundColor);
|
||||
|
||||
painter->drawRect(0, opt.rect.top(), opt.rect.width() + opt.rect.left(), opt.rect.height());
|
||||
|
||||
QColor textColor;
|
||||
// Set Text Color
|
||||
if (opt.state & QStyle::State_Selected)
|
||||
textColor = palette.highlightedText().color();
|
||||
else
|
||||
textColor = palette.text().color();
|
||||
painter->setPen(textColor);
|
||||
|
||||
if (!node->displayName().isEmpty()) {
|
||||
QIcon icon(QLatin1String(":/core/images/darkarrowdown.png"));
|
||||
int size = opt.rect.bottom() - opt.rect.top();
|
||||
QPixmap pixmap = icon.pixmap(size, size);
|
||||
painter->drawPixmap((size - pixmap.width()) / 2, opt.rect.top() + (size - pixmap.height()) / 2, pixmap);
|
||||
|
||||
// We have a top level node
|
||||
QFont font = opt.font;
|
||||
font.setPointSizeF(font.pointSizeF() * 1.2);
|
||||
font.setBold(true);
|
||||
|
||||
QFontMetrics fm(font);
|
||||
painter->setFont(font);
|
||||
int top = (opt.rect.bottom() + opt.rect.top() - fm.height()) / 2 + fm.ascent();
|
||||
painter->drawText(size, top, node->displayName());
|
||||
} else {
|
||||
QIcon icon(device.type == AndroidDeviceInfo::Hardware ? QLatin1String(":/projectexplorer/images/MaemoDevice.png")
|
||||
: QLatin1String(":/projectexplorer/images/Simulator.png"));
|
||||
int size = opt.rect.bottom() - opt.rect.top() - 12;
|
||||
QPixmap pixmap = icon.pixmap(size, size);
|
||||
painter->drawPixmap(6 + (size - pixmap.width()) / 2, opt.rect.top() + 6 + (size - pixmap.width()) / 2, pixmap);
|
||||
|
||||
QFontMetrics fm(opt.font);
|
||||
// TopLeft
|
||||
QString topLeft = device.serialNumber;
|
||||
if (device.type == AndroidDeviceInfo::Hardware)
|
||||
topLeft = AndroidConfigurations::instance().getProductModel(device.serialNumber);
|
||||
painter->drawText(size + 12, 2 + opt.rect.top() + fm.ascent(), topLeft);
|
||||
|
||||
QString topRight = device.serialNumber;
|
||||
// topRight
|
||||
if (device.type == AndroidDeviceInfo::Hardware) // otherwise it's not very informative
|
||||
painter->drawText(opt.rect.right() - fm.width(topRight) - 6 , 2 + opt.rect.top() + fm.ascent(), topRight);
|
||||
|
||||
// Directory
|
||||
QColor mix;
|
||||
mix.setRgbF(0.7 * textColor.redF() + 0.3 * backgroundColor.redF(),
|
||||
0.7 * textColor.greenF() + 0.3 * backgroundColor.greenF(),
|
||||
0.7 * textColor.blueF() + 0.3 * backgroundColor.blueF());
|
||||
painter->setPen(mix);
|
||||
|
||||
QString lineText;
|
||||
if (node->incompatibleReason().isEmpty()) {
|
||||
lineText = AndroidManager::androidNameForApiLevel(device.sdk) + QLatin1String(" ");
|
||||
lineText += tr("ABI:") + device.cpuAbi.join(QLatin1String(" "));
|
||||
} else {
|
||||
lineText = node->incompatibleReason();
|
||||
}
|
||||
painter->drawText(size + 12, opt.rect.top() + fm.ascent() + fm.height() + 6, lineText);
|
||||
}
|
||||
|
||||
// Separator lines
|
||||
painter->setPen(QColor::fromRgb(150,150,150));
|
||||
painter->drawLine(0, opt.rect.bottom(), opt.rect.right(), opt.rect.bottom());
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
QStyleOptionViewItemV4 opt = option;
|
||||
initStyleOption(&opt, index);
|
||||
|
||||
QFontMetrics fm(option.font);
|
||||
QSize s;
|
||||
s.setWidth(option.rect.width());
|
||||
s.setHeight(fm.height() * 2 + 10);
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
class AndroidDeviceModel : public QAbstractItemModel
|
||||
{
|
||||
public:
|
||||
AndroidDeviceModel(int apiLevel, const QString &abi);
|
||||
QModelIndex index(int row, int column,
|
||||
const QModelIndex &parent = QModelIndex()) const;
|
||||
QModelIndex parent(const QModelIndex &child) const;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
|
||||
AndroidDeviceInfo device(QModelIndex index);
|
||||
void setDevices(const QVector<AndroidDeviceInfo> &devices);
|
||||
|
||||
QModelIndex indexFor(const QString &serial);
|
||||
private:
|
||||
int m_apiLevel;
|
||||
QString m_abi;
|
||||
AndroidDeviceModelNode *m_root;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
/////////////////
|
||||
// AndroidDeviceModel
|
||||
/////////////////
|
||||
AndroidDeviceModel::AndroidDeviceModel(int apiLevel, const QString &abi)
|
||||
: m_apiLevel(apiLevel), m_abi(abi), m_root(0)
|
||||
{
|
||||
}
|
||||
|
||||
QModelIndex AndroidDeviceModel::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
if (column != 0)
|
||||
return QModelIndex();
|
||||
|
||||
if (!m_root)
|
||||
return QModelIndex();
|
||||
|
||||
if (!parent.isValid()) {
|
||||
if (row < 0 || row >= m_root->children().count())
|
||||
return QModelIndex();
|
||||
return createIndex(row, column, m_root->children().at(row));
|
||||
}
|
||||
|
||||
AndroidDeviceModelNode *node = static_cast<AndroidDeviceModelNode *>(parent.internalPointer());
|
||||
if (row < node->children().count())
|
||||
return createIndex(row, column, node->children().at(row));
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QModelIndex AndroidDeviceModel::parent(const QModelIndex &child) const
|
||||
{
|
||||
if (!child.isValid())
|
||||
return QModelIndex();
|
||||
if (!m_root)
|
||||
return QModelIndex();
|
||||
AndroidDeviceModelNode *node = static_cast<AndroidDeviceModelNode *>(child.internalPointer());
|
||||
if (node == m_root)
|
||||
return QModelIndex();
|
||||
AndroidDeviceModelNode *parent = node->parent();
|
||||
|
||||
if (parent == m_root)
|
||||
return QModelIndex();
|
||||
|
||||
AndroidDeviceModelNode *grandParent = parent->parent();
|
||||
return createIndex(grandParent->children().indexOf(parent), 0, parent);
|
||||
}
|
||||
|
||||
int AndroidDeviceModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (!m_root)
|
||||
return 0;
|
||||
if (!parent.isValid())
|
||||
return m_root->children().count();
|
||||
AndroidDeviceModelNode *node = static_cast<AndroidDeviceModelNode *>(parent.internalPointer());
|
||||
return node->children().count();
|
||||
}
|
||||
|
||||
int AndroidDeviceModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
return 1;
|
||||
}
|
||||
|
||||
QVariant AndroidDeviceModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (role != Qt::DisplayRole)
|
||||
return QVariant();
|
||||
AndroidDeviceModelNode *node = static_cast<AndroidDeviceModelNode *>(index.internalPointer());
|
||||
if (!node)
|
||||
return QVariant();
|
||||
return node->deviceInfo().serialNumber;
|
||||
}
|
||||
|
||||
Qt::ItemFlags AndroidDeviceModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
AndroidDeviceModelNode *node = static_cast<AndroidDeviceModelNode *>(index.internalPointer());
|
||||
if (node)
|
||||
if (node->displayName().isEmpty() && node->incompatibleReason().isEmpty())
|
||||
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
|
||||
|
||||
return Qt::NoItemFlags;
|
||||
}
|
||||
|
||||
AndroidDeviceInfo AndroidDeviceModel::device(QModelIndex index)
|
||||
{
|
||||
AndroidDeviceModelNode *node = static_cast<AndroidDeviceModelNode *>(index.internalPointer());
|
||||
if (!node)
|
||||
return AndroidDeviceInfo();
|
||||
return node->deviceInfo();
|
||||
}
|
||||
|
||||
void AndroidDeviceModel::setDevices(const QVector<AndroidDeviceInfo> &devices)
|
||||
{
|
||||
beginResetModel();
|
||||
delete m_root;
|
||||
m_root = new AndroidDeviceModelNode(0, QString());
|
||||
|
||||
AndroidDeviceModelNode *compatibleDevices = new AndroidDeviceModelNode(m_root, tr("Compatible devices"));
|
||||
AndroidDeviceModelNode *incompatibleDevices = 0; // created on demand
|
||||
foreach (const AndroidDeviceInfo &device, devices) {
|
||||
QString error;
|
||||
if (device.unauthorized) {
|
||||
error = tr("Unauthorized. Please check the confirmation dialog on your device..").arg(device.serialNumber);
|
||||
} else if (!device.cpuAbi.contains(m_abi)) {
|
||||
error = tr("ABI is incompatible, device supports ABIs: %2.")
|
||||
.arg(AndroidConfigurations::instance().getProductModel(device.serialNumber))
|
||||
.arg(device.cpuAbi.join(QLatin1String(" ")));
|
||||
} else if (device.sdk < m_apiLevel) {
|
||||
error = tr("API Level of device is: %2.")
|
||||
.arg(AndroidConfigurations::instance().getProductModel(device.serialNumber))
|
||||
.arg(device.sdk);
|
||||
} else {
|
||||
new AndroidDeviceModelNode(compatibleDevices, device);
|
||||
continue;
|
||||
}
|
||||
if (!incompatibleDevices)
|
||||
incompatibleDevices = new AndroidDeviceModelNode(m_root, tr("Incompatible devices"));
|
||||
new AndroidDeviceModelNode(incompatibleDevices, device, error);
|
||||
}
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QModelIndex AndroidDeviceModel::indexFor(const QString &serial)
|
||||
{
|
||||
foreach (AndroidDeviceModelNode *topLevelNode, m_root->children()) {
|
||||
QList<AndroidDeviceModelNode *> deviceNodes = topLevelNode->children();
|
||||
for (int i = 0; i < deviceNodes.size(); ++i) {
|
||||
if (deviceNodes.at(i)->deviceInfo().serialNumber == serial)
|
||||
return createIndex(i, 0, deviceNodes.at(i));
|
||||
}
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
/////////////////
|
||||
// AndroidDeviceDialog
|
||||
/////////////////
|
||||
AndroidDeviceDialog::AndroidDeviceDialog(int apiLevel, const QString &abi, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
m_model(new AndroidDeviceModel(apiLevel, abi)),
|
||||
m_ui(new Ui::AndroidDeviceDialog),
|
||||
m_apiLevel(apiLevel),
|
||||
m_abi(abi)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
m_ui->deviceView->setModel(m_model);
|
||||
m_ui->deviceView->setItemDelegate(new AndroidDeviceModelDelegate(m_ui->deviceView));
|
||||
m_ui->deviceView->setHeaderHidden(true);
|
||||
m_ui->deviceView->setRootIsDecorated(false);
|
||||
m_ui->deviceView->setUniformRowHeights(true);
|
||||
|
||||
m_ui->defaultDeviceCheckBox->setText(tr("Always use this device for architecture %1").arg(abi));
|
||||
|
||||
connect(m_ui->refreshDevicesButton, SIGNAL(clicked()),
|
||||
this, SLOT(refreshDeviceList()));
|
||||
|
||||
connect(m_ui->createAVDButton, SIGNAL(clicked()),
|
||||
this, SLOT(createAvd()));
|
||||
|
||||
refreshDeviceList();
|
||||
}
|
||||
|
||||
AndroidDeviceDialog::~AndroidDeviceDialog()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
AndroidDeviceInfo AndroidDeviceDialog::device()
|
||||
{
|
||||
if (result() == QDialog::Accepted)
|
||||
return m_model->device(m_ui->deviceView->currentIndex());
|
||||
return AndroidDeviceInfo();
|
||||
}
|
||||
|
||||
void AndroidDeviceDialog::accept()
|
||||
{
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
bool AndroidDeviceDialog::saveDeviceSelection()
|
||||
{
|
||||
return m_ui->defaultDeviceCheckBox->isChecked();
|
||||
}
|
||||
|
||||
void AndroidDeviceDialog::refreshDeviceList()
|
||||
{
|
||||
QString serialNumber;
|
||||
QModelIndex currentIndex = m_ui->deviceView->currentIndex();
|
||||
if (currentIndex.isValid())
|
||||
serialNumber = m_model->device(currentIndex).serialNumber;
|
||||
|
||||
QVector<AndroidDeviceInfo> devices;
|
||||
foreach (const AndroidDeviceInfo &info, AndroidConfigurations::instance().connectedDevices())
|
||||
if (info.type == AndroidDeviceInfo::Hardware)
|
||||
devices << info;
|
||||
|
||||
devices += AndroidConfigurations::instance().androidVirtualDevices();
|
||||
m_model->setDevices(devices);
|
||||
|
||||
m_ui->deviceView->expand(m_model->index(0, 0));
|
||||
|
||||
// Smartly select a index
|
||||
QModelIndex newIndex;
|
||||
if (!serialNumber.isEmpty())
|
||||
newIndex = m_model->indexFor(serialNumber);
|
||||
|
||||
if (!newIndex.isValid() && !devices.isEmpty())
|
||||
newIndex = m_model->indexFor(devices.first().serialNumber);
|
||||
|
||||
m_ui->deviceView->setCurrentIndex(newIndex);
|
||||
}
|
||||
|
||||
void AndroidDeviceDialog::createAvd()
|
||||
{
|
||||
QString avd = AndroidConfigurations::instance().createAVD(m_apiLevel, m_abi);
|
||||
if (avd.isEmpty())
|
||||
return;
|
||||
refreshDeviceList();
|
||||
QModelIndex index = m_model->indexFor(avd);
|
||||
m_ui->deviceView->setCurrentIndex(index);
|
||||
}
|
||||
|
||||
// Does not work.
|
||||
void AndroidDeviceDialog::clickedOnView(const QModelIndex &idx)
|
||||
{
|
||||
if (idx.isValid()) {
|
||||
AndroidDeviceModelNode *node = static_cast<AndroidDeviceModelNode *>(idx.internalPointer());
|
||||
if (!node->displayName().isEmpty()) {
|
||||
if (m_ui->deviceView->isExpanded(idx))
|
||||
m_ui->deviceView->collapse(idx);
|
||||
else
|
||||
m_ui->deviceView->expand(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
78
src/plugins/android/androiddevicedialog.h
Normal file
78
src/plugins/android/androiddevicedialog.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** 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 ANDROIDDEVICEDIALOG_H
|
||||
#define ANDROIDDEVICEDIALOG_H
|
||||
|
||||
#include "androidconfigurations.h"
|
||||
|
||||
#include <QVector>
|
||||
#include <QDialog>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QModelIndex;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Ui {
|
||||
class AndroidDeviceDialog;
|
||||
}
|
||||
|
||||
namespace Android {
|
||||
namespace Internal {
|
||||
|
||||
class AndroidDeviceModel;
|
||||
|
||||
class AndroidDeviceDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AndroidDeviceDialog(int apiLevel, const QString &abi, QWidget *parent = 0);
|
||||
~AndroidDeviceDialog();
|
||||
|
||||
AndroidDeviceInfo device();
|
||||
void accept();
|
||||
|
||||
bool saveDeviceSelection();
|
||||
|
||||
private slots:
|
||||
void refreshDeviceList();
|
||||
void createAvd();
|
||||
void clickedOnView(const QModelIndex &idx);
|
||||
private:
|
||||
AndroidDeviceModel *m_model;
|
||||
Ui::AndroidDeviceDialog *m_ui;
|
||||
int m_apiLevel;
|
||||
QString m_abi;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ANDROIDDEVICEDIALOG_H
|
||||
95
src/plugins/android/androiddevicedialog.ui
Normal file
95
src/plugins/android/androiddevicedialog.ui
Normal file
@@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AndroidDeviceDialog</class>
|
||||
<widget class="QDialog" name="AndroidDeviceDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>618</width>
|
||||
<height>400</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Select Android Device</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QPushButton" name="refreshDevicesButton">
|
||||
<property name="text">
|
||||
<string>Refresh Device List</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="createAVDButton">
|
||||
<property name="text">
|
||||
<string>Create Android Virtual Device</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="defaultDeviceCheckBox">
|
||||
<property name="text">
|
||||
<string>Always use this device for architecture %1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<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>
|
||||
<item row="0" column="0" colspan="3">
|
||||
<widget class="QTreeView" name="deviceView">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>600</width>
|
||||
<height>300</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>AndroidDeviceDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>AndroidDeviceDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
Reference in New Issue
Block a user