diff --git a/src/plugins/android/CMakeLists.txt b/src/plugins/android/CMakeLists.txt index 522ad3d394a..f7fa5a095e9 100644 --- a/src/plugins/android/CMakeLists.txt +++ b/src/plugins/android/CMakeLists.txt @@ -40,7 +40,7 @@ add_qtc_plugin(Android androidsdkmodel.cpp androidsdkmodel.h androidsdkpackage.cpp androidsdkpackage.h androidservicewidget.cpp androidservicewidget.h androidservicewidget_p.h - androidsettingswidget.cpp androidsettingswidget.h androidsettingswidget.ui + androidsettingswidget.cpp androidsettingswidget.h androidsignaloperation.cpp androidsignaloperation.h androidtoolchain.cpp androidtoolchain.h avddialog.cpp avddialog.h diff --git a/src/plugins/android/android.qbs b/src/plugins/android/android.qbs index 4db566e9054..2dc2d8ac68e 100644 --- a/src/plugins/android/android.qbs +++ b/src/plugins/android/android.qbs @@ -93,7 +93,6 @@ Project { "androidservicewidget_p.h", "androidsettingswidget.cpp", "androidsettingswidget.h", - "androidsettingswidget.ui", "androidsignaloperation.cpp", "androidsignaloperation.h", "androidtoolchain.cpp", diff --git a/src/plugins/android/androidsettingswidget.cpp b/src/plugins/android/androidsettingswidget.cpp index 325148b7d1a..d4e0daff97f 100644 --- a/src/plugins/android/androidsettingswidget.cpp +++ b/src/plugins/android/androidsettingswidget.cpp @@ -25,8 +25,6 @@ #include "androidsettingswidget.h" -#include "ui_androidsettingswidget.h" - #include "androidconfigurations.h" #include "androidconstants.h" #include "androidsdkdownloader.h" @@ -35,100 +33,39 @@ #include +#include #include #include +#include #include #include #include #include #include +#include #include #include #include +#include #include +#include #include #include +#include #include #include +#include #include -#include +#include #include using namespace Utils; -namespace { +namespace Android::Internal { + static Q_LOGGING_CATEGORY(androidsettingswidget, "qtc.android.androidsettingswidget", QtWarningMsg); -} - -namespace Android { -namespace Internal { - -class AndroidSdkManagerWidget; -class SummaryWidget; - -class AndroidSettingsWidget final : public Core::IOptionsPageWidget -{ - Q_DECLARE_TR_FUNCTIONS(Android::Internal::AndroidSettingsWidget) - -public: - // Todo: This would be so much simpler if it just used Utils::PathChooser!!! - AndroidSettingsWidget(); - ~AndroidSettingsWidget() final; - -private: - void apply() final { AndroidConfigurations::setConfig(m_androidConfig); } - - void showEvent(QShowEvent *event) override; - - void validateJdk(); - void updateNdkList(); - void onSdkPathChanged(); - void validateSdk(); - void openSDKDownloadUrl(); - void openNDKDownloadUrl(); - void openOpenJDKDownloadUrl(); - void downloadOpenSslRepo(const bool silent = false); - void createKitToggled(); - - void updateUI(); - - void downloadSdk(); - void addCustomNdkItem(); - bool isDefaultNdkSelected() const; - void validateOpenSsl(); - - Ui_AndroidSettingsWidget m_ui; - AndroidSdkManagerWidget *m_sdkManagerWidget = nullptr; - AndroidConfig &m_androidConfig{AndroidConfigurations::currentConfig()}; - - AndroidSdkManager m_sdkManager{m_androidConfig}; - AndroidSdkDownloader m_sdkDownloader; - bool m_isInitialReloadDone = false; - - SummaryWidget *m_androidSummary = nullptr; - SummaryWidget *m_openSslSummary = nullptr; - - ProgressIndicator *m_androidProgress = nullptr; -}; - -enum AndroidValidation { - JavaPathExistsAndWritableRow, - SdkPathExistsAndWritableRow, - SdkToolsInstalledRow, - PlatformToolsInstalledRow, - SdkManagerSuccessfulRow, - PlatformSdkInstalledRow, - BuildToolsInstalledRow, - AllEssentialsInstalledRow, -}; - -enum OpenSslValidation { - OpenSslPathExistsRow, - OpenSslPriPathExists, - OpenSslCmakeListsPathExists -}; class SummaryWidget : public QWidget { @@ -222,133 +159,116 @@ private: QMap m_validationData; }; -void AndroidSettingsWidget::showEvent(QShowEvent *event) +class AndroidSettingsWidget final : public Core::IOptionsPageWidget { - Q_UNUSED(event) - if (!m_isInitialReloadDone) { - validateJdk(); - // Reloading SDK packages (force) is still synchronous. Use zero timer - // to let settings dialog open first. - QTimer::singleShot(0, &m_sdkManager, std::bind(&AndroidSdkManager::reloadPackages, - &m_sdkManager, false)); - validateOpenSsl(); - m_isInitialReloadDone = true; - } -} + Q_DECLARE_TR_FUNCTIONS(Android::Internal::AndroidSettingsWidget) -void AndroidSettingsWidget::updateNdkList() -{ - m_ui.ndkListWidget->clear(); - const auto installedPkgs = m_sdkManager.installedNdkPackages(); - for (const Ndk *ndk : installedPkgs) { - m_ui.ndkListWidget->addItem(new QListWidgetItem(Icons::LOCKED.icon(), - ndk->installedLocation().toUserOutput())); - } +public: + // Todo: This would be so much simpler if it just used Utils::PathChooser!!! + AndroidSettingsWidget(); + ~AndroidSettingsWidget() final; - const auto customNdks = m_androidConfig.getCustomNdkList(); - for (const QString &ndk : customNdks) { - if (m_androidConfig.isValidNdk(ndk)) { - m_ui.ndkListWidget->addItem(new QListWidgetItem(Icons::UNLOCKED.icon(), ndk)); - } else { - m_androidConfig.removeCustomNdk(ndk); - } - } +private: + void apply() final { AndroidConfigurations::setConfig(m_androidConfig); } - m_ui.ndkListWidget->setCurrentRow(0); + void showEvent(QShowEvent *event) override; - updateUI(); -} + void validateJdk(); + void updateNdkList(); + void onSdkPathChanged(); + void validateSdk(); + void openSDKDownloadUrl(); + void openNDKDownloadUrl(); + void openOpenJDKDownloadUrl(); + void downloadOpenSslRepo(const bool silent = false); + void createKitToggled(); -void AndroidSettingsWidget::addCustomNdkItem() -{ - const QString homePath = QStandardPaths::standardLocations(QStandardPaths::HomeLocation) - .constFirst(); - const QString ndkPath = QFileDialog::getExistingDirectory(this, tr("Select an NDK"), homePath); + void updateUI(); - if (m_androidConfig.isValidNdk(ndkPath)) { - m_androidConfig.addCustomNdk(ndkPath); - if (m_ui.ndkListWidget->findItems(ndkPath, Qt::MatchExactly).size() == 0) { - m_ui.ndkListWidget->addItem(new QListWidgetItem(Icons::UNLOCKED.icon(), ndkPath)); - } - } else if (!ndkPath.isEmpty()) { - QMessageBox::warning( - this, - tr("Add Custom NDK"), - tr("The selected path has an invalid NDK. This might mean that the path contains space " - "characters, or that it does not have a \"toolchains\" sub-directory, or that the " - "NDK version could not be retrieved because of a missing \"source.properties\" or " - "\"RELEASE.TXT\" file")); - } -} + void downloadSdk(); + void addCustomNdkItem(); + bool isDefaultNdkSelected() const; + void validateOpenSsl(); + AndroidSdkManagerWidget *m_sdkManagerWidget = nullptr; + AndroidConfig &m_androidConfig{AndroidConfigurations::currentConfig()}; -bool AndroidSettingsWidget::isDefaultNdkSelected() const -{ - if (!m_androidConfig.defaultNdk().isEmpty()) { - if (const QListWidgetItem *item = m_ui.ndkListWidget->currentItem()) { - return FilePath::fromUserInput(item->text()) == m_androidConfig.defaultNdk(); - } - } - return false; -} + AndroidSdkManager m_sdkManager{m_androidConfig}; + AndroidSdkDownloader m_sdkDownloader; + bool m_isInitialReloadDone = false; + + SummaryWidget *m_androidSummary = nullptr; + SummaryWidget *m_openSslSummary = nullptr; + + ProgressIndicator *m_androidProgress = nullptr; + + PathChooser *m_sdkLocationPathChooser; + QPushButton *m_makeDefaultNdkButton; + QListWidget *m_ndkListWidget; + PathChooser *m_openJdkLocationPathChooser; + QCheckBox *m_createKitCheckBox; + PathChooser *m_openSslPathChooser; +}; + +enum AndroidValidation { + JavaPathExistsAndWritableRow, + SdkPathExistsAndWritableRow, + SdkToolsInstalledRow, + PlatformToolsInstalledRow, + SdkManagerSuccessfulRow, + PlatformSdkInstalledRow, + BuildToolsInstalledRow, + AllEssentialsInstalledRow, +}; + +enum OpenSslValidation { + OpenSslPathExistsRow, + OpenSslPriPathExists, + OpenSslCmakeListsPathExists +}; AndroidSettingsWidget::AndroidSettingsWidget() { - m_ui.setupUi(this); - m_sdkManagerWidget = new AndroidSdkManagerWidget(m_androidConfig, &m_sdkManager, this); - QMap androidValidationPoints; - androidValidationPoints[SdkPathExistsAndWritableRow] = - tr("Android SDK path exists and is writable."); - androidValidationPoints[JavaPathExistsAndWritableRow] = tr("JDK path exists and is writable."); - androidValidationPoints[SdkToolsInstalledRow] = tr("SDK tools installed."); - androidValidationPoints[SdkManagerSuccessfulRow] = tr("SDK manager runs."); - androidValidationPoints[PlatformToolsInstalledRow] = tr("Platform tools installed."); - androidValidationPoints[AllEssentialsInstalledRow] = tr( - "All essential packages installed for all installed Qt versions."); - androidValidationPoints[BuildToolsInstalledRow] = tr("Build tools installed."); - androidValidationPoints[PlatformSdkInstalledRow] = tr("Platform SDK installed."); - m_androidSummary = new SummaryWidget(androidValidationPoints, tr("Android settings are OK."), - tr("Android settings have errors."), - m_ui.androidDetailsWidget); - m_androidProgress = new ProgressIndicator(ProgressIndicatorSize::Medium, this); - m_androidProgress->attachToWidget(m_ui.androidDetailsWidget); - m_androidProgress->hide(); - - QMap openSslValidationPoints; - openSslValidationPoints[OpenSslPathExistsRow] = tr("OpenSSL path exists."); - openSslValidationPoints[OpenSslPriPathExists] = tr( - "QMake include project (openssl.pri) exists."); - openSslValidationPoints[OpenSslCmakeListsPathExists] = tr( - "CMake include project (CMakeLists.txt) exists."); - m_openSslSummary = new SummaryWidget(openSslValidationPoints, - tr("OpenSSL Settings are OK."), - tr("OpenSSL settings have errors."), - m_ui.openSslDetailsWidget); - - connect(m_ui.OpenJDKLocationPathChooser, &PathChooser::rawPathChanged, - this, &AndroidSettingsWidget::validateJdk); - if (m_androidConfig.openJDKLocation().isEmpty()) - m_androidConfig.setOpenJDKLocation(AndroidConfig::getJdkPath()); - m_ui.OpenJDKLocationPathChooser->setFilePath(m_androidConfig.openJDKLocation()); - m_ui.OpenJDKLocationPathChooser->setPromptDialogTitle(tr("Select JDK Path")); - - if (m_androidConfig.sdkLocation().isEmpty()) - m_androidConfig.setSdkLocation(AndroidConfig::defaultSdkPath()); - m_ui.SDKLocationPathChooser->setFilePath(m_androidConfig.sdkLocation()); - m_ui.SDKLocationPathChooser->setPromptDialogTitle(tr("Select Android SDK Folder")); - - m_ui.openSslPathChooser->setPromptDialogTitle(tr("Select OpenSSL Include Project File")); - if (m_androidConfig.openSslLocation().isEmpty()) - m_androidConfig.setOpenSslLocation(m_androidConfig.sdkLocation() / ("android_openssl")); - m_ui.openSslPathChooser->setFilePath(m_androidConfig.openSslLocation()); - - m_ui.CreateKitCheckBox->setChecked(m_androidConfig.automaticKitCreation()); + setWindowTitle(tr("Android Configuration")); const QIcon downloadIcon = Icons::ONLINE.icon(); - m_ui.downloadSDKToolButton->setIcon(downloadIcon); - m_ui.downloadNDKToolButton->setIcon(downloadIcon); - m_ui.downloadOpenJDKToolButton->setIcon(downloadIcon); - m_ui.sdkToolsAutoDownloadButton->setToolTip( + + m_sdkLocationPathChooser = new PathChooser; + + auto downloadSdkToolButton = new QToolButton; + downloadSdkToolButton->setIcon(downloadIcon); + downloadSdkToolButton->setToolTip(tr("Open Android SDK download URL in the system's browser.")); + + auto addCustomNdkButton = new QPushButton(tr("Add...")); + addCustomNdkButton->setToolTip(tr("Add the selected custom NDK. The toolchains " + "and debuggers will be created automatically.")); + + auto removeCustomNdkButton = new QPushButton(tr("Remove")); + removeCustomNdkButton->setEnabled(false); + removeCustomNdkButton->setToolTip(tr("Remove the selected NDK if it has been added manually.")); + + m_makeDefaultNdkButton = new QPushButton; + m_makeDefaultNdkButton->setToolTip(tr("Force a specific NDK installation to be used by all " + "Android kits.
Note that the forced NDK might not " + "be compatible with all registered Qt versions.")); + + auto androidDetailsWidget = new DetailsWidget; + + m_ndkListWidget = new QListWidget; + m_ndkListWidget->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); + m_ndkListWidget->setIconSize(QSize(16, 16)); + m_ndkListWidget->setResizeMode(QListView::Adjust); + m_ndkListWidget->setModelColumn(0); + m_ndkListWidget->setSortingEnabled(false); + + m_openJdkLocationPathChooser = new PathChooser; + + auto downloadOpenJdkToolButton = new QToolButton; + downloadOpenJdkToolButton->setIcon(downloadIcon); + downloadOpenJdkToolButton->setToolTip(tr("Open JDK download URL in the system's browser.")); + + auto sdkToolsAutoDownloadButton = new QPushButton(tr("Set Up SDK")); + sdkToolsAutoDownloadButton->setToolTip( tr("Automatically download Android SDK Tools to selected location.\n\n" "If the selected path contains no valid SDK Tools, the SDK Tools package is downloaded\n" "from %1,\n" @@ -357,7 +277,21 @@ AndroidSettingsWidget::AndroidSettingsWidget() "packages required for Qt to build for Android.") .arg(m_androidConfig.sdkToolsUrl().toString())); - m_ui.downloadOpenSSLPrebuiltLibs->setToolTip( + auto sdkManagerToolButton = new QPushButton(tr("SDK Manager")); + + auto downloadNdkToolButton = new QToolButton; + downloadNdkToolButton->setToolTip(tr("Open Android NDK download URL in the system's browser.")); + + m_createKitCheckBox = new QCheckBox(tr("Automatically create kits for Android tool chains")); + m_createKitCheckBox->setChecked(true); + + auto openSslDetailsWidget = new DetailsWidget; + + m_openSslPathChooser = new PathChooser; + m_openSslPathChooser->setToolTip(tr("Select the path of the prebuilt OpenSSL binaries.")); + + auto downloadOpenSslPrebuiltLibs = new QPushButton(tr("Download OpenSSL")); + downloadOpenSslPrebuiltLibs->setToolTip( tr("Automatically download OpenSSL prebuilt libraries.\n\n" "These libraries can be shipped with your application if any SSL operations\n" "are performed. Find the checkbox under \"Projects > Build > Build Steps >\n" @@ -365,41 +299,147 @@ AndroidSettingsWidget::AndroidSettingsWidget() "If the automatic download fails, Qt Creator proposes to open the download URL\n" "in the system's browser for manual download.")); - connect(m_ui.SDKLocationPathChooser, &PathChooser::rawPathChanged, + + m_sdkManagerWidget = new AndroidSdkManagerWidget(m_androidConfig, &m_sdkManager, this); + + const QMap androidValidationPoints = { + { SdkPathExistsAndWritableRow, tr("Android SDK path exists and is writable.") }, + { JavaPathExistsAndWritableRow, tr("JDK path exists and is writable.") }, + { SdkToolsInstalledRow, tr("SDK tools installed.") }, + { SdkManagerSuccessfulRow, tr("SDK manager runs.") }, + { PlatformToolsInstalledRow, tr("Platform tools installed.") }, + { AllEssentialsInstalledRow, + tr( "All essential packages installed for all installed Qt versions.") }, + { BuildToolsInstalledRow, tr("Build tools installed.") }, + { PlatformSdkInstalledRow, tr("Platform SDK installed.") } + }; + + m_androidSummary = new SummaryWidget(androidValidationPoints, tr("Android settings are OK."), + tr("Android settings have errors."), + androidDetailsWidget); + m_androidProgress = new ProgressIndicator(ProgressIndicatorSize::Medium, this); + m_androidProgress->attachToWidget(androidDetailsWidget); + m_androidProgress->hide(); + + const QMap openSslValidationPoints = { + { OpenSslPathExistsRow, tr("OpenSSL path exists.") }, + { OpenSslPriPathExists, tr("QMake include project (openssl.pri) exists.") }, + { OpenSslCmakeListsPathExists, tr("CMake include project (CMakeLists.txt) exists.") } + }; + m_openSslSummary = new SummaryWidget(openSslValidationPoints, + tr("OpenSSL Settings are OK."), + tr("OpenSSL settings have errors."), + openSslDetailsWidget); + + connect(m_openJdkLocationPathChooser, &PathChooser::rawPathChanged, + this, &AndroidSettingsWidget::validateJdk); + if (m_androidConfig.openJDKLocation().isEmpty()) + m_androidConfig.setOpenJDKLocation(AndroidConfig::getJdkPath()); + m_openJdkLocationPathChooser->setFilePath(m_androidConfig.openJDKLocation()); + m_openJdkLocationPathChooser->setPromptDialogTitle(tr("Select JDK Path")); + + if (m_androidConfig.sdkLocation().isEmpty()) + m_androidConfig.setSdkLocation(AndroidConfig::defaultSdkPath()); + m_sdkLocationPathChooser->setFilePath(m_androidConfig.sdkLocation()); + m_sdkLocationPathChooser->setPromptDialogTitle(tr("Select Android SDK Folder")); + + m_openSslPathChooser->setPromptDialogTitle(tr("Select OpenSSL Include Project File")); + if (m_androidConfig.openSslLocation().isEmpty()) + m_androidConfig.setOpenSslLocation(m_androidConfig.sdkLocation() / ("android_openssl")); + m_openSslPathChooser->setFilePath(m_androidConfig.openSslLocation()); + + m_createKitCheckBox->setChecked(m_androidConfig.automaticKitCreation()); + + downloadNdkToolButton->setIcon(downloadIcon); + + using namespace Layouting; + const Break br; + const Space empty; + + Column { + Group { + Title(tr("Android Settings")), + Grid { + tr("JDK location:"), + m_openJdkLocationPathChooser, + empty, + downloadOpenJdkToolButton, + br, + + tr("Android SDK location:"), + m_sdkLocationPathChooser, + sdkToolsAutoDownloadButton, + downloadSdkToolButton, + br, + + empty, empty, sdkManagerToolButton, br, + + Column { tr("Android NDK list:"), Stretch() }, + m_ndkListWidget, + Column { + addCustomNdkButton, + removeCustomNdkButton, + m_makeDefaultNdkButton, + }, + downloadNdkToolButton, + br, + + Span(4, androidDetailsWidget), br, + + Span(4, m_createKitCheckBox) + } + }, + Group { + Title(tr("Android OpenSSL settings (Optional)")), + Grid { + tr("OpenSSL binaries location:"), + m_openSslPathChooser, + downloadOpenSslPrebuiltLibs, + br, + + Span(4, openSslDetailsWidget) + } + }, + Stretch(), + }.attachTo(this); + + connect(m_sdkLocationPathChooser, &PathChooser::rawPathChanged, this, &AndroidSettingsWidget::onSdkPathChanged); - connect(m_ui.ndkListWidget, &QListWidget::currentTextChanged, [this](const QString &ndk) { + connect(m_ndkListWidget, &QListWidget::currentTextChanged, + [this, removeCustomNdkButton](const QString &ndk) { updateUI(); - m_ui.removeCustomNdkButton->setEnabled(m_androidConfig.getCustomNdkList().contains(ndk)); + removeCustomNdkButton->setEnabled(m_androidConfig.getCustomNdkList().contains(ndk)); }); - connect(m_ui.addCustomNdkButton, &QPushButton::clicked, this, + connect(addCustomNdkButton, &QPushButton::clicked, this, &AndroidSettingsWidget::addCustomNdkItem); - connect(m_ui.removeCustomNdkButton, &QPushButton::clicked, this, [this] { + connect(removeCustomNdkButton, &QPushButton::clicked, this, [this] { if (isDefaultNdkSelected()) m_androidConfig.setDefaultNdk({}); - m_androidConfig.removeCustomNdk(m_ui.ndkListWidget->currentItem()->text()); - m_ui.ndkListWidget->takeItem(m_ui.ndkListWidget->currentRow()); + m_androidConfig.removeCustomNdk(m_ndkListWidget->currentItem()->text()); + m_ndkListWidget->takeItem(m_ndkListWidget->currentRow()); }); - connect(m_ui.makeDefaultNdkButton, &QPushButton::clicked, this, [this] { + connect(m_makeDefaultNdkButton, &QPushButton::clicked, this, [this] { const FilePath defaultNdk = isDefaultNdkSelected() ? FilePath() - : FilePath::fromUserInput(m_ui.ndkListWidget->currentItem()->text()); + : FilePath::fromUserInput(m_ndkListWidget->currentItem()->text()); m_androidConfig.setDefaultNdk(defaultNdk); updateUI(); }); - connect(m_ui.openSslPathChooser, &PathChooser::rawPathChanged, + connect(m_openSslPathChooser, &PathChooser::rawPathChanged, this, &AndroidSettingsWidget::validateOpenSsl); - connect(m_ui.CreateKitCheckBox, &QAbstractButton::toggled, + connect(m_createKitCheckBox, &QAbstractButton::toggled, this, &AndroidSettingsWidget::createKitToggled); - connect(m_ui.downloadNDKToolButton, &QAbstractButton::clicked, + connect(downloadNdkToolButton, &QAbstractButton::clicked, this, &AndroidSettingsWidget::openNDKDownloadUrl); - connect(m_ui.downloadSDKToolButton, &QAbstractButton::clicked, + connect(downloadSdkToolButton, &QAbstractButton::clicked, this, &AndroidSettingsWidget::openSDKDownloadUrl); - connect(m_ui.downloadOpenSSLPrebuiltLibs, &QAbstractButton::clicked, + connect(downloadOpenSslPrebuiltLibs, &QAbstractButton::clicked, this, &AndroidSettingsWidget::downloadOpenSslRepo); - connect(m_ui.downloadOpenJDKToolButton, &QAbstractButton::clicked, + connect(downloadOpenJdkToolButton, &QAbstractButton::clicked, this, &AndroidSettingsWidget::openOpenJDKDownloadUrl); + // Validate SDK again after any change in SDK packages. connect(&m_sdkManager, &AndroidSdkManager::packageReloadFinished, this, &AndroidSettingsWidget::validateSdk); @@ -409,9 +449,9 @@ AndroidSettingsWidget::AndroidSettingsWidget() m_androidSummary->setInProgressText("Retrieving packages information"); m_androidProgress->show(); }); - connect(m_ui.sdkManagerToolButton, &QAbstractButton::clicked, + connect(sdkManagerToolButton, &QAbstractButton::clicked, this, [this] { m_sdkManagerWidget->exec(); }); - connect(m_ui.sdkToolsAutoDownloadButton, &QAbstractButton::clicked, + connect(sdkToolsAutoDownloadButton, &QAbstractButton::clicked, this, &AndroidSettingsWidget::downloadSdk); connect(&m_sdkDownloader, &AndroidSdkDownloader::sdkDownloaderError, this, [this](const QString &error) { QMessageBox::warning(this, AndroidSdkDownloader::dialogTitle(), error); @@ -444,9 +484,79 @@ AndroidSettingsWidget::~AndroidSettingsWidget() delete m_sdkManagerWidget; } +void AndroidSettingsWidget::showEvent(QShowEvent *event) +{ + Q_UNUSED(event) + if (!m_isInitialReloadDone) { + validateJdk(); + // Reloading SDK packages (force) is still synchronous. Use zero timer + // to let settings dialog open first. + QTimer::singleShot(0, &m_sdkManager, std::bind(&AndroidSdkManager::reloadPackages, + &m_sdkManager, false)); + validateOpenSsl(); + m_isInitialReloadDone = true; + } +} + +void AndroidSettingsWidget::updateNdkList() +{ + m_ndkListWidget->clear(); + const auto installedPkgs = m_sdkManager.installedNdkPackages(); + for (const Ndk *ndk : installedPkgs) { + m_ndkListWidget->addItem(new QListWidgetItem(Icons::LOCKED.icon(), + ndk->installedLocation().toUserOutput())); + } + + const auto customNdks = m_androidConfig.getCustomNdkList(); + for (const QString &ndk : customNdks) { + if (m_androidConfig.isValidNdk(ndk)) { + m_ndkListWidget->addItem(new QListWidgetItem(Icons::UNLOCKED.icon(), ndk)); + } else { + m_androidConfig.removeCustomNdk(ndk); + } + } + + m_ndkListWidget->setCurrentRow(0); + + updateUI(); +} + +void AndroidSettingsWidget::addCustomNdkItem() +{ + const QString homePath = QStandardPaths::standardLocations(QStandardPaths::HomeLocation) + .constFirst(); + const QString ndkPath = QFileDialog::getExistingDirectory(this, tr("Select an NDK"), homePath); + + if (m_androidConfig.isValidNdk(ndkPath)) { + m_androidConfig.addCustomNdk(ndkPath); + if (m_ndkListWidget->findItems(ndkPath, Qt::MatchExactly).size() == 0) { + m_ndkListWidget->addItem(new QListWidgetItem(Icons::UNLOCKED.icon(), ndkPath)); + } + } else if (!ndkPath.isEmpty()) { + QMessageBox::warning( + this, + tr("Add Custom NDK"), + tr("The selected path has an invalid NDK. This might mean that the path contains space " + "characters, or that it does not have a \"toolchains\" sub-directory, or that the " + "NDK version could not be retrieved because of a missing \"source.properties\" or " + "\"RELEASE.TXT\" file")); + } +} + + +bool AndroidSettingsWidget::isDefaultNdkSelected() const +{ + if (!m_androidConfig.defaultNdk().isEmpty()) { + if (const QListWidgetItem *item = m_ndkListWidget->currentItem()) { + return FilePath::fromUserInput(item->text()) == m_androidConfig.defaultNdk(); + } + } + return false; +} + void AndroidSettingsWidget::validateJdk() { - m_androidConfig.setOpenJDKLocation(m_ui.OpenJDKLocationPathChooser->filePath()); + m_androidConfig.setOpenJDKLocation(m_openJdkLocationPathChooser->filePath()); bool jdkPathExists = m_androidConfig.openJDKLocation().exists(); const FilePath bin = m_androidConfig.openJDKLocation() .pathAppended("bin/javac" QTC_HOST_EXE_SUFFIX); @@ -460,7 +570,7 @@ void AndroidSettingsWidget::validateJdk() void AndroidSettingsWidget::validateOpenSsl() { - m_androidConfig.setOpenSslLocation(m_ui.openSslPathChooser->filePath()); + m_androidConfig.setOpenSslLocation(m_openSslPathChooser->filePath()); m_openSslSummary->setPointValid(OpenSslPathExistsRow, m_androidConfig.openSslLocation().exists()); @@ -475,19 +585,19 @@ void AndroidSettingsWidget::validateOpenSsl() void AndroidSettingsWidget::onSdkPathChanged() { - const FilePath sdkPath = m_ui.SDKLocationPathChooser->filePath().cleanPath(); + const FilePath sdkPath = m_sdkLocationPathChooser->filePath().cleanPath(); m_androidConfig.setSdkLocation(sdkPath); FilePath currentOpenSslPath = m_androidConfig.openSslLocation(); if (currentOpenSslPath.isEmpty() || !currentOpenSslPath.exists()) currentOpenSslPath = sdkPath.pathAppended("android_openssl"); - m_ui.openSslPathChooser->setFilePath(currentOpenSslPath); + m_openSslPathChooser->setFilePath(currentOpenSslPath); // Package reload will trigger validateSdk. m_sdkManager.reloadPackages(); } void AndroidSettingsWidget::validateSdk() { - const FilePath sdkPath = m_ui.SDKLocationPathChooser->filePath().cleanPath(); + const FilePath sdkPath = m_sdkLocationPathChooser->filePath().cleanPath(); m_androidConfig.setSdkLocation(sdkPath); const FilePath path = m_androidConfig.sdkLocation(); @@ -542,7 +652,7 @@ void AndroidSettingsWidget::openOpenJDKDownloadUrl() void AndroidSettingsWidget::downloadOpenSslRepo(const bool silent) { - const FilePath openSslPath = m_ui.openSslPathChooser->filePath(); + const FilePath openSslPath = m_openSslPathChooser->filePath(); const QString openSslCloneTitle(tr("OpenSSL Cloning")); if (m_openSslSummary->allRowsOk()) { @@ -610,7 +720,7 @@ void AndroidSettingsWidget::downloadOpenSslRepo(const bool silent) } } validateOpenSsl(); - m_ui.openSslPathChooser->triggerChanged(); // After cloning, the path exists + m_openSslPathChooser->triggerChanged(); // After cloning, the path exists if (!openSslProgressDialog->wasCanceled() || gitCloner->result() == ProcessResult::FinishedWithError) { @@ -624,7 +734,7 @@ void AndroidSettingsWidget::downloadOpenSslRepo(const bool silent) void AndroidSettingsWidget::createKitToggled() { - m_androidConfig.setAutomaticKitCreation(m_ui.CreateKitCheckBox->isChecked()); + m_androidConfig.setAutomaticKitCreation(m_createKitCheckBox->isChecked()); } void AndroidSettingsWidget::updateUI() @@ -632,7 +742,7 @@ void AndroidSettingsWidget::updateUI() const bool androidSetupOk = m_androidSummary->allRowsOk(); const bool openSslOk = m_openSslSummary->allRowsOk(); - const QListWidgetItem *currentItem = m_ui.ndkListWidget->currentItem(); + const QListWidgetItem *currentItem = m_ndkListWidget->currentItem(); const FilePath currentNdk = FilePath::fromString(currentItem ? currentItem->text() : ""); const QString infoText = tr("(SDK Version: %1, NDK Version: %2)") .arg(m_androidConfig.sdkToolsVersion().toString()) @@ -644,19 +754,19 @@ void AndroidSettingsWidget::updateUI() // Mark default entry in NDK list widget { - const QFont font = m_ui.ndkListWidget->font(); + const QFont font = m_ndkListWidget->font(); QFont markedFont = font; markedFont.setItalic(true); - for (int row = 0; row < m_ui.ndkListWidget->count(); ++row) { - QListWidgetItem *item = m_ui.ndkListWidget->item(row); + for (int row = 0; row < m_ndkListWidget->count(); ++row) { + QListWidgetItem *item = m_ndkListWidget->item(row); const bool isDefaultNdk = FilePath::fromUserInput(item->text()) == m_androidConfig.defaultNdk(); item->setFont(isDefaultNdk ? markedFont : font); } } - m_ui.makeDefaultNdkButton->setText(isDefaultNdkSelected() ? tr("Unset Default") - : tr("Make Default")); + m_makeDefaultNdkButton->setText(isDefaultNdkSelected() ? tr("Unset Default") + : tr("Make Default")); } void AndroidSettingsWidget::downloadSdk() @@ -669,7 +779,7 @@ void AndroidSettingsWidget::downloadSdk() } const QString message = tr("Download and install Android SDK Tools to %1?") - .arg("\n\"" + m_ui.SDKLocationPathChooser->filePath().cleanPath().toUserOutput() + .arg("\n\"" + m_sdkLocationPathChooser->filePath().cleanPath().toUserOutput() + "\""); auto userInput = QMessageBox::information(this, AndroidSdkDownloader::dialogTitle(), message, QMessageBox::Yes | QMessageBox::No); @@ -687,5 +797,4 @@ AndroidSettingsPage::AndroidSettingsPage() setWidgetCreator([] { return new AndroidSettingsWidget; }); } -} // namespace Internal -} // namespace Android +} // Android::Internal diff --git a/src/plugins/android/androidsettingswidget.h b/src/plugins/android/androidsettingswidget.h index b411705f7e0..2ca7c122605 100644 --- a/src/plugins/android/androidsettingswidget.h +++ b/src/plugins/android/androidsettingswidget.h @@ -27,8 +27,7 @@ #include -namespace Android { -namespace Internal { +namespace Android::Internal { class AndroidSettingsPage final : public Core::IOptionsPage { @@ -36,5 +35,4 @@ public: AndroidSettingsPage(); }; -} // namespace Internal -} // namespace Android +} // Android::Internal diff --git a/src/plugins/android/androidsettingswidget.ui b/src/plugins/android/androidsettingswidget.ui deleted file mode 100644 index a4d3df36453..00000000000 --- a/src/plugins/android/androidsettingswidget.ui +++ /dev/null @@ -1,272 +0,0 @@ - - - AndroidSettingsWidget - - - Android Configuration - - - - - - Android Settings - - - - - - - - - Open Android SDK download URL in the system's browser. - - - - - - - - - true - - - - 0 - 0 - - - - Add the selected custom NDK. The toolchains and debuggers will be created automatically. - - - Add... - - - - - - - false - - - - 0 - 0 - - - - Remove the selected NDK if it has been added manually. - - - Remove - - - - - - - Force a specific NDK installation to be used by all Android kits.<br/>Note that the forced NDK might not be compatible with all registered Qt versions. - - - - - - - - - - - - - 0 - 0 - - - - QAbstractScrollArea::AdjustToContents - - - - 16 - 16 - - - - QListView::Adjust - - - 0 - - - false - - - - - - - - 0 - 0 - - - - JDK location: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - - - - Open JDK download URL in the system's browser. - - - - - - - - 0 - 0 - - - - Android SDK location: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Set Up SDK - - - - - - - SDK Manager - - - - - - - Android NDK list: - - - - - - - Open Android NDK download URL in the system's browser. - - - - - - - - - - Automatically create kits for Android tool chains - - - true - - - - - - - - - - Android OpenSSL settings (Optional) - - - - - - - 0 - 0 - - - - OpenSSL binaries location: - - - - - - - - - - - 0 - 0 - - - - Download OpenSSL - - - - - - - Select the path of the prebuilt OpenSSL binaries. - - - - - - - - - - Qt::Vertical - - - - - - - - Utils::PathChooser - QWidget -
utils/pathchooser.h
- 1 - - editingFinished() - browsingFinished() - -
- - Utils::DetailsWidget - QWidget -
utils/detailswidget.h
- 1 -
-
- - -