forked from qt-creator/qt-creator
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:
@@ -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()) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user