forked from qt-creator/qt-creator
Android: Edge towards AndroidApkBuildStep aspectification
Unexport AndroidApkBuildStep, remove AndroidBuildApkWidget file pair, de-Q_OBJECT-ify AndroidBuildApkWidget (and as roadkill PasswordInputDialog). Change-Id: Id3b51dd33774aac70a4f23a8ab4cfb556ed1f2b5 Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
@@ -8,7 +8,6 @@ add_qtc_plugin(Android
|
|||||||
android_global.h
|
android_global.h
|
||||||
androidavdmanager.cpp androidavdmanager.h
|
androidavdmanager.cpp androidavdmanager.h
|
||||||
androidbuildapkstep.cpp androidbuildapkstep.h
|
androidbuildapkstep.cpp androidbuildapkstep.h
|
||||||
androidbuildapkwidget.cpp androidbuildapkwidget.h
|
|
||||||
androidconfigurations.cpp androidconfigurations.h
|
androidconfigurations.cpp androidconfigurations.h
|
||||||
androidconstants.h
|
androidconstants.h
|
||||||
androidcreatekeystorecertificate.cpp androidcreatekeystorecertificate.h androidcreatekeystorecertificate.ui
|
androidcreatekeystorecertificate.cpp androidcreatekeystorecertificate.h androidcreatekeystorecertificate.ui
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ HEADERS += \
|
|||||||
avddialog.h \
|
avddialog.h \
|
||||||
android_global.h \
|
android_global.h \
|
||||||
androidbuildapkstep.h \
|
androidbuildapkstep.h \
|
||||||
androidbuildapkwidget.h \
|
|
||||||
androidsdkmanager.h \
|
androidsdkmanager.h \
|
||||||
androidavdmanager.h \
|
androidavdmanager.h \
|
||||||
adbcommandswidget.h \
|
adbcommandswidget.h \
|
||||||
@@ -88,7 +87,6 @@ SOURCES += \
|
|||||||
javaindenter.cpp \
|
javaindenter.cpp \
|
||||||
avddialog.cpp \
|
avddialog.cpp \
|
||||||
androidbuildapkstep.cpp \
|
androidbuildapkstep.cpp \
|
||||||
androidbuildapkwidget.cpp \
|
|
||||||
androidsdkmanager.cpp \
|
androidsdkmanager.cpp \
|
||||||
androidavdmanager.cpp \
|
androidavdmanager.cpp \
|
||||||
adbcommandswidget.cpp \
|
adbcommandswidget.cpp \
|
||||||
|
|||||||
@@ -34,8 +34,6 @@ Project {
|
|||||||
"androidcreatekeystorecertificate.ui",
|
"androidcreatekeystorecertificate.ui",
|
||||||
"androidbuildapkstep.cpp",
|
"androidbuildapkstep.cpp",
|
||||||
"androidbuildapkstep.h",
|
"androidbuildapkstep.h",
|
||||||
"androidbuildapkwidget.cpp",
|
|
||||||
"androidbuildapkwidget.h",
|
|
||||||
"androiddeployqtstep.cpp",
|
"androiddeployqtstep.cpp",
|
||||||
"androiddeployqtstep.h",
|
"androiddeployqtstep.h",
|
||||||
"androiddebugsupport.cpp",
|
"androiddebugsupport.cpp",
|
||||||
|
|||||||
@@ -26,12 +26,14 @@
|
|||||||
|
|
||||||
#include "androidbuildapkstep.h"
|
#include "androidbuildapkstep.h"
|
||||||
|
|
||||||
#include "androidbuildapkwidget.h"
|
|
||||||
#include "androidconfigurations.h"
|
#include "androidconfigurations.h"
|
||||||
#include "androidconstants.h"
|
#include "androidconstants.h"
|
||||||
|
#include "androidcreatekeystorecertificate.h"
|
||||||
|
#include "androidextralibrarylistmodel.h"
|
||||||
#include "androidmanager.h"
|
#include "androidmanager.h"
|
||||||
#include "androidsdkmanager.h"
|
#include "androidsdkmanager.h"
|
||||||
#include "certificatesmodel.h"
|
#include "certificatesmodel.h"
|
||||||
|
#include "createandroidmanifestwizard.h"
|
||||||
|
|
||||||
#include "javaparser.h"
|
#include "javaparser.h"
|
||||||
|
|
||||||
@@ -39,11 +41,12 @@
|
|||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
|
|
||||||
#include <projectexplorer/buildconfiguration.h>
|
#include <projectexplorer/buildconfiguration.h>
|
||||||
|
#include <projectexplorer/buildstep.h>
|
||||||
#include <projectexplorer/buildsteplist.h>
|
#include <projectexplorer/buildsteplist.h>
|
||||||
#include <projectexplorer/buildsystem.h>
|
#include <projectexplorer/buildsystem.h>
|
||||||
#include <projectexplorer/processparameters.h>
|
#include <projectexplorer/processparameters.h>
|
||||||
#include <projectexplorer/project.h>
|
|
||||||
#include <projectexplorer/projectexplorerconstants.h>
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
|
#include <projectexplorer/project.h>
|
||||||
#include <projectexplorer/projectnodes.h>
|
#include <projectexplorer/projectnodes.h>
|
||||||
#include <projectexplorer/target.h>
|
#include <projectexplorer/target.h>
|
||||||
#include <projectexplorer/taskhub.h>
|
#include <projectexplorer/taskhub.h>
|
||||||
@@ -51,36 +54,44 @@
|
|||||||
#include <qtsupport/qtkitinformation.h>
|
#include <qtsupport/qtkitinformation.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
|
#include <utils/fancylineedit.h>
|
||||||
#include <utils/infolabel.h>
|
#include <utils/infolabel.h>
|
||||||
|
#include <utils/pathchooser.h>
|
||||||
#include <utils/qtcprocess.h>
|
#include <utils/qtcprocess.h>
|
||||||
#include <utils/synchronousprocess.h>
|
#include <utils/synchronousprocess.h>
|
||||||
|
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QComboBox>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QFormLayout>
|
||||||
|
#include <QGroupBox>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
|
#include <QListView>
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <QToolButton>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
using namespace ProjectExplorer;
|
using namespace ProjectExplorer;
|
||||||
using namespace QtSupport;
|
using namespace QtSupport;
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
using namespace Android::Internal;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
static Q_LOGGING_CATEGORY(buildapkstepLog, "qtc.android.build.androidbuildapkstep", QtWarningMsg)
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Android {
|
namespace Android {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
static Q_LOGGING_CATEGORY(buildapkstepLog, "qtc.android.build.androidbuildapkstep", QtWarningMsg)
|
||||||
|
|
||||||
const QVersionNumber gradleScriptRevokedSdkVersion(25, 3, 0);
|
const QVersionNumber gradleScriptRevokedSdkVersion(25, 3, 0);
|
||||||
const char KeystoreLocationKey[] = "KeystoreLocation";
|
const char KeystoreLocationKey[] = "KeystoreLocation";
|
||||||
@@ -89,7 +100,7 @@ const char VerboseOutputKey[] = "VerboseOutput";
|
|||||||
|
|
||||||
class PasswordInputDialog : public QDialog
|
class PasswordInputDialog : public QDialog
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_DECLARE_TR_FUNCTIONS(Android::Internal::AndroidBuildApkStep)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Context{
|
enum Context{
|
||||||
@@ -114,6 +125,368 @@ private:
|
|||||||
this);
|
this);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// AndroidBuildApkWidget
|
||||||
|
|
||||||
|
class AndroidBuildApkWidget : public BuildStepConfigWidget
|
||||||
|
{
|
||||||
|
Q_DECLARE_TR_FUNCTIONS(Android::Internal::AndroidBuildApkStep)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit AndroidBuildApkWidget(AndroidBuildApkStep *step);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setCertificates();
|
||||||
|
void updateSigningWarning();
|
||||||
|
void signPackageCheckBoxToggled(bool checked);
|
||||||
|
void onOpenSslCheckBoxChanged();
|
||||||
|
bool isOpenSslLibsIncluded();
|
||||||
|
QString openSslIncludeFileContent(const FilePath &projectPath);
|
||||||
|
|
||||||
|
QWidget *createApplicationGroup();
|
||||||
|
QWidget *createSignPackageGroup();
|
||||||
|
QWidget *createAdvancedGroup();
|
||||||
|
QWidget *createAdditionalLibrariesGroup();
|
||||||
|
|
||||||
|
private:
|
||||||
|
AndroidBuildApkStep *m_step = nullptr;
|
||||||
|
QCheckBox *m_signPackageCheckBox = nullptr;
|
||||||
|
InfoLabel *m_signingDebugWarningLabel = nullptr;
|
||||||
|
QComboBox *m_certificatesAliasComboBox = nullptr;
|
||||||
|
QCheckBox *m_addDebuggerCheckBox = nullptr;
|
||||||
|
QCheckBox *m_openSslCheckBox = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidBuildApkWidget::AndroidBuildApkWidget(AndroidBuildApkStep *step)
|
||||||
|
: BuildStepConfigWidget(step), m_step(step)
|
||||||
|
{
|
||||||
|
setDisplayName("<b>" + tr("Build Android APK") + "</b>");
|
||||||
|
setSummaryText(displayName());
|
||||||
|
|
||||||
|
auto vbox = new QVBoxLayout(this);
|
||||||
|
vbox->addWidget(createSignPackageGroup());
|
||||||
|
vbox->addWidget(createApplicationGroup());
|
||||||
|
vbox->addWidget(createAdvancedGroup());
|
||||||
|
vbox->addWidget(createAdditionalLibrariesGroup());
|
||||||
|
|
||||||
|
connect(m_step->buildConfiguration(), &BuildConfiguration::buildTypeChanged,
|
||||||
|
this, &AndroidBuildApkWidget::updateSigningWarning);
|
||||||
|
|
||||||
|
connect(m_signPackageCheckBox, &QAbstractButton::clicked,
|
||||||
|
m_addDebuggerCheckBox, &QWidget::setEnabled);
|
||||||
|
|
||||||
|
signPackageCheckBoxToggled(m_step->signPackage());
|
||||||
|
updateSigningWarning();
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget *AndroidBuildApkWidget::createApplicationGroup()
|
||||||
|
{
|
||||||
|
const int minApiSupported = AndroidManager::apiLevelRange().first;
|
||||||
|
QStringList targets = AndroidConfig::apiLevelNamesFor(AndroidConfigurations::sdkManager()->
|
||||||
|
filteredSdkPlatforms(minApiSupported));
|
||||||
|
targets.removeDuplicates();
|
||||||
|
|
||||||
|
auto group = new QGroupBox(tr("Application"), this);
|
||||||
|
|
||||||
|
auto targetSDKComboBox = new QComboBox();
|
||||||
|
targetSDKComboBox->addItems(targets);
|
||||||
|
targetSDKComboBox->setCurrentIndex(targets.indexOf(m_step->buildTargetSdk()));
|
||||||
|
|
||||||
|
const auto cbActivated = QOverload<int>::of(&QComboBox::activated);
|
||||||
|
connect(targetSDKComboBox, cbActivated, this, [this, targetSDKComboBox](int idx) {
|
||||||
|
const QString sdk = targetSDKComboBox->itemText(idx);
|
||||||
|
m_step->setBuildTargetSdk(sdk);
|
||||||
|
AndroidManager::updateGradleProperties(m_step->target(), QString()); // FIXME: Use real key.
|
||||||
|
});
|
||||||
|
|
||||||
|
auto formLayout = new QFormLayout(group);
|
||||||
|
formLayout->addRow(tr("Android build SDK:"), targetSDKComboBox);
|
||||||
|
|
||||||
|
auto createAndroidTemplatesButton = new QPushButton(tr("Create Templates"));
|
||||||
|
createAndroidTemplatesButton->setToolTip(
|
||||||
|
tr("Create an Android package for Custom Java code, assets, and Gradle configurations."));
|
||||||
|
connect(createAndroidTemplatesButton, &QAbstractButton::clicked, this, [this] {
|
||||||
|
CreateAndroidManifestWizard wizard(m_step->buildSystem());
|
||||||
|
wizard.exec();
|
||||||
|
});
|
||||||
|
|
||||||
|
formLayout->addRow(tr("Android customization:"), createAndroidTemplatesButton);
|
||||||
|
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget *AndroidBuildApkWidget::createSignPackageGroup()
|
||||||
|
{
|
||||||
|
QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
|
||||||
|
sizePolicy.setHorizontalStretch(0);
|
||||||
|
sizePolicy.setVerticalStretch(0);
|
||||||
|
|
||||||
|
auto group = new QGroupBox(tr("Application Signature"), this);
|
||||||
|
|
||||||
|
auto keystoreLocationLabel = new QLabel(tr("Keystore:"), group);
|
||||||
|
keystoreLocationLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
|
||||||
|
|
||||||
|
auto keystoreLocationChooser = new PathChooser(group);
|
||||||
|
keystoreLocationChooser->setExpectedKind(PathChooser::File);
|
||||||
|
keystoreLocationChooser->lineEdit()->setReadOnly(true);
|
||||||
|
keystoreLocationChooser->setPath(m_step->keystorePath().toUserOutput());
|
||||||
|
keystoreLocationChooser->setInitialBrowsePathBackup(QDir::homePath());
|
||||||
|
keystoreLocationChooser->setPromptDialogFilter(tr("Keystore files (*.keystore *.jks)"));
|
||||||
|
keystoreLocationChooser->setPromptDialogTitle(tr("Select Keystore File"));
|
||||||
|
connect(keystoreLocationChooser, &PathChooser::pathChanged, this, [this](const QString &path) {
|
||||||
|
FilePath file = FilePath::fromString(path);
|
||||||
|
m_step->setKeystorePath(file);
|
||||||
|
m_signPackageCheckBox->setChecked(!file.isEmpty());
|
||||||
|
if (!file.isEmpty())
|
||||||
|
setCertificates();
|
||||||
|
});
|
||||||
|
|
||||||
|
auto keystoreCreateButton = new QPushButton(tr("Create..."), group);
|
||||||
|
connect(keystoreCreateButton, &QAbstractButton::clicked, this, [this, keystoreLocationChooser] {
|
||||||
|
AndroidCreateKeystoreCertificate d;
|
||||||
|
if (d.exec() != QDialog::Accepted)
|
||||||
|
return;
|
||||||
|
keystoreLocationChooser->setPath(d.keystoreFilePath().toUserOutput());
|
||||||
|
m_step->setKeystorePath(d.keystoreFilePath());
|
||||||
|
m_step->setKeystorePassword(d.keystorePassword());
|
||||||
|
m_step->setCertificateAlias(d.certificateAlias());
|
||||||
|
m_step->setCertificatePassword(d.certificatePassword());
|
||||||
|
setCertificates();
|
||||||
|
});
|
||||||
|
|
||||||
|
m_signPackageCheckBox = new QCheckBox(tr("Sign package"), group);
|
||||||
|
m_signPackageCheckBox->setChecked(m_step->signPackage());
|
||||||
|
|
||||||
|
m_signingDebugWarningLabel = new Utils::InfoLabel(tr("Signing a debug package"),
|
||||||
|
Utils::InfoLabel::Warning, group);
|
||||||
|
m_signingDebugWarningLabel->hide();
|
||||||
|
|
||||||
|
auto certificateAliasLabel = new QLabel(tr("Certificate alias:"), group);
|
||||||
|
certificateAliasLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
|
||||||
|
|
||||||
|
m_certificatesAliasComboBox = new QComboBox(group);
|
||||||
|
m_certificatesAliasComboBox->setEnabled(false);
|
||||||
|
QSizePolicy sizePolicy2(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||||
|
sizePolicy2.setHorizontalStretch(0);
|
||||||
|
sizePolicy2.setVerticalStretch(0);
|
||||||
|
m_certificatesAliasComboBox->setSizePolicy(sizePolicy2);
|
||||||
|
m_certificatesAliasComboBox->setMinimumSize(QSize(300, 0));
|
||||||
|
|
||||||
|
auto horizontalLayout_2 = new QHBoxLayout;
|
||||||
|
horizontalLayout_2->addWidget(keystoreLocationLabel);
|
||||||
|
horizontalLayout_2->addWidget(keystoreLocationChooser);
|
||||||
|
horizontalLayout_2->addWidget(keystoreCreateButton);
|
||||||
|
|
||||||
|
auto horizontalLayout_3 = new QHBoxLayout;
|
||||||
|
horizontalLayout_3->addWidget(m_signingDebugWarningLabel);
|
||||||
|
horizontalLayout_3->addWidget(certificateAliasLabel);
|
||||||
|
horizontalLayout_3->addWidget(m_certificatesAliasComboBox);
|
||||||
|
|
||||||
|
auto vbox = new QVBoxLayout(group);
|
||||||
|
vbox->addLayout(horizontalLayout_2);
|
||||||
|
vbox->addWidget(m_signPackageCheckBox);
|
||||||
|
vbox->addLayout(horizontalLayout_3);
|
||||||
|
|
||||||
|
connect(m_signPackageCheckBox, &QAbstractButton::toggled,
|
||||||
|
this, &AndroidBuildApkWidget::signPackageCheckBoxToggled);
|
||||||
|
|
||||||
|
auto updateAlias = [this](int idx) {
|
||||||
|
QString alias = m_certificatesAliasComboBox->itemText(idx);
|
||||||
|
if (!alias.isEmpty())
|
||||||
|
m_step->setCertificateAlias(alias);
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto cbActivated = QOverload<int>::of(&QComboBox::activated);
|
||||||
|
const auto cbCurrentIndexChanged = QOverload<int>::of(&QComboBox::currentIndexChanged);
|
||||||
|
|
||||||
|
connect(m_certificatesAliasComboBox, cbActivated, this, updateAlias);
|
||||||
|
connect(m_certificatesAliasComboBox, cbCurrentIndexChanged, this, updateAlias);
|
||||||
|
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget *AndroidBuildApkWidget::createAdvancedGroup()
|
||||||
|
{
|
||||||
|
auto group = new QGroupBox(tr("Advanced Actions"), this);
|
||||||
|
|
||||||
|
auto openPackageLocationCheckBox = new QCheckBox(tr("Open package location after build"), group);
|
||||||
|
openPackageLocationCheckBox->setChecked(m_step->openPackageLocation());
|
||||||
|
connect(openPackageLocationCheckBox, &QAbstractButton::toggled,
|
||||||
|
this, [this](bool checked) { m_step->setOpenPackageLocation(checked); });
|
||||||
|
|
||||||
|
m_addDebuggerCheckBox = new QCheckBox(tr("Add debug server"), group);
|
||||||
|
m_addDebuggerCheckBox->setEnabled(false);
|
||||||
|
m_addDebuggerCheckBox->setToolTip(tr("Packages debug server with "
|
||||||
|
"the APK to enable debugging. For the signed APK this option is unchecked by default."));
|
||||||
|
m_addDebuggerCheckBox->setChecked(m_step->addDebugger());
|
||||||
|
connect(m_addDebuggerCheckBox, &QAbstractButton::toggled,
|
||||||
|
m_step, &AndroidBuildApkStep::setAddDebugger);
|
||||||
|
|
||||||
|
auto verboseOutputCheckBox = new QCheckBox(tr("Verbose output"), group);
|
||||||
|
verboseOutputCheckBox->setChecked(m_step->verboseOutput());
|
||||||
|
|
||||||
|
auto vbox = new QVBoxLayout(group);
|
||||||
|
QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(m_step->kit());
|
||||||
|
if (version && version->supportsMultipleQtAbis()) {
|
||||||
|
auto buildAAB = new QCheckBox(tr("Build .aab (Android App Bundle)"), group);
|
||||||
|
buildAAB->setChecked(m_step->buildAAB());
|
||||||
|
connect(buildAAB, &QAbstractButton::toggled, m_step, &AndroidBuildApkStep::setBuildAAB);
|
||||||
|
vbox->addWidget(buildAAB);
|
||||||
|
}
|
||||||
|
vbox->addWidget(openPackageLocationCheckBox);
|
||||||
|
vbox->addWidget(verboseOutputCheckBox);
|
||||||
|
vbox->addWidget(m_addDebuggerCheckBox);
|
||||||
|
|
||||||
|
connect(verboseOutputCheckBox, &QAbstractButton::toggled,
|
||||||
|
this, [this](bool checked) { m_step->setVerboseOutput(checked); });
|
||||||
|
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget *AndroidBuildApkWidget::createAdditionalLibrariesGroup()
|
||||||
|
{
|
||||||
|
auto group = new QGroupBox(tr("Additional Libraries"));
|
||||||
|
group->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
|
||||||
|
|
||||||
|
auto libsModel = new AndroidExtraLibraryListModel(m_step->buildSystem(), this);
|
||||||
|
connect(libsModel, &AndroidExtraLibraryListModel::enabledChanged, this,
|
||||||
|
[this, group](const bool enabled) {
|
||||||
|
group->setEnabled(enabled);
|
||||||
|
m_openSslCheckBox->setChecked(isOpenSslLibsIncluded());
|
||||||
|
});
|
||||||
|
|
||||||
|
auto libsView = new QListView;
|
||||||
|
libsView->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||||
|
libsView->setToolTip(tr("List of extra libraries to include in Android package and load on startup."));
|
||||||
|
libsView->setModel(libsModel);
|
||||||
|
|
||||||
|
auto addLibButton = new QToolButton;
|
||||||
|
addLibButton->setText(tr("Add..."));
|
||||||
|
addLibButton->setToolTip(tr("Select library to include in package."));
|
||||||
|
addLibButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
|
||||||
|
addLibButton->setToolButtonStyle(Qt::ToolButtonTextOnly);
|
||||||
|
connect(addLibButton, &QAbstractButton::clicked, this, [this, libsModel] {
|
||||||
|
QStringList fileNames = QFileDialog::getOpenFileNames(this,
|
||||||
|
tr("Select additional libraries"),
|
||||||
|
QDir::homePath(),
|
||||||
|
tr("Libraries (*.so)"));
|
||||||
|
if (!fileNames.isEmpty())
|
||||||
|
libsModel->addEntries(fileNames);
|
||||||
|
});
|
||||||
|
|
||||||
|
auto removeLibButton = new QToolButton;
|
||||||
|
removeLibButton->setText(tr("Remove"));
|
||||||
|
removeLibButton->setToolTip(tr("Remove currently selected library from list."));
|
||||||
|
connect(removeLibButton, &QAbstractButton::clicked, this, [libsModel, libsView] {
|
||||||
|
QModelIndexList removeList = libsView->selectionModel()->selectedIndexes();
|
||||||
|
libsModel->removeEntries(removeList);
|
||||||
|
});
|
||||||
|
|
||||||
|
auto libsButtonLayout = new QVBoxLayout;
|
||||||
|
libsButtonLayout->addWidget(addLibButton);
|
||||||
|
libsButtonLayout->addWidget(removeLibButton);
|
||||||
|
libsButtonLayout->addStretch(1);
|
||||||
|
|
||||||
|
m_openSslCheckBox = new QCheckBox(tr("Include prebuilt OpenSSL libraries"));
|
||||||
|
m_openSslCheckBox->setToolTip(tr("This is useful for apps that use SSL operations. The path "
|
||||||
|
"can be defined in Tools > Options > Devices > Android."));
|
||||||
|
connect(m_openSslCheckBox, &QAbstractButton::clicked, this,
|
||||||
|
&AndroidBuildApkWidget::onOpenSslCheckBoxChanged);
|
||||||
|
|
||||||
|
auto grid = new QGridLayout(group);
|
||||||
|
grid->addWidget(m_openSslCheckBox, 0, 0);
|
||||||
|
grid->addWidget(libsView, 1, 0);
|
||||||
|
grid->addLayout(libsButtonLayout, 1, 1);
|
||||||
|
|
||||||
|
QItemSelectionModel *libSelection = libsView->selectionModel();
|
||||||
|
connect(libSelection, &QItemSelectionModel::selectionChanged, this, [libSelection, removeLibButton] {
|
||||||
|
removeLibButton->setEnabled(libSelection->hasSelection());
|
||||||
|
});
|
||||||
|
|
||||||
|
Target *target = m_step->target();
|
||||||
|
const QString buildKey = target->activeBuildKey();
|
||||||
|
const ProjectNode *node = target->project()->findNodeForBuildKey(buildKey);
|
||||||
|
group->setEnabled(node && !node->parseInProgress());
|
||||||
|
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidBuildApkWidget::signPackageCheckBoxToggled(bool checked)
|
||||||
|
{
|
||||||
|
m_certificatesAliasComboBox->setEnabled(checked);
|
||||||
|
m_step->setSignPackage(checked);
|
||||||
|
m_addDebuggerCheckBox->setChecked(!checked);
|
||||||
|
updateSigningWarning();
|
||||||
|
if (!checked)
|
||||||
|
return;
|
||||||
|
if (!m_step->keystorePath().isEmpty())
|
||||||
|
setCertificates();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidBuildApkWidget::onOpenSslCheckBoxChanged()
|
||||||
|
{
|
||||||
|
Utils::FilePath projectPath = m_step->buildConfiguration()->buildSystem()->projectFilePath();
|
||||||
|
QFile projectFile(projectPath.toString());
|
||||||
|
if (!projectFile.open(QIODevice::ReadWrite | QIODevice::Text)) {
|
||||||
|
qWarning() << "Cound't open project file to add OpenSSL extra libs: " << projectPath;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString searchStr = openSslIncludeFileContent(projectPath);
|
||||||
|
QTextStream textStream(&projectFile);
|
||||||
|
|
||||||
|
QString fileContent = textStream.readAll();
|
||||||
|
if (!m_openSslCheckBox->isChecked()) {
|
||||||
|
fileContent.remove("\n" + searchStr);
|
||||||
|
} else if (!fileContent.contains(searchStr, Qt::CaseSensitive)) {
|
||||||
|
fileContent.append(searchStr + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
projectFile.resize(0);
|
||||||
|
textStream << fileContent;
|
||||||
|
projectFile.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AndroidBuildApkWidget::isOpenSslLibsIncluded()
|
||||||
|
{
|
||||||
|
Utils::FilePath projectPath = m_step->buildConfiguration()->buildSystem()->projectFilePath();
|
||||||
|
const QString searchStr = openSslIncludeFileContent(projectPath);
|
||||||
|
QFile projectFile(projectPath.toString());
|
||||||
|
projectFile.open(QIODevice::ReadOnly);
|
||||||
|
QTextStream textStream(&projectFile);
|
||||||
|
QString fileContent = textStream.readAll();
|
||||||
|
projectFile.close();
|
||||||
|
return fileContent.contains(searchStr, Qt::CaseSensitive);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString AndroidBuildApkWidget::openSslIncludeFileContent(const FilePath &projectPath)
|
||||||
|
{
|
||||||
|
QString openSslPath = AndroidConfigurations::currentConfig().openSslLocation().toString();
|
||||||
|
if (projectPath.endsWith(".pro"))
|
||||||
|
return "android: include(" + openSslPath + "/openssl.pri)";
|
||||||
|
if (projectPath.endsWith("CMakeLists.txt"))
|
||||||
|
return "if (ANDROID)\n include(" + openSslPath + "/CMakeLists.txt)\nendif()";
|
||||||
|
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidBuildApkWidget::setCertificates()
|
||||||
|
{
|
||||||
|
QAbstractItemModel *certificates = m_step->keystoreCertificates();
|
||||||
|
if (certificates) {
|
||||||
|
m_signPackageCheckBox->setChecked(certificates);
|
||||||
|
m_certificatesAliasComboBox->setModel(certificates);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidBuildApkWidget::updateSigningWarning()
|
||||||
|
{
|
||||||
|
bool nonRelease = m_step->buildType() != BuildConfiguration::Release;
|
||||||
|
bool visible = m_step->signPackage() && nonRelease;
|
||||||
|
m_signingDebugWarningLabel->setVisible(visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
// AndroidBuildApkStep
|
||||||
|
|
||||||
AndroidBuildApkStep::AndroidBuildApkStep(BuildStepList *parent, Utils::Id id)
|
AndroidBuildApkStep::AndroidBuildApkStep(BuildStepList *parent, Utils::Id id)
|
||||||
: AbstractProcessStep(parent, id),
|
: AbstractProcessStep(parent, id),
|
||||||
m_buildTargetSdk(AndroidConfig::apiLevelNameFor(AndroidConfigurations::
|
m_buildTargetSdk(AndroidConfig::apiLevelNameFor(AndroidConfigurations::
|
||||||
@@ -710,8 +1083,6 @@ QString PasswordInputDialog::getPassword(Context context, std::function<bool (co
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
// AndroidBuildApkStepFactory
|
// AndroidBuildApkStepFactory
|
||||||
|
|
||||||
AndroidBuildApkStepFactory::AndroidBuildApkStepFactory()
|
AndroidBuildApkStepFactory::AndroidBuildApkStepFactory()
|
||||||
@@ -725,5 +1096,3 @@ AndroidBuildApkStepFactory::AndroidBuildApkStepFactory()
|
|||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace Android
|
} // namespace Android
|
||||||
|
|
||||||
#include "androidbuildapkstep.moc"
|
|
||||||
|
|||||||
@@ -37,8 +37,9 @@ class QAbstractItemModel;
|
|||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace Android {
|
namespace Android {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
class ANDROID_EXPORT AndroidBuildApkStep : public ProjectExplorer::AbstractProcessStep
|
class AndroidBuildApkStep : public ProjectExplorer::AbstractProcessStep
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@@ -110,8 +111,6 @@ private:
|
|||||||
QString m_inputFile;
|
QString m_inputFile;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class AndroidBuildApkStepFactory : public ProjectExplorer::BuildStepFactory
|
class AndroidBuildApkStepFactory : public ProjectExplorer::BuildStepFactory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -1,398 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
|
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
|
||||||
** Contact: https://www.qt.io/licensing/
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator.
|
|
||||||
**
|
|
||||||
** Commercial License Usage
|
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
|
||||||
** accordance with the commercial license agreement provided with the
|
|
||||||
** Software or, alternatively, in accordance with the terms contained in
|
|
||||||
** a written agreement between you and The Qt Company. For licensing terms
|
|
||||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
||||||
** information use the contact form at https://www.qt.io/contact-us.
|
|
||||||
**
|
|
||||||
** GNU General Public License Usage
|
|
||||||
** Alternatively, this file may be used under the terms of the GNU
|
|
||||||
** General Public License version 3 as published by the Free Software
|
|
||||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
||||||
** included in the packaging of this file. Please review the following
|
|
||||||
** information to ensure the GNU General Public License requirements will
|
|
||||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
|
||||||
**
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#include "androidbuildapkwidget.h"
|
|
||||||
|
|
||||||
#include "androidbuildapkstep.h"
|
|
||||||
#include "androidconfigurations.h"
|
|
||||||
#include "androidextralibrarylistmodel.h"
|
|
||||||
#include "androidcreatekeystorecertificate.h"
|
|
||||||
#include "androidmanager.h"
|
|
||||||
#include "androidsdkmanager.h"
|
|
||||||
#include "createandroidmanifestwizard.h"
|
|
||||||
|
|
||||||
#include <projectexplorer/buildconfiguration.h>
|
|
||||||
#include <projectexplorer/buildsystem.h>
|
|
||||||
#include <projectexplorer/project.h>
|
|
||||||
#include <projectexplorer/projectnodes.h>
|
|
||||||
#include <projectexplorer/target.h>
|
|
||||||
|
|
||||||
#include <qtsupport/qtkitinformation.h>
|
|
||||||
|
|
||||||
#include <utils/infolabel.h>
|
|
||||||
#include <utils/fancylineedit.h>
|
|
||||||
#include <utils/pathchooser.h>
|
|
||||||
|
|
||||||
#include <QCheckBox>
|
|
||||||
#include <QComboBox>
|
|
||||||
#include <QGroupBox>
|
|
||||||
#include <QFileDialog>
|
|
||||||
#include <QFormLayout>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QListView>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QToolButton>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
using namespace ProjectExplorer;
|
|
||||||
using namespace Utils;
|
|
||||||
|
|
||||||
namespace Android {
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
AndroidBuildApkWidget::AndroidBuildApkWidget(AndroidBuildApkStep *step)
|
|
||||||
: BuildStepConfigWidget(step), m_step(step)
|
|
||||||
{
|
|
||||||
setDisplayName("<b>" + tr("Build Android APK") + "</b>");
|
|
||||||
setSummaryText(displayName());
|
|
||||||
|
|
||||||
auto vbox = new QVBoxLayout(this);
|
|
||||||
vbox->addWidget(createSignPackageGroup());
|
|
||||||
vbox->addWidget(createApplicationGroup());
|
|
||||||
vbox->addWidget(createAdvancedGroup());
|
|
||||||
vbox->addWidget(createAdditionalLibrariesGroup());
|
|
||||||
|
|
||||||
connect(m_step->buildConfiguration(), &BuildConfiguration::buildTypeChanged,
|
|
||||||
this, &AndroidBuildApkWidget::updateSigningWarning);
|
|
||||||
|
|
||||||
connect(m_signPackageCheckBox, &QAbstractButton::clicked,
|
|
||||||
m_addDebuggerCheckBox, &QWidget::setEnabled);
|
|
||||||
|
|
||||||
signPackageCheckBoxToggled(m_step->signPackage());
|
|
||||||
updateSigningWarning();
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget *AndroidBuildApkWidget::createApplicationGroup()
|
|
||||||
{
|
|
||||||
const int minApiSupported = AndroidManager::apiLevelRange().first;
|
|
||||||
QStringList targets = AndroidConfig::apiLevelNamesFor(AndroidConfigurations::sdkManager()->
|
|
||||||
filteredSdkPlatforms(minApiSupported));
|
|
||||||
targets.removeDuplicates();
|
|
||||||
|
|
||||||
auto group = new QGroupBox(tr("Application"), this);
|
|
||||||
|
|
||||||
auto targetSDKComboBox = new QComboBox();
|
|
||||||
targetSDKComboBox->addItems(targets);
|
|
||||||
targetSDKComboBox->setCurrentIndex(targets.indexOf(m_step->buildTargetSdk()));
|
|
||||||
|
|
||||||
const auto cbActivated = QOverload<int>::of(&QComboBox::activated);
|
|
||||||
connect(targetSDKComboBox, cbActivated, this, [this, targetSDKComboBox](int idx) {
|
|
||||||
const QString sdk = targetSDKComboBox->itemText(idx);
|
|
||||||
m_step->setBuildTargetSdk(sdk);
|
|
||||||
AndroidManager::updateGradleProperties(step()->target(), QString()); // FIXME: Use real key.
|
|
||||||
});
|
|
||||||
|
|
||||||
auto formLayout = new QFormLayout(group);
|
|
||||||
formLayout->addRow(tr("Android build SDK:"), targetSDKComboBox);
|
|
||||||
|
|
||||||
auto createAndroidTemplatesButton = new QPushButton(tr("Create Templates"));
|
|
||||||
createAndroidTemplatesButton->setToolTip(
|
|
||||||
tr("Create an Android package for Custom Java code, assets, and Gradle configurations."));
|
|
||||||
connect(createAndroidTemplatesButton, &QAbstractButton::clicked, this, [this] {
|
|
||||||
CreateAndroidManifestWizard wizard(m_step->buildSystem());
|
|
||||||
wizard.exec();
|
|
||||||
});
|
|
||||||
|
|
||||||
formLayout->addRow(tr("Android customization:"), createAndroidTemplatesButton);
|
|
||||||
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget *AndroidBuildApkWidget::createSignPackageGroup()
|
|
||||||
{
|
|
||||||
QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
|
|
||||||
sizePolicy.setHorizontalStretch(0);
|
|
||||||
sizePolicy.setVerticalStretch(0);
|
|
||||||
|
|
||||||
auto group = new QGroupBox(tr("Application Signature"), this);
|
|
||||||
|
|
||||||
auto keystoreLocationLabel = new QLabel(tr("Keystore:"), group);
|
|
||||||
keystoreLocationLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
|
|
||||||
|
|
||||||
auto keystoreLocationChooser = new PathChooser(group);
|
|
||||||
keystoreLocationChooser->setExpectedKind(PathChooser::File);
|
|
||||||
keystoreLocationChooser->lineEdit()->setReadOnly(true);
|
|
||||||
keystoreLocationChooser->setPath(m_step->keystorePath().toUserOutput());
|
|
||||||
keystoreLocationChooser->setInitialBrowsePathBackup(QDir::homePath());
|
|
||||||
keystoreLocationChooser->setPromptDialogFilter(tr("Keystore files (*.keystore *.jks)"));
|
|
||||||
keystoreLocationChooser->setPromptDialogTitle(tr("Select Keystore File"));
|
|
||||||
connect(keystoreLocationChooser, &PathChooser::pathChanged, this, [this](const QString &path) {
|
|
||||||
FilePath file = FilePath::fromString(path);
|
|
||||||
m_step->setKeystorePath(file);
|
|
||||||
m_signPackageCheckBox->setChecked(!file.isEmpty());
|
|
||||||
if (!file.isEmpty())
|
|
||||||
setCertificates();
|
|
||||||
});
|
|
||||||
|
|
||||||
auto keystoreCreateButton = new QPushButton(tr("Create..."), group);
|
|
||||||
connect(keystoreCreateButton, &QAbstractButton::clicked, this, [this, keystoreLocationChooser] {
|
|
||||||
AndroidCreateKeystoreCertificate d;
|
|
||||||
if (d.exec() != QDialog::Accepted)
|
|
||||||
return;
|
|
||||||
keystoreLocationChooser->setPath(d.keystoreFilePath().toUserOutput());
|
|
||||||
m_step->setKeystorePath(d.keystoreFilePath());
|
|
||||||
m_step->setKeystorePassword(d.keystorePassword());
|
|
||||||
m_step->setCertificateAlias(d.certificateAlias());
|
|
||||||
m_step->setCertificatePassword(d.certificatePassword());
|
|
||||||
setCertificates();
|
|
||||||
});
|
|
||||||
|
|
||||||
m_signPackageCheckBox = new QCheckBox(tr("Sign package"), group);
|
|
||||||
m_signPackageCheckBox->setChecked(m_step->signPackage());
|
|
||||||
|
|
||||||
m_signingDebugWarningLabel = new Utils::InfoLabel(tr("Signing a debug package"),
|
|
||||||
Utils::InfoLabel::Warning, group);
|
|
||||||
m_signingDebugWarningLabel->hide();
|
|
||||||
|
|
||||||
auto certificateAliasLabel = new QLabel(tr("Certificate alias:"), group);
|
|
||||||
certificateAliasLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
|
|
||||||
|
|
||||||
m_certificatesAliasComboBox = new QComboBox(group);
|
|
||||||
m_certificatesAliasComboBox->setEnabled(false);
|
|
||||||
QSizePolicy sizePolicy2(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
|
||||||
sizePolicy2.setHorizontalStretch(0);
|
|
||||||
sizePolicy2.setVerticalStretch(0);
|
|
||||||
m_certificatesAliasComboBox->setSizePolicy(sizePolicy2);
|
|
||||||
m_certificatesAliasComboBox->setMinimumSize(QSize(300, 0));
|
|
||||||
|
|
||||||
auto horizontalLayout_2 = new QHBoxLayout;
|
|
||||||
horizontalLayout_2->addWidget(keystoreLocationLabel);
|
|
||||||
horizontalLayout_2->addWidget(keystoreLocationChooser);
|
|
||||||
horizontalLayout_2->addWidget(keystoreCreateButton);
|
|
||||||
|
|
||||||
auto horizontalLayout_3 = new QHBoxLayout;
|
|
||||||
horizontalLayout_3->addWidget(m_signingDebugWarningLabel);
|
|
||||||
horizontalLayout_3->addWidget(certificateAliasLabel);
|
|
||||||
horizontalLayout_3->addWidget(m_certificatesAliasComboBox);
|
|
||||||
|
|
||||||
auto vbox = new QVBoxLayout(group);
|
|
||||||
vbox->addLayout(horizontalLayout_2);
|
|
||||||
vbox->addWidget(m_signPackageCheckBox);
|
|
||||||
vbox->addLayout(horizontalLayout_3);
|
|
||||||
|
|
||||||
connect(m_signPackageCheckBox, &QAbstractButton::toggled,
|
|
||||||
this, &AndroidBuildApkWidget::signPackageCheckBoxToggled);
|
|
||||||
|
|
||||||
auto updateAlias = [this](int idx) {
|
|
||||||
QString alias = m_certificatesAliasComboBox->itemText(idx);
|
|
||||||
if (!alias.isEmpty())
|
|
||||||
m_step->setCertificateAlias(alias);
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto cbActivated = QOverload<int>::of(&QComboBox::activated);
|
|
||||||
const auto cbCurrentIndexChanged = QOverload<int>::of(&QComboBox::currentIndexChanged);
|
|
||||||
|
|
||||||
connect(m_certificatesAliasComboBox, cbActivated, this, updateAlias);
|
|
||||||
connect(m_certificatesAliasComboBox, cbCurrentIndexChanged, this, updateAlias);
|
|
||||||
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget *AndroidBuildApkWidget::createAdvancedGroup()
|
|
||||||
{
|
|
||||||
auto group = new QGroupBox(tr("Advanced Actions"), this);
|
|
||||||
|
|
||||||
auto openPackageLocationCheckBox = new QCheckBox(tr("Open package location after build"), group);
|
|
||||||
openPackageLocationCheckBox->setChecked(m_step->openPackageLocation());
|
|
||||||
connect(openPackageLocationCheckBox, &QAbstractButton::toggled,
|
|
||||||
this, [this](bool checked) { m_step->setOpenPackageLocation(checked); });
|
|
||||||
|
|
||||||
m_addDebuggerCheckBox = new QCheckBox(tr("Add debug server"), group);
|
|
||||||
m_addDebuggerCheckBox->setEnabled(false);
|
|
||||||
m_addDebuggerCheckBox->setToolTip(tr("Packages debug server with "
|
|
||||||
"the APK to enable debugging. For the signed APK this option is unchecked by default."));
|
|
||||||
m_addDebuggerCheckBox->setChecked(m_step->addDebugger());
|
|
||||||
connect(m_addDebuggerCheckBox, &QAbstractButton::toggled,
|
|
||||||
m_step, &AndroidBuildApkStep::setAddDebugger);
|
|
||||||
|
|
||||||
auto verboseOutputCheckBox = new QCheckBox(tr("Verbose output"), group);
|
|
||||||
verboseOutputCheckBox->setChecked(m_step->verboseOutput());
|
|
||||||
|
|
||||||
auto vbox = new QVBoxLayout(group);
|
|
||||||
QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(step()->kit());
|
|
||||||
if (version && version->supportsMultipleQtAbis()) {
|
|
||||||
auto buildAAB = new QCheckBox(tr("Build .aab (Android App Bundle)"), group);
|
|
||||||
buildAAB->setChecked(m_step->buildAAB());
|
|
||||||
connect(buildAAB, &QAbstractButton::toggled, m_step, &AndroidBuildApkStep::setBuildAAB);
|
|
||||||
vbox->addWidget(buildAAB);
|
|
||||||
}
|
|
||||||
vbox->addWidget(openPackageLocationCheckBox);
|
|
||||||
vbox->addWidget(verboseOutputCheckBox);
|
|
||||||
vbox->addWidget(m_addDebuggerCheckBox);
|
|
||||||
|
|
||||||
connect(verboseOutputCheckBox, &QAbstractButton::toggled,
|
|
||||||
this, [this](bool checked) { m_step->setVerboseOutput(checked); });
|
|
||||||
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget *AndroidBuildApkWidget::createAdditionalLibrariesGroup()
|
|
||||||
{
|
|
||||||
auto group = new QGroupBox(tr("Additional Libraries"));
|
|
||||||
group->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
|
|
||||||
|
|
||||||
auto libsModel = new AndroidExtraLibraryListModel(m_step->buildSystem(), this);
|
|
||||||
connect(libsModel, &AndroidExtraLibraryListModel::enabledChanged, this,
|
|
||||||
[this, group](const bool enabled) {
|
|
||||||
group->setEnabled(enabled);
|
|
||||||
m_openSslCheckBox->setChecked(isOpenSslLibsIncluded());
|
|
||||||
});
|
|
||||||
|
|
||||||
auto libsView = new QListView;
|
|
||||||
libsView->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
|
||||||
libsView->setToolTip(tr("List of extra libraries to include in Android package and load on startup."));
|
|
||||||
libsView->setModel(libsModel);
|
|
||||||
|
|
||||||
auto addLibButton = new QToolButton;
|
|
||||||
addLibButton->setText(tr("Add..."));
|
|
||||||
addLibButton->setToolTip(tr("Select library to include in package."));
|
|
||||||
addLibButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
|
|
||||||
addLibButton->setToolButtonStyle(Qt::ToolButtonTextOnly);
|
|
||||||
connect(addLibButton, &QAbstractButton::clicked, this, [this, libsModel] {
|
|
||||||
QStringList fileNames = QFileDialog::getOpenFileNames(this,
|
|
||||||
tr("Select additional libraries"),
|
|
||||||
QDir::homePath(),
|
|
||||||
tr("Libraries (*.so)"));
|
|
||||||
if (!fileNames.isEmpty())
|
|
||||||
libsModel->addEntries(fileNames);
|
|
||||||
});
|
|
||||||
|
|
||||||
auto removeLibButton = new QToolButton;
|
|
||||||
removeLibButton->setText(tr("Remove"));
|
|
||||||
removeLibButton->setToolTip(tr("Remove currently selected library from list."));
|
|
||||||
connect(removeLibButton, &QAbstractButton::clicked, this, [libsModel, libsView] {
|
|
||||||
QModelIndexList removeList = libsView->selectionModel()->selectedIndexes();
|
|
||||||
libsModel->removeEntries(removeList);
|
|
||||||
});
|
|
||||||
|
|
||||||
auto libsButtonLayout = new QVBoxLayout;
|
|
||||||
libsButtonLayout->addWidget(addLibButton);
|
|
||||||
libsButtonLayout->addWidget(removeLibButton);
|
|
||||||
libsButtonLayout->addStretch(1);
|
|
||||||
|
|
||||||
m_openSslCheckBox = new QCheckBox(tr("Include prebuilt OpenSSL libraries"));
|
|
||||||
m_openSslCheckBox->setToolTip(tr("This is useful for apps that use SSL operations. The path "
|
|
||||||
"can be defined in Tools > Options > Devices > Android."));
|
|
||||||
connect(m_openSslCheckBox, &QAbstractButton::clicked, this,
|
|
||||||
&AndroidBuildApkWidget::onOpenSslCheckBoxChanged);
|
|
||||||
|
|
||||||
auto grid = new QGridLayout(group);
|
|
||||||
grid->addWidget(m_openSslCheckBox, 0, 0);
|
|
||||||
grid->addWidget(libsView, 1, 0);
|
|
||||||
grid->addLayout(libsButtonLayout, 1, 1);
|
|
||||||
|
|
||||||
QItemSelectionModel *libSelection = libsView->selectionModel();
|
|
||||||
connect(libSelection, &QItemSelectionModel::selectionChanged, this, [libSelection, removeLibButton] {
|
|
||||||
removeLibButton->setEnabled(libSelection->hasSelection());
|
|
||||||
});
|
|
||||||
|
|
||||||
Target *target = m_step->target();
|
|
||||||
const QString buildKey = target->activeBuildKey();
|
|
||||||
const ProjectNode *node = target->project()->findNodeForBuildKey(buildKey);
|
|
||||||
group->setEnabled(node && !node->parseInProgress());
|
|
||||||
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidBuildApkWidget::signPackageCheckBoxToggled(bool checked)
|
|
||||||
{
|
|
||||||
m_certificatesAliasComboBox->setEnabled(checked);
|
|
||||||
m_step->setSignPackage(checked);
|
|
||||||
m_addDebuggerCheckBox->setChecked(!checked);
|
|
||||||
updateSigningWarning();
|
|
||||||
if (!checked)
|
|
||||||
return;
|
|
||||||
if (!m_step->keystorePath().isEmpty())
|
|
||||||
setCertificates();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidBuildApkWidget::onOpenSslCheckBoxChanged()
|
|
||||||
{
|
|
||||||
Utils::FilePath projectPath = m_step->buildConfiguration()->buildSystem()->projectFilePath();
|
|
||||||
QFile projectFile(projectPath.toString());
|
|
||||||
if (!projectFile.open(QIODevice::ReadWrite | QIODevice::Text)) {
|
|
||||||
qWarning() << "Cound't open project file to add OpenSSL extra libs: " << projectPath;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString searchStr = openSslIncludeFileContent(projectPath);
|
|
||||||
QTextStream textStream(&projectFile);
|
|
||||||
|
|
||||||
QString fileContent = textStream.readAll();
|
|
||||||
if (!m_openSslCheckBox->isChecked()) {
|
|
||||||
fileContent.remove("\n" + searchStr);
|
|
||||||
} else if (!fileContent.contains(searchStr, Qt::CaseSensitive)) {
|
|
||||||
fileContent.append(searchStr + "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
projectFile.resize(0);
|
|
||||||
textStream << fileContent;
|
|
||||||
projectFile.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AndroidBuildApkWidget::isOpenSslLibsIncluded()
|
|
||||||
{
|
|
||||||
Utils::FilePath projectPath = m_step->buildConfiguration()->buildSystem()->projectFilePath();
|
|
||||||
const QString searchStr = openSslIncludeFileContent(projectPath);
|
|
||||||
QFile projectFile(projectPath.toString());
|
|
||||||
projectFile.open(QIODevice::ReadOnly);
|
|
||||||
QTextStream textStream(&projectFile);
|
|
||||||
QString fileContent = textStream.readAll();
|
|
||||||
projectFile.close();
|
|
||||||
return fileContent.contains(searchStr, Qt::CaseSensitive);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString AndroidBuildApkWidget::openSslIncludeFileContent(const Utils::FilePath &projectPath)
|
|
||||||
{
|
|
||||||
QString openSslPath = AndroidConfigurations::currentConfig().openSslLocation().toString();
|
|
||||||
if (projectPath.endsWith(".pro"))
|
|
||||||
return "android: include(" + openSslPath + "/openssl.pri)";
|
|
||||||
if (projectPath.endsWith("CMakeLists.txt"))
|
|
||||||
return "if (ANDROID)\n include(" + openSslPath + "/CMakeLists.txt)\nendif()";
|
|
||||||
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidBuildApkWidget::setCertificates()
|
|
||||||
{
|
|
||||||
QAbstractItemModel *certificates = m_step->keystoreCertificates();
|
|
||||||
if (certificates) {
|
|
||||||
m_signPackageCheckBox->setChecked(certificates);
|
|
||||||
m_certificatesAliasComboBox->setModel(certificates);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidBuildApkWidget::updateSigningWarning()
|
|
||||||
{
|
|
||||||
bool nonRelease = m_step->buildType() != BuildConfiguration::Release;
|
|
||||||
bool visible = m_step->signPackage() && nonRelease;
|
|
||||||
m_signingDebugWarningLabel->setVisible(visible);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // Internal
|
|
||||||
} // Android
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
|
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
|
||||||
** Contact: https://www.qt.io/licensing/
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator.
|
|
||||||
**
|
|
||||||
** Commercial License Usage
|
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
|
||||||
** accordance with the commercial license agreement provided with the
|
|
||||||
** Software or, alternatively, in accordance with the terms contained in
|
|
||||||
** a written agreement between you and The Qt Company. For licensing terms
|
|
||||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
||||||
** information use the contact form at https://www.qt.io/contact-us.
|
|
||||||
**
|
|
||||||
** GNU General Public License Usage
|
|
||||||
** Alternatively, this file may be used under the terms of the GNU
|
|
||||||
** General Public License version 3 as published by the Free Software
|
|
||||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
||||||
** included in the packaging of this file. Please review the following
|
|
||||||
** information to ensure the GNU General Public License requirements will
|
|
||||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
|
||||||
**
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "android_global.h"
|
|
||||||
|
|
||||||
#include "androidbuildapkstep.h"
|
|
||||||
|
|
||||||
#include <projectexplorer/buildstep.h>
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
class QCheckBox;
|
|
||||||
class QComboBox;
|
|
||||||
class QLabel;
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
namespace Utils {
|
|
||||||
class InfoLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Android {
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class AndroidBuildApkWidget : public ProjectExplorer::BuildStepConfigWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit AndroidBuildApkWidget(AndroidBuildApkStep *step);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void setCertificates();
|
|
||||||
void updateSigningWarning();
|
|
||||||
void signPackageCheckBoxToggled(bool checked);
|
|
||||||
void onOpenSslCheckBoxChanged();
|
|
||||||
bool isOpenSslLibsIncluded();
|
|
||||||
QString openSslIncludeFileContent(const Utils::FilePath &projectPath);
|
|
||||||
|
|
||||||
QWidget *createApplicationGroup();
|
|
||||||
QWidget *createSignPackageGroup();
|
|
||||||
QWidget *createAdvancedGroup();
|
|
||||||
QWidget *createAdditionalLibrariesGroup();
|
|
||||||
|
|
||||||
private:
|
|
||||||
AndroidBuildApkStep *m_step = nullptr;
|
|
||||||
QCheckBox *m_signPackageCheckBox = nullptr;
|
|
||||||
Utils::InfoLabel *m_signingDebugWarningLabel = nullptr;
|
|
||||||
QComboBox *m_certificatesAliasComboBox = nullptr;
|
|
||||||
QCheckBox *m_addDebuggerCheckBox = nullptr;
|
|
||||||
QCheckBox *m_openSslCheckBox = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace Android
|
|
||||||
Reference in New Issue
Block a user