diff options
author | BogDan Vatra <bogdan@kde.org> | 2014-06-25 15:42:11 +0200 |
---|---|---|
committer | Daniel Teske <daniel.teske@digia.com> | 2014-07-21 12:41:28 +0200 |
commit | 64e5a543a845d8d800504206a42c58d4e28ac89c (patch) | |
tree | 205faff83b9fb890c65309fe4c7cc7878826f515 /src | |
parent | 4657ac7452662d19823412e82d599bf4079a3c4d (diff) | |
download | qt-creator-64e5a543a845d8d800504206a42c58d4e28ac89c.tar.gz |
Move qmake specific part to qmake plugin, generalize android support
- Split up androiddeployqt into two steps: One building the apk,
and one deploying it to the device.
- The build apk step base class AndroidBuildApkStep is ihneritaged by
the qmake specific class QmakeAndroidBuildApkStep.
- The deployment step is still called androiddeployqt
- Move all qmake specific code to the qmakeprojectmanager plguin
- Flip the depencency between the android and qmake plugin, now
the qmake plugin depends on the android plugin, implementing
a interface the android plugin provides.
- Note: This removes the debug deployment for now.
Change-Id: I1c386640159ed14b637668abde8eb3b9009ab803
Reviewed-by: BogDan Vatra <bogdan@kde.org>
Diffstat (limited to 'src')
57 files changed, 2612 insertions, 1276 deletions
diff --git a/src/plugins/android/android.pro b/src/plugins/android/android.pro index 230c410104..9bb43171f2 100644 --- a/src/plugins/android/android.pro +++ b/src/plugins/android/android.pro @@ -16,8 +16,6 @@ HEADERS += \ androidsettingspage.h \ androidsettingswidget.h \ androidtoolchain.h \ - androidpackageinstallationstep.h \ - androidpackageinstallationfactory.h \ androiderrormessage.h \ androidglobal.h \ androidrunner.h \ @@ -41,9 +39,7 @@ HEADERS += \ androiddeployqtstep.h \ certificatesmodel.h \ androiddeployqtwidget.h \ - createandroidmanifestwizard.h \ androidpotentialkit.h \ - androidextralibrarylistmodel.h \ androidsignaloperation.h \ javaeditor.h \ javaeditorfactory.h \ @@ -53,9 +49,8 @@ HEADERS += \ javafilewizard.h \ avddialog.h \ android_global.h \ - qmakeandroidsupport.h \ - qmakeandroidrunfactories.h \ - qmakeandroidrunconfiguration.h + androidbuildapkstep.h \ + androidbuildapkwidget.h SOURCES += \ androidconfigurations.cpp \ @@ -66,8 +61,6 @@ SOURCES += \ androidsettingspage.cpp \ androidsettingswidget.cpp \ androidtoolchain.cpp \ - androidpackageinstallationstep.cpp \ - androidpackageinstallationfactory.cpp \ androiderrormessage.cpp \ androidrunner.cpp \ androiddebugsupport.cpp \ @@ -90,9 +83,7 @@ SOURCES += \ androiddeployqtstep.cpp \ certificatesmodel.cpp \ androiddeployqtwidget.cpp \ - createandroidmanifestwizard.cpp \ androidpotentialkit.cpp \ - androidextralibrarylistmodel.cpp \ androidsignaloperation.cpp \ javaeditor.cpp \ javaeditorfactory.cpp \ @@ -101,16 +92,17 @@ SOURCES += \ javacompletionassistprovider.cpp \ javafilewizard.cpp \ avddialog.cpp \ - qmakeandroidsupport.cpp \ - qmakeandroidrunfactories.cpp \ - qmakeandroidrunconfiguration.cpp + androidbuildapkstep.cpp \ + androidbuildapkwidget.cpp FORMS += \ androidsettingswidget.ui \ addnewavddialog.ui \ androidcreatekeystorecertificate.ui \ androiddevicedialog.ui \ - androiddeployqtwidget.ui + androiddeployqtwidget.ui \ + androidbuildapkwidget.ui RESOURCES = android.qrc + DEFINES += ANDROID_LIBRARY diff --git a/src/plugins/android/android.qbs b/src/plugins/android/android.qbs index e247a04e3f..30ac7a10d7 100644 --- a/src/plugins/android/android.qbs +++ b/src/plugins/android/android.qbs @@ -5,19 +5,15 @@ import QtcPlugin QtcPlugin { name: "Android" + Depends { name: "Qt"; submodules: ["widgets", "xml", "network"] } + Depends { name: "AnalyzerBase" } Depends { name: "Core" } - Depends { name: "ProjectExplorer" } - Depends { name: "QmakeProjectManager" } Depends { name: "Debugger" } + Depends { name: "ProjectExplorer" } Depends { name: "QmlDebug" } Depends { name: "QtSupport" } Depends { name: "TextEditor" } - Depends { name: "AnalyzerBase" } Depends { name: "Utils" } - Depends { name: "Qt"; submodules: ["widgets", "xml", "network"] } - - property bool enable: false - pluginspecreplacements: ({"ANDROID_EXPERIMENTAL_STR": (enable ? "false": "true")}) files: [ "android_global.h", @@ -31,6 +27,11 @@ QtcPlugin { "androidcreatekeystorecertificate.cpp", "androidcreatekeystorecertificate.h", "androidcreatekeystorecertificate.ui", + "androidbuildapkstep.cpp", + "androidbuildapkstep.h", + "androidbuildapkwidget.cpp", + "androidbuildapkwidget.h", + "androidbuildapkwidget.ui", "androiddeployqtstep.cpp", "androiddeployqtstep.h", "androiddebugsupport.cpp", @@ -49,8 +50,6 @@ QtcPlugin { "androiddevicefactory.h", "androiderrormessage.h", "androiderrormessage.cpp", - "androidextralibrarylistmodel.cpp", - "androidextralibrarylistmodel.h", "androidgdbserverkitinformation.cpp", "androidgdbserverkitinformation.h", "androidglobal.h", @@ -64,10 +63,6 @@ QtcPlugin { "androidmanifesteditorfactory.h", "androidmanifesteditorwidget.cpp", "androidmanifesteditorwidget.h", - "androidpackageinstallationfactory.cpp", - "androidpackageinstallationfactory.h", - "androidpackageinstallationstep.cpp", - "androidpackageinstallationstep.h", "androidplugin.cpp", "androidplugin.h", "androidpotentialkit.cpp", @@ -100,8 +95,6 @@ QtcPlugin { "avddialog.h", "certificatesmodel.cpp", "certificatesmodel.h", - "createandroidmanifestwizard.cpp", - "createandroidmanifestwizard.h", "javaautocompleter.cpp", "javaautocompleter.h", "javacompletionassistprovider.cpp", @@ -116,12 +109,5 @@ QtcPlugin { "javaindenter.h", "javaparser.cpp", "javaparser.h", - "qmakeandroidrunconfiguration.cpp", - "qmakeandroidrunconfiguration.h", - "qmakeandroidrunfactories.cpp", - "qmakeandroidrunfactories.h", - "qmakeandroidsupport.cpp", - "qmakeandroidsupport.h", - ] } diff --git a/src/plugins/android/android_dependencies.pri b/src/plugins/android/android_dependencies.pri index 0064a8319e..94fa4d8f36 100644 --- a/src/plugins/android/android_dependencies.pri +++ b/src/plugins/android/android_dependencies.pri @@ -3,7 +3,6 @@ QTC_PLUGIN_DEPENDS += \ coreplugin \ debugger \ projectexplorer \ - qmakeprojectmanager \ qtsupport \ texteditor \ analyzerbase diff --git a/src/plugins/android/androidanalyzesupport.h b/src/plugins/android/androidanalyzesupport.h index 15db38589a..1a0c3b3489 100644 --- a/src/plugins/android/androidanalyzesupport.h +++ b/src/plugins/android/androidanalyzesupport.h @@ -40,7 +40,6 @@ namespace Android { class AndroidRunConfiguration; namespace Internal { - class AndroidRunner; class AndroidAnalyzeSupport : public AndroidRunSupport diff --git a/src/plugins/android/androidbuildapkstep.cpp b/src/plugins/android/androidbuildapkstep.cpp new file mode 100644 index 0000000000..f2e6539458 --- /dev/null +++ b/src/plugins/android/androidbuildapkstep.cpp @@ -0,0 +1,313 @@ +/************************************************************************** +** +** Copyright (c) 2014 BogDan Vatra <bog_dan_ro@yahoo.com> +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "androidbuildapkstep.h" +#include "androidbuildapkwidget.h" +#include "androidconfigurations.h" +#include "androidconstants.h" +#include "androidmanager.h" +#include "androidqtsupport.h" +#include "certificatesmodel.h" + +#include "javaparser.h" + +#include <coreplugin/fileutils.h> +#include <coreplugin/icore.h> + +#include <projectexplorer/buildconfiguration.h> +#include <projectexplorer/project.h> +#include <projectexplorer/target.h> + +#include <qtsupport/qtkitinformation.h> + +#include <utils/qtcprocess.h> + +#include <QInputDialog> +#include <QMessageBox> + +namespace Android { +using namespace Internal; + +const QLatin1String DeployActionKey("Qt4ProjectManager.AndroidDeployQtStep.DeployQtAction"); +const QLatin1String KeystoreLocationKey("KeystoreLocation"); +const QLatin1String BuildTargetSdkKey("BuildTargetSdk"); +const QLatin1String VerboseOutputKey("VerboseOutput"); + +AndroidBuildApkStep::AndroidBuildApkStep(ProjectExplorer::BuildStepList *parent, const Core::Id id) + : ProjectExplorer::AbstractProcessStep(parent, id), + m_deployAction(BundleLibrariesDeployment), + m_signPackage(false), + m_verbose(false), + m_openPackageLocation(false), + m_buildTargetSdk(AndroidConfig::apiLevelNameFor(AndroidConfigurations::currentConfig().highestAndroidSdk())) +{ + //: AndroidBuildApkStep default display name + setDefaultDisplayName(tr("Build Android APK")); +} + +AndroidBuildApkStep::AndroidBuildApkStep(ProjectExplorer::BuildStepList *parent, + AndroidBuildApkStep *other) + : ProjectExplorer::AbstractProcessStep(parent, other), + m_deployAction(other->deployAction()), + m_signPackage(other->signPackage()), + m_verbose(other->m_verbose), + m_openPackageLocation(other->m_openPackageLocation), + m_buildTargetSdk(other->m_buildTargetSdk) +{ + +} + +bool AndroidBuildApkStep::init() +{ + ProjectExplorer::BuildConfiguration *bc = buildConfiguration(); + + if (m_signPackage) { + // check keystore and certificate passwords + while (!AndroidManager::checkKeystorePassword(m_keystorePath.toString(), m_keystorePasswd)) { + if (!keystorePassword()) + return false; // user canceled + } + + while (!AndroidManager::checkCertificatePassword(m_keystorePath.toString(), m_keystorePasswd, m_certificateAlias, m_certificatePasswd)) { + if (!certificatePassword()) + return false; // user canceled + } + + + if (bc->buildType() == ProjectExplorer::BuildConfiguration::Debug) + emit addOutput(tr("Warning: Signing a debug package."), BuildStep::ErrorMessageOutput); + } + + QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target()->kit()); + if (!version) + return false; + + JavaParser *parser = new JavaParser; + parser->setProjectFileList(target()->project()->files(ProjectExplorer::Project::AllFiles)); + parser->setSourceDirectory(androidPackageSourceDir()); + parser->setBuildDirectory(Utils::FileName::fromString(bc->buildDirectory().appendPath(QLatin1String(Constants::ANDROID_BUILDDIRECTORY)).toString())); + setOutputParser(parser); + + m_openPackageLocationForRun = m_openPackageLocation; + m_apkPath = AndroidManager::androidQtSupport(target())->apkPath(target(), m_signPackage ? AndroidQtSupport::ReleaseBuildSigned + : AndroidQtSupport::DebugBuild).toString(); + + bool result = AbstractProcessStep::init(); + if (!result) + return false; + + return true; +} + +void AndroidBuildApkStep::showInGraphicalShell() +{ + Core::FileUtils::showInGraphicalShell(Core::ICore::instance()->mainWindow(), m_apkPath); +} + +ProjectExplorer::BuildStepConfigWidget *AndroidBuildApkStep::createConfigWidget() +{ + return new AndroidBuildApkWidget(this); +} + +void AndroidBuildApkStep::processFinished(int exitCode, QProcess::ExitStatus status) +{ + AbstractProcessStep::processFinished(exitCode, status); + if (m_openPackageLocationForRun && status == QProcess::NormalExit && exitCode == 0) + QMetaObject::invokeMethod(this, "showInGraphicalShell", Qt::QueuedConnection); +} + +bool AndroidBuildApkStep::fromMap(const QVariantMap &map) +{ + m_deployAction = AndroidDeployAction(map.value(DeployActionKey, BundleLibrariesDeployment).toInt()); + if ( m_deployAction == DebugDeployment + && QtSupport::QtKitInformation::qtVersion(target()->kit())->qtVersion() < QtSupport::QtVersionNumber(5, 4, 0)) { + m_deployAction = BundleLibrariesDeployment; + } + + m_keystorePath = Utils::FileName::fromString(map.value(KeystoreLocationKey).toString()); + m_signPackage = false; // don't restore this + m_buildTargetSdk = map.value(BuildTargetSdkKey).toString(); + if (m_buildTargetSdk.isEmpty()) + m_buildTargetSdk = AndroidConfig::apiLevelNameFor(AndroidConfigurations::currentConfig().highestAndroidSdk()); + m_verbose = map.value(VerboseOutputKey).toBool(); + return ProjectExplorer::BuildStep::fromMap(map); +} + +QVariantMap AndroidBuildApkStep::toMap() const +{ + QVariantMap map = ProjectExplorer::AbstractProcessStep::toMap(); + map.insert(DeployActionKey, m_deployAction); + map.insert(KeystoreLocationKey, m_keystorePath.toString()); + map.insert(BuildTargetSdkKey, m_buildTargetSdk); + map.insert(VerboseOutputKey, m_verbose); + return map; +} + +Utils::FileName AndroidBuildApkStep::keystorePath() +{ + return m_keystorePath; +} + +QString AndroidBuildApkStep::buildTargetSdk() const +{ + return m_buildTargetSdk; +} + +void AndroidBuildApkStep::setBuildTargetSdk(const QString &sdk) +{ + m_buildTargetSdk = sdk; +} + +AndroidBuildApkStep::AndroidDeployAction AndroidBuildApkStep::deployAction() const +{ + return m_deployAction; +} + +void AndroidBuildApkStep::setDeployAction(AndroidDeployAction deploy) +{ + m_deployAction = deploy; +} + +void AndroidBuildApkStep::setKeystorePath(const Utils::FileName &path) +{ + m_keystorePath = path; + m_certificatePasswd.clear(); + m_keystorePasswd.clear(); +} + +void AndroidBuildApkStep::setKeystorePassword(const QString &pwd) +{ + m_keystorePasswd = pwd; +} + +void AndroidBuildApkStep::setCertificateAlias(const QString &alias) +{ + m_certificateAlias = alias; +} + +void AndroidBuildApkStep::setCertificatePassword(const QString &pwd) +{ + m_certificatePasswd = pwd; +} + +bool AndroidBuildApkStep::signPackage() const +{ + return m_signPackage; +} + +void AndroidBuildApkStep::setSignPackage(bool b) +{ + m_signPackage = b; +} + +bool AndroidBuildApkStep::openPackageLocation() const +{ + return m_openPackageLocation; +} + +void AndroidBuildApkStep::setOpenPackageLocation(bool open) +{ + m_openPackageLocation = open; +} + +void AndroidBuildApkStep::setVerboseOutput(bool verbose) +{ + m_verbose = verbose; +} + +bool AndroidBuildApkStep::runInGuiThread() const +{ + return true; +} + +bool AndroidBuildApkStep::verboseOutput() const +{ + return m_verbose; +} + +QAbstractItemModel *AndroidBuildApkStep::keystoreCertificates() +{ + QString rawCerts; + QProcess keytoolProc; + while (!rawCerts.length() || !m_keystorePasswd.length()) { + QStringList params; + params << QLatin1String("-list") << QLatin1String("-v") << QLatin1String("-keystore") << m_keystorePath.toUserOutput() << QLatin1String("-storepass"); + if (!m_keystorePasswd.length()) + keystorePassword(); + if (!m_keystorePasswd.length()) + return 0; + params << m_keystorePasswd; + params << QLatin1String("-J-Duser.language=en"); + keytoolProc.start(AndroidConfigurations::currentConfig().keytoolPath().toString(), params); + if (!keytoolProc.waitForStarted() || !keytoolProc.waitForFinished()) { + QMessageBox::critical(0, tr("Error"), + tr("Failed to run keytool.")); + return 0; + } + + if (keytoolProc.exitCode()) { + QMessageBox::critical(0, tr("Error"), + tr("Invalid password.")); + m_keystorePasswd.clear(); + } + rawCerts = QString::fromLatin1(keytoolProc.readAllStandardOutput()); + } + return new CertificatesModel(rawCerts, this); +} + +bool AndroidBuildApkStep::keystorePassword() +{ + m_keystorePasswd.clear(); + bool ok; + QString text = QInputDialog::getText(0, tr("Keystore"), + tr("Keystore password:"), QLineEdit::Password, + QString(), &ok); + if (ok && !text.isEmpty()) { + m_keystorePasswd = text; + return true; + } + return false; +} + +bool AndroidBuildApkStep::certificatePassword() +{ + m_certificatePasswd.clear(); + bool ok; + QString text = QInputDialog::getText(0, tr("Certificate"), + tr("Certificate password (%1):").arg(m_certificateAlias), QLineEdit::Password, + QString(), &ok); + if (ok && !text.isEmpty()) { + m_certificatePasswd = text; + return true; + } + return false; +} + +} // namespace Android diff --git a/src/plugins/android/androidbuildapkstep.h b/src/plugins/android/androidbuildapkstep.h new file mode 100644 index 0000000000..668f5b4b7e --- /dev/null +++ b/src/plugins/android/androidbuildapkstep.h @@ -0,0 +1,117 @@ +/************************************************************************** +** +** Copyright (c) 2014 BogDan Vatra <bog_dan_ro@yahoo.com> +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef ANDROIDBUILDAPKSTEP_H +#define ANDROIDBUILDAPKSTEP_H + +#include "android_global.h" +#include <projectexplorer/abstractprocessstep.h> +#include <qtsupport/baseqtversion.h> + +QT_BEGIN_NAMESPACE +class QAbstractItemModel; +QT_END_NAMESPACE + +namespace Android { + +class ANDROID_EXPORT AndroidBuildApkStep : public ProjectExplorer::AbstractProcessStep +{ + Q_OBJECT +public: + AndroidBuildApkStep(ProjectExplorer::BuildStepList *bc, const Core::Id id); + + enum AndroidDeployAction + { + MinistroDeployment, // use ministro + DebugDeployment, + BundleLibrariesDeployment + }; + + bool fromMap(const QVariantMap &map); + QVariantMap toMap() const; + + AndroidDeployAction deployAction() const; + + // signing + Utils::FileName keystorePath(); + void setKeystorePath(const Utils::FileName &path); + void setKeystorePassword(const QString &pwd); + void setCertificateAlias(const QString &alias); + void setCertificatePassword(const QString &pwd); + + QAbstractItemModel *keystoreCertificates(); + bool signPackage() const; + void setSignPackage(bool b); + + bool openPackageLocation() const; + void setOpenPackageLocation(bool open); + bool verboseOutput() const; + void setVerboseOutput(bool verbose); + + bool runInGuiThread() const; + + QString buildTargetSdk() const; + void setBuildTargetSdk(const QString &sdk); +public slots: + void setDeployAction(AndroidDeployAction deploy); + +protected slots: + void showInGraphicalShell(); + +protected: + AndroidBuildApkStep(ProjectExplorer::BuildStepList *bc, + AndroidBuildApkStep *other); + bool keystorePassword(); + bool certificatePassword(); + + bool init(); + ProjectExplorer::BuildStepConfigWidget *createConfigWidget(); + bool immutable() const { return true; } + void processFinished(int exitCode, QProcess::ExitStatus status); + virtual Utils::FileName androidPackageSourceDir() const = 0; + +protected: + AndroidDeployAction m_deployAction; + bool m_signPackage; + bool m_verbose; + bool m_openPackageLocation; + bool m_openPackageLocationForRun; + QString m_buildTargetSdk; + + Utils::FileName m_keystorePath; + QString m_keystorePasswd; + QString m_certificateAlias; + QString m_certificatePasswd; + QString m_apkPath; +}; + +} // namespace Android + +#endif // ANDROIDBUILDAPKSTEP_H diff --git a/src/plugins/android/androidbuildapkwidget.cpp b/src/plugins/android/androidbuildapkwidget.cpp new file mode 100644 index 0000000000..fb45115949 --- /dev/null +++ b/src/plugins/android/androidbuildapkwidget.cpp @@ -0,0 +1,238 @@ +/************************************************************************** +** +** Copyright (c) 2014 BogDan Vatra <bog_dan_ro@yahoo.com> +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "androidbuildapkstep.h" +#include "androidbuildapkwidget.h" +#include "androidconfigurations.h" +#include "androidcreatekeystorecertificate.h" +#include "androidmanager.h" +#include "ui_androidbuildapkwidget.h" + +#include <projectexplorer/buildconfiguration.h> +#include <projectexplorer/project.h> +#include <projectexplorer/target.h> +#include <qtsupport/qtkitinformation.h> + +#include <utils/fancylineedit.h> +#include <utils/pathchooser.h> + +#include <QFileDialog> + +#include <algorithm> + +using namespace Android; +using namespace Internal; + +AndroidBuildApkWidget::AndroidBuildApkWidget(AndroidBuildApkStep *step) + : ProjectExplorer::BuildStepConfigWidget(), + m_ui(new Ui::AndroidBuildApkWidget), + m_step(step) +{ + m_ui->setupUi(this); + + // Target sdk combobox + int minApiLevel = 9; + QStringList targets = AndroidConfig::apiLevelNamesFor(AndroidConfigurations::currentConfig().sdkTargets(minApiLevel)); + m_ui->targetSDKComboBox->addItems(targets); + m_ui->targetSDKComboBox->setCurrentIndex(targets.indexOf(AndroidManager::buildTargetSDK(step->target()))); + + // deployment option + switch (m_step->deployAction()) { + case AndroidBuildApkStep::MinistroDeployment: + m_ui->ministroOption->setChecked(true); + break; + case AndroidBuildApkStep::DebugDeployment: + m_ui->temporaryQtOption->setChecked(true); + break; + case AndroidBuildApkStep::BundleLibrariesDeployment: + m_ui->bundleQtOption->setChecked(true); + break; + default: + // can't happen + break; + } + + // signing + m_ui->signPackageCheckBox->setChecked(m_step->signPackage()); + m_ui->KeystoreLocationPathChooser->setExpectedKind(Utils::PathChooser::File); + m_ui->KeystoreLocationPathChooser->lineEdit()->setReadOnly(true); + m_ui->KeystoreLocationPathChooser->setPath(m_step->keystorePath().toUserOutput()); + m_ui->KeystoreLocationPathChooser->setInitialBrowsePathBackup(QDir::homePath()); + m_ui->KeystoreLocationPathChooser->setPromptDialogFilter(tr("Keystore files (*.keystore *.jks)")); + m_ui->KeystoreLocationPathChooser->setPromptDialogTitle(tr("Select Keystore File")); + m_ui->signingDebugWarningIcon->hide(); + m_ui->signingDebugWarningLabel->hide(); + signPackageCheckBoxToggled(m_step->signPackage()); + + m_ui->verboseOutputCheckBox->setChecked(m_step->verboseOutput()); + m_ui->openPackageLocationCheckBox->setChecked(m_step->openPackageLocation()); + + // target sdk + connect(m_ui->targetSDKComboBox, SIGNAL(activated(QString)), SLOT(setTargetSdk(QString))); + + // deployment options + connect(m_ui->ministroOption, SIGNAL(clicked()), SLOT(setMinistro())); + connect(m_ui->temporaryQtOption, SIGNAL(clicked()), SLOT(setDeployLocalQtLibs())); + connect(m_ui->bundleQtOption, SIGNAL(clicked()), SLOT(setBundleQtLibs())); + + connect(m_ui->openPackageLocationCheckBox, SIGNAL(toggled(bool)), + this, SLOT(openPackageLocationCheckBoxToggled(bool))); + connect(m_ui->verboseOutputCheckBox, SIGNAL(toggled(bool)), + this, SLOT(verboseOutputCheckBoxToggled(bool))); + + //signing + connect(m_ui->signPackageCheckBox, SIGNAL(toggled(bool)), + this, SLOT(signPackageCheckBoxToggled(bool))); + connect(m_ui->KeystoreCreatePushButton, SIGNAL(clicked()), + this, SLOT(createKeyStore())); + connect(m_ui->KeystoreLocationPathChooser, SIGNAL(pathChanged(QString)), + SLOT(updateKeyStorePath(QString))); + connect(m_ui->certificatesAliasComboBox, SIGNAL(activated(QString)), + this, SLOT(certificatesAliasComboBoxActivated(QString))); + connect(m_ui->certificatesAliasComboBox, SIGNAL(currentIndexChanged(QString)), + this, SLOT(certificatesAliasComboBoxCurrentIndexChanged(QString))); + + connect(m_step->buildConfiguration(), SIGNAL(buildTypeChanged()), + this, SLOT(updateSigningWarning())); + + updateSigningWarning(); + QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(step->target()->kit()); + m_ui->temporaryQtOption->setVisible(qt->qtVersion() >= QtSupport::QtVersionNumber(5, 4, 0)); +} + +AndroidBuildApkWidget::~AndroidBuildApkWidget() +{ + delete m_ui; +} + +QString AndroidBuildApkWidget::displayName() const +{ + return tr("<b>Build Android APK</b>"); +} + +QString AndroidBuildApkWidget::summaryText() const +{ + return displayName(); +} + +void AndroidBuildApkWidget::setTargetSdk(const QString &sdk) +{ + m_step->setBuildTargetSdk(sdk); +} + +void AndroidBuildApkWidget::setMinistro() +{ + m_step->setDeployAction(AndroidBuildApkStep::MinistroDeployment); +} + +void AndroidBuildApkWidget::setDeployLocalQtLibs() +{ + m_step->setDeployAction(AndroidBuildApkStep::DebugDeployment); +} + +void AndroidBuildApkWidget::setBundleQtLibs() +{ + m_step->setDeployAction(AndroidBuildApkStep::BundleLibrariesDeployment); +} + +void AndroidBuildApkWidget::signPackageCheckBoxToggled(bool checked) +{ + m_ui->certificatesAliasComboBox->setEnabled(checked); + m_step->setSignPackage(checked); + updateSigningWarning(); + if (!checked) + return; + if (!m_step->keystorePath().isEmpty()) + setCertificates(); +} + +void AndroidBuildApkWidget::createKeyStore() +{ + AndroidCreateKeystoreCertificate d; + if (d.exec() != QDialog::Accepted) + return; + m_ui->KeystoreLocationPathChooser->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(); +} + +void AndroidBuildApkWidget::setCertificates() +{ + QAbstractItemModel *certificates = m_step->keystoreCertificates(); + m_ui->signPackageCheckBox->setChecked(certificates); + m_ui->certificatesAliasComboBox->setModel(certificates); +} + +void AndroidBuildApkWidget::updateKeyStorePath(const QString &path) +{ + Utils::FileName file = Utils::FileName::fromString(path); + m_step->setKeystorePath(file); + m_ui->signPackageCheckBox->setChecked(!file.isEmpty()); + if (!file.isEmpty()) + setCertificates(); +} + +void AndroidBuildApkWidget::certificatesAliasComboBoxActivated(const QString &alias) +{ + if (alias.length()) + m_step->setCertificateAlias(alias); +} + +void AndroidBuildApkWidget::certificatesAliasComboBoxCurrentIndexChanged(const QString &alias) +{ + if (alias.length()) + m_step->setCertificateAlias(alias); +} + +void AndroidBuildApkWidget::openPackageLocationCheckBoxToggled(bool checked) +{ + m_step->setOpenPackageLocation(checked); +} + +void AndroidBuildApkWidget::verboseOutputCheckBoxToggled(bool checked) +{ + m_step->setVerboseOutput(checked); +} + +void AndroidBuildApkWidget::updateSigningWarning() +{ + bool debug = m_step->buildConfiguration()->buildType() == ProjectExplorer::BuildConfiguration::Debug; + if (m_step->signPackage() && debug) { + m_ui->signingDebugWarningIcon->setVisible(true); + m_ui->signingDebugWarningLabel->setVisible(true); + } else { + m_ui->signingDebugWarningIcon->setVisible(false); + m_ui->signingDebugWarningLabel->setVisible(false); + } +} + diff --git a/src/plugins/android/androidbuildapkwidget.h b/src/plugins/android/androidbuildapkwidget.h new file mode 100644 index 0000000000..5a7f896df7 --- /dev/null +++ b/src/plugins/android/androidbuildapkwidget.h @@ -0,0 +1,82 @@ +/************************************************************************** +** +** Copyright (c) 2014 BogDan Vatra <bog_dan_ro@yahoo.com> +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef ANDROIDBUILDAPKWIDGET_H +#define ANDROIDBUILDAPKWIDGET_H + +#include "android_global.h" + +#include <projectexplorer/buildstep.h> + +#include <QWidget> + +QT_BEGIN_NAMESPACE +namespace Ui { class AndroidBuildApkWidget; } +QT_END_NAMESPACE + +namespace QmakeProjectManager { class QmakeBuildConfiguration; } + +namespace Android { +class AndroidBuildApkStep; + +class ANDROID_EXPORT AndroidBuildApkWidget : public ProjectExplorer::BuildStepConfigWidget +{ + Q_OBJECT + +public: + AndroidBuildApkWidget(AndroidBuildApkStep *step); + ~AndroidBuildApkWidget(); + +private slots: + void setTargetSdk(const QString &sdk); + void setMinistro(); + void setDeployLocalQtLibs(); + void setBundleQtLibs(); + void createKeyStore(); + void certificatesAliasComboBoxCurrentIndexChanged(const QString &alias); + void certificatesAliasComboBoxActivated(const QString &alias); + void updateSigningWarning(); + void openPackageLocationCheckBoxToggled(bool checked); + void verboseOutputCheckBoxToggled(bool checked); + void updateKeyStorePath(const QString &path); + void signPackageCheckBoxToggled(bool checked); + +private: + virtual QString summaryText() const; + virtual QString displayName() const; + void setCertificates(); + + Ui::AndroidBuildApkWidget *m_ui; + AndroidBuildApkStep *m_step; +}; + +} + +#endif // ANDROIDBUILDAPKWIDGET_H diff --git a/src/plugins/android/androidbuildapkwidget.ui b/src/plugins/android/androidbuildapkwidget.ui new file mode 100644 index 0000000000..f663669028 --- /dev/null +++ b/src/plugins/android/androidbuildapkwidget.ui @@ -0,0 +1,228 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>AndroidBuildApkWidget</class> + <widget class="QWidget" name="AndroidBuildApkWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>819</width> + <height>390</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="1" column="0" colspan="2"> + <widget class="QGroupBox" name="signPackage"> + <property name="title"> + <string>Sign package</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QLabel" name="KeystoreLocationLabel"> + <property name="text"> + <string>Keystore:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item> + <widget class="Utils::PathChooser" name="KeystoreLocationPathChooser" native="true"/> + </item> + <item> + <widget class="QPushButton" name="KeystoreCreatePushButton"> + <property name="text"> + <string>Create...</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <item> + <widget class="QCheckBox" name="signPackageCheckBox"> + <property name="text"> + <string>Sign package</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QLabel" name="signingDebugWarningIcon"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string/> + </property> + <property name="pixmap"> + <pixmap resource="../coreplugin/core.qrc">:/core/images/warning.png</pixmap> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="signingDebugWarningLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Signing a debug package</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="KeystoreLocationLabel_2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Certificate alias:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="certificatesAliasComboBox"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>300</width> + <height>0</height> + </size> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item row="0" column="0" colspan="2"> + <widget class="QGroupBox" name="application"> + <property name="title"> + <string>Application</string> + </property> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="0" column="0"> + <widget class="QLabel" name="targetSDKLabel"> + <property name="text"> + <string>Android build SDK:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="targetSDKComboBox"/> + </item> + </layout> + </widget> + </item> + <item row="2" column="1"> + <widget class="QGroupBox" name="advancedActions"> + <property name="title"> + <string>Advanced Actions</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="1" column="0"> + <widget class="QCheckBox" name="verboseOutputCheckBox"> + <property name="text"> + <string>Verbose output</string> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QCheckBox" name="openPackageLocationCheckBox"> + <property name="text"> + <string>Open package location after build</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item row="2" column="0"> + <widget class="QGroupBox" name="qtDeployment"> + <property name="title"> + <string>Qt Deployment</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QRadioButton" name="ministroOption"> + <property name="toolTip"> + <string>Uses the external Ministro application to download and maintain Qt libraries.</string> + </property> + <property name="text"> + <string>Use Ministro service to install Qt</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="bundleQtOption"> + <property name="toolTip"> + <string>Creates a standalone APK.</string> + </property> + <property name="text"> + <string>Bundle Qt libraries in APK</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="temporaryQtOption"> + <property name="toolTip"> + <string>Pushes local Qt libraries to device. You must have Qt libraries compiled for that platform. +The APK will not be usable on any other device.</string> + </property> + <property name="text"> + <string>Deploy local Qt libraries to temporary directory</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>Utils::PathChooser</class> + <extends>QWidget</extends> + <header location="global">utils/pathchooser.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources> + <include location="../coreplugin/core.qrc"/> + </resources> + <connections/> +</ui> diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp index 84416075f4..7fa5c938a9 100644 --- a/src/plugins/android/androidconfigurations.cpp +++ b/src/plugins/android/androidconfigurations.cpp @@ -73,7 +73,7 @@ using namespace ProjectExplorer; using namespace Utils; namespace Android { -namespace Internal { +using namespace Internal; namespace { const QLatin1String SettingsGroup("AndroidConfigurations"); @@ -343,6 +343,11 @@ QStringList AndroidConfig::apiLevelNamesFor(const QList<SdkPlatform> &platforms) return results; } +QString AndroidConfig::apiLevelNameFor(const SdkPlatform &platform) +{ + return QLatin1String("android-") + QString::number(platform.apiLevel); +} + QList<SdkPlatform> AndroidConfig::sdkTargets(int minApiLevel) const { updateAvailableSdkPlatforms(); @@ -1294,5 +1299,4 @@ void AndroidConfigurations::updateAndroidDevice() AndroidConfigurations *AndroidConfigurations::m_instance = 0; -} // namespace Internal } // namespace Android diff --git a/src/plugins/android/androidconfigurations.h b/src/plugins/android/androidconfigurations.h index 98a1474669..3b28c80f79 100644 --- a/src/plugins/android/androidconfigurations.h +++ b/src/plugins/android/androidconfigurations.h @@ -30,6 +30,8 @@ #ifndef ANDROIDCONFIGURATIONS_H #define ANDROIDCONFIGURATIONS_H +#include "android_global.h" + #include <QObject> #include <QString> #include <QStringList> @@ -37,7 +39,9 @@ #include <QHash> #include <QMap> #include <QFutureInterface> + #include <projectexplorer/abi.h> + #include <utils/fileutils.h> #include <utils/environment.h> @@ -49,7 +53,6 @@ namespace ProjectExplorer { class Project; } namespace Android { class AndroidPlugin; -namespace Internal { struct AndroidDeviceInfo { @@ -76,7 +79,7 @@ public: QStringList abis; }; -class AndroidConfig +class ANDROID_EXPORT AndroidConfig { public: AndroidConfig(); @@ -85,6 +88,7 @@ public: void save(QSettings &settings) const; static QStringList apiLevelNamesFor(const QList<SdkPlatform> &platforms); + static QString apiLevelNameFor(const SdkPlatform &platform); QList<SdkPlatform> sdkTargets(int minApiLevel = 0) const; Utils::FileName sdkLocation() const; @@ -192,7 +196,7 @@ private: mutable QHash<QString, QString> m_serialNumberToDeviceName; }; -class AndroidConfigurations : public QObject +class ANDROID_EXPORT AndroidConfigurations : public QObject { friend class Android::AndroidPlugin; Q_OBJECT @@ -225,7 +229,6 @@ private: QMap<ProjectExplorer::Project *, QMap<QString, QString> > m_defaultDeviceForAbi; }; -} // namespace Internal } // namespace Android #endif // ANDROIDCONFIGURATIONS_H diff --git a/src/plugins/android/androidconstants.h b/src/plugins/android/androidconstants.h index f84e18f9b8..d05555661e 100644 --- a/src/plugins/android/androidconstants.h +++ b/src/plugins/android/androidconstants.h @@ -73,6 +73,11 @@ const char JAVA_MIMETYPE[] = "text/x-java"; const char WIZARD_JAVA[] = "Wizard.Java"; const char JAVA_WIZARD_CATEGORY[] = "U.Java"; const char JAVA_DISPLAY_CATEGORY[] = "Java"; +const char ANDROID_ARCHITECTURE[] = "Android.Architecture"; +const char ANDROID_DEPLOY_SETTINGS_FILE[] = "AndroidDeploySettingsFile"; +const char ANDROID_PACKAGE_SOURCE_DIR[] = "AndroidPackageSourceDir"; +const char ANDROID_EXTRA_LIBS[] = "AndroidExtraLibs"; + } // namespace Constants; } // namespace Android diff --git a/src/plugins/android/androiddebugsupport.h b/src/plugins/android/androiddebugsupport.h index 5cea83a0db..ef705f644a 100644 --- a/src/plugins/android/androiddebugsupport.h +++ b/src/plugins/android/androiddebugsupport.h @@ -42,7 +42,6 @@ namespace Android { class AndroidRunConfiguration; namespace Internal { - class AndroidRunner; class AndroidDebugSupport : public AndroidRunSupport diff --git a/src/plugins/android/androiddeployconfiguration.cpp b/src/plugins/android/androiddeployconfiguration.cpp index f90c33e214..177413f4ce 100644 --- a/src/plugins/android/androiddeployconfiguration.cpp +++ b/src/plugins/android/androiddeployconfiguration.cpp @@ -29,15 +29,15 @@ #include "androiddeployconfiguration.h" #include "androidconstants.h" -#include "androidpackageinstallationstep.h" #include "androiddeployqtstep.h" #include "androidmanager.h" +#include "androidqtsupport.h" #include <projectexplorer/buildsteplist.h> +#include <projectexplorer/project.h> #include <projectexplorer/target.h> #include <projectexplorer/toolchain.h> -#include <qmakeprojectmanager/qmakeproject.h> #include <qtsupport/qtkitinformation.h> #include <qtsupport/qtsupportconstants.h> @@ -73,9 +73,7 @@ bool AndroidDeployConfigurationFactory::canCreate(Target *parent, Core::Id id) c DeployConfiguration *AndroidDeployConfigurationFactory::create(Target *parent, Core::Id id) { AndroidDeployConfiguration *dc = new AndroidDeployConfiguration(parent, id); - - dc->stepList()->insertStep(0, new AndroidPackageInstallationStep(AndroidPackageInstallationStep::BuildDirectory, dc->stepList())); - dc->stepList()->insertStep(1, new AndroidDeployQtStep(dc->stepList())); + dc->stepList()->insertStep(0, new AndroidDeployQtStep(dc->stepList())); return dc; } @@ -114,9 +112,6 @@ DeployConfiguration *AndroidDeployConfigurationFactory::clone(Target *parent, De QList<Core::Id> AndroidDeployConfigurationFactory::availableCreationIds(Target *parent) const { QList<Core::Id> ids; - if (!qobject_cast<QmakeProjectManager::QmakeProject *>(parent->project())) - return ids; - if (!parent->project()->supportsKit(parent->kit())) return ids; diff --git a/src/plugins/android/androiddeployqtstep.cpp b/src/plugins/android/androiddeployqtstep.cpp index 6263d6292c..cc3ec1a596 100644 --- a/src/plugins/android/androiddeployqtstep.cpp +++ b/src/plugins/android/androiddeployqtstep.cpp @@ -30,38 +30,43 @@ #include "androiddeployqtstep.h" #include "androiddeployqtwidget.h" +#include "androidqtsupport.h" #include "certificatesmodel.h" #include "javaparser.h" #include "androidmanager.h" #include "androidconstants.h" -#include <utils/qtcassert.h> -#include <utils/qtcprocess.h> #include <coreplugin/fileutils.h> #include <coreplugin/icore.h> #include <coreplugin/messagemanager.h> + +#include <projectexplorer/buildconfiguration.h> #include <projectexplorer/buildsteplist.h> #include <projectexplorer/projectexplorerconstants.h> -#include <projectexplorer/target.h> #include <projectexplorer/project.h> +#include <projectexplorer/target.h> + #include <qtsupport/qtkitinformation.h> -#include <qmakeprojectmanager/qmakebuildconfiguration.h> -#include <qmakeprojectmanager/qmakeproject.h> -#include <qmakeprojectmanager/qmakenodes.h> + +#include <utils/qtcassert.h> +#include <utils/qtcprocess.h> + #include <QInputDialog> #include <QMessageBox> + using namespace Android; using namespace Android::Internal; -const QLatin1String DeployActionKey("Qt4ProjectManager.AndroidDeployQtStep.DeployQtAction"); +const QLatin1String UninstallPreviousPackageKey("UninstallPreviousPackage"); const QLatin1String KeystoreLocationKey("KeystoreLocation"); const QLatin1String SignPackageKey("SignPackage"); const QLatin1String BuildTargetSdkKey("BuildTargetSdk"); const QLatin1String VerboseOutputKey("VerboseOutput"); const QLatin1String InputFile("InputFile"); const QLatin1String ProFilePathForInputFile("ProFilePathForInputFile"); +const QLatin1String InstallFailedInconsistentCertificatesString("INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES"); const Core::Id AndroidDeployQtStep::Id("Qt4ProjectManager.AndroidDeployQtStep"); ////////////////// @@ -149,20 +154,12 @@ AndroidDeployQtStep::AndroidDeployQtStep(ProjectExplorer::BuildStepList *parent, void AndroidDeployQtStep::ctor() { + m_uninstallPreviousPackage = false; + m_uninstallPreviousPackageTemp = false; + m_uninstallPreviousPackageRun = false; + //: AndroidDeployQtStep default display name setDefaultDisplayName(tr("Deploy to Android device")); - m_deployAction = BundleLibrariesDeployment; - m_signPackage = false; - m_openPackageLocation = false; - m_verbose = false; - - // will be overwriten by settings if the user choose something different - SdkPlatform sdk = AndroidConfigurations::currentConfig().highestAndroidSdk(); - if (sdk.apiLevel > 0) - m_buildTargetSdk = QLatin1String("android-") + QString::number(sdk.apiLevel); - - connect(project(), SIGNAL(proFilesEvaluated()), - this, SLOT(updateInputFile())); } bool AndroidDeployQtStep::init() @@ -188,109 +185,34 @@ bool AndroidDeployQtStep::init() m_avdName.clear(); m_serialNumber = info.serialNumber; } + AndroidManager::setDeviceSerialNumber(target(), m_serialNumber); - QmakeProjectManager::QmakeBuildConfiguration *bc - = static_cast<QmakeProjectManager::QmakeBuildConfiguration *>(target()->activeBuildConfiguration()); - - if (m_signPackage) { - // check keystore and certificate passwords - while (!AndroidManager::checkKeystorePassword(m_keystorePath.toString(), m_keystorePasswd)) { - if (!keystorePassword()) - return false; // user canceled - } - - while (!AndroidManager::checkCertificatePassword(m_keystorePath.toString(), m_keystorePasswd, m_certificateAlias, m_certificatePasswd)) { - if (!certificatePassword()) - return false; // user canceled - } - - - if ((bc->qmakeBuildConfiguration() & QtSupport::BaseQtVersion::DebugBuild)) - emit addOutput(tr("Warning: Signing a debug package."), BuildStep::ErrorMessageOutput); - } + ProjectExplorer::BuildConfiguration *bc = target()->activeBuildConfiguration(); QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target()->kit()); if (!version) return false; - QmakeProjectManager::QmakeProject *pro = static_cast<QmakeProjectManager::QmakeProject *>(project()); - JavaParser *parser = new JavaParser; - parser->setProjectFileList(pro->files(ProjectExplorer::Project::AllFiles)); - setOutputParser(parser); - - QString command = version->qmakeProperty("QT_HOST_BINS"); - if (!command.endsWith(QLatin1Char('/'))) - command += QLatin1Char('/'); - command += Utils::HostOsInfo::withExecutableSuffix(QLatin1String("androiddeployqt")); - - QString deploymentMethod; - if (m_deployAction == MinistroDeployment) - deploymentMethod = QLatin1String("ministro"); - else if (m_deployAction == DebugDeployment) - deploymentMethod = QLatin1String("debug"); - else if (m_deployAction == BundleLibrariesDeployment) - deploymentMethod = QLatin1String("bundled"); - - QString outputDir = bc->buildDirectory().appendPath(QLatin1String(Constants::ANDROID_BUILDDIRECTORY)).toString(); - const QmakeProjectManager::QmakeProFileNode *node = pro->rootQmakeProjectNode()->findProFileFor(m_proFilePathForInputFile); - if (!node) { // should never happen - emit addOutput(tr("Internal Error: Could not find .pro file."), BuildStep::ErrorMessageOutput); - return false; - } - - QString inputFile = node->singleVariableValue(QmakeProjectManager::AndroidDeploySettingsFile); - if (inputFile.isEmpty()) { // should never happen - emit addOutput(tr("Internal Error: Unknown Android deployment JSON file location."), BuildStep::ErrorMessageOutput); - return false; - } - - QStringList arguments; - arguments << QLatin1String("--input") - << inputFile - << QLatin1String("--output") - << outputDir - << QLatin1String("--deployment") - << deploymentMethod - << QLatin1String("--install") - << QLatin1String("--ant") - << AndroidConfigurations::currentConfig().antToolPath().toString() - << QLatin1String("--android-platform") - << m_buildTargetSdk - << QLatin1String("--jdk") - << AndroidConfigurations::currentConfig().openJDKLocation().toString(); - - parser->setSourceDirectory(Utils::FileName::fromString(node->singleVariableValue(QmakeProjectManager::AndroidPackageSourceDir))); - parser->setBuildDirectory(Utils::FileName::fromString(outputDir)); - - if (m_verbose) - arguments << QLatin1String("--verbose"); - if (m_avdName.isEmpty()) - arguments << QLatin1String("--device") - << info.serialNumber; - - if (m_signPackage) { - arguments << QLatin1String("--sign") - << m_keystorePath.toString() - << m_certificateAlias - << QLatin1String("--storepass") - << m_keystorePasswd; - if (!m_certificatePasswd.isEmpty()) - arguments << QLatin1String("--keypass") - << m_certificatePasswd; + m_uninstallPreviousPackageRun = m_uninstallPreviousPackage || m_uninstallPreviousPackageTemp; + m_uninstallPreviousPackageTemp = false; + if (m_uninstallPreviousPackageRun) { + m_packageName = AndroidManager::packageName(target()); + if (m_packageName.isEmpty()){ + emit addOutput(tr("Cannot find the package name."), ErrorOutput); + return false; + } } ProjectExplorer::ProcessParameters *pp = processParameters(); + pp->setCommand(AndroidConfigurations::currentConfig().adbToolPath().toString()); pp->setMacroExpander(bc->macroExpander()); pp->setWorkingDirectory(bc->buildDirectory().toString()); Utils::Environment env = bc->environment(); pp->setEnvironment(env); - pp->setCommand(command); - pp->setArguments(Utils::QtcProcess::joinArgs(arguments)); - pp->resolveAll(); + m_apkPath = AndroidManager::androidQtSupport(target())->apkPath(target(), AndroidManager::signPackage(target()) + ? AndroidQtSupport::ReleaseBuildSigned + : AndroidQtSupport::DebugBuild).toString(); - m_openPackageLocationForRun = m_openPackageLocation; - m_apkPath = AndroidManager::apkPath(target(), m_signPackage ? AndroidManager::ReleaseBuildSigned - : AndroidManager::DebugBuild).toString(); m_buildDirectory = bc->buildDirectory().toString(); bool result = AbstractProcessStep::init(); @@ -304,6 +226,7 @@ bool AndroidDeployQtStep::init() void AndroidDeployQtStep::run(QFutureInterface<bool> &fi) { + m_installOk = true; if (!m_avdName.isEmpty()) { QString serialNumber = AndroidConfigurations::currentConfig().waitForAvd(m_deviceAPILevel, m_targetArch, fi); if (serialNumber.isEmpty()) { @@ -312,12 +235,27 @@ void AndroidDeployQtStep::run(QFutureInterface<bool> &fi) return; } m_serialNumber = serialNumber; - QString args = processParameters()->arguments(); - Utils::QtcProcess::addArg(&args, QLatin1String("--device")); - Utils::QtcProcess::addArg(&args, serialNumber); - processParameters()->setArguments(args); + AndroidManager::setDeviceSerialNumber(target(), serialNumber); + } + + if (m_uninstallPreviousPackageRun) { + emit addOutput(tr("Uninstall previous package %1.").arg(m_packageName), MessageOutput); + runCommand(AndroidConfigurations::currentConfig().adbToolPath().toString(), + AndroidDeviceInfo::adbSelector(m_serialNumber) + << QLatin1String("uninstall") << m_packageName); } + ProjectExplorer::ProcessParameters *pp = processParameters(); + QString args; + for (const QString arg : AndroidDeviceInfo::adbSelector(m_serialNumber)) + Utils::QtcProcess::addArg(&args, arg); + + Utils::QtcProcess::addArg(&args, QLatin1String("install")); + Utils::QtcProcess::addArg(&args, QLatin1String("-r")); + Utils::QtcProcess::addArg(&args, m_apkPath); + pp->setArguments(args); + pp->resolveAll(); + AbstractProcessStep::run(fi); emit addOutput(tr("Pulling files necessary for debugging."), MessageOutput); @@ -334,17 +272,17 @@ void AndroidDeployQtStep::run(QFutureInterface<bool> &fi) void AndroidDeployQtStep::runCommand(const QString &program, const QStringList &arguments) { QProcess buildProc; - emit addOutput(tr("Package deploy: Running command '%1 %2'.").arg(program).arg(arguments.join(QLatin1String(" "))), BuildStep::MessageOutput); + emit addOutput(tr("Package deploy: Running command \"%1 %2\".").arg(program).arg(arguments.join(QLatin1String(" "))), BuildStep::MessageOutput); buildProc.start(program, arguments); if (!buildProc.waitForStarted()) { - emit addOutput(tr("Packaging error: Could not start command '%1 %2'. Reason: %3") + emit addOutput(tr("Packaging error: Could not start command \"%1 %2\". Reason: %3") .arg(program).arg(arguments.join(QLatin1String(" "))).arg(buildProc.errorString()), BuildStep::ErrorMessageOutput); return; } if (!buildProc.waitForFinished(2 * 60 * 1000) || buildProc.error() != QProcess::UnknownError || buildProc.exitCode() != 0) { - QString mainMessage = tr("Packaging Error: Command '%1 %2' failed.") + QString mainMessage = tr("Packaging Error: Command \"%1 %2\" failed.") .arg(program).arg(arguments.join(QLatin1String(" "))); if (buildProc.error() != QProcess::UnknownError) mainMessage += QLatin1Char(' ') + tr("Reason: %1").arg(buildProc.errorString()); @@ -354,148 +292,55 @@ void AndroidDeployQtStep::runCommand(const QString &program, const QStringList & } } -void AndroidDeployQtStep::updateInputFile() +ProjectExplorer::BuildStepConfigWidget *AndroidDeployQtStep::createConfigWidget() { - QmakeProjectManager::QmakeProject *pro = static_cast<QmakeProjectManager::QmakeProject *>(project()); - QList<QmakeProjectManager::QmakeProFileNode *> nodes = pro->applicationProFiles(); - - const QmakeProjectManager::QmakeProFileNode *node = pro->rootQmakeProjectNode()->findProFileFor(m_proFilePathForInputFile); - if (!nodes.contains(const_cast<QmakeProjectManager::QmakeProFileNode *>(node))) { - if (!nodes.isEmpty()) - m_proFilePathForInputFile = nodes.first()->path(); - else - m_proFilePathForInputFile.clear(); - } - - emit inputFileChanged(); + return new AndroidDeployQtWidget(this); } -void AndroidDeployQtStep::showInGraphicalShell() +void AndroidDeployQtStep::stdOutput(const QString &line) { - Core::FileUtils::showInGraphicalShell(Core::ICore::instance()->mainWindow(), m_apkPath); + if (line.contains(InstallFailedInconsistentCertificatesString)) + m_installOk = false; + AbstractProcessStep::stdOutput(line); } -ProjectExplorer::BuildStepConfigWidget *AndroidDeployQtStep::createConfigWidget() +void AndroidDeployQtStep::stdError(const QString &line) { - return new AndroidDeployQtWidget(this); + if (line.contains(InstallFailedInconsistentCertificatesString)) + m_installOk = false; + AbstractProcessStep::stdError(line); } -void AndroidDeployQtStep::processFinished(int exitCode, QProcess::ExitStatus status) +bool AndroidDeployQtStep::processSucceeded(int exitCode, QProcess::ExitStatus status) { - AbstractProcessStep::processFinished(exitCode, status); - if (m_openPackageLocationForRun && status == QProcess::NormalExit && exitCode == 0) - QMetaObject::invokeMethod(this, "showInGraphicalShell", Qt::QueuedConnection); + if (!m_installOk && !m_uninstallPreviousPackageRun && + QMessageBox::critical(0, tr("Install failed"), + tr("Another application with the same package id but signed with " + "different ceritificate already exists.\n" + "Do you want to install the existing package next time?"), + QMessageBox::Yes, QMessageBox::No) + == QMessageBox::Yes) { + m_uninstallPreviousPackageTemp = true; + } + return m_installOk && AbstractProcessStep::processSucceeded(exitCode, status); } bool AndroidDeployQtStep::fromMap(const QVariantMap &map) { - m_deployAction = AndroidDeployQtAction(map.value(QLatin1String(DeployActionKey), - BundleLibrariesDeployment).toInt()); - m_keystorePath = Utils::FileName::fromString(map.value(KeystoreLocationKey).toString()); - m_signPackage = false; // don't restore this - m_buildTargetSdk = map.value(BuildTargetSdkKey).toString(); - m_verbose = map.value(VerboseOutputKey).toBool(); - m_proFilePathForInputFile = map.value(ProFilePathForInputFile).toString(); + m_uninstallPreviousPackage = map.value(UninstallPreviousPackageKey, false).toBool(); return ProjectExplorer::BuildStep::fromMap(map); } QVariantMap AndroidDeployQtStep::toMap() const { QVariantMap map = ProjectExplorer::BuildStep::toMap(); - map.insert(QLatin1String(DeployActionKey), m_deployAction); - map.insert(KeystoreLocationKey, m_keystorePath.toString()); - map.insert(SignPackageKey, m_signPackage); - map.insert(BuildTargetSdkKey, m_buildTargetSdk); - map.insert(VerboseOutputKey, m_verbose); - map.insert(ProFilePathForInputFile, m_proFilePathForInputFile); + map.insert(UninstallPreviousPackageKey, m_uninstallPreviousPackage); return map; } -void AndroidDeployQtStep::setBuildTargetSdk(const QString &sdk) -{ - m_buildTargetSdk = sdk; -} - -QString AndroidDeployQtStep::buildTargetSdk() const -{ - return m_buildTargetSdk; -} - -Utils::FileName AndroidDeployQtStep::keystorePath() -{ - return m_keystorePath; -} - -AndroidDeployQtStep::AndroidDeployQtAction AndroidDeployQtStep::deployAction() const -{ - return m_deployAction; -} - -void AndroidDeployQtStep::setDeployAction(AndroidDeployQtStep::AndroidDeployQtAction deploy) -{ - m_deployAction = deploy; -} - -void AndroidDeployQtStep::setKeystorePath(const Utils::FileName &path) -{ - m_keystorePath = path; - m_certificatePasswd.clear(); - m_keystorePasswd.clear(); -} - -void AndroidDeployQtStep::setKeystorePassword(const QString &pwd) -{ - m_keystorePasswd = pwd; -} - -void AndroidDeployQtStep::setCertificateAlias(const QString &alias) -{ - m_certificateAlias = alias; -} - -void AndroidDeployQtStep::setCertificatePassword(const QString &pwd) -{ - m_certificatePasswd = pwd; -} - -bool AndroidDeployQtStep::signPackage() const -{ - return m_signPackage; -} - -void AndroidDeployQtStep::setSignPackage(bool b) -{ - m_signPackage = b; -} - -QString AndroidDeployQtStep::deviceSerialNumber() -{ - return m_serialNumber; -} - -bool AndroidDeployQtStep::openPackageLocation() const -{ - return m_openPackageLocation; -} - -void AndroidDeployQtStep::setOpenPackageLocation(bool open) +void AndroidDeployQtStep::setUninstallPreviousPackage(bool uninstall) { - m_openPackageLocation = open; -} - -void AndroidDeployQtStep::setVerboseOutput(bool verbose) -{ - m_verbose = verbose; -} - -QString AndroidDeployQtStep::proFilePathForInputFile() const -{ - return m_proFilePathForInputFile; -} - -void AndroidDeployQtStep::setProFilePathForInputFile(const QString &path) -{ - m_proFilePathForInputFile = path; + m_uninstallPreviousPackage = uninstall; } bool AndroidDeployQtStep::runInGuiThread() const @@ -503,69 +348,7 @@ bool AndroidDeployQtStep::runInGuiThread() const return true; } -bool AndroidDeployQtStep::verboseOutput() const -{ - return m_verbose; -} - -// Note this functions is duplicated between AndroidDeployStep and AndroidDeployQtStep -// since it does modify the stored password in AndroidDeployQtStep it's not easily -// extractable. The situation will clean itself up once AndroidDeployStep is no longer -// necessary -QAbstractItemModel *AndroidDeployQtStep::keystoreCertificates() +bool AndroidDeployQtStep::uninstallPreviousPackage() { - QString rawCerts; - QProcess keytoolProc; - while (!rawCerts.length() || !m_keystorePasswd.length()) { - QStringList params; - params << QLatin1String("-list") << QLatin1String("-v") << QLatin1String("-keystore") << m_keystorePath.toUserOutput() << QLatin1String("-storepass"); - if (!m_keystorePasswd.length()) - keystorePassword(); - if (!m_keystorePasswd.length()) - return 0; - params << m_keystorePasswd; - params << QLatin1String("-J-Duser.language=en"); - keytoolProc.start(AndroidConfigurations::currentConfig().keytoolPath().toString(), params); - if (!keytoolProc.waitForStarted() || !keytoolProc.waitForFinished()) { - QMessageBox::critical(0, tr("Error"), - tr("Failed to run keytool.")); - return 0; - } - - if (keytoolProc.exitCode()) { - QMessageBox::critical(0, tr("Error"), - tr("Invalid password.")); - m_keystorePasswd.clear(); - } - rawCerts = QString::fromLatin1(keytoolProc.readAllStandardOutput()); - } - return new CertificatesModel(rawCerts, this); -} - -bool AndroidDeployQtStep::keystorePassword() -{ - m_keystorePasswd.clear(); - bool ok; - QString text = QInputDialog::getText(0, tr("Keystore"), - tr("Keystore password:"), QLineEdit::Password, - QString(), &ok); - if (ok && !text.isEmpty()) { - m_keystorePasswd = text; - return true; - } - return false; -} - -bool AndroidDeployQtStep::certificatePassword() -{ - m_certificatePasswd.clear(); - bool ok; - QString text = QInputDialog::getText(0, tr("Certificate"), - tr("Certificate password (%1):").arg(m_certificateAlias), QLineEdit::Password, - QString(), &ok); - if (ok && !text.isEmpty()) { - m_certificatePasswd = text; - return true; - } - return false; + return m_uninstallPreviousPackage; } diff --git a/src/plugins/android/androiddeployqtstep.h b/src/plugins/android/androiddeployqtstep.h index 01745ccb5c..68f94bd552 100644 --- a/src/plugins/android/androiddeployqtstep.h +++ b/src/plugins/android/androiddeployqtstep.h @@ -71,91 +71,46 @@ class AndroidDeployQtStep : public ProjectExplorer::AbstractProcessStep public: AndroidDeployQtStep(ProjectExplorer::BuildStepList *bc); - enum AndroidDeployQtAction - { - MinistroDeployment, // use ministro - DebugDeployment, - BundleLibrariesDeployment - }; - bool fromMap(const QVariantMap &map); QVariantMap toMap() const; - AndroidDeployQtStep::AndroidDeployQtAction deployAction() const; - QString deviceSerialNumber(); - - void setBuildTargetSdk(const QString &sdk); - QString buildTargetSdk() const; - - // signing - Utils::FileName keystorePath(); - void setKeystorePath(const Utils::FileName &path); - void setKeystorePassword(const QString &pwd); - void setCertificateAlias(const QString &alias); - void setCertificatePassword(const QString &pwd); - - QAbstractItemModel *keystoreCertificates(); - bool signPackage() const; - void setSignPackage(bool b); - - bool openPackageLocation() const; - void setOpenPackageLocation(bool open); - bool verboseOutput() const; - void setVerboseOutput(bool verbose); - - QString proFilePathForInputFile() const; - void setProFilePathForInputFile(const QString &path); - bool runInGuiThread() const; -signals: - // also on purpose emitted if the possible values of this changed - void inputFileChanged(); + bool uninstallPreviousPackage(); public slots: - void setDeployAction(AndroidDeployQtAction deploy); // slot? - -private slots: - void showInGraphicalShell(); + void setUninstallPreviousPackage(bool uninstall); - void updateInputFile(); private: AndroidDeployQtStep(ProjectExplorer::BuildStepList *bc, AndroidDeployQtStep *other); void ctor(); - bool keystorePassword(); - bool certificatePassword(); void runCommand(const QString &program, const QStringList &arguments); bool init(); void run(QFutureInterface<bool> &fi); ProjectExplorer::BuildStepConfigWidget *createConfigWidget(); bool immutable() const { return true; } - void processFinished(int exitCode, QProcess::ExitStatus status); + void stdOutput(const QString &line); + void stdError(const QString &line); + virtual bool processSucceeded(int exitCode, QProcess::ExitStatus status); - QString m_buildTargetSdk; + QString m_packageName; QString m_serialNumber; - AndroidDeployQtAction m_deployAction; - bool m_signPackage; - bool m_verbose; - bool m_openPackageLocation; - bool m_openPackageLocationForRun; QString m_buildDirectory; - - Utils::FileName m_keystorePath; - QString m_keystorePasswd; - QString m_certificateAlias; - QString m_certificatePasswd; QString m_avdName; QString m_apkPath; + QString m_targetArch; - QString m_proFilePathForInputFile; int m_deviceAPILevel; - + bool m_uninstallPreviousPackage; + bool m_uninstallPreviousPackageTemp; + bool m_uninstallPreviousPackageRun; static const Core::Id Id; + bool m_installOk; }; } -} +} // namespace Android #endif // ANDROIDDEPLOYQTSTEP_H diff --git a/src/plugins/android/androiddeployqtwidget.cpp b/src/plugins/android/androiddeployqtwidget.cpp index b07ab8f827..11f9bf9bdb 100644 --- a/src/plugins/android/androiddeployqtwidget.cpp +++ b/src/plugins/android/androiddeployqtwidget.cpp @@ -31,133 +31,28 @@ #include "androiddeployqtwidget.h" #include "ui_androiddeployqtwidget.h" -#include "androidcreatekeystorecertificate.h" #include "androiddeployqtstep.h" #include "androidmanager.h" -#include "createandroidmanifestwizard.h" -#include "androidextralibrarylistmodel.h" - -#include <projectexplorer/target.h> -#include <qmakeprojectmanager/qmakebuildconfiguration.h> -#include <qmakeprojectmanager/qmakeproject.h> -#include <qmakeprojectmanager/qmakenodes.h> -#include <utils/fancylineedit.h> -#include <utils/pathchooser.h> #include <QFileDialog> -#include <algorithm> - - using namespace Android; using namespace Internal; AndroidDeployQtWidget::AndroidDeployQtWidget(AndroidDeployQtStep *step) : ProjectExplorer::BuildStepConfigWidget(), m_ui(new Ui::AndroidDeployQtWidget), - m_step(step), - m_currentBuildConfiguration(0), - m_ignoreChange(false) + m_step(step) { m_ui->setupUi(this); - // Target sdk combobox - int minApiLevel = 9; - QStringList targets = AndroidConfig::apiLevelNamesFor(AndroidConfigurations::currentConfig().sdkTargets(minApiLevel)); - m_ui->targetSDKComboBox->addItems(targets); - m_ui->targetSDKComboBox->setCurrentIndex(targets.indexOf(step->buildTargetSdk())); - - // deployment option - switch (m_step->deployAction()) { - case AndroidDeployQtStep::MinistroDeployment: - m_ui->ministroOption->setChecked(true); - break; - case AndroidDeployQtStep::DebugDeployment: - m_ui->temporaryQtOption->setChecked(true); - break; - case AndroidDeployQtStep::BundleLibrariesDeployment: - m_ui->bundleQtOption->setChecked(true); - break; - default: - // can't happen - break; - } - - // signing - m_ui->signPackageCheckBox->setChecked(m_step->signPackage()); - m_ui->KeystoreLocationPathChooser->setExpectedKind(Utils::PathChooser::File); - m_ui->KeystoreLocationPathChooser->lineEdit()->setReadOnly(true); - m_ui->KeystoreLocationPathChooser->setPath(m_step->keystorePath().toUserOutput()); - m_ui->KeystoreLocationPathChooser->setInitialBrowsePathBackup(QDir::homePath()); - m_ui->KeystoreLocationPathChooser->setPromptDialogFilter(tr("Keystore files (*.keystore *.jks)")); - m_ui->KeystoreLocationPathChooser->setPromptDialogTitle(tr("Select keystore file")); - m_ui->signingDebugWarningIcon->hide(); - m_ui->signingDebugWarningLabel->hide(); - signPackageCheckBoxToggled(m_step->signPackage()); - - m_ui->verboseOutputCheckBox->setChecked(m_step->verboseOutput()); - m_ui->openPackageLocationCheckBox->setChecked(m_step->openPackageLocation()); - - bool oldFiles = AndroidManager::checkForQt51Files(m_step->project()->projectDirectory()); - m_ui->oldFilesWarningIcon->setVisible(oldFiles); - m_ui->oldFilesWarningLabel->setVisible(oldFiles); - - // target sdk - connect(m_ui->targetSDKComboBox, SIGNAL(activated(QString)), SLOT(setTargetSdk(QString))); - - // deployment options - connect(m_ui->ministroOption, SIGNAL(clicked()), SLOT(setMinistro())); - connect(m_ui->temporaryQtOption, SIGNAL(clicked()), SLOT(setDeployLocalQtLibs())); - connect(m_ui->bundleQtOption, SIGNAL(clicked()), SLOT(setBundleQtLibs())); - + m_ui->uninstallPreviousPackage->setChecked(m_step->uninstallPreviousPackage()); connect(m_ui->installMinistroButton, SIGNAL(clicked()), SLOT(installMinistro())); connect(m_ui->cleanLibsPushButton, SIGNAL(clicked()), SLOT(cleanLibsOnDevice())); connect(m_ui->resetDefaultDevices, SIGNAL(clicked()), SLOT(resetDefaultDevices())); - connect(m_ui->openPackageLocationCheckBox, SIGNAL(toggled(bool)), - this, SLOT(openPackageLocationCheckBoxToggled(bool))); - connect(m_ui->verboseOutputCheckBox, SIGNAL(toggled(bool)), - this, SLOT(verboseOutputCheckBoxToggled(bool))); - - //signing - connect(m_ui->signPackageCheckBox, SIGNAL(toggled(bool)), - this, SLOT(signPackageCheckBoxToggled(bool))); - connect(m_ui->KeystoreCreatePushButton, SIGNAL(clicked()), - this, SLOT(createKeyStore())); - connect(m_ui->KeystoreLocationPathChooser, SIGNAL(pathChanged(QString)), - SLOT(updateKeyStorePath(QString))); - connect(m_ui->certificatesAliasComboBox, SIGNAL(activated(QString)), - this, SLOT(certificatesAliasComboBoxActivated(QString))); - connect(m_ui->certificatesAliasComboBox, SIGNAL(currentIndexChanged(QString)), - this, SLOT(certificatesAliasComboBoxCurrentIndexChanged(QString))); + connect(m_ui->uninstallPreviousPackage, SIGNAL(toggled(bool)), + m_step, SLOT(setUninstallPreviousPackage(bool))); - activeBuildConfigurationChanged(); - connect(m_step->target(), SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)), - this, SLOT(activeBuildConfigurationChanged())); - - connect(m_ui->inputFileComboBox, SIGNAL(currentIndexChanged(int)), - this, SLOT(inputFileComboBoxIndexChanged())); - - updateInputFileUi(); - connect(m_step, SIGNAL(inputFileChanged()), - this, SLOT(updateInputFileUi())); - - connect(m_ui->createAndroidManifestButton, SIGNAL(clicked()), - this, SLOT(createManifestButton())); - - m_extraLibraryListModel = new AndroidExtraLibraryListModel(static_cast<QmakeProjectManager::QmakeProject *>(m_step->project()), - this); - m_ui->androidExtraLibsListView->setModel(m_extraLibraryListModel); - - connect(m_ui->androidExtraLibsListView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), - this, SLOT(checkEnableRemoveButton())); - - connect(m_ui->addAndroidExtraLibButton, SIGNAL(clicked()), this, SLOT(addAndroidExtraLib())); - connect(m_ui->removeAndroidExtraLibButton, SIGNAL(clicked()), this, SLOT(removeAndroidExtraLib())); - - connect(m_extraLibraryListModel, SIGNAL(enabledChanged(bool)), - m_ui->additionalLibrariesGroupBox, SLOT(setEnabled(bool))); - - m_ui->additionalLibrariesGroupBox->setEnabled(m_extraLibraryListModel->isEnabled()); } AndroidDeployQtWidget::~AndroidDeployQtWidget() @@ -165,45 +60,6 @@ AndroidDeployQtWidget::~AndroidDeployQtWidget() delete m_ui; } -void AndroidDeployQtWidget::createManifestButton() -{ - CreateAndroidManifestWizard wizard(m_step->target()); - wizard.exec(); -} - -void AndroidDeployQtWidget::updateInputFileUi() -{ - QmakeProjectManager::QmakeProject *project - = static_cast<QmakeProjectManager::QmakeProject *>(m_step->project()); - QList<QmakeProjectManager::QmakeProFileNode *> nodes = project->applicationProFiles(); - int size = nodes.size(); - if (size == 0 || size == 1) { - // there's nothing to select, e.g. before parsing - m_ui->inputFileLabel->setVisible(false); - m_ui->inputFileComboBox->setVisible(false); - } else { - m_ignoreChange = true; - m_ui->inputFileLabel->setVisible(true); - m_ui->inputFileComboBox->setVisible(true); - - m_ui->inputFileComboBox->clear(); - foreach (QmakeProjectManager::QmakeProFileNode *node, nodes) - m_ui->inputFileComboBox->addItem(node->displayName(), node->path()); - - int index = m_ui->inputFileComboBox->findData(m_step->proFilePathForInputFile()); - m_ui->inputFileComboBox->setCurrentIndex(index); - m_ignoreChange = false; - } -} - -void AndroidDeployQtWidget::inputFileComboBoxIndexChanged() -{ - if (m_ignoreChange) - return; - QString proFilePath = m_ui->inputFileComboBox->itemData(m_ui->inputFileComboBox->currentIndex()).toString(); - m_step->setProFilePathForInputFile(proFilePath); -} - QString AndroidDeployQtWidget::displayName() const { return tr("<b>Deploy configurations</b>"); @@ -214,26 +70,6 @@ QString AndroidDeployQtWidget::summaryText() const return displayName(); } -void AndroidDeployQtWidget::setTargetSdk(const QString &sdk) -{ - m_step->setBuildTargetSdk(sdk); -} - -void AndroidDeployQtWidget::setMinistro() -{ - m_step->setDeployAction(AndroidDeployQtStep::MinistroDeployment); -} - -void AndroidDeployQtWidget::setDeployLocalQtLibs() -{ - m_step->setDeployAction(AndroidDeployQtStep::DebugDeployment); -} - -void AndroidDeployQtWidget::setBundleQtLibs() -{ - m_step->setDeployAction(AndroidDeployQtStep::BundleLibrariesDeployment); -} - void AndroidDeployQtWidget::installMinistro() { QString packagePath = @@ -253,113 +89,3 @@ void AndroidDeployQtWidget::resetDefaultDevices() AndroidConfigurations::clearDefaultDevices(m_step->project()); } -void AndroidDeployQtWidget::signPackageCheckBoxToggled(bool checked) -{ - m_ui->certificatesAliasComboBox->setEnabled(checked); - m_step->setSignPackage(checked); - updateSigningWarning(); - if (!checked) - return; - if (!m_step->keystorePath().isEmpty()) - setCertificates(); -} - -void AndroidDeployQtWidget::createKeyStore() -{ - AndroidCreateKeystoreCertificate d; - if (d.exec() != QDialog::Accepted) - return; - m_ui->KeystoreLocationPathChooser->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(); -} - -void AndroidDeployQtWidget::setCertificates() -{ - QAbstractItemModel *certificates = m_step->keystoreCertificates(); - m_ui->signPackageCheckBox->setChecked(certificates); - m_ui->certificatesAliasComboBox->setModel(certificates); -} - -void AndroidDeployQtWidget::updateKeyStorePath(const QString &path) -{ - Utils::FileName file = Utils::FileName::fromString(path); - m_step->setKeystorePath(file); - m_ui->signPackageCheckBox->setChecked(!file.isEmpty()); - if (!file.isEmpty()) - setCertificates(); -} - -void AndroidDeployQtWidget::certificatesAliasComboBoxActivated(const QString &alias) -{ - if (alias.length()) - m_step->setCertificateAlias(alias); -} - -void AndroidDeployQtWidget::certificatesAliasComboBoxCurrentIndexChanged(const QString &alias) -{ - if (alias.length()) - m_step->setCertificateAlias(alias); -} - -void AndroidDeployQtWidget::openPackageLocationCheckBoxToggled(bool checked) -{ - m_step->setOpenPackageLocation(checked); -} - -void AndroidDeployQtWidget::verboseOutputCheckBoxToggled(bool checked) -{ - m_step->setVerboseOutput(checked); -} - -void AndroidDeployQtWidget::activeBuildConfigurationChanged() -{ - if (m_currentBuildConfiguration) - disconnect(m_currentBuildConfiguration, SIGNAL(qmakeBuildConfigurationChanged()), - this, SLOT(updateSigningWarning())); - updateSigningWarning(); - QmakeProjectManager::QmakeBuildConfiguration *bc - = qobject_cast<QmakeProjectManager::QmakeBuildConfiguration *>(m_step->target()->activeBuildConfiguration()); - m_currentBuildConfiguration = bc; - if (bc) - connect(bc, SIGNAL(qmakeBuildConfigurationChanged()), this, SLOT(updateSigningWarning())); - m_currentBuildConfiguration = bc; -} - -void AndroidDeployQtWidget::updateSigningWarning() -{ - QmakeProjectManager::QmakeBuildConfiguration *bc = qobject_cast<QmakeProjectManager::QmakeBuildConfiguration *>(m_step->target()->activeBuildConfiguration()); - bool debug = bc && (bc->qmakeBuildConfiguration() & QtSupport::BaseQtVersion::DebugBuild); - if (m_step->signPackage() && debug) { - m_ui->signingDebugWarningIcon->setVisible(true); - m_ui->signingDebugWarningLabel->setVisible(true); - } else { - m_ui->signingDebugWarningIcon->setVisible(false); - m_ui->signingDebugWarningLabel->setVisible(false); - } -} - -void AndroidDeployQtWidget::addAndroidExtraLib() -{ - QStringList fileNames = QFileDialog::getOpenFileNames(this, - tr("Select additional libraries"), - m_currentBuildConfiguration->target()->project()->projectDirectory().toString(), - tr("Libraries (*.so)")); - - if (!fileNames.isEmpty()) - m_extraLibraryListModel->addEntries(fileNames); -} - -void AndroidDeployQtWidget::removeAndroidExtraLib() -{ - QModelIndexList removeList = m_ui->androidExtraLibsListView->selectionModel()->selectedIndexes(); - m_extraLibraryListModel->removeEntries(removeList); -} - -void AndroidDeployQtWidget::checkEnableRemoveButton() -{ - m_ui->removeAndroidExtraLibButton->setEnabled(m_ui->androidExtraLibsListView->selectionModel()->hasSelection()); -} diff --git a/src/plugins/android/androiddeployqtwidget.h b/src/plugins/android/androiddeployqtwidget.h index d44a79186a..158b530593 100644 --- a/src/plugins/android/androiddeployqtwidget.h +++ b/src/plugins/android/androiddeployqtwidget.h @@ -38,12 +38,10 @@ QT_BEGIN_NAMESPACE namespace Ui { class AndroidDeployQtWidget; } QT_END_NAMESPACE -namespace QmakeProjectManager { class QmakeBuildConfiguration; } - namespace Android { namespace Internal { class AndroidDeployQtStep; -class AndroidExtraLibraryListModel; + class AndroidDeployQtWidget : public ProjectExplorer::BuildStepConfigWidget { Q_OBJECT @@ -53,39 +51,16 @@ public: ~AndroidDeployQtWidget(); private slots: - void setTargetSdk(const QString &sdk); - void setMinistro(); - void setDeployLocalQtLibs(); - void setBundleQtLibs(); void installMinistro(); void cleanLibsOnDevice(); void resetDefaultDevices(); - void createKeyStore(); - void certificatesAliasComboBoxCurrentIndexChanged(const QString &alias); - void certificatesAliasComboBoxActivated(const QString &alias); - void activeBuildConfigurationChanged(); - void updateSigningWarning(); - void openPackageLocationCheckBoxToggled(bool checked); - void verboseOutputCheckBoxToggled(bool checked); - void updateKeyStorePath(const QString &path); - void signPackageCheckBoxToggled(bool checked); - void updateInputFileUi(); - void inputFileComboBoxIndexChanged(); - void createManifestButton(); - void addAndroidExtraLib(); - void removeAndroidExtraLib(); - void checkEnableRemoveButton(); private: virtual QString summaryText() const; virtual QString displayName() const; - void setCertificates(); Ui::AndroidDeployQtWidget *m_ui; AndroidDeployQtStep *m_step; - AndroidExtraLibraryListModel *m_extraLibraryListModel; - QmakeProjectManager::QmakeBuildConfiguration *m_currentBuildConfiguration; - bool m_ignoreChange; }; } diff --git a/src/plugins/android/androiddeployqtwidget.ui b/src/plugins/android/androiddeployqtwidget.ui index fc744a6955..204d1d886f 100644 --- a/src/plugins/android/androiddeployqtwidget.ui +++ b/src/plugins/android/androiddeployqtwidget.ui @@ -6,376 +6,53 @@ <rect> <x>0</x> <y>0</y> - <width>682</width> - <height>615</height> + <width>403</width> + <height>178</height> </rect> </property> <property name="windowTitle"> <string>Form</string> </property> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="2" column="0" colspan="2"> - <widget class="QGroupBox" name="signPackage"> - <property name="title"> - <string>Sign package</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <widget class="QLabel" name="KeystoreLocationLabel"> - <property name="text"> - <string>Keystore:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item> - <widget class="Utils::PathChooser" name="KeystoreLocationPathChooser" native="true"/> - </item> - <item> - <widget class="QPushButton" name="KeystoreCreatePushButton"> - <property name="text"> - <string>Create...</string> - </property> - </widget> - </item> - </layout> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_4"> - <item> - <widget class="QCheckBox" name="signPackageCheckBox"> - <property name="text"> - <string>Sign package</string> - </property> - </widget> - </item> - </layout> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_3"> - <item> - <widget class="QLabel" name="signingDebugWarningIcon"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string/> - </property> - <property name="pixmap"> - <pixmap resource="../coreplugin/core.qrc">:/core/images/warning.png</pixmap> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="signingDebugWarningLabel"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Signing a debug package</string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="KeystoreLocationLabel_2"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Certificate alias:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="certificatesAliasComboBox"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>300</width> - <height>0</height> - </size> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </item> - <item row="3" column="1"> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> <widget class="QGroupBox" name="advancedActions"> <property name="title"> - <string>Advanced Actions</string> + <string>Deploy options</string> </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="4" column="0"> - <widget class="QPushButton" name="cleanLibsPushButton"> - <property name="text"> - <string>Clean Temporary Libraries Directory on Device</string> - </property> - </widget> - </item> - <item row="5" column="0"> - <widget class="QPushButton" name="installMinistroButton"> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QCheckBox" name="uninstallPreviousPackage"> <property name="text"> - <string>Install Ministro from APK</string> + <string>Uninstall previous package</string> </property> </widget> </item> - <item row="3" column="0"> + <item> <widget class="QPushButton" name="resetDefaultDevices"> <property name="text"> <string>Reset Default Devices</string> </property> </widget> </item> - <item row="0" column="0"> - <widget class="QCheckBox" name="openPackageLocationCheckBox"> - <property name="text"> - <string>Open package location after build</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QCheckBox" name="verboseOutputCheckBox"> - <property name="text"> - <string>Verbose output</string> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QPushButton" name="createAndroidManifestButton"> - <property name="text"> - <string>Create AndroidManifest.xml</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item row="1" column="0" colspan="2"> - <widget class="QGroupBox" name="application"> - <property name="title"> - <string>Application</string> - </property> - <layout class="QGridLayout" name="gridLayout_3"> - <item row="1" column="1"> - <widget class="QComboBox" name="targetSDKComboBox"/> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="targetSDKLabel"> - <property name="text"> - <string>Android build SDK:</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QComboBox" name="inputFileComboBox"/> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="inputFileLabel"> - <property name="text"> - <string>Input file for androiddeployqt:</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item row="0" column="0" colspan="2"> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QLabel" name="oldFilesWarningIcon"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string/> - </property> - <property name="pixmap"> - <pixmap resource="../coreplugin/core.qrc">:/core/images/warning.png</pixmap> - </property> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="oldFilesWarningLabel"> - <property name="text"> - <string>Qt no longer uses the folder "android" in the project's source directory.</string> - </property> - <property name="wordWrap"> - <bool>true</bool> - </property> - </widget> - </item> - </layout> - </item> - <item row="3" column="0"> - <widget class="QGroupBox" name="qtDeployment"> - <property name="title"> - <string>Qt Deployment</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QRadioButton" name="ministroOption"> - <property name="toolTip"> - <string>Uses the external Ministro application to download and maintain Qt libraries.<br/><br/>Ministro is a third-party tool which provides the open source Qt libraries on demand. These libraries are compatible with the default open source binary package and will not always be up-to-date.</string> - </property> - <property name="text"> - <string>Use Ministro service to install Qt</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> <item> - <widget class="QRadioButton" name="temporaryQtOption"> - <property name="toolTip"> - <string>Pushes local Qt libraries to device. You must have Qt libraries compiled for that platform. -The APK will not be usable on any other device.</string> - </property> + <widget class="QPushButton" name="cleanLibsPushButton"> <property name="text"> - <string>Deploy local Qt libraries to temporary directory</string> + <string>Clean Temporary Libraries Directory on Device</string> </property> </widget> </item> <item> - <widget class="QRadioButton" name="bundleQtOption"> - <property name="toolTip"> - <string>Creates a standalone APK.</string> - </property> + <widget class="QPushButton" name="installMinistroButton"> <property name="text"> - <string>Bundle Qt libraries in APK</string> + <string>Install Ministro from APK</string> </property> </widget> </item> - <item> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </item> - <item row="4" column="0" colspan="2"> - <widget class="QGroupBox" name="additionalLibrariesGroupBox"> - <property name="title"> - <string>Additional Libraries</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout_3"> - <item> - <layout class="QHBoxLayout" name="androidExtraLibsLayout"> - <item> - <widget class="QListView" name="androidExtraLibsListView"> - <property name="toolTip"> - <string>List of extra libraries to include in Android package and load on startup.</string> - </property> - <property name="selectionMode"> - <enum>QAbstractItemView::ExtendedSelection</enum> - </property> - </widget> - </item> - <item> - <layout class="QVBoxLayout" name="androidExtraLibsButtonLayout"> - <item> - <widget class="QToolButton" name="addAndroidExtraLibButton"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="toolTip"> - <string>Select library to include in package.</string> - </property> - <property name="text"> - <string>Add...</string> - </property> - <property name="toolButtonStyle"> - <enum>Qt::ToolButtonTextOnly</enum> - </property> - </widget> - </item> - <item> - <widget class="QToolButton" name="removeAndroidExtraLibButton"> - <property name="toolTip"> - <string>Remove currently selected library from list.</string> - </property> - <property name="text"> - <string>Remove</string> - </property> - </widget> - </item> - <item> - <spacer name="verticalSpacer_2"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - </layout> - </item> </layout> </widget> </item> </layout> </widget> - <customwidgets> - <customwidget> - <class>Utils::PathChooser</class> - <extends>QWidget</extends> - <header location="global">utils/pathchooser.h</header> - <container>1</container> - </customwidget> - </customwidgets> - <resources> - <include location="../projectexplorer/projectexplorer.qrc"/> - </resources> + <resources/> <connections/> </ui> diff --git a/src/plugins/android/androiddevice.h b/src/plugins/android/androiddevice.h index ae119a96c3..3456bc0b90 100644 --- a/src/plugins/android/androiddevice.h +++ b/src/plugins/android/androiddevice.h @@ -33,9 +33,10 @@ #include <projectexplorer/devicesupport/idevice.h> namespace Android { -namespace Internal { class AndroidConfigurations; // needed for friend declaration +namespace Internal { + class AndroidDevice : public ProjectExplorer::IDevice { public: @@ -54,7 +55,7 @@ public: protected: friend class AndroidDeviceFactory; - friend class AndroidConfigurations; + friend class Android::AndroidConfigurations; AndroidDevice(); AndroidDevice(const AndroidDevice &other); }; diff --git a/src/plugins/android/androidglobal.h b/src/plugins/android/androidglobal.h index dc93a878b4..04acc7a527 100644 --- a/src/plugins/android/androidglobal.h +++ b/src/plugins/android/androidglobal.h @@ -32,7 +32,7 @@ #include <utils/environment.h> -#include <projectexplorer/deployconfiguration.h> +#include <projectexplorer/buildconfiguration.h> #include <projectexplorer/buildsteplist.h> #define ASSERT_STATE_GENERIC(State, expected, actual) \ @@ -45,15 +45,17 @@ class AndroidGlobal { public: - template<class T> static T *buildStep(const ProjectExplorer::DeployConfiguration *dc) + template<class T> static T *buildStep(const ProjectExplorer::BuildConfiguration *dc) { - ProjectExplorer::BuildStepList *bsl = dc->stepList(); - if (!bsl) - return 0; - const QList<ProjectExplorer::BuildStep *> &buildSteps = bsl->steps(); - for (int i = buildSteps.count() - 1; i >= 0; --i) { - if (T * const step = qobject_cast<T *>(buildSteps.at(i))) - return step; + for (const Core::Id &id : dc->knownStepLists()) { + ProjectExplorer::BuildStepList *bsl = dc->stepList(id); + if (!bsl) + return 0; + const QList<ProjectExplorer::BuildStep *> &buildSteps = bsl->steps(); + for (int i = buildSteps.count() - 1; i >= 0; --i) { + if (T * const step = qobject_cast<T *>(buildSteps.at(i))) + return step; + } } return 0; } diff --git a/src/plugins/android/androidmanager.cpp b/src/plugins/android/androidmanager.cpp index cd22d4443c..922007e8e5 100644 --- a/src/plugins/android/androidmanager.cpp +++ b/src/plugins/android/androidmanager.cpp @@ -35,6 +35,8 @@ #include "androidtoolchain.h" #include "androiddeployqtstep.h" #include "androidqtsupport.h" +#include "androidqtversion.h" +#include "androidbuildapkstep.h" #include <coreplugin/documentmanager.h> #include <coreplugin/messagemanager.h> @@ -42,13 +44,12 @@ #include <extensionsystem/pluginmanager.h> +#include <projectexplorer/buildconfiguration.h> +#include <projectexplorer/project.h> #include <projectexplorer/projectexplorer.h> #include <projectexplorer/session.h> #include <projectexplorer/target.h> -#include <qmakeprojectmanager/qmakenodes.h> -#include <qmakeprojectmanager/qmakeproject.h> -#include <qmakeprojectmanager/qmakeprojectmanagerconstants.h> -#include <qmakeprojectmanager/qmakebuildconfiguration.h> + #include <qtsupport/customexecutablerunconfiguration.h> #include <qtsupport/qtkitinformation.h> #include <qtsupport/qtsupportconstants.h> @@ -66,21 +67,26 @@ namespace { const QLatin1String AndroidDirName("android"); const QLatin1String AndroidManifestName("AndroidManifest.xml"); const QLatin1String AndroidLibsFileName("/res/values/libs.xml"); - const QLatin1String AndroidStringsFileName("/res/values/strings.xml"); const QLatin1String AndroidDefaultPropertiesName("project.properties"); + const QLatin1String AndroidDeviceSn("AndroidDeviceSerialNumber"); + } // anonymous namespace namespace Android { -namespace Internal { -bool AndroidManager::supportsAndroid(ProjectExplorer::Target *target) +using namespace Internal; + +bool AndroidManager::supportsAndroid(const ProjectExplorer::Kit *kit) { - if (!qobject_cast<QmakeProjectManager::QmakeProject *>(target->project())) - return false; - QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target->kit()); + QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(kit); return version && version->platformName() == QLatin1String(QtSupport::Constants::ANDROID_PLATFORM); } +bool AndroidManager::supportsAndroid(const ProjectExplorer::Target *target) +{ + return supportsAndroid(target->kit()); +} + QString AndroidManager::packageName(ProjectExplorer::Target *target) { QDomDocument doc; @@ -124,23 +130,28 @@ int AndroidManager::minimumSDK(ProjectExplorer::Target *target) QString AndroidManager::buildTargetSDK(ProjectExplorer::Target *target) { - if (!target->activeDeployConfiguration()) - return QLatin1String("android-9"); - AndroidDeployQtStep *step = AndroidGlobal::buildStep<AndroidDeployQtStep>(target->activeDeployConfiguration()); - if (step) - return step->buildTargetSdk(); - return QLatin1String("android-9"); + AndroidBuildApkStep *androidBuildApkStep + = AndroidGlobal::buildStep<AndroidBuildApkStep>(target->activeBuildConfiguration()); + if (androidBuildApkStep) + return androidBuildApkStep->buildTargetSdk(); + + QString fallback = AndroidConfig::apiLevelNameFor(AndroidConfigurations::currentConfig().highestAndroidSdk()); + return fallback; +} + +bool AndroidManager::signPackage(ProjectExplorer::Target *target) +{ + AndroidBuildApkStep *androidBuildApkStep + = AndroidGlobal::buildStep<AndroidBuildApkStep>(target->activeBuildConfiguration()); + if (androidBuildApkStep) + return androidBuildApkStep->signPackage(); + return false; } QString AndroidManager::targetArch(ProjectExplorer::Target *target) { - QmakeProjectManager::QmakeProject *pro = qobject_cast<QmakeProjectManager::QmakeProject *>(target->project()); - if (!pro) - return QString(); - QmakeProjectManager::QmakeProFileNode *node = pro->rootQmakeProjectNode(); - if (!node) - return QString(); - return node->singleVariableValue(QmakeProjectManager::AndroidArchVar); + AndroidQtVersion *qt = static_cast<AndroidQtVersion *>(QtSupport::QtKitInformation::qtVersion(target->kit())); + return qt->targetArch(); } Utils::FileName AndroidManager::dirPath(ProjectExplorer::Target *target) @@ -163,60 +174,23 @@ Utils::FileName AndroidManager::defaultPropertiesPath(ProjectExplorer::Target *t return dirPath(target).appendPath(AndroidDefaultPropertiesName); } -Utils::FileName AndroidManager::apkPath(ProjectExplorer::Target *target, BuildType buildType) -{ - QString packageName = QLatin1String("QtApp"); - QString buildTypeName; - if (buildType == DebugBuild) - buildTypeName = QLatin1String("debug"); - else if (buildType == ReleaseBuildUnsigned) - buildTypeName =QLatin1String("release-unsigned"); - else - buildTypeName = QLatin1String("release"); - - return dirPath(target) - .appendPath(QLatin1String("bin")) - .appendPath(QString::fromLatin1("%1-%2.apk") - .arg(packageName) - .arg(buildTypeName)); -} - -QStringList AndroidManager::availableTargetApplications(ProjectExplorer::Target *target) -{ - QStringList apps; - QmakeProjectManager::QmakeProject *qmakeProject = qobject_cast<QmakeProjectManager::QmakeProject *>(target->project()); - if (!qmakeProject) - return apps; - foreach (QmakeProjectManager::QmakeProFileNode *proFile, qmakeProject->applicationProFiles()) { - if (proFile->projectType() == QmakeProjectManager::ApplicationTemplate) { - if (proFile->targetInformation().target.startsWith(QLatin1String("lib")) - && proFile->targetInformation().target.endsWith(QLatin1String(".so"))) - apps << proFile->targetInformation().target.mid(3, proFile->targetInformation().target.lastIndexOf(QLatin1Char('.')) - 3); - else - apps << proFile->targetInformation().target; - } - } - apps.sort(); - return apps; -} - bool AndroidManager::bundleQt(ProjectExplorer::Target *target) { - AndroidDeployQtStep *androidDeployQtStep - = AndroidGlobal::buildStep<AndroidDeployQtStep>(target->activeDeployConfiguration()); - if (androidDeployQtStep) - return androidDeployQtStep->deployAction() == AndroidDeployQtStep::BundleLibrariesDeployment; + AndroidBuildApkStep *androidBuildApkStep + = AndroidGlobal::buildStep<AndroidBuildApkStep>(target->activeBuildConfiguration()); + if (androidBuildApkStep) + return androidBuildApkStep->deployAction() == AndroidBuildApkStep::BundleLibrariesDeployment; return false; } bool AndroidManager::useLocalLibs(ProjectExplorer::Target *target) { - AndroidDeployQtStep *androidDeployQtStep - = AndroidGlobal::buildStep<AndroidDeployQtStep>(target->activeDeployConfiguration()); - if (androidDeployQtStep) { - return androidDeployQtStep->deployAction() == AndroidDeployQtStep::DebugDeployment - || androidDeployQtStep->deployAction() == AndroidDeployQtStep::BundleLibrariesDeployment; + AndroidBuildApkStep *androidBuildApkStep + = AndroidGlobal::buildStep<AndroidBuildApkStep>(target->activeBuildConfiguration()); + if (androidBuildApkStep) { + return androidBuildApkStep->deployAction() == AndroidBuildApkStep::DebugDeployment + || androidBuildApkStep->deployAction() == AndroidBuildApkStep::BundleLibrariesDeployment; } return false; @@ -224,11 +198,12 @@ bool AndroidManager::useLocalLibs(ProjectExplorer::Target *target) QString AndroidManager::deviceSerialNumber(ProjectExplorer::Target *target) { - AndroidDeployQtStep *androidDeployQtStep - = AndroidGlobal::buildStep<AndroidDeployQtStep>(target->activeDeployConfiguration()); - if (androidDeployQtStep) - return androidDeployQtStep->deviceSerialNumber(); - return QString(); + return target->namedSettings(AndroidDeviceSn).toString(); +} + +void AndroidManager::setDeviceSerialNumber(ProjectExplorer::Target *target, const QString &deviceSerialNumber) +{ + target->setNamedSettings(AndroidDeviceSn, deviceSerialNumber); } Utils::FileName AndroidManager::localLibsRulesFilePath(ProjectExplorer::Target *target) @@ -688,5 +663,4 @@ AndroidQtSupport *AndroidManager::androidQtSupport(ProjectExplorer::Target *targ return 0; } -} // namespace Internal } // namespace Android diff --git a/src/plugins/android/androidmanager.h b/src/plugins/android/androidmanager.h index 44eb9b57ab..04345ba659 100644 --- a/src/plugins/android/androidmanager.h +++ b/src/plugins/android/androidmanager.h @@ -30,45 +30,47 @@ #ifndef ANDROIDMANAGER_H #define ANDROIDMANAGER_H +#include "android_global.h" #include <utils/fileutils.h> -#include <QDomDocument> #include <QPair> #include <QObject> #include <QStringList> -namespace ProjectExplorer { class Target; } +class QDomDocument; + +namespace ProjectExplorer { +class Kit; +class Target; +} namespace Android { + class AndroidQtSupport; -namespace Internal { -class AndroidManager : public QObject +class ANDROID_EXPORT AndroidManager : public QObject { Q_OBJECT public: - enum BuildType - { - DebugBuild, - ReleaseBuildUnsigned, - ReleaseBuildSigned - }; - static bool supportsAndroid(ProjectExplorer::Target *target); + static bool supportsAndroid(const ProjectExplorer::Kit *kit); + static bool supportsAndroid(const ProjectExplorer::Target *target); static QString packageName(ProjectExplorer::Target *target); static QString intentName(ProjectExplorer::Target *target); static QString activityName(ProjectExplorer::Target *target); - static QStringList availableTargetApplications(ProjectExplorer::Target *target); - static bool bundleQt(ProjectExplorer::Target *target); static bool useLocalLibs(ProjectExplorer::Target *target); static QString deviceSerialNumber(ProjectExplorer::Target *target); + static void setDeviceSerialNumber(ProjectExplorer::Target *target, const QString &deviceSerialNumber); static QString buildTargetSDK(ProjectExplorer::Target *target); + + static bool signPackage(ProjectExplorer::Target *target); + static int minimumSDK(ProjectExplorer::Target *target); static QString targetArch(ProjectExplorer::Target *target); @@ -77,7 +79,6 @@ public: static Utils::FileName manifestPath(ProjectExplorer::Target *target); static Utils::FileName libsPath(ProjectExplorer::Target *target); static Utils::FileName defaultPropertiesPath(ProjectExplorer::Target *target); - static Utils::FileName apkPath(ProjectExplorer::Target *target, BuildType buildType); static Utils::FileName localLibsRulesFilePath(ProjectExplorer::Target *target); static QString loadLocalLibs(ProjectExplorer::Target *target, int apiLevel = -1); @@ -134,7 +135,6 @@ private: }; -} // namespace Internal } // namespace Android #endif // ANDROIDMANAGER_H diff --git a/src/plugins/android/androidmanifesteditorwidget.cpp b/src/plugins/android/androidmanifesteditorwidget.cpp index f0f6e7af33..bc94f74c9e 100644 --- a/src/plugins/android/androidmanifesteditorwidget.cpp +++ b/src/plugins/android/androidmanifesteditorwidget.cpp @@ -32,12 +32,13 @@ #include "androidconstants.h" #include "androidmanifestdocument.h" #include "androidmanager.h" +#include "androidqtsupport.h" #include <coreplugin/coreconstants.h> #include <coreplugin/icore.h> #include <coreplugin/infobar.h> #include <coreplugin/editormanager/ieditor.h> -#include <texteditor/plaintexteditor.h> + #include <projectexplorer/project.h> #include <projectexplorer/projectwindow.h> #include <projectexplorer/iprojectproperties.h> @@ -45,9 +46,10 @@ #include <projectexplorer/target.h> #include <projectexplorer/projectexplorer.h> #include <projectexplorer/kitinformation.h> + #include <texteditor/texteditoractionhandler.h> #include <texteditor/texteditorsettings.h> -#include <qmakeprojectmanager/qmakeproject.h> +#include <texteditor/plaintexteditor.h> #include <utils/algorithm.h> #include <QLineEdit> @@ -476,7 +478,7 @@ void AndroidManifestEditorWidget::updateTargetComboBox() if (project) { ProjectExplorer::Kit *kit = project->activeTarget()->kit(); if (ProjectExplorer::DeviceTypeKitInformation::deviceTypeId(kit) == Constants::ANDROID_DEVICE_TYPE) - items = AndroidManager::availableTargetApplications(project->activeTarget()); + items = AndroidManager::androidQtSupport(project->activeTarget())->projectTargetApplications(project->activeTarget()); } // QComboBox randomly resets what the user has entered diff --git a/src/plugins/android/androidplugin.cpp b/src/plugins/android/androidplugin.cpp index cf90b06134..ff0592fd31 100644 --- a/src/plugins/android/androidplugin.cpp +++ b/src/plugins/android/androidplugin.cpp @@ -35,7 +35,6 @@ #include "androiddevice.h" #include "androiddevicefactory.h" #include "androidmanager.h" -#include "androidpackageinstallationfactory.h" #include "androidrunfactories.h" #include "androidsettingspage.h" #include "androidtoolchain.h" @@ -47,8 +46,6 @@ #include "javaeditorfactory.h" #include "javacompletionassistprovider.h" #include "javafilewizard.h" -#include "qmakeandroidsupport.h" -#include "qmakeandroidrunfactories.h" #ifdef HAVE_QBS # include "androidqbspropertyprovider.h" #endif @@ -72,11 +69,9 @@ bool AndroidPlugin::initialize(const QStringList &arguments, QString *errorMessa Q_UNUSED(arguments); Q_UNUSED(errorMessage); - new Internal::AndroidConfigurations(this); + new AndroidConfigurations(this); addAutoReleasedObject(new Internal::AndroidRunControlFactory); - addAutoReleasedObject(new Internal::QmakeAndroidRunConfigurationFactory); - addAutoReleasedObject(new Internal::AndroidPackageInstallationFactory); addAutoReleasedObject(new Internal::AndroidDeployQtStepFactory); addAutoReleasedObject(new Internal::AndroidSettingsPage); addAutoReleasedObject(new Internal::AndroidQtVersionFactory); @@ -87,7 +82,6 @@ bool AndroidPlugin::initialize(const QStringList &arguments, QString *errorMessa addAutoReleasedObject(new Internal::JavaEditorFactory); addAutoReleasedObject(new Internal::JavaCompletionAssistProvider); addAutoReleasedObject(new Internal::JavaFileWizard); - addAutoReleasedObject(new Internal::QmakeAndroidSupport); ProjectExplorer::KitManager::registerKitInformation(new Internal::AndroidGdbServerKitInformation); // AndroidManifest.xml editor @@ -117,16 +111,16 @@ bool AndroidPlugin::initialize(const QStringList &arguments, QString *errorMessa void AndroidPlugin::kitsRestored() { - Internal::AndroidConfigurations::updateAutomaticKitList(); + AndroidConfigurations::updateAutomaticKitList(); connect(QtSupport::QtVersionManager::instance(), SIGNAL(qtVersionsChanged(QList<int>,QList<int>,QList<int>)), - Internal::AndroidConfigurations::instance(), SLOT(updateAutomaticKitList())); + AndroidConfigurations::instance(), SLOT(updateAutomaticKitList())); disconnect(ProjectExplorer::KitManager::instance(), SIGNAL(kitsChanged()), this, SLOT(kitsRestored())); } void AndroidPlugin::updateDevice() { - Internal::AndroidConfigurations::updateAndroidDevice(); + AndroidConfigurations::updateAndroidDevice(); } } // namespace Android diff --git a/src/plugins/android/androidqtsupport.h b/src/plugins/android/androidqtsupport.h index 8e60612151..96cbf342f8 100644 --- a/src/plugins/android/androidqtsupport.h +++ b/src/plugins/android/androidqtsupport.h @@ -58,10 +58,13 @@ public: ReleaseBuildSigned }; - public: virtual bool canHandle(const ProjectExplorer::Target *target) const = 0; virtual QStringList soLibSearchPath(const ProjectExplorer::Target *target) const = 0; + virtual QStringList projectTargetApplications(const ProjectExplorer::Target *target) const = 0; + virtual Utils::FileName apkPath(ProjectExplorer::Target *target, BuildType buildType) const = 0; + + virtual void resetBuild(const ProjectExplorer::Target *target) = 0; }; } // namespace QtSupport diff --git a/src/plugins/android/androidqtversion.cpp b/src/plugins/android/androidqtversion.cpp index 559dd28f13..c808ecfb29 100644 --- a/src/plugins/android/androidqtversion.cpp +++ b/src/plugins/android/androidqtversion.cpp @@ -35,22 +35,19 @@ #include <utils/environment.h> #include <utils/hostosinfo.h> -#include <qmakeprojectmanager/qmakeproject.h> -#include <qmakeprojectmanager/qmakeprojectmanagerconstants.h> - #include <qtsupport/qtkitinformation.h> #include <qtsupport/qtsupportconstants.h> #include <qtsupport/qtversionmanager.h> #include <projectexplorer/target.h> #include <projectexplorer/kit.h> +#include <projectexplorer/project.h> #include <projectexplorer/projectexplorer.h> #include <proparser/profileevaluator.h> using namespace Android::Internal; using namespace ProjectExplorer; -using namespace QmakeProjectManager; AndroidQtVersion::AndroidQtVersion() : QtSupport::BaseQtVersion() @@ -109,12 +106,12 @@ void AndroidQtVersion::addToEnvironment(const ProjectExplorer::Kit *k, Utils::En env.set(QLatin1String("ANDROID_NDK_HOST"), AndroidConfigurations::currentConfig().toolchainHost()); env.set(QLatin1String("ANDROID_NDK_ROOT"), AndroidConfigurations::currentConfig().ndkLocation().toUserOutput()); - QmakeProject *qmakeProject = qobject_cast<QmakeProjectManager::QmakeProject *>(ProjectExplorerPlugin::instance()->currentProject()); - if (!qmakeProject || !qmakeProject->activeTarget() + Project *project = ProjectExplorerPlugin::instance()->currentProject(); + if (!project || !project->activeTarget() || QtSupport::QtKitInformation::qtVersion(k)->type() != QLatin1String(Constants::ANDROIDQT)) return; - Target *target = qmakeProject->activeTarget(); + Target *target = project->activeTarget(); if (DeviceTypeKitInformation::deviceTypeId(target->kit()) != Constants::ANDROID_DEVICE_TYPE) return; if (AndroidConfigurations::currentConfig().ndkLocation().isEmpty() diff --git a/src/plugins/android/androidruncontrol.h b/src/plugins/android/androidruncontrol.h index 2f6d87acdc..ab624b507d 100644 --- a/src/plugins/android/androidruncontrol.h +++ b/src/plugins/android/androidruncontrol.h @@ -36,7 +36,6 @@ namespace Android { class AndroidRunConfiguration; namespace Internal { - class AndroidRunner; class AndroidRunControl : public ProjectExplorer::RunControl diff --git a/src/plugins/android/androidrunner.h b/src/plugins/android/androidrunner.h index be0c48216a..9e9fee4b52 100644 --- a/src/plugins/android/androidrunner.h +++ b/src/plugins/android/androidrunner.h @@ -45,7 +45,6 @@ class AndroidRunConfiguration; namespace Internal { - class AndroidRunner : public QThread { Q_OBJECT diff --git a/src/plugins/android/avddialog.h b/src/plugins/android/avddialog.h index d0aefc2221..706da287a9 100644 --- a/src/plugins/android/avddialog.h +++ b/src/plugins/android/avddialog.h @@ -34,9 +34,10 @@ #include <QDialog> namespace Android { -namespace Internal { class AndroidConfig; +namespace Internal { + class AvdDialog : public QDialog { Q_OBJECT diff --git a/src/plugins/projectexplorer/settingsaccessor.cpp b/src/plugins/projectexplorer/settingsaccessor.cpp index 101d77546b..42ae2a179e 100644 --- a/src/plugins/projectexplorer/settingsaccessor.cpp +++ b/src/plugins/projectexplorer/settingsaccessor.cpp @@ -321,6 +321,37 @@ public: QString backupExtension() const { return QLatin1String("3.2-pre1"); } QVariantMap upgrade(const QVariantMap &map); }; + +// Version 16 Changed android deployment +class UserFileVersion16Upgrader : public VersionUpgrader +{ +public: + int version() const { return 16; } + QString backupExtension() const { return QLatin1String("3.3-pre1"); } + QVariantMap upgrade(const QVariantMap &data); +private: + class OldStepMaps + { + public: + QString defaultDisplayName; + QString displayName; + QVariantMap androidPackageInstall; + QVariantMap androidDeployQt; + bool isEmpty() + { + return androidPackageInstall.isEmpty() || androidDeployQt.isEmpty(); + } + }; + + + QVariantMap removeAndroidPackageStep(QVariantMap deployMap); + OldStepMaps extractStepMaps(const QVariantMap &deployMap); + enum NamePolicy { KeepName, RenameBuildConfiguration }; + QVariantMap insertSteps(QVariantMap buildConfigurationMap, + const OldStepMaps &oldStepMap, + NamePolicy policy); +}; + } // namespace // @@ -403,6 +434,7 @@ UserFileAccessor::UserFileAccessor(Project *project) addVersionUpgrader(new UserFileVersion13Upgrader); addVersionUpgrader(new UserFileVersion14Upgrader); addVersionUpgrader(new UserFileVersion15Upgrader); + addVersionUpgrader(new UserFileVersion16Upgrader); } QVariantMap UserFileAccessor::prepareSettings(const QVariantMap &data) const @@ -2401,3 +2433,221 @@ QVariantMap UserFileVersion15Upgrader::upgrade(const QVariantMap &map) return renameKeys(changes, QVariantMap(map)); } + +// -------------------------------------------------------------------- +// UserFileVersion16Upgrader: +// -------------------------------------------------------------------- + +UserFileVersion16Upgrader::OldStepMaps UserFileVersion16Upgrader::extractStepMaps(const QVariantMap &deployMap) +{ + OldStepMaps result; + result.defaultDisplayName = deployMap.value(QLatin1String("ProjectExplorer.ProjectConfiguration.DefaultDisplayName")).toString(); + result.displayName = deployMap.value(QLatin1String("ProjectExplorer.ProjectConfiguration.DisplayName")).toString(); + const QString stepListKey = QLatin1String("ProjectExplorer.BuildConfiguration.BuildStepList.0"); + QVariantMap stepListMap = deployMap.value(stepListKey).toMap(); + int stepCount = stepListMap.value(QLatin1String("ProjectExplorer.BuildStepList.StepsCount"), 0).toInt(); + QString stepKey = QLatin1String("ProjectExplorer.BuildStepList.Step."); + for (int i = 0; i < stepCount; ++i) { + QVariantMap stepMap = stepListMap.value(stepKey + QString::number(i)).toMap(); + const QString id = stepMap.value(QLatin1String("ProjectExplorer.ProjectConfiguration.Id")).toString(); + if (id == QLatin1String("Qt4ProjectManager.AndroidDeployQtStep")) + result.androidDeployQt = stepMap; + else if (id == QLatin1String("Qt4ProjectManager.AndroidPackageInstallationStep")) + result.androidPackageInstall = stepMap; + if (!result.isEmpty()) + return result; + + } + return result; +} + +QVariantMap UserFileVersion16Upgrader::removeAndroidPackageStep(QVariantMap deployMap) +{ + const QString stepListKey = QLatin1String("ProjectExplorer.BuildConfiguration.BuildStepList.0"); + QVariantMap stepListMap = deployMap.value(stepListKey).toMap(); + const QString stepCountKey = QLatin1String("ProjectExplorer.BuildStepList.StepsCount"); + int stepCount = stepListMap.value(stepCountKey, 0).toInt(); + QString stepKey = QLatin1String("ProjectExplorer.BuildStepList.Step."); + int targetPosition = 0; + for (int sourcePosition = 0; sourcePosition < stepCount; ++sourcePosition) { + QVariantMap stepMap = stepListMap.value(stepKey + QString::number(sourcePosition)).toMap(); + if (stepMap.value(QLatin1String("ProjectExplorer.ProjectConfiguration.Id")).toString() + != QLatin1String("Qt4ProjectManager.AndroidPackageInstallationStep")) { + stepListMap.insert(stepKey + QString::number(targetPosition), stepMap); + ++targetPosition; + } + } + + stepListMap.insert(stepCountKey, targetPosition); + + for (int i = targetPosition; i < stepCount; ++i) + stepListMap.remove(stepKey + QString::number(i)); + + deployMap.insert(stepListKey, stepListMap); + return deployMap; +} + +QVariantMap UserFileVersion16Upgrader::insertSteps(QVariantMap buildConfigurationMap, + const OldStepMaps &oldStepMap, + NamePolicy policy) +{ + const QString bslCountKey = QLatin1String("ProjectExplorer.BuildConfiguration.BuildStepListCount"); + int stepListCount = buildConfigurationMap.value(bslCountKey).toInt(); + + const QString bslKey = QLatin1String("ProjectExplorer.BuildConfiguration.BuildStepList."); + const QString bslTypeKey = QLatin1String("ProjectExplorer.ProjectConfiguration.Id"); + for (int bslNumber = 0; bslNumber < stepListCount; ++bslNumber) { + QVariantMap buildStepListMap = buildConfigurationMap.value(bslKey + QString::number(bslNumber)).toMap(); + if (buildStepListMap.value(bslTypeKey) != QLatin1String("ProjectExplorer.BuildSteps.Build")) + continue; + + const QString bslStepCountKey = QLatin1String("ProjectExplorer.BuildStepList.StepsCount"); + + int stepCount = buildStepListMap.value(bslStepCountKey).toInt(); + buildStepListMap.insert(bslStepCountKey, stepCount + 2); + + QVariantMap androidPackageInstallStep; + QVariantMap androidBuildApkStep; + + // common settings of all buildsteps + const QString enabledKey = QLatin1String("ProjectExplorer.BuildStep.Enabled"); + const QString idKey = QLatin1String("ProjectExplorer.ProjectConfiguration.Id"); + const QString displayNameKey = QLatin1String("ProjectExplorer.ProjectConfiguration.DisplayName"); + const QString defaultDisplayNameKey = QLatin1String("ProjectExplorer.ProjectConfiguration.DefaultDisplayName"); + + QString displayName = oldStepMap.androidPackageInstall.value(displayNameKey).toString(); + QString defaultDisplayName = oldStepMap.androidPackageInstall.value(defaultDisplayNameKey).toString(); + bool enabled = oldStepMap.androidPackageInstall.value(enabledKey).toBool(); + + androidPackageInstallStep.insert(idKey, Core::Id("Qt4ProjectManager.AndroidPackageInstallationStep").toSetting()); + androidPackageInstallStep.insert(displayNameKey, displayName); + androidPackageInstallStep.insert(defaultDisplayNameKey, defaultDisplayName); + androidPackageInstallStep.insert(enabledKey, enabled); + + displayName = oldStepMap.androidDeployQt.value(displayName).toString(); + defaultDisplayName = oldStepMap.androidDeployQt.value(defaultDisplayNameKey).toString(); + enabled = oldStepMap.androidDeployQt.value(enabledKey).toBool(); + + androidBuildApkStep.insert(idKey, Core::Id("QmakeProjectManager.AndroidBuildApkStep").toSetting()); + androidBuildApkStep.insert(displayNameKey, displayName); + androidBuildApkStep.insert(defaultDisplayNameKey, defaultDisplayName); + androidBuildApkStep.insert(enabledKey, enabled); + + // settings transferred from AndroidDeployQtStep to QmakeBuildApkStep + const QString ProFilePathForInputFile = QLatin1String("ProFilePathForInputFile"); + const QString DeployActionKey = QLatin1String("Qt4ProjectManager.AndroidDeployQtStep.DeployQtAction"); + const QString KeystoreLocationKey = QLatin1String("KeystoreLocation"); + const QString BuildTargetSdkKey = QLatin1String("BuildTargetSdk"); + const QString VerboseOutputKey = QLatin1String("VerboseOutput"); + + QString inputFile = oldStepMap.androidDeployQt.value(ProFilePathForInputFile).toString(); + int oldDeployAction = oldStepMap.androidDeployQt.value(DeployActionKey).toInt(); + QString keyStorePath = oldStepMap.androidDeployQt.value(KeystoreLocationKey).toString(); + QString buildTargetSdk = oldStepMap.androidDeployQt.value(BuildTargetSdkKey).toString(); + bool verbose = oldStepMap.androidDeployQt.value(VerboseOutputKey).toBool(); + androidBuildApkStep.insert(ProFilePathForInputFile, inputFile); + androidBuildApkStep.insert(DeployActionKey, oldDeployAction); + androidBuildApkStep.insert(KeystoreLocationKey, keyStorePath); + androidBuildApkStep.insert(BuildTargetSdkKey, buildTargetSdk); + androidBuildApkStep.insert(VerboseOutputKey, verbose); + + const QString buildStepKey = QLatin1String("ProjectExplorer.BuildStepList.Step."); + buildStepListMap.insert(buildStepKey + QString::number(stepCount), androidPackageInstallStep); + buildStepListMap.insert(buildStepKey + QString::number(stepCount + 1), androidBuildApkStep); + + buildConfigurationMap.insert(bslKey + QString::number(bslNumber), buildStepListMap); + } + + if (policy == RenameBuildConfiguration) { + const QString displayNameKey = QLatin1String("ProjectExplorer.ProjectConfiguration.DisplayName"); + const QString defaultDisplayNameKey = QLatin1String("ProjectExplorer.ProjectConfiguration.DefaultDisplayName"); + + QString defaultDisplayName = buildConfigurationMap.value(defaultDisplayNameKey).toString(); + QString displayName = buildConfigurationMap.value(displayNameKey).toString(); + if (displayName.isEmpty()) + displayName = defaultDisplayName; + QString oldDisplayname = oldStepMap.displayName; + if (oldDisplayname.isEmpty()) + oldDisplayname = oldStepMap.defaultDisplayName; + + displayName.append(QLatin1String(" - ")); + displayName.append(oldDisplayname); + buildConfigurationMap.insert(displayNameKey, displayName); + + defaultDisplayName.append(QLatin1String(" - ")); + defaultDisplayName.append(oldStepMap.defaultDisplayName); + buildConfigurationMap.insert(defaultDisplayNameKey, defaultDisplayName); + } + + return buildConfigurationMap; +} + +QVariantMap UserFileVersion16Upgrader::upgrade(const QVariantMap &data) +{ + int targetCount = data.value(QLatin1String("ProjectExplorer.Project.TargetCount"), 0).toInt(); + if (!targetCount) + return data; + + QVariantMap result = data; + + for (int i = 0; i < targetCount; ++i) { + QString targetKey = QLatin1String("ProjectExplorer.Project.Target.") + QString::number(i); + QVariantMap targetMap = data.value(targetKey).toMap(); + + const QString dcCountKey = QLatin1String("ProjectExplorer.Target.DeployConfigurationCount"); + int deployconfigurationCount = targetMap.value(dcCountKey).toInt(); + if (!deployconfigurationCount) // should never happen + continue; + + QList<OldStepMaps> oldSteps; + QList<QVariantMap> oldBuildConfigurations; + + QString deployKey = QLatin1String("ProjectExplorer.Target.DeployConfiguration."); + for (int j = 0; j < deployconfigurationCount; ++j) { + QVariantMap deployConfigurationMap + = targetMap.value(deployKey + QString::number(j)).toMap(); + OldStepMaps oldStep = extractStepMaps(deployConfigurationMap); + if (!oldStep.isEmpty()) { + oldSteps.append(oldStep); + deployConfigurationMap = removeAndroidPackageStep(deployConfigurationMap); + targetMap.insert(deployKey + QString::number(j), deployConfigurationMap); + } + } + + if (oldSteps.isEmpty()) // no android target? + continue; + + const QString bcCountKey = QLatin1String("ProjectExplorer.Target.BuildConfigurationCount"); + int buildConfigurationCount + = targetMap.value(bcCountKey).toInt(); + + if (!buildConfigurationCount) // should never happen + continue; + + QString bcKey = QLatin1String("ProjectExplorer.Target.BuildConfiguration."); + for (int j = 0; j < buildConfigurationCount; ++j) { + QVariantMap oldBuildConfigurationMap = targetMap.value(bcKey + QString::number(j)).toMap(); + oldBuildConfigurations.append(oldBuildConfigurationMap); + } + + QList<QVariantMap> newBuildConfigurations; + + NamePolicy policy = oldSteps.size() > 1 ? RenameBuildConfiguration : KeepName; + + foreach (const QVariantMap &oldBuildConfiguration, oldBuildConfigurations) { + foreach (const OldStepMaps &oldStep, oldSteps) { + QVariantMap newBuildConfiguration = insertSteps(oldBuildConfiguration, oldStep, policy); + if (!newBuildConfiguration.isEmpty()) + newBuildConfigurations.append(newBuildConfiguration); + } + } + + targetMap.insert(bcCountKey, newBuildConfigurations.size()); + + for (int j = 0; j < newBuildConfigurations.size(); ++j) + targetMap.insert(bcKey + QString::number(j), newBuildConfigurations.at(j)); + result.insert(targetKey, targetMap); + } + + return result; +} diff --git a/src/plugins/android/androidextralibrarylistmodel.cpp b/src/plugins/qmakeprojectmanager/androidextralibrarylistmodel.cpp index b2499bcc0b..fc509457cb 100644 --- a/src/plugins/android/androidextralibrarylistmodel.cpp +++ b/src/plugins/qmakeprojectmanager/androidextralibrarylistmodel.cpp @@ -33,7 +33,7 @@ #include <qmakeprojectmanager/qmakenodes.h> #include <proparser/prowriter.h> -using namespace Android; +using namespace QmakeProjectManager; using namespace Internal; AndroidExtraLibraryListModel::AndroidExtraLibraryListModel(QmakeProjectManager::QmakeProject *project, diff --git a/src/plugins/android/androidextralibrarylistmodel.h b/src/plugins/qmakeprojectmanager/androidextralibrarylistmodel.h index 86e82672ea..acc7adea61 100644 --- a/src/plugins/android/androidextralibrarylistmodel.h +++ b/src/plugins/qmakeprojectmanager/androidextralibrarylistmodel.h @@ -37,9 +37,7 @@ namespace QmakeProjectManager { class QmakeProject; class QmakeProFileNode; -} -namespace Android { namespace Internal { class AndroidExtraLibraryListModel : public QAbstractItemModel { @@ -72,6 +70,6 @@ private: }; } // namespace Internal -} // namespace Android +} // namespace QmakeProjectManager #endif // ANDROIDEXTRALIBRARYLISTMODEL_H diff --git a/src/plugins/android/androidpackageinstallationfactory.cpp b/src/plugins/qmakeprojectmanager/androidpackageinstallationfactory.cpp index 791f9a7bea..a4ea9c378e 100644 --- a/src/plugins/android/androidpackageinstallationfactory.cpp +++ b/src/plugins/qmakeprojectmanager/androidpackageinstallationfactory.cpp @@ -28,19 +28,18 @@ ****************************************************************************/ #include "androidpackageinstallationfactory.h" - #include "androidpackageinstallationstep.h" -#include "androidmanager.h" #include <projectexplorer/buildsteplist.h> #include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/target.h> #include <qtsupport/qtkitinformation.h> #include <qtsupport/qtsupportconstants.h> +#include <android/androidmanager.h> using namespace ProjectExplorer; -namespace Android { +namespace QmakeProjectManager { namespace Internal { AndroidPackageInstallationFactory::AndroidPackageInstallationFactory(QObject *parent) @@ -77,9 +76,9 @@ BuildStep *AndroidPackageInstallationFactory::create(BuildStepList *parent, Core bool AndroidPackageInstallationFactory::canRestore(BuildStepList *parent, const QVariantMap &map) const { - if (parent->id() != ProjectExplorer::Constants::BUILDSTEPS_DEPLOY) + if (parent->id() != ProjectExplorer::Constants::BUILDSTEPS_BUILD) return false; - if (!AndroidManager::supportsAndroid(parent->target())) + if (!Android::AndroidManager::supportsAndroid(parent->target())) return false; if (parent->contains(AndroidPackageInstallationStep::Id)) return false; @@ -89,7 +88,7 @@ bool AndroidPackageInstallationFactory::canRestore(BuildStepList *parent, const BuildStep *AndroidPackageInstallationFactory::restore(BuildStepList *parent, const QVariantMap &map) { Q_ASSERT(canRestore(parent, map)); - AndroidPackageInstallationStep * const step = new AndroidPackageInstallationStep(AndroidPackageInstallationStep::ProjectDirectory, parent); + AndroidPackageInstallationStep * const step = new AndroidPackageInstallationStep(parent); if (!step->fromMap(map)) { delete step; return 0; diff --git a/src/plugins/android/androidpackageinstallationfactory.h b/src/plugins/qmakeprojectmanager/androidpackageinstallationfactory.h index b2ea80f89f..0202819f18 100644 --- a/src/plugins/android/androidpackageinstallationfactory.h +++ b/src/plugins/qmakeprojectmanager/androidpackageinstallationfactory.h @@ -32,7 +32,7 @@ #include <projectexplorer/buildstep.h> -namespace Android { +namespace QmakeProjectManager { namespace Internal { class AndroidPackageInstallationFactory: public ProjectExplorer::IBuildStepFactory diff --git a/src/plugins/android/androidpackageinstallationstep.cpp b/src/plugins/qmakeprojectmanager/androidpackageinstallationstep.cpp index a3e0f34ac6..55d5e05860 100644 --- a/src/plugins/android/androidpackageinstallationstep.cpp +++ b/src/plugins/qmakeprojectmanager/androidpackageinstallationstep.cpp @@ -28,8 +28,8 @@ ****************************************************************************/ #include "androidpackageinstallationstep.h" -#include "androidmanager.h" -#include "androidconstants.h" + +#include <android/androidconstants.h> #include <projectexplorer/buildsteplist.h> #include <projectexplorer/target.h> @@ -38,19 +38,19 @@ #include <projectexplorer/kitinformation.h> #include <projectexplorer/gnumakeparser.h> #include <utils/hostosinfo.h> -#include <qmakeprojectmanager/qmakeparser.h> #include <QDir> -using namespace Android::Internal; +using namespace Android; +using namespace QmakeProjectManager::Internal; const Core::Id AndroidPackageInstallationStep::Id = Core::Id("Qt4ProjectManager.AndroidPackageInstallationStep"); namespace { const char ANDROIDDIRECTORY[] = "Android.AndroidPackageInstallationStep.AndroidDirectory"; } -AndroidPackageInstallationStep::AndroidPackageInstallationStep(AndroidDirectory mode,ProjectExplorer::BuildStepList *bsl) - : AbstractProcessStep(bsl, Id), m_androidDirectory(mode) +AndroidPackageInstallationStep::AndroidPackageInstallationStep(ProjectExplorer::BuildStepList *bsl) + : AbstractProcessStep(bsl, Id) { const QString name = tr("Copy application data"); setDefaultDisplayName(name); @@ -64,13 +64,7 @@ AndroidPackageInstallationStep::AndroidPackageInstallationStep(ProjectExplorer:: bool AndroidPackageInstallationStep::init() { ProjectExplorer::BuildConfiguration *bc = buildConfiguration(); - if (!bc) - bc = target()->activeBuildConfiguration(); - QString dirPath; - if (m_androidDirectory == ProjectDirectory) - dirPath = AndroidManager::dirPath(target()).toString(); - else - dirPath = bc->buildDirectory().appendPath(QLatin1String(Constants::ANDROID_BUILDDIRECTORY)).toString(); + QString dirPath = bc->buildDirectory().appendPath(QLatin1String(Constants::ANDROID_BUILDDIRECTORY)).toString(); if (Utils::HostOsInfo::isWindowsHost()) if (bc->environment().searchInPath(QLatin1String("sh.exe")).isEmpty()) dirPath = QDir::toNativeSeparators(dirPath); @@ -95,19 +89,11 @@ bool AndroidPackageInstallationStep::init() appendOutputParser(parser); outputParser()->setWorkingDirectory(pp->effectiveWorkingDirectory()); - m_androidDirToClean = m_androidDirectory == BuildDirectory ? dirPath : QString(); + m_androidDirToClean = dirPath; return AbstractProcessStep::init(); } -bool AndroidPackageInstallationStep::fromMap(const QVariantMap &map) -{ - if (!AbstractProcessStep::fromMap(map)) - return false; - m_androidDirectory = AndroidDirectory(map.value(QLatin1String(ANDROIDDIRECTORY)).toInt()); - return true; -} - void AndroidPackageInstallationStep::run(QFutureInterface<bool> &fi) { QString error; @@ -124,13 +110,6 @@ void AndroidPackageInstallationStep::run(QFutureInterface<bool> &fi) AbstractProcessStep::run(fi); } -QVariantMap AndroidPackageInstallationStep::toMap() const -{ - QVariantMap map = AbstractProcessStep::toMap(); - map.insert(QLatin1String(ANDROIDDIRECTORY), m_androidDirectory); - return map; -} - ProjectExplorer::BuildStepConfigWidget *AndroidPackageInstallationStep::createConfigWidget() { return new AndroidPackageInstallationStepWidget(this); diff --git a/src/plugins/android/androidpackageinstallationstep.h b/src/plugins/qmakeprojectmanager/androidpackageinstallationstep.h index dd61729925..7d439aa965 100644 --- a/src/plugins/android/androidpackageinstallationstep.h +++ b/src/plugins/qmakeprojectmanager/androidpackageinstallationstep.h @@ -33,7 +33,7 @@ #include <projectexplorer/buildstep.h> #include <projectexplorer/abstractprocessstep.h> -namespace Android { +namespace QmakeProjectManager { namespace Internal { class AndroidPackageInstallationStep : public ProjectExplorer::AbstractProcessStep @@ -42,13 +42,9 @@ class AndroidPackageInstallationStep : public ProjectExplorer::AbstractProcessSt friend class AndroidPackageInstallationFactory; public: - enum AndroidDirectory { ProjectDirectory, BuildDirectory }; - explicit AndroidPackageInstallationStep(AndroidDirectory mode, ProjectExplorer::BuildStepList *bsl); + explicit AndroidPackageInstallationStep(ProjectExplorer::BuildStepList *bsl); bool init(); - bool fromMap(const QVariantMap &map); - QVariantMap toMap() const; - ProjectExplorer::BuildStepConfigWidget *createConfigWidget(); bool immutable() const; @@ -56,7 +52,6 @@ public: private: AndroidPackageInstallationStep(ProjectExplorer::BuildStepList *bc, AndroidPackageInstallationStep *other); - AndroidDirectory m_androidDirectory; QString m_androidDirToClean; static const Core::Id Id; }; diff --git a/src/plugins/android/qmakeandroidsupport.cpp b/src/plugins/qmakeprojectmanager/androidqmakebuildconfigurationfactory.cpp index 5c25ecfbae..4cbaa63ab8 100644 --- a/src/plugins/android/qmakeandroidsupport.cpp +++ b/src/plugins/qmakeprojectmanager/androidqmakebuildconfigurationfactory.cpp @@ -1,6 +1,6 @@ -/************************************************************************** +/**************************************************************************** ** -** Copyright (c) 2014 BogDan Vatra <bog_dan_ro@yahoo.com> +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. @@ -27,49 +27,45 @@ ** ****************************************************************************/ -#include "qmakeandroidsupport.h" - -#include "androidconstants.h" +#include "androidqmakebuildconfigurationfactory.h" +#include "qmakeandroidbuildapkstep.h" #include "androidpackageinstallationstep.h" -#include <projectexplorer/buildmanager.h> +#include <android/androidmanager.h> #include <projectexplorer/buildsteplist.h> -#include <projectexplorer/deployconfiguration.h> -#include <projectexplorer/projectexplorer.h> #include <projectexplorer/projectexplorerconstants.h> -#include <projectexplorer/target.h> -#include <qtsupport/qtkitinformation.h> - -#include <qmakeprojectmanager/qmakebuildconfiguration.h> -#include <qmakeprojectmanager/qmakenodes.h> -#include <qmakeprojectmanager/qmakeproject.h> -#include <qmakeprojectmanager/qmakestep.h> -using namespace QmakeProjectManager; // The class will eventually be moved there anyway +using namespace QmakeProjectManager; +using namespace QmakeProjectManager::Internal; -namespace Android { -namespace Internal { -bool QmakeAndroidSupport::canHandle(const ProjectExplorer::Target *target) const +int AndroidQmakeBuildConfigurationFactory::priority(const ProjectExplorer::Kit *k, const QString &projectPath) const { - return qobject_cast<QmakeProject*>(target->project()); + if (QmakeBuildConfigurationFactory::priority(k, projectPath) >= 0 + && Android::AndroidManager::supportsAndroid(k)) + return 1; + return -1; } -QStringList QmakeAndroidSupport::soLibSearchPath(const ProjectExplorer::Target *target) const +int AndroidQmakeBuildConfigurationFactory::priority(const ProjectExplorer::Target *parent) const { - QStringList res; - QmakeBuildConfiguration *bc = qobject_cast<QmakeBuildConfiguration*>(target->activeBuildConfiguration()); - QmakeProject *project = qobject_cast<QmakeProject*>(target->project()); - Q_ASSERT(project); - if (!project) - return res; + if (QmakeBuildConfigurationFactory::priority(parent) >= 0 + && Android::AndroidManager::supportsAndroid(parent)) + return 1; + return -1; +} - foreach (QmakeProFileNode *node, project->allProFiles()) { - res << node->buildDir(bc); - } +ProjectExplorer::BuildConfiguration *AndroidQmakeBuildConfigurationFactory::create(ProjectExplorer::Target *parent, const ProjectExplorer::BuildInfo *info) const +{ + ProjectExplorer::BuildConfiguration *bc = QmakeBuildConfigurationFactory::create(parent, info); + ProjectExplorer::BuildStepList *buildSteps = bc->stepList(Core::Id(ProjectExplorer::Constants::BUILDSTEPS_BUILD)); + buildSteps->insertStep(2, new AndroidPackageInstallationStep(buildSteps)); + buildSteps->insertStep(3, new QmakeAndroidBuildApkStep(buildSteps)); - return res; + return bc; } -} // namespace Internal -} // namespace Android +// should the buildconfiguration have its own id? +// and implement restore/clone then? + + diff --git a/src/plugins/qmakeprojectmanager/androidqmakebuildconfigurationfactory.h b/src/plugins/qmakeprojectmanager/androidqmakebuildconfigurationfactory.h new file mode 100644 index 0000000000..4625024538 --- /dev/null +++ b/src/plugins/qmakeprojectmanager/androidqmakebuildconfigurationfactory.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef ANDROIDQMAKEBUILDCONFIGURATIONFACTORY_H +#define ANDROIDQMAKEBUILDCONFIGURATIONFACTORY_H + +#include "qmakebuildconfiguration.h" + +namespace QmakeProjectManager { +namespace Internal { + + +class AndroidQmakeBuildConfigurationFactory : public QmakeBuildConfigurationFactory +{ +public: + explicit AndroidQmakeBuildConfigurationFactory(QObject *parent = 0) + : QmakeBuildConfigurationFactory(parent) + { } + + int priority(const ProjectExplorer::Kit *k, const QString &projectPath) const; + int priority(const ProjectExplorer::Target *parent) const; + + ProjectExplorer::BuildConfiguration *create(ProjectExplorer::Target *parent, + const ProjectExplorer::BuildInfo *info) const; + // The clone and restore from QmakeBuildConfigurationFactory + // work for us too. +}; + +} // namespace Internal +} // namespace QmakeProjectManager + + +#endif // ANDROIDQMAKEBUILDCONFIGURATIONFACTORY_H diff --git a/src/plugins/android/createandroidmanifestwizard.cpp b/src/plugins/qmakeprojectmanager/createandroidmanifestwizard.cpp index fffe8e5e5b..180616037d 100644 --- a/src/plugins/android/createandroidmanifestwizard.cpp +++ b/src/plugins/qmakeprojectmanager/createandroidmanifestwizard.cpp @@ -29,21 +29,31 @@ #include "createandroidmanifestwizard.h" +#include <android/androidmanager.h> +#include <android/androidqtsupport.h> + +#include <coreplugin/editormanager/editormanager.h> +#include <coreplugin/coreconstants.h> + #include <projectexplorer/target.h> + #include <qmakeprojectmanager/qmakeproject.h> #include <qmakeprojectmanager/qmakenodes.h> + #include <proparser/prowriter.h> + +#include <qtsupport/qtkitinformation.h> + #include <QComboBox> #include <QFormLayout> #include <QLabel> #include <QMessageBox> #include <QVBoxLayout> -#include <qtsupport/qtkitinformation.h> -#include <coreplugin/coreconstants.h> -#include <coreplugin/editormanager/editormanager.h> using namespace Android; -using namespace Android::Internal; +using namespace QmakeProjectManager; +using namespace QmakeProjectManager::Internal; + using QmakeProjectManager::QmakeProject; using QmakeProjectManager::QmakeProFileNode; diff --git a/src/plugins/android/createandroidmanifestwizard.h b/src/plugins/qmakeprojectmanager/createandroidmanifestwizard.h index 8cb8c95b7f..e084782c13 100644 --- a/src/plugins/android/createandroidmanifestwizard.h +++ b/src/plugins/qmakeprojectmanager/createandroidmanifestwizard.h @@ -40,7 +40,7 @@ QT_END_NAMESPACE namespace ProjectExplorer { class Target; } namespace QmakeProjectManager { class QmakeProFileNode; } -namespace Android { +namespace QmakeProjectManager { namespace Internal { class CreateAndroidManifestWizard; @@ -104,7 +104,8 @@ private: QmakeProjectManager::QmakeProFileNode *m_node; QString m_directory; }; -} -} + +} //namespace QmakeProjectManager +} //namespace Internal #endif // CREATEANDROIDMANIFESTWIZARD_H diff --git a/src/plugins/qmakeprojectmanager/qmakeandroidbuildapkstep.cpp b/src/plugins/qmakeprojectmanager/qmakeandroidbuildapkstep.cpp new file mode 100644 index 0000000000..1848a6536b --- /dev/null +++ b/src/plugins/qmakeprojectmanager/qmakeandroidbuildapkstep.cpp @@ -0,0 +1,293 @@ +/************************************************************************** +** +** Copyright (c) 2014 BogDan Vatra <bog_dan_ro@yahoo.com> +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmakeandroidbuildapkstep.h" +#include "qmakeandroidbuildapkwidget.h" +#include "qmakenodes.h" +#include "qmakeproject.h" + +#include <android/androidconfigurations.h> +#include <android/androidconstants.h> +#include <android/androidmanager.h> +#include <android/androidqtsupport.h> + +#include <projectexplorer/buildconfiguration.h> +#include <projectexplorer/buildsteplist.h> +#include <projectexplorer/project.h> +#include <projectexplorer/projectexplorer.h> +#include <projectexplorer/target.h> + +#include <qtsupport/qtkitinformation.h> + +#include <utils/qtcprocess.h> + +#include <QHBoxLayout> + +using namespace Android; + +namespace QmakeProjectManager { +namespace Internal { + +const Core::Id ANDROID_BUILD_APK_ID("QmakeProjectManager.AndroidBuildApkStep"); +const QLatin1String ProFilePathForInputFile("ProFilePathForInputFile"); + + +////////////////// +// QmakeAndroidBuildApkStepFactory +///////////////// + +QmakeAndroidBuildApkStepFactory::QmakeAndroidBuildApkStepFactory(QObject *parent) + : IBuildStepFactory(parent) +{ +} + +QList<Core::Id> QmakeAndroidBuildApkStepFactory::availableCreationIds(ProjectExplorer::BuildStepList *parent) const +{ + if (parent->id() != ProjectExplorer::Constants::BUILDSTEPS_BUILD + || !canHandle(parent->target()) + || parent->contains(ANDROID_BUILD_APK_ID)) { + return QList<Core::Id>(); + } + + return QList<Core::Id>() << ANDROID_BUILD_APK_ID; +} + +QString QmakeAndroidBuildApkStepFactory::displayNameForId(const Core::Id id) const +{ + if (id == ANDROID_BUILD_APK_ID) + return tr("Build Android APK"); + return QString(); +} + +bool QmakeAndroidBuildApkStepFactory::canCreate(ProjectExplorer::BuildStepList *parent, const Core::Id id) const +{ + return availableCreationIds(parent).contains(id); +} + +ProjectExplorer::BuildStep *QmakeAndroidBuildApkStepFactory::create(ProjectExplorer::BuildStepList *parent, const Core::Id id) +{ + Q_ASSERT(canCreate(parent, id)); + Q_UNUSED(id); + return new QmakeAndroidBuildApkStep(parent); +} + +bool QmakeAndroidBuildApkStepFactory::canRestore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) const +{ + return canCreate(parent, ProjectExplorer::idFromMap(map)); +} + +ProjectExplorer::BuildStep *QmakeAndroidBuildApkStepFactory::restore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) +{ + Q_ASSERT(canRestore(parent, map)); + QmakeAndroidBuildApkStep * const step = new QmakeAndroidBuildApkStep(parent); + if (!step->fromMap(map)) { + delete step; + return 0; + } + return step; +} + +bool QmakeAndroidBuildApkStepFactory::canClone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product) const +{ + return canCreate(parent, product->id()); +} + +ProjectExplorer::BuildStep *QmakeAndroidBuildApkStepFactory::clone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product) +{ + Q_ASSERT(canClone(parent, product)); + return new QmakeAndroidBuildApkStep(parent, static_cast<QmakeAndroidBuildApkStep *>(product)); +} + +bool QmakeAndroidBuildApkStepFactory::canHandle(ProjectExplorer::Target *t) const +{ + return t->project()->supportsKit(t->kit()) + && AndroidManager::supportsAndroid(t) + && qobject_cast<QmakeProject *>(t->project()); +} + + +QmakeAndroidBuildApkStep::QmakeAndroidBuildApkStep(ProjectExplorer::BuildStepList *bc) + :Android::AndroidBuildApkStep(bc, ANDROID_BUILD_APK_ID) +{ + ctor(); +} + +QString QmakeAndroidBuildApkStep::proFilePathForInputFile() const +{ + return m_proFilePathForInputFile; +} + +void QmakeAndroidBuildApkStep::setProFilePathForInputFile(const QString &path) +{ + m_proFilePathForInputFile = path; +} + +QmakeAndroidBuildApkStep::QmakeAndroidBuildApkStep(ProjectExplorer::BuildStepList *bc, QmakeAndroidBuildApkStep *other) + : Android::AndroidBuildApkStep(bc, other), + m_proFilePathForInputFile(other->m_proFilePathForInputFile) +{ + ctor(); +} + +Utils::FileName QmakeAndroidBuildApkStep::androidPackageSourceDir() const +{ + QmakeProjectManager::QmakeProject *pro = static_cast<QmakeProjectManager::QmakeProject *>(project()); + const QmakeProjectManager::QmakeProFileNode *node + = pro->rootQmakeProjectNode()->findProFileFor(m_proFilePathForInputFile); + if (!node) + return Utils::FileName(); + return Utils::FileName::fromString(node->singleVariableValue(QmakeProjectManager::AndroidPackageSourceDir)); +} + +void QmakeAndroidBuildApkStep::ctor() +{ + connect(project(), SIGNAL(proFilesEvaluated()), + this, SLOT(updateInputFile())); +} + +bool QmakeAndroidBuildApkStep::init() +{ + if (AndroidManager::checkForQt51Files(project()->projectDirectory())) + emit addOutput(tr("Found old folder \"android\" in source directory. Qt 5.2 does not use that folder by default."), ErrorOutput); + + if (!Android::AndroidBuildApkStep::init()) + return false; + + QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target()->kit()); + if (!version) + return false; + + QString command = version->qmakeProperty("QT_HOST_BINS"); + if (!command.endsWith(QLatin1Char('/'))) + command += QLatin1Char('/'); + command += QLatin1String("androiddeployqt"); + if (Utils::HostOsInfo::isWindowsHost()) + command += QLatin1String(".exe"); + + QString deploymentMethod; + if (m_deployAction == MinistroDeployment) + deploymentMethod = QLatin1String("ministro"); + else if (m_deployAction == DebugDeployment) + deploymentMethod = QLatin1String("debug"); + else if (m_deployAction == BundleLibrariesDeployment) + deploymentMethod = QLatin1String("bundled"); + + ProjectExplorer::BuildConfiguration *bc = buildConfiguration(); + QString outputDir = bc->buildDirectory().appendPath(QLatin1String(Constants::ANDROID_BUILDDIRECTORY)).toString(); + + const auto *pro = static_cast<QmakeProjectManager::QmakeProject *>(project()); + const QmakeProjectManager::QmakeProFileNode *node = pro->rootQmakeProjectNode()->findProFileFor(m_proFilePathForInputFile); + if (!node) { // should never happen + emit addOutput(tr("Internal Error: Could not find .pro file."), BuildStep::ErrorMessageOutput); + return false; + } + + QString inputFile = node->singleVariableValue(QmakeProjectManager::AndroidDeploySettingsFile); + if (inputFile.isEmpty()) { // should never happen + emit addOutput(tr("Internal Error: Unknown Android deployment JSON file location."), BuildStep::ErrorMessageOutput); + return false; + } + + QStringList arguments; + arguments << QLatin1String("--input") + << inputFile + << QLatin1String("--output") + << outputDir + << QLatin1String("--deployment") + << deploymentMethod + << QLatin1String("--ant") + << AndroidConfigurations::currentConfig().antToolPath().toString() + << QLatin1String("--android-platform") + << AndroidManager::buildTargetSDK(target()) + << QLatin1String("--jdk") + << AndroidConfigurations::currentConfig().openJDKLocation().toString(); + + if (m_verbose) + arguments << QLatin1String("--verbose"); + + if (m_signPackage) { + arguments << QLatin1String("--sign") + << m_keystorePath.toString() + << m_certificateAlias + << QLatin1String("--storepass") + << m_keystorePasswd; + if (!m_certificatePasswd.isEmpty()) + arguments << QLatin1String("--keypass") + << m_certificatePasswd; + } + + ProjectExplorer::ProcessParameters *pp = processParameters(); + pp->setMacroExpander(bc->macroExpander()); + pp->setWorkingDirectory(bc->buildDirectory().toString()); + Utils::Environment env = bc->environment(); + pp->setEnvironment(env); + pp->setCommand(command); + pp->setArguments(Utils::QtcProcess::joinArgs(arguments)); + pp->resolveAll(); + + return true; +} + +ProjectExplorer::BuildStepConfigWidget *QmakeAndroidBuildApkStep::createConfigWidget() +{ + return new QmakeAndroidBuildApkWidget(this); +} + +bool QmakeAndroidBuildApkStep::fromMap(const QVariantMap &map) +{ + m_proFilePathForInputFile = map.value(ProFilePathForInputFile).toString(); + return Android::AndroidBuildApkStep::fromMap(map); +} + +QVariantMap QmakeAndroidBuildApkStep::toMap() const +{ + QVariantMap map = Android::AndroidBuildApkStep::toMap(); + map.insert(ProFilePathForInputFile, m_proFilePathForInputFile); + return map; +} + +void QmakeAndroidBuildApkStep::updateInputFile() +{ + QmakeProject *pro = static_cast<QmakeProject *>(project()); + QList<QmakeProFileNode *> nodes = pro->applicationProFiles(); + + const QmakeProFileNode *node = pro->rootQmakeProjectNode()->findProFileFor(m_proFilePathForInputFile); + if (!nodes.contains(const_cast<QmakeProFileNode *>(node))) { + if (!nodes.isEmpty()) + m_proFilePathForInputFile = nodes.first()->path(); + else + m_proFilePathForInputFile.clear(); + } + + emit inputFileChanged(); +} + +} // namespace Internal +} // namespace QmakeProjectManager diff --git a/src/plugins/qmakeprojectmanager/qmakeandroidbuildapkstep.h b/src/plugins/qmakeprojectmanager/qmakeandroidbuildapkstep.h new file mode 100644 index 0000000000..3a25c3bf04 --- /dev/null +++ b/src/plugins/qmakeprojectmanager/qmakeandroidbuildapkstep.h @@ -0,0 +1,101 @@ +/************************************************************************** +** +** Copyright (c) 2014 BogDan Vatra <bog_dan_ro@yahoo.com> +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMAKEANDROIDBUILDAPKSTEP_H +#define QMAKEANDROIDBUILDAPKSTEP_H + +#include <android/androidbuildapkstep.h> + +namespace QmakeProjectManager { +namespace Internal { + + +class QmakeAndroidBuildApkStepFactory : public ProjectExplorer::IBuildStepFactory +{ + Q_OBJECT +public: + explicit QmakeAndroidBuildApkStepFactory(QObject *parent = 0); + + QList<Core::Id> availableCreationIds(ProjectExplorer::BuildStepList *parent) const; + QString displayNameForId(const Core::Id id) const; + + bool canCreate(ProjectExplorer::BuildStepList *parent, + const Core::Id id) const; + ProjectExplorer::BuildStep *create(ProjectExplorer::BuildStepList *parent, const Core::Id id); + + bool canRestore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) const; + ProjectExplorer::BuildStep *restore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map); + + bool canClone(ProjectExplorer::BuildStepList *parent, + ProjectExplorer::BuildStep *product) const; + ProjectExplorer::BuildStep *clone(ProjectExplorer::BuildStepList *parent, + ProjectExplorer::BuildStep *product); +private: + bool canHandle(ProjectExplorer::Target *t) const; + +}; + +class QmakeAndroidBuildApkStep : public Android::AndroidBuildApkStep +{ + Q_OBJECT +public: + QmakeAndroidBuildApkStep(ProjectExplorer::BuildStepList *bc); + QString proFilePathForInputFile() const; + void setProFilePathForInputFile(const QString &path); + +protected: + friend class QmakeAndroidBuildApkStepFactory; + QmakeAndroidBuildApkStep(ProjectExplorer::BuildStepList *bc, + QmakeAndroidBuildApkStep *other); + + Utils::FileName androidPackageSourceDir() const; + +protected: + void ctor(); + bool init(); + ProjectExplorer::BuildStepConfigWidget *createConfigWidget(); + bool fromMap(const QVariantMap &map); + QVariantMap toMap() const; + +signals: + // also on purpose emitted if the possible values of this changed + void inputFileChanged(); + +private slots: + void updateInputFile(); + +private: + QString m_proFilePathForInputFile; +}; + +} // namespace Internal +} // namespace QmakeProjectManager + +#endif // QMAKEANDROIDBUILDAPKSTEP_H diff --git a/src/plugins/qmakeprojectmanager/qmakeandroidbuildapkwidget.cpp b/src/plugins/qmakeprojectmanager/qmakeandroidbuildapkwidget.cpp new file mode 100644 index 0000000000..c6844891f2 --- /dev/null +++ b/src/plugins/qmakeprojectmanager/qmakeandroidbuildapkwidget.cpp @@ -0,0 +1,190 @@ +/************************************************************************** +** +** Copyright (c) 2014 BogDan Vatra <bog_dan_ro@yahoo.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "createandroidmanifestwizard.h" +#include "qmakeandroidbuildapkstep.h" +#include "qmakeandroidbuildapkwidget.h" +#include "qmakenodes.h" +#include "qmakeproject.h" +#include "ui_qmakeandroidbuildapkwidget.h" + +#include <android/androidbuildapkwidget.h> +#include <android/androidmanager.h> + +#include <QFileDialog> + +namespace QmakeProjectManager { +namespace Internal { + +QmakeAndroidBuildApkWidget::QmakeAndroidBuildApkWidget(QmakeAndroidBuildApkStep *step) : + ProjectExplorer::BuildStepConfigWidget(), + m_ui(new Ui::QmakeAndroidBuildApkWidget), + m_step(step), + m_extraLibraryListModel(0), + m_ignoreChange(false) +{ + QVBoxLayout *topLayout = new QVBoxLayout; + + QHBoxLayout *qt51WarningLayout = new QHBoxLayout(); + QLabel *oldFilesWarningIcon = new QLabel(this); + oldFilesWarningIcon->setObjectName(QStringLiteral("oldFilesWarningIcon")); + QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(0); + sizePolicy.setHeightForWidth(oldFilesWarningIcon->sizePolicy().hasHeightForWidth()); + oldFilesWarningIcon->setSizePolicy(sizePolicy); + oldFilesWarningIcon->setPixmap(QPixmap(QLatin1String(":/core/images/warning.png"))); + oldFilesWarningIcon->setAlignment(Qt::Alignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop)); + qt51WarningLayout->addWidget(oldFilesWarningIcon); + + QLabel *oldFilesWarningLabel = new QLabel(this); + oldFilesWarningLabel->setObjectName(QStringLiteral("oldFilesWarningLabel")); + oldFilesWarningLabel->setWordWrap(true); + qt51WarningLayout->addWidget(oldFilesWarningLabel); + + topLayout->addWidget(new Android::AndroidBuildApkWidget(step)); + + QWidget *widget = new QWidget(this); + m_ui->setupUi(widget); + topLayout->addWidget(widget); + setLayout(topLayout); + + bool oldFiles = Android::AndroidManager::checkForQt51Files(m_step->project()->projectDirectory()); + oldFilesWarningIcon->setVisible(oldFiles); + oldFilesWarningLabel->setVisible(oldFiles); + + m_extraLibraryListModel = new AndroidExtraLibraryListModel(static_cast<QmakeProject *>(m_step->project()), this); + m_ui->androidExtraLibsListView->setModel(m_extraLibraryListModel); + + updateInputFileUi(); + connect(m_step, SIGNAL(inputFileChanged()), + SLOT(updateInputFileUi())); + + connect(m_ui->inputFileComboBox, SIGNAL(currentIndexChanged(int)), + SLOT(inputFileComboBoxIndexChanged())); + + connect(m_ui->createAndroidManifestButton, SIGNAL(clicked()), + SLOT(createManifestButton())); + + connect(m_ui->addAndroidExtraLibButton, SIGNAL(clicked()), + SLOT(addAndroidExtraLib())); + + connect(m_ui->removeAndroidExtraLibButton, SIGNAL(clicked()), + SLOT(removeAndroidExtraLib())); + + connect(m_ui->androidExtraLibsListView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + SLOT(checkEnableRemoveButton())); + + connect(m_extraLibraryListModel, SIGNAL(enabledChanged(bool)), + m_ui->additionalLibrariesGroupBox, SLOT(setEnabled(bool))); + + m_ui->additionalLibrariesGroupBox->setEnabled(m_extraLibraryListModel->isEnabled()); +} + +QmakeAndroidBuildApkWidget::~QmakeAndroidBuildApkWidget() +{ + delete m_ui; +} + +void QmakeAndroidBuildApkWidget::updateInputFileUi() +{ + QmakeProject *project + = static_cast<QmakeProject *>(m_step->project()); + QList<QmakeProFileNode *> nodes = project->applicationProFiles(); + int size = nodes.size(); + if (size == 0 || size == 1) { + // there's nothing to select, e.g. before parsing + m_ui->inputFileLabel->setVisible(false); + m_ui->inputFileComboBox->setVisible(false); + } else { + m_ignoreChange = true; + m_ui->inputFileLabel->setVisible(true); + m_ui->inputFileComboBox->setVisible(true); + + m_ui->inputFileComboBox->clear(); + foreach (QmakeProFileNode *node, nodes) + m_ui->inputFileComboBox->addItem(node->displayName(), node->path()); + + int index = m_ui->inputFileComboBox->findData(m_step->proFilePathForInputFile()); + m_ui->inputFileComboBox->setCurrentIndex(index); + m_ignoreChange = false; + } +} + +void QmakeAndroidBuildApkWidget::inputFileComboBoxIndexChanged() +{ + if (m_ignoreChange) + return; + + QString proFilePath = m_ui->inputFileComboBox->itemData(m_ui->inputFileComboBox->currentIndex()).toString(); + m_step->setProFilePathForInputFile(proFilePath); +} + +void QmakeAndroidBuildApkWidget::createManifestButton() +{ + CreateAndroidManifestWizard wizard(m_step->target()); + wizard.exec(); +} + +void QmakeAndroidBuildApkWidget::addAndroidExtraLib() +{ + QStringList fileNames = QFileDialog::getOpenFileNames(this, + tr("Select additional libraries"), + QDir::homePath(), + tr("Libraries (*.so)")); + + if (!fileNames.isEmpty()) + m_extraLibraryListModel->addEntries(fileNames); +} + +void QmakeAndroidBuildApkWidget::removeAndroidExtraLib() +{ + QModelIndexList removeList = m_ui->androidExtraLibsListView->selectionModel()->selectedIndexes(); + m_extraLibraryListModel->removeEntries(removeList); +} + +void QmakeAndroidBuildApkWidget::checkEnableRemoveButton() +{ + m_ui->removeAndroidExtraLibButton->setEnabled(m_ui->androidExtraLibsListView->selectionModel()->hasSelection()); +} + +QString QmakeAndroidBuildApkWidget::summaryText() const +{ + return tr("<b>Build Android APK</b>"); +} + +QString QmakeAndroidBuildApkWidget::displayName() const +{ + return summaryText(); +} + +} // namespace Internal +} // namespace QmakeProjectManager + + diff --git a/src/plugins/qmakeprojectmanager/qmakeandroidbuildapkwidget.h b/src/plugins/qmakeprojectmanager/qmakeandroidbuildapkwidget.h new file mode 100644 index 0000000000..f21db18d88 --- /dev/null +++ b/src/plugins/qmakeprojectmanager/qmakeandroidbuildapkwidget.h @@ -0,0 +1,85 @@ +/************************************************************************** +** +** Copyright (c) 2014 BogDan Vatra <bog_dan_ro@yahoo.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMAKEANDROIDBUILDAPKWIDGET_H +#define QMAKEANDROIDBUILDAPKWIDGET_H + +#include "androidextralibrarylistmodel.h" + +#include <QWidget> + +#include <projectexplorer/buildstep.h> + +QT_BEGIN_NAMESPACE +class QLabel; +QT_END_NAMESPACE + +namespace QmakeProjectManager { +class QmakeBuildConfiguration; + +namespace Internal { + +namespace Ui { +class QmakeAndroidBuildApkWidget; +} + +class QmakeAndroidBuildApkStep; + +class QmakeAndroidBuildApkWidget : public ProjectExplorer::BuildStepConfigWidget +{ + Q_OBJECT + +public: + explicit QmakeAndroidBuildApkWidget(QmakeAndroidBuildApkStep *step); + ~QmakeAndroidBuildApkWidget(); + +private slots: + void updateInputFileUi(); + void inputFileComboBoxIndexChanged(); + void createManifestButton(); + void addAndroidExtraLib(); + void removeAndroidExtraLib(); + void checkEnableRemoveButton(); + +private: + Ui::QmakeAndroidBuildApkWidget *m_ui; + QmakeAndroidBuildApkStep *m_step; + AndroidExtraLibraryListModel *m_extraLibraryListModel; + bool m_ignoreChange; + + // BuildStepConfigWidget interface +public: + QString summaryText() const; + QString displayName() const; +}; + +} // namespace Internal +} // namespace QmakeProjectManager + +#endif // QMAKEANDROIDBUILDAPKWIDGET_H diff --git a/src/plugins/qmakeprojectmanager/qmakeandroidbuildapkwidget.ui b/src/plugins/qmakeprojectmanager/qmakeandroidbuildapkwidget.ui new file mode 100644 index 0000000000..c92178da0f --- /dev/null +++ b/src/plugins/qmakeprojectmanager/qmakeandroidbuildapkwidget.ui @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>QmakeProjectManager::Internal::QmakeAndroidBuildApkWidget</class> + <widget class="QWidget" name="QmakeProjectManager::Internal::QmakeAndroidBuildApkWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>680</width> + <height>435</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QGroupBox" name="additionalLibrariesGroupBox_2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Android</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QPushButton" name="createAndroidManifestButton"> + <property name="text"> + <string>Create AndroidManifest.xml</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QLabel" name="inputFileLabel"> + <property name="text"> + <string>Input file for androiddeployqt:</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="inputFileComboBox"/> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="additionalLibrariesGroupBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Additional Libraries</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <layout class="QHBoxLayout" name="androidExtraLibsLayout"> + <item> + <widget class="QListView" name="androidExtraLibsListView"> + <property name="toolTip"> + <string>List of extra libraries to include in Android package and load on startup.</string> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::ExtendedSelection</enum> + </property> + </widget> + </item> + <item> + <layout class="QVBoxLayout" name="androidExtraLibsButtonLayout"> + <item> + <widget class="QToolButton" name="addAndroidExtraLibButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Select library to include in package.</string> + </property> + <property name="text"> + <string>Add...</string> + </property> + <property name="toolButtonStyle"> + <enum>Qt::ToolButtonTextOnly</enum> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="removeAndroidExtraLibButton"> + <property name="toolTip"> + <string>Remove currently selected library from list.</string> + </property> + <property name="text"> + <string>Remove</string> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src/plugins/android/qmakeandroidrunconfiguration.cpp b/src/plugins/qmakeprojectmanager/qmakeandroidrunconfiguration.cpp index 1f5baf6c1c..83bca386d0 100644 --- a/src/plugins/android/qmakeandroidrunconfiguration.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeandroidrunconfiguration.cpp @@ -45,7 +45,7 @@ namespace { using namespace ProjectExplorer; using QmakeProjectManager::QmakeProject; -namespace Android { +namespace QmakeProjectManager { namespace Internal { QmakeAndroidRunConfiguration::QmakeAndroidRunConfiguration(Target *parent, Core::Id id, const QString &path) diff --git a/src/plugins/android/qmakeandroidrunconfiguration.h b/src/plugins/qmakeprojectmanager/qmakeandroidrunconfiguration.h index 95fd4fbe9a..612c78957d 100644 --- a/src/plugins/android/qmakeandroidrunconfiguration.h +++ b/src/plugins/qmakeprojectmanager/qmakeandroidrunconfiguration.h @@ -30,11 +30,11 @@ #ifndef QMAKE_ANDROIDRUNCONFIGURATION_H #define QMAKE_ANDROIDRUNCONFIGURATION_H -#include "androidrunconfiguration.h" +#include <android/androidrunconfiguration.h> -namespace QmakeProjectManager { class QmakeProFileNode; } +namespace QmakeProjectManager { +class QmakeProFileNode; -namespace Android { namespace Internal { class QmakeAndroidRunConfiguration : public Android::AndroidRunConfiguration diff --git a/src/plugins/android/qmakeandroidrunfactories.cpp b/src/plugins/qmakeprojectmanager/qmakeandroidrunfactories.cpp index d559579508..0cea9cc73b 100644 --- a/src/plugins/android/qmakeandroidrunfactories.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeandroidrunfactories.cpp @@ -45,9 +45,8 @@ using namespace Android; using namespace ProjectExplorer; -using namespace QmakeProjectManager; -namespace Android { +namespace QmakeProjectManager { namespace Internal { static const char ANDROID_RC_ID_PREFIX[] = "Qt4ProjectManager.AndroidRunConfiguration:"; diff --git a/src/plugins/android/qmakeandroidrunfactories.h b/src/plugins/qmakeprojectmanager/qmakeandroidrunfactories.h index 9286612c92..bc4a71aead 100644 --- a/src/plugins/android/qmakeandroidrunfactories.h +++ b/src/plugins/qmakeprojectmanager/qmakeandroidrunfactories.h @@ -41,7 +41,7 @@ class Target; class Node; } // namespace ProjectExplorer -namespace Android { +namespace QmakeProjectManager { namespace Internal { class QmakeAndroidRunConfigurationFactory : public ProjectExplorer::IRunConfigurationFactory diff --git a/src/plugins/qmakeprojectmanager/qmakeandroidsupport.cpp b/src/plugins/qmakeprojectmanager/qmakeandroidsupport.cpp new file mode 100644 index 0000000000..1267e9e3b0 --- /dev/null +++ b/src/plugins/qmakeprojectmanager/qmakeandroidsupport.cpp @@ -0,0 +1,133 @@ +/************************************************************************** +** +** Copyright (c) 2014 BogDan Vatra <bog_dan_ro@yahoo.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "androidpackageinstallationstep.h" +#include "qmakeandroidsupport.h" +#include "qmakebuildconfiguration.h" +#include "qmakenodes.h" +#include "qmakeproject.h" +#include "qmakestep.h" + +#include <android/androidconstants.h> +#include <projectexplorer/buildmanager.h> +#include <projectexplorer/buildsteplist.h> +#include <projectexplorer/deployconfiguration.h> +#include <projectexplorer/projectexplorer.h> +#include <projectexplorer/projectexplorerconstants.h> +#include <projectexplorer/target.h> +#include <qtsupport/qtkitinformation.h> + +namespace QmakeProjectManager { +namespace Internal { + +bool QmakeAndroidSupport::canHandle(const ProjectExplorer::Target *target) const +{ + return qobject_cast<QmakeProject*>(target->project()); +} + +QStringList QmakeAndroidSupport::soLibSearchPath(const ProjectExplorer::Target *target) const +{ + QStringList res; + QmakeBuildConfiguration *bc = qobject_cast<QmakeBuildConfiguration*>(target->activeBuildConfiguration()); + QmakeProject *project = qobject_cast<QmakeProject*>(target->project()); + Q_ASSERT(project); + if (!project) + return res; + + foreach (QmakeProFileNode *node, project->allProFiles()) { + res << node->buildDir(bc); + } + + return res; +} + +QStringList QmakeAndroidSupport::projectTargetApplications(const ProjectExplorer::Target *target) const +{ + QStringList apps; + QmakeProject *qmakeProject = qobject_cast<QmakeProject *>(target->project()); + if (!qmakeProject) + return apps; + foreach (QmakeProFileNode *proFile, qmakeProject->applicationProFiles()) { + if (proFile->projectType() == ApplicationTemplate) { + if (proFile->targetInformation().target.startsWith(QLatin1String("lib")) + && proFile->targetInformation().target.endsWith(QLatin1String(".so"))) + apps << proFile->targetInformation().target.mid(3, proFile->targetInformation().target.lastIndexOf(QLatin1Char('.')) - 3); + else + apps << proFile->targetInformation().target; + } + } + apps.sort(); + return apps; + +} + +Utils::FileName QmakeAndroidSupport::apkPath(ProjectExplorer::Target *target, AndroidQtSupport::BuildType buildType) const +{ + QString packageName = QLatin1String("QtApp"); + QString buildTypeName; + if (buildType == DebugBuild) + buildTypeName = QLatin1String("debug"); + else if (buildType == ReleaseBuildUnsigned) + buildTypeName =QLatin1String("release-unsigned"); + else + buildTypeName = QLatin1String("release"); + + return target->activeBuildConfiguration()->buildDirectory() + .appendPath(QLatin1String(Android::Constants::ANDROID_BUILDDIRECTORY)) + .appendPath(QLatin1String("bin")) + .appendPath(QString::fromLatin1("%1-%2.apk") + .arg(packageName) + .arg(buildTypeName)); +} + +void QmakeAndroidSupport::resetBuild(const ProjectExplorer::Target *target) +{ + QmakeBuildConfiguration *bc = qobject_cast<QmakeBuildConfiguration*>(target->activeBuildConfiguration()); + if (!bc) + return; + + QMakeStep *qs = bc->qmakeStep(); + if (!qs) + return; + + qs->setForced(true); + + ProjectExplorer::BuildManager::buildList(bc->stepList(ProjectExplorer::Constants::BUILDSTEPS_CLEAN), + ProjectExplorer::ProjectExplorerPlugin::displayNameForStepId(ProjectExplorer::Constants::BUILDSTEPS_CLEAN)); + ProjectExplorer::BuildManager::appendStep(qs, ProjectExplorer::ProjectExplorerPlugin::displayNameForStepId(ProjectExplorer::Constants::BUILDSTEPS_CLEAN)); + bc->setSubNodeBuild(0); + // Make the buildconfiguration emit a evironmentChanged() signal + // TODO find a better way + bool use = bc->useSystemEnvironment(); + bc->setUseSystemEnvironment(!use); + bc->setUseSystemEnvironment(use); +} + +} // namespace Internal +} // namespace QmakeProjectManager diff --git a/src/plugins/android/qmakeandroidsupport.h b/src/plugins/qmakeprojectmanager/qmakeandroidsupport.h index 65094d3727..e2439173dd 100644 --- a/src/plugins/android/qmakeandroidsupport.h +++ b/src/plugins/qmakeprojectmanager/qmakeandroidsupport.h @@ -30,9 +30,9 @@ #ifndef QMAKEANDROIDSUPPORT_H #define QMAKEANDROIDSUPPORT_H -#include "androidqtsupport.h" +#include <android/androidqtsupport.h> -namespace Android { +namespace QmakeProjectManager { namespace Internal { class QmakeAndroidSupport : public Android::AndroidQtSupport @@ -41,9 +41,13 @@ class QmakeAndroidSupport : public Android::AndroidQtSupport public: bool canHandle(const ProjectExplorer::Target *target) const; QStringList soLibSearchPath(const ProjectExplorer::Target *target) const; + QStringList projectTargetApplications(const ProjectExplorer::Target *target) const; + Utils::FileName apkPath(ProjectExplorer::Target *target, BuildType buildType) const; + + void resetBuild(const ProjectExplorer::Target *target); }; } // namespace Internal -} // namespace Android +} // namespace QmakeProjectManager #endif // QMAKEANDROIDSUPPORT_H diff --git a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp index a5ef01d4fd..b716816786 100644 --- a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp +++ b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp @@ -52,6 +52,7 @@ #include <qtsupport/qtversionmanager.h> #include <utils/qtcassert.h> #include <QDebug> +#include <android/androidmanager.h> #include <QInputDialog> diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.pro b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.pro index 7146c0f11b..b8295e9188 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.pro +++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.pro @@ -5,6 +5,10 @@ DEFINES += \ QMAKEPROJECTMANAGER_LIBRARY HEADERS += \ + androidextralibrarylistmodel.h \ + androidpackageinstallationfactory.h \ + androidpackageinstallationstep.h \ + createandroidmanifestwizard.h \ qmakebuildinfo.h \ qmakekitinformation.h \ qmakekitconfigwidget.h \ @@ -54,9 +58,19 @@ HEADERS += \ findqmakeprofiles.h \ qmakeprojectmanager_global.h \ desktopqmakerunconfiguration.h \ - profilecompletionassist.h + profilecompletionassist.h \ + qmakeandroidsupport.h \ + qmakeandroidrunconfiguration.h \ + qmakeandroidrunfactories.h \ + qmakeandroidbuildapkstep.h \ + qmakeandroidbuildapkwidget.h \ + androidqmakebuildconfigurationfactory.h SOURCES += \ + androidextralibrarylistmodel.cpp \ + androidpackageinstallationfactory.cpp \ + androidpackageinstallationstep.cpp \ + createandroidmanifestwizard.cpp \ qmakekitconfigwidget.cpp \ qmakekitinformation.cpp \ qmakeprojectimporter.cpp \ @@ -103,13 +117,20 @@ SOURCES += \ librarydetailscontroller.cpp \ findqmakeprofiles.cpp \ desktopqmakerunconfiguration.cpp \ - profilecompletionassist.cpp + profilecompletionassist.cpp \ + qmakeandroidsupport.cpp \ + qmakeandroidrunconfiguration.cpp \ + qmakeandroidrunfactories.cpp \ + qmakeandroidbuildapkstep.cpp \ + qmakeandroidbuildapkwidget.cpp \ + androidqmakebuildconfigurationfactory.cpp FORMS += makestep.ui \ qmakestep.ui \ qmakeprojectconfigwidget.ui \ librarydetailswidget.ui \ - wizards/testwizardpage.ui + wizards/testwizardpage.ui \ + qmakeandroidbuildapkwidget.ui RESOURCES += qmakeprojectmanager.qrc \ wizards/wizards.qrc diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs index 564a0b75a7..5e0b7f3cb7 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs +++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs @@ -17,6 +17,7 @@ QtcPlugin { Depends { name: "TextEditor" } Depends { name: "QmlJSTools" } Depends { name: "ResourceEditor" } + Depends { name: "Android" } pluginRecommends: [ "Designer" @@ -26,6 +27,11 @@ QtcPlugin { name: "General" files: [ "addlibrarywizard.cpp", "addlibrarywizard.h", + "androidextralibrarylistmodel.cpp", "androidextralibrarylistmodel.h", + "androidpackageinstallationfactory.cpp", "androidpackageinstallationfactory.h", + "androidpackageinstallationstep.cpp", "androidpackageinstallationstep.h", + "androidqmakebuildconfigurationfactory.cpp", "androidqmakebuildconfigurationfactory.h", + "createandroidmanifestwizard.cpp", "createandroidmanifestwizard.h", "desktopqmakerunconfiguration.cpp", "desktopqmakerunconfiguration.h", "externaleditors.cpp", "externaleditors.h", "findqmakeprofiles.cpp", "findqmakeprofiles.h", @@ -37,6 +43,11 @@ QtcPlugin { "profileeditorfactory.cpp", "profileeditorfactory.h", "profilehighlighter.cpp", "profilehighlighter.h", "profilehoverhandler.cpp", "profilehoverhandler.h", + "qmakeandroidrunconfiguration.cpp", "qmakeandroidrunconfiguration.h", + "qmakeandroidrunfactories.cpp", "qmakeandroidrunfactories.h", + "qmakeandroidbuildapkstep.cpp", "qmakeandroidbuildapkstep.h", + "qmakeandroidbuildapkwidget.cpp", "qmakeandroidbuildapkwidget.h", "qmakeandroidbuildapkwidget.ui", + "qmakeandroidsupport.cpp", "qmakeandroidsupport.h", "qmakebuildinfo.h", "qmakekitconfigwidget.cpp", "qmakekitconfigwidget.h", "qmakekitinformation.cpp", "qmakekitinformation.h", diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanager_dependencies.pri b/src/plugins/qmakeprojectmanager/qmakeprojectmanager_dependencies.pri index 60744c7674..07f17bee56 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectmanager_dependencies.pri +++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanager_dependencies.pri @@ -11,6 +11,8 @@ QTC_PLUGIN_DEPENDS += \ texteditor \ cpptools \ qmljstools \ - resourceeditor + resourceeditor \ + android + QTC_PLUGIN_RECOMMENDS += \ designer diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp index 83df8908f6..4633996037 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp @@ -27,6 +27,11 @@ ** ****************************************************************************/ +#include "androidpackageinstallationfactory.h" +#include "androidqmakebuildconfigurationfactory.h" +#include "qmakeandroidbuildapkstep.h" +#include "qmakeandroidrunfactories.h" +#include "qmakeandroidsupport.h" #include "qmakeprojectmanagerplugin.h" #include "qmakeprojectmanager.h" @@ -133,6 +138,7 @@ bool QmakeProjectManagerPlugin::initialize(const QStringList &arguments, QString addAutoReleasedObject(new MakeStepFactory); addAutoReleasedObject(new QmakeBuildConfigurationFactory); + addAutoReleasedObject(new AndroidQmakeBuildConfigurationFactory); addAutoReleasedObject(new DesktopQmakeRunConfigurationFactory); if (Utils::HostOsInfo::isMacHost()) @@ -152,6 +158,12 @@ bool QmakeProjectManagerPlugin::initialize(const QStringList &arguments, QString hf->addMimeType(QmakeProjectManager::Constants::PROFEATUREFILE_MIMETYPE); addAutoReleasedObject(hf); + // Android stuff + addAutoReleasedObject(new AndroidPackageInstallationFactory); + addAutoReleasedObject(new QmakeAndroidBuildApkStepFactory); + addAutoReleasedObject(new QmakeAndroidRunConfigurationFactory); + addAutoReleasedObject(new QmakeAndroidSupport); + //menus Core::ActionContainer *mbuild = Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_BUILDPROJECT); |