Android: Re-design android settings

Make Android setup related issues visible to user

Change-Id: Ib543c41edd9031d2bf12ac2e87b84bf4791781b7
Reviewed-by: BogDan Vatra <bogdan@kdab.com>
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
This commit is contained in:
Vikas Pachdha
2017-09-14 13:29:46 +02:00
parent eaa5cfaa98
commit 240d310a81
3 changed files with 397 additions and 483 deletions

View File

@@ -32,7 +32,9 @@
#include "androidtoolchain.h"
#include "androidavdmanager.h"
#include <utils/qtcassert.h>
#include <utils/environment.h>
#include <utils/elidinglabel.h>
#include <utils/hostosinfo.h>
#include <utils/pathchooser.h>
#include <utils/runextensions.h>
@@ -59,6 +61,89 @@
namespace Android {
namespace Internal {
namespace {
enum JavaValidation {
JavaPathExistsRow,
JavaJdkValidRow
};
enum AndroidValidation {
SdkPathExistsRow,
SdkToolsInstalledRow,
PlatformToolsInstalledRow,
BuildToolsInstalledRow,
PlatformSdkInstalledRow,
NdkPathExistsRow,
NdkDirStructureRow,
NdkinstallDirOkRow
};
}
class SummaryWidget : public QWidget
{
class RowData {
public:
QLabel *m_iconLabel = nullptr;
Utils::ElidingLabel *m_textLabel = nullptr;
bool m_valid = false;
};
public:
SummaryWidget(const QMap<int, QString> &validationPoints, const QString &validText,
const QString &invalidText, Utils::DetailsWidget *detailsWidget) :
QWidget(detailsWidget),
m_validText(validText),
m_invalidText(invalidText),
m_detailsWidget(detailsWidget)
{
QTC_CHECK(m_detailsWidget);
auto layout = new QGridLayout(this);
layout->setMargin(12);
int row = 0;
for (auto itr = validationPoints.cbegin(); itr != validationPoints.cend(); ++itr) {
RowData data;
data.m_iconLabel = new QLabel(this);
layout->addWidget(data.m_iconLabel, row, 0, 1, 1);
data.m_textLabel = new Utils::ElidingLabel(itr.value(), this);
data.m_textLabel->setElideMode(Qt::ElideRight);
data.m_textLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
layout->addWidget(data.m_textLabel, row, 1, 1, 1);
m_validationData[itr.key()] = data;
setPointValid(itr.key(), true);
++row;
}
}
void setPointValid(int key, bool valid)
{
if (!m_validationData.contains(key))
return;
RowData& data = m_validationData[key];
data.m_valid = valid;
data.m_iconLabel->setPixmap(data.m_valid ? Utils::Icons::OK.pixmap() :
Utils::Icons::BROKEN.pixmap());
bool ok = allRowsOk();
m_detailsWidget->setIcon(ok ? Utils::Icons::OK.icon() :
Utils::Icons::CRITICAL.icon());
m_detailsWidget->setSummaryText(ok ? m_validText : m_invalidText);
}
bool allRowsOk() const
{
for (auto itr = m_validationData.cbegin(); itr != m_validationData.cend(); ++itr) {
if (!itr.value().m_valid)
return false;
}
return true;
}
private:
QString m_validText;
QString m_invalidText;
Utils::DetailsWidget *m_detailsWidget = nullptr;
QMap<int, RowData> m_validationData;
};
void AvdModel::setAvdList(const AndroidDeviceInfoList &list)
{
beginResetModel();
@@ -125,15 +210,39 @@ int AvdModel::columnCount(const QModelIndex &/*parent*/) const
AndroidSettingsWidget::AndroidSettingsWidget(QWidget *parent)
: QWidget(parent),
m_sdkState(NotSet),
m_ndkState(NotSet),
m_javaState(NotSet),
m_ui(new Ui_AndroidSettingsWidget),
m_androidConfig(AndroidConfigurations::currentConfig()),
m_avdManager(new AndroidAvdManager(m_androidConfig))
{
m_ui->setupUi(this);
QMap<int, QString> javaValidationPoints;
javaValidationPoints[JavaPathExistsRow] = tr("JDK path exists.");
javaValidationPoints[JavaJdkValidRow] = tr("JDK path is a valid JDK root folder.");
auto javaSummary = new SummaryWidget(javaValidationPoints, tr("Java Settings are OK."),
tr("Java settings have errors."), m_ui->javaDetailsWidget);
m_ui->javaDetailsWidget->setWidget(javaSummary);
QMap<int, QString> androidValidationPoints;
androidValidationPoints[SdkPathExistsRow] = tr("Android SDK path exists.");
androidValidationPoints[SdkToolsInstalledRow] = tr("SDK tools installed.");
androidValidationPoints[PlatformToolsInstalledRow] = tr("Platform tools installed.");
androidValidationPoints[BuildToolsInstalledRow] = tr("Build tools installed.");
androidValidationPoints[PlatformSdkInstalledRow] = tr("Platform SDK installed.");
androidValidationPoints[NdkPathExistsRow] = tr("Android NDK path exists.");
androidValidationPoints[NdkDirStructureRow] = tr("Android NDK directory structure is correct.");
androidValidationPoints[NdkinstallDirOkRow] = tr("Android NDK installed into a path without "
"spaces.");
auto androidSummary = new SummaryWidget(androidValidationPoints, tr("Android settings are OK."),
tr("Android settings have errors."),
m_ui->androidDetailsWidget);
m_ui->androidDetailsWidget->setWidget(androidSummary);
auto kitsDetailsLabel = new QLabel(m_ui->kitWarningDetails);
kitsDetailsLabel->setWordWrap(true);
m_ui->kitWarningDetails->setWidget(kitsDetailsLabel);
m_ui->kitWarningDetails->setIcon(Utils::Icons::WARNING.icon());
m_ui->SDKLocationPathChooser->setFileName(m_androidConfig.sdkLocation());
m_ui->SDKLocationPathChooser->setPromptDialogTitle(tr("Select Android SDK folder"));
m_ui->NDKLocationPathChooser->setFileName(m_androidConfig.ndkLocation());
@@ -149,29 +258,16 @@ AndroidSettingsWidget::AndroidSettingsWidget(QWidget *parent)
m_ui->downloadOpenJDKToolButton->setVisible(!Utils::HostOsInfo::isLinuxHost());
const QPixmap warningPixmap = Utils::Icons::WARNING.pixmap();
m_ui->jdkWarningIconLabel->setPixmap(warningPixmap);
m_ui->kitWarningIconLabel->setPixmap(warningPixmap);
const QPixmap errorPixmap = Utils::Icons::CRITICAL.pixmap();
m_ui->sdkWarningIconLabel->setPixmap(errorPixmap);
m_ui->ndkWarningIconLabel->setPixmap(errorPixmap);
connect(&m_virtualDevicesWatcher, &QFutureWatcherBase::finished,
this, &AndroidSettingsWidget::updateAvds);
check(All);
applyToUi(All);
connect(&m_futureWatcher, &QFutureWatcherBase::finished,
this, &AndroidSettingsWidget::avdAdded);
connect(m_ui->NDKLocationPathChooser, &Utils::PathChooser::rawPathChanged,
this, &AndroidSettingsWidget::ndkLocationEditingFinished);
this, &AndroidSettingsWidget::validateNdk);
connect(m_ui->SDKLocationPathChooser, &Utils::PathChooser::rawPathChanged,
this, &AndroidSettingsWidget::sdkLocationEditingFinished);
this, &AndroidSettingsWidget::validateSdk);
connect(m_ui->OpenJDKLocationPathChooser, &Utils::PathChooser::rawPathChanged,
this, &AndroidSettingsWidget::openJDKLocationEditingFinished);
this, &AndroidSettingsWidget::validateJdk);
connect(m_ui->AVDAddPushButton, &QAbstractButton::clicked,
this, &AndroidSettingsWidget::addAVD);
connect(m_ui->AVDRemovePushButton, &QAbstractButton::clicked,
@@ -194,6 +290,10 @@ AndroidSettingsWidget::AndroidSettingsWidget(QWidget *parent)
this, &AndroidSettingsWidget::openNDKDownloadUrl);
connect(m_ui->downloadOpenJDKToolButton, &QAbstractButton::clicked,
this, &AndroidSettingsWidget::openOpenJDKDownloadUrl);
validateJdk();
validateNdk();
validateSdk();
}
AndroidSettingsWidget::~AndroidSettingsWidget()
@@ -202,144 +302,6 @@ AndroidSettingsWidget::~AndroidSettingsWidget()
m_futureWatcher.waitForFinished();
}
void AndroidSettingsWidget::check(AndroidSettingsWidget::Mode mode)
{
if (mode & Sdk) {
m_sdkState = verifySdkInstallation(&m_sdkInstallationError) ? Okay : Error;
}
if (mode & Ndk) {
m_ndkState = Okay;
Utils::FileName platformPath = m_androidConfig.ndkLocation();
Utils::FileName toolChainPath = m_androidConfig.ndkLocation();
Utils::FileName sourcesPath = m_androidConfig.ndkLocation();
if (m_androidConfig.ndkLocation().isEmpty()) {
m_ndkState = NotSet;
} else if (!platformPath.appendPath(QLatin1String("platforms")).exists()
|| !toolChainPath.appendPath(QLatin1String("toolchains")).exists()
|| !sourcesPath.appendPath(QLatin1String("sources/cxx-stl")).exists()) {
m_ndkState = Error;
m_ndkErrorMessage = tr("\"%1\" does not seem to be an Android NDK top folder.")
.arg(m_androidConfig.ndkLocation().toUserOutput());
} else if (platformPath.toString().contains(QLatin1Char(' '))) {
m_ndkState = Error;
m_ndkErrorMessage = tr("The Android NDK cannot be installed into a path with spaces.");
} else {
QList<AndroidToolChainFactory::AndroidToolChainInformation> compilerPaths
= AndroidToolChainFactory::toolchainPathsForNdk(m_androidConfig.ndkLocation());
m_ndkCompilerCount = compilerPaths.count();
// See if we have qt versions for those toolchains
QSet<ProjectExplorer::Abi> toolchainsForAbi;
foreach (const AndroidToolChainFactory::AndroidToolChainInformation &ati, compilerPaths) {
if (ati.language == Core::Id(ProjectExplorer::Constants::CXX_LANGUAGE_ID))
toolchainsForAbi.insert(ati.abi);
}
const QList<QtSupport::BaseQtVersion *> androidQts
= QtSupport::QtVersionManager::versions([](const QtSupport::BaseQtVersion *v) {
return v->type() == QLatin1String(Constants::ANDROIDQT) && !v->qtAbis().isEmpty();
});
QSet<ProjectExplorer::Abi> qtVersionsForAbi;
foreach (QtSupport::BaseQtVersion *qtVersion, androidQts)
qtVersionsForAbi.insert(qtVersion->qtAbis().first());
QSet<ProjectExplorer::Abi> missingQtArchs = toolchainsForAbi.subtract(qtVersionsForAbi);
if (missingQtArchs.isEmpty()) {
m_ndkMissingQtArchs.clear();
} else {
if (missingQtArchs.count() == 1) {
m_ndkMissingQtArchs = tr("Qt version for architecture %1 is missing.\n"
"To add the Qt version, select Options > Build & Run > Qt Versions.")
.arg((*missingQtArchs.constBegin()).toString());
} else {
m_ndkMissingQtArchs = tr("Qt versions for %n architectures are missing.\n"
"To add the Qt versions, select Options > Build & Run > Qt Versions.",
nullptr, missingQtArchs.size());
}
}
}
}
if (mode & Java) {
m_javaState = Okay;
if (m_androidConfig.openJDKLocation().isEmpty()) {
m_javaState = NotSet;
} else {
Utils::FileName bin = m_androidConfig.openJDKLocation();
bin.appendPath(QLatin1String("bin/javac" QTC_HOST_EXE_SUFFIX));
if (!m_androidConfig.openJDKLocation().exists() || !bin.exists())
m_javaState = Error;
}
}
}
void AndroidSettingsWidget::applyToUi(AndroidSettingsWidget::Mode mode)
{
if (mode & Sdk) {
if (m_sdkState == Error) {
m_ui->sdkWarningIconLabel->setVisible(true);
m_ui->sdkWarningLabel->setVisible(true);
m_ui->sdkWarningLabel->setText(m_sdkInstallationError);
} else {
m_ui->sdkWarningIconLabel->setVisible(false);
m_ui->sdkWarningLabel->setVisible(false);
}
}
if (mode & Ndk) {
if (m_ndkState == NotSet) {
m_ui->ndkWarningIconLabel->setVisible(false);
m_ui->toolchainFoundLabel->setVisible(false);
m_ui->kitWarningIconLabel->setVisible(false);
m_ui->kitWarningLabel->setVisible(false);
} else if (m_ndkState == Error) {
m_ui->toolchainFoundLabel->setText(m_ndkErrorMessage);
m_ui->toolchainFoundLabel->setVisible(true);
m_ui->ndkWarningIconLabel->setVisible(true);
m_ui->kitWarningIconLabel->setVisible(false);
m_ui->kitWarningLabel->setVisible(false);
} else {
if (m_ndkCompilerCount > 0) {
m_ui->ndkWarningIconLabel->setVisible(false);
m_ui->toolchainFoundLabel->setText(tr("Found %n toolchains for this NDK.", 0, m_ndkCompilerCount));
m_ui->toolchainFoundLabel->setVisible(true);
} else {
m_ui->ndkWarningIconLabel->setVisible(false);
m_ui->toolchainFoundLabel->setVisible(false);
}
if (m_ndkMissingQtArchs.isEmpty()) {
m_ui->kitWarningIconLabel->setVisible(false);
m_ui->kitWarningLabel->setVisible(false);
} else {
m_ui->kitWarningIconLabel->setVisible(true);
m_ui->kitWarningLabel->setVisible(true);
m_ui->kitWarningLabel->setText(m_ndkMissingQtArchs);
}
}
}
if (mode & Java) {
Utils::FileName location = m_androidConfig.openJDKLocation();
bool error = m_javaState == Error;
m_ui->jdkWarningIconLabel->setVisible(error);
m_ui->jdkWarningLabel->setVisible(error);
if (error)
m_ui->jdkWarningLabel->setText(tr("\"%1\" does not seem to be a JDK folder.").arg(location.toUserOutput()));
}
if (mode & Sdk || mode & Java) {
if (m_sdkState == Okay && m_javaState == Okay) {
m_ui->AVDManagerFrame->setEnabled(true);
} else {
m_ui->AVDManagerFrame->setEnabled(false);
}
startUpdateAvd();
}
}
void AndroidSettingsWidget::disableAvdControls()
{
m_ui->AVDAddPushButton->setEnabled(false);
@@ -371,75 +333,65 @@ void AndroidSettingsWidget::updateAvds()
enableAvdControls();
}
bool AndroidSettingsWidget::verifySdkInstallation(QString *errorDetails) const
{
if (m_androidConfig.sdkLocation().isEmpty()) {
if (errorDetails)
*errorDetails = tr("Android SDK path not set.");
return false;
}
if (!m_androidConfig.sdkLocation().exists()) {
if (errorDetails)
*errorDetails = tr("Android SDK path does not exist.");
return false;
}
if (m_androidConfig.sdkToolsVersion().isNull()) {
if (errorDetails)
*errorDetails = tr("The SDK path does not seem to be a valid Android SDK top folder.");
return false;
}
QStringList missingComponents;
if (!m_androidConfig.adbToolPath().exists())
missingComponents << "Platform Tools";
if (m_androidConfig.buildToolsVersion().isNull())
missingComponents << "Build Tools";
if (m_androidConfig.sdkTargets().isEmpty())
missingComponents << "Platform SDK";
if (!missingComponents.isEmpty() && errorDetails) {
*errorDetails = tr("Android SDK components missing (%1).\nUse Android SDK Manager to "
"manage SDK components.").arg(missingComponents.join(", "));
}
return missingComponents.isEmpty();
}
void AndroidSettingsWidget::saveSettings()
{
sdkLocationEditingFinished();
ndkLocationEditingFinished();
openJDKLocationEditingFinished();
dataPartitionSizeEditingFinished();
AndroidConfigurations::setConfig(m_androidConfig);
}
void AndroidSettingsWidget::sdkLocationEditingFinished()
void AndroidSettingsWidget::validateJdk()
{
m_androidConfig.setSdkLocation(Utils::FileName::fromUserInput(m_ui->SDKLocationPathChooser->rawPath()));
auto javaPath = Utils::FileName::fromUserInput(m_ui->OpenJDKLocationPathChooser->rawPath());
m_androidConfig.setOpenJDKLocation(javaPath);
bool jdkPathExists = m_androidConfig.openJDKLocation().exists();
auto summaryWidget = static_cast<SummaryWidget *>(m_ui->javaDetailsWidget->widget());
summaryWidget->setPointValid(JavaPathExistsRow, jdkPathExists);
check(Sdk);
applyToUi(Sdk);
Utils::FileName bin = m_androidConfig.openJDKLocation();
bin.appendPath(QLatin1String("bin/javac" QTC_HOST_EXE_SUFFIX));
summaryWidget->setPointValid(JavaJdkValidRow, jdkPathExists && bin.exists());
updateUI();
}
void AndroidSettingsWidget::ndkLocationEditingFinished()
void AndroidSettingsWidget::validateNdk()
{
m_androidConfig.setNdkLocation(Utils::FileName::fromUserInput(m_ui->NDKLocationPathChooser->rawPath()));
auto ndkPath = Utils::FileName::fromUserInput(m_ui->NDKLocationPathChooser->rawPath());
m_androidConfig.setNdkLocation(ndkPath);
check(Ndk);
applyToUi(Ndk);
auto summaryWidget = static_cast<SummaryWidget *>(m_ui->androidDetailsWidget->widget());
summaryWidget->setPointValid(NdkPathExistsRow, m_androidConfig.ndkLocation().exists());
Utils::FileName ndkPlatformsDir(ndkPath);
ndkPlatformsDir.appendPath("platforms");
Utils::FileName ndkToolChainsDir(ndkPath);
ndkToolChainsDir.appendPath("toolchains");
Utils::FileName ndkSourcesDir(ndkPath);
ndkSourcesDir.appendPath("sources/cxx-stl");
summaryWidget->setPointValid(NdkDirStructureRow,
ndkPlatformsDir.exists()
&& ndkToolChainsDir.exists()
&& ndkSourcesDir.exists());
summaryWidget->setPointValid(NdkinstallDirOkRow,
ndkPlatformsDir.exists() &&
!ndkPlatformsDir.toString().contains(' '));
updateUI();
}
void AndroidSettingsWidget::openJDKLocationEditingFinished()
void AndroidSettingsWidget::validateSdk()
{
m_androidConfig.setOpenJDKLocation(Utils::FileName::fromUserInput(m_ui->OpenJDKLocationPathChooser->rawPath()));
auto sdkPath = Utils::FileName::fromUserInput(m_ui->SDKLocationPathChooser->rawPath());
m_androidConfig.setSdkLocation(sdkPath);
check(Java);
applyToUi(Java);
auto summaryWidget = static_cast<SummaryWidget *>(m_ui->androidDetailsWidget->widget());
summaryWidget->setPointValid(SdkPathExistsRow, m_androidConfig.sdkLocation().exists());
summaryWidget->setPointValid(SdkToolsInstalledRow,
!m_androidConfig.sdkToolsVersion().isNull());
summaryWidget->setPointValid(PlatformToolsInstalledRow,
m_androidConfig.adbToolPath().exists());
summaryWidget->setPointValid(BuildToolsInstalledRow,
!m_androidConfig.buildToolsVersion().isNull());
summaryWidget->setPointValid(PlatformSdkInstalledRow,
!m_androidConfig.sdkTargets().isEmpty());
updateUI();
}
void AndroidSettingsWidget::openSDKDownloadUrl()
@@ -520,6 +472,64 @@ void AndroidSettingsWidget::createKitToggled()
m_androidConfig.setAutomaticKitCreation(m_ui->CreateKitCheckBox->isChecked());
}
void AndroidSettingsWidget::checkMissingQtVersion()
{
auto summaryWidget = static_cast<SummaryWidget *>(m_ui->androidDetailsWidget->widget());
if (!summaryWidget->allRowsOk()) {
m_ui->kitWarningDetails->setVisible(false);
m_ui->kitWarningDetails->setState(Utils::DetailsWidget::Collapsed);
return;
}
QList<AndroidToolChainFactory::AndroidToolChainInformation> compilerPaths
= AndroidToolChainFactory::toolchainPathsForNdk(m_androidConfig.ndkLocation());
// See if we have qt versions for those toolchains
QSet<ProjectExplorer::Abi> toolchainsForAbi;
foreach (const AndroidToolChainFactory::AndroidToolChainInformation &ati, compilerPaths) {
if (ati.language == Core::Id(ProjectExplorer::Constants::CXX_LANGUAGE_ID))
toolchainsForAbi.insert(ati.abi);
}
const QList<QtSupport::BaseQtVersion *> androidQts
= QtSupport::QtVersionManager::versions([](const QtSupport::BaseQtVersion *v) {
return v->type() == QLatin1String(Constants::ANDROIDQT) && !v->qtAbis().isEmpty();
});
QSet<ProjectExplorer::Abi> qtVersionsForAbi;
foreach (QtSupport::BaseQtVersion *qtVersion, androidQts)
qtVersionsForAbi.insert(qtVersion->qtAbis().first());
QSet<ProjectExplorer::Abi> missingQtArchs = toolchainsForAbi.subtract(qtVersionsForAbi);
bool isArchMissing = !missingQtArchs.isEmpty();
m_ui->kitWarningDetails->setVisible(isArchMissing);
if (isArchMissing) {
m_ui->kitWarningDetails->setSummaryText(tr("Cannot create kits for all architectures."));
QLabel *detailsLabel = static_cast<QLabel *>(m_ui->kitWarningDetails->widget());
QStringList archNames;
for (auto abi : missingQtArchs)
archNames << abi.toString();
detailsLabel->setText(tr("Qt versions are missing for the following architectures:\n%1"
"\n\nTo add the Qt version, select Options > Build & Run > Qt"
" Versions.").arg(archNames.join(", ")));
}
}
void AndroidSettingsWidget::updateUI()
{
auto javaSummaryWidget = static_cast<SummaryWidget *>(m_ui->javaDetailsWidget->widget());
auto androidSummaryWidget = static_cast<SummaryWidget *>(m_ui->androidDetailsWidget->widget());
m_ui->AVDManagerFrame->setEnabled(javaSummaryWidget->allRowsOk()
&& androidSummaryWidget->allRowsOk());
m_ui->javaDetailsWidget->setState(javaSummaryWidget->allRowsOk() ?
Utils::DetailsWidget::Collapsed :
Utils::DetailsWidget::Expanded);
m_ui->androidDetailsWidget->setState(androidSummaryWidget->allRowsOk() ?
Utils::DetailsWidget::Collapsed :
Utils::DetailsWidget::Expanded);
startUpdateAvd();
checkMissingQtVersion();
}
void AndroidSettingsWidget::manageAVD()
{
if (m_avdManager->avdManagerUiToolAvailable()) {

View File

@@ -73,9 +73,9 @@ public:
void saveSettings();
private:
void sdkLocationEditingFinished();
void ndkLocationEditingFinished();
void openJDKLocationEditingFinished();
void validateJdk();
void validateNdk();
void validateSdk();
void openSDKDownloadUrl();
void openNDKDownloadUrl();
void openOpenJDKDownloadUrl();
@@ -88,26 +88,15 @@ private:
void manageAVD();
void createKitToggled();
void checkMissingQtVersion();
void updateUI();
void updateAvds();
private:
enum Mode { Sdk = 1, Ndk = 2, Java = 4, All = Sdk | Ndk | Java };
enum State { NotSet = 0, Okay = 1, Error = 2 };
bool verifySdkInstallation(QString *errorDetails = nullptr) const;
void check(Mode mode);
void applyToUi(Mode mode);
void startUpdateAvd();
void enableAvdControls();
void disableAvdControls();
State m_sdkState;
QString m_sdkInstallationError;
State m_ndkState;
QString m_ndkErrorMessage;
int m_ndkCompilerCount;
QString m_ndkMissingQtArchs;
State m_javaState;
Ui_AndroidSettingsWidget *m_ui;
AndroidConfig m_androidConfig;
AvdModel m_AVDModel;

View File

@@ -6,15 +6,175 @@
<rect>
<x>0</x>
<y>0</y>
<width>843</width>
<height>625</height>
<width>938</width>
<height>728</height>
</rect>
</property>
<property name="windowTitle">
<string>Android Configuration</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="9" column="0" colspan="2">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="javaSettingsGroup">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="title">
<string>Java Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="Utils::PathChooser" name="OpenJDKLocationPathChooser" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="downloadOpenJDKToolButton">
<property name="toolTip">
<string>Download JDK</string>
</property>
<property name="icon">
<iconset resource="android.qrc">
<normaloff>:/android/images/download.png</normaloff>:/android/images/download.png</iconset>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="OpenJDKLocationLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>JDK location:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="0" colspan="3">
<widget class="Utils::DetailsWidget" name="javaDetailsWidget" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Android Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="1">
<widget class="Utils::PathChooser" name="NDKLocationPathChooser" native="true"/>
</item>
<item row="0" column="1">
<widget class="Utils::PathChooser" name="SDKLocationPathChooser" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QToolButton" name="downloadNDKToolButton">
<property name="toolTip">
<string>Download Android NDK</string>
</property>
<property name="icon">
<iconset resource="android.qrc">
<normaloff>:/android/images/download.png</normaloff>:/android/images/download.png</iconset>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="NDKLocationLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Android NDK location:</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="SDKLocationLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Android SDK location:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="downloadSDKToolButton">
<property name="toolTip">
<string>Download Android SDK</string>
</property>
<property name="icon">
<iconset resource="android.qrc">
<normaloff>:/android/images/download.png</normaloff>:/android/images/download.png</iconset>
</property>
</widget>
</item>
<item row="2" column="0" colspan="3">
<widget class="Utils::DetailsWidget" name="androidDetailsWidget" native="true"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QCheckBox" name="CreateKitCheckBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Automatically create kits for Android tool chains</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="Utils::DetailsWidget" name="kitWarningDetails" native="true"/>
</item>
<item>
<widget class="QFrame" name="AVDManagerFrame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
@@ -133,264 +293,19 @@
</layout>
</widget>
</item>
<item row="0" column="1">
<widget class="Utils::PathChooser" name="OpenJDKLocationPathChooser" native="true"/>
</item>
<item row="2" column="1">
<widget class="Utils::PathChooser" name="SDKLocationPathChooser" native="true"/>
</item>
<item row="4" column="1">
<widget class="Utils::PathChooser" name="NDKLocationPathChooser" native="true"/>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLabel" name="jdkWarningIconLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="jdkWarningLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="2">
<widget class="QToolButton" name="downloadNDKToolButton">
<property name="toolTip">
<string>Download Android NDK</string>
</property>
<property name="icon">
<iconset resource="android.qrc">
<normaloff>:/android/images/download.png</normaloff>:/android/images/download.png</iconset>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="SDKLocationLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Android SDK location:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="downloadOpenJDKToolButton">
<property name="toolTip">
<string>Download JDK</string>
</property>
<property name="icon">
<iconset resource="android.qrc">
<normaloff>:/android/images/download.png</normaloff>:/android/images/download.png</iconset>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QToolButton" name="downloadSDKToolButton">
<property name="toolTip">
<string>Download Android SDK</string>
</property>
<property name="icon">
<iconset resource="android.qrc">
<normaloff>:/android/images/download.png</normaloff>:/android/images/download.png</iconset>
</property>
</widget>
</item>
<item row="8" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>2</number>
</property>
<item>
<widget class="QLabel" name="kitWarningIconLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="kitWarningLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="7" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_8">
<property name="spacing">
<number>2</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="CreateKitCheckBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Automatically create kits for Android tool chains</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="0">
<widget class="QLabel" name="NDKLocationLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Android NDK location:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="5" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>2</number>
</property>
<item>
<widget class="QLabel" name="ndkWarningIconLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="toolchainFoundLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="sdkWarningIconLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="sdkWarningLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QLabel" name="OpenJDKLocationLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>JDK location:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Utils::PathChooser</class>
<extends>QWidget</extends>
<header location="global">utils/pathchooser.h</header>
<header>utils/pathchooser.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>Utils::DetailsWidget</class>
<extends>QWidget</extends>
<header location="global">utils/detailswidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>