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>
This commit is contained in:
BogDan Vatra
2014-06-25 15:42:11 +02:00
committed by Daniel Teske
parent 4657ac7452
commit 64e5a543a8
57 changed files with 2617 additions and 1281 deletions

View File

@@ -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

View File

@@ -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",
]
}

View File

@@ -3,7 +3,6 @@ QTC_PLUGIN_DEPENDS += \
coreplugin \
debugger \
projectexplorer \
qmakeprojectmanager \
qtsupport \
texteditor \
analyzerbase

View File

@@ -40,7 +40,6 @@ namespace Android {
class AndroidRunConfiguration;
namespace Internal {
class AndroidRunner;
class AndroidAnalyzeSupport : public AndroidRunSupport

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -28,50 +28,55 @@
**
****************************************************************************/
#ifndef ANDROIDEXTRALIBRARYLISTMODEL_H
#define ANDROIDEXTRALIBRARYLISTMODEL_H
#ifndef ANDROIDBUILDAPKWIDGET_H
#define ANDROIDBUILDAPKWIDGET_H
#include <QAbstractItemModel>
#include <QStringList>
#include "android_global.h"
namespace QmakeProjectManager {
class QmakeProject;
class QmakeProFileNode;
}
#include <projectexplorer/buildstep.h>
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class AndroidBuildApkWidget; }
QT_END_NAMESPACE
namespace QmakeProjectManager { class QmakeBuildConfiguration; }
namespace Android {
namespace Internal {
class AndroidExtraLibraryListModel : public QAbstractItemModel
class AndroidBuildApkStep;
class ANDROID_EXPORT AndroidBuildApkWidget : public ProjectExplorer::BuildStepConfigWidget
{
Q_OBJECT
public:
explicit AndroidExtraLibraryListModel(QmakeProjectManager::QmakeProject *project,
QObject *parent = 0);
QModelIndex index(int row, int column, const QModelIndex &parent) const;
QModelIndex parent(const QModelIndex &child) const;
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
void removeEntries(QModelIndexList list);
void addEntries(const QStringList &list);
bool isEnabled() const;
signals:
void enabledChanged(bool);
AndroidBuildApkWidget(AndroidBuildApkStep *step);
~AndroidBuildApkWidget();
private slots:
void proFileUpdated(QmakeProjectManager::QmakeProFileNode *node, bool success, bool parseInProgress);
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:
QmakeProjectManager::QmakeProject *m_project;
QStringList m_entries;
QString m_scope;
virtual QString summaryText() const;
virtual QString displayName() const;
void setCertificates();
Ui::AndroidBuildApkWidget *m_ui;
AndroidBuildApkStep *m_step;
};
} // namespace Internal
} // namespace Android
}
#endif // ANDROIDEXTRALIBRARYLISTMODEL_H
#endif // ANDROIDBUILDAPKWIDGET_H

View File

@@ -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>

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -42,7 +42,6 @@ namespace Android {
class AndroidRunConfiguration;
namespace Internal {
class AndroidRunner;
class AndroidDebugSupport : public AndroidRunSupport

View File

@@ -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;

View File

@@ -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()
{
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();
}
void AndroidDeployQtStep::showInGraphicalShell()
{
Core::FileUtils::showInGraphicalShell(Core::ICore::instance()->mainWindow(), m_apkPath);
}
ProjectExplorer::BuildStepConfigWidget *AndroidDeployQtStep::createConfigWidget()
{
return new AndroidDeployQtWidget(this);
}
void AndroidDeployQtStep::processFinished(int exitCode, QProcess::ExitStatus status)
void AndroidDeployQtStep::stdOutput(const QString &line)
{
AbstractProcessStep::processFinished(exitCode, status);
if (m_openPackageLocationForRun && status == QProcess::NormalExit && exitCode == 0)
QMetaObject::invokeMethod(this, "showInGraphicalShell", Qt::QueuedConnection);
if (line.contains(InstallFailedInconsistentCertificatesString))
m_installOk = false;
AbstractProcessStep::stdOutput(line);
}
void AndroidDeployQtStep::stdError(const QString &line)
{
if (line.contains(InstallFailedInconsistentCertificatesString))
m_installOk = false;
AbstractProcessStep::stdError(line);
}
bool AndroidDeployQtStep::processSucceeded(int exitCode, QProcess::ExitStatus status)
{
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)
void AndroidDeployQtStep::setUninstallPreviousPackage(bool uninstall)
{
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)
{
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
bool AndroidDeployQtStep::uninstallPreviousPackage()
{
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()
{
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;
}

View File

@@ -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?
void setUninstallPreviousPackage(bool uninstall);
private slots:
void showInGraphicalShell();
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;
QString m_targetArch;
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

View File

@@ -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)));
connect(m_ui->uninstallPreviousPackage, SIGNAL(toggled(bool)),
m_step, SLOT(setUninstallPreviousPackage(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)));
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());
}

View File

@@ -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;
};
}

View File

@@ -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">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="uninstallPreviousPackage">
<property name="text">
<string>Clean Temporary Libraries Directory on Device</string>
<string>Uninstall previous package</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QPushButton" name="installMinistroButton">
<property name="text">
<string>Install Ministro from APK</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 &quot;android&quot; 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.&lt;br/&gt;&lt;br/&gt;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>
<widget class="QPushButton" name="cleanLibsPushButton">
<property name="text">
<string>Use Ministro service to install Qt</string>
</property>
<property name="checked">
<bool>true</bool>
<string>Clean Temporary Libraries Directory on Device</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>
<widget class="QPushButton" name="installMinistroButton">
<property name="text">
<string>Deploy local Qt libraries to temporary directory</string>
<string>Install Ministro from APK</string>
</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>
<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>

View File

@@ -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);
};

View File

@@ -1,167 +0,0 @@
/**************************************************************************
**
** 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 "androidextralibrarylistmodel.h"
#include <qmakeprojectmanager/qmakeproject.h>
#include <qmakeprojectmanager/qmakenodes.h>
#include <proparser/prowriter.h>
using namespace Android;
using namespace Internal;
AndroidExtraLibraryListModel::AndroidExtraLibraryListModel(QmakeProjectManager::QmakeProject *project,
QObject *parent)
: QAbstractItemModel(parent)
, m_project(project)
{
QmakeProjectManager::QmakeProFileNode *node = m_project->rootQmakeProjectNode();
proFileUpdated(node, node->validParse(), node->parseInProgress());
connect(m_project, SIGNAL(proFileUpdated(QmakeProjectManager::QmakeProFileNode*,bool,bool)),
this, SLOT(proFileUpdated(QmakeProjectManager::QmakeProFileNode*,bool,bool)));
}
QModelIndex AndroidExtraLibraryListModel::index(int row, int column, const QModelIndex &) const
{
return createIndex(row, column);
}
QModelIndex AndroidExtraLibraryListModel::parent(const QModelIndex &) const
{
return QModelIndex();
}
int AndroidExtraLibraryListModel::rowCount(const QModelIndex &) const
{
return m_entries.size();
}
int AndroidExtraLibraryListModel::columnCount(const QModelIndex &) const
{
return 1;
}
QVariant AndroidExtraLibraryListModel::data(const QModelIndex &index, int role) const
{
Q_ASSERT(index.row() >= 0 && index.row() < m_entries.size());
const QString &entry = QDir::cleanPath(m_entries.at(index.row()));
switch (role) {
case Qt::DisplayRole: return entry;
default: return QVariant();
};
}
void AndroidExtraLibraryListModel::proFileUpdated(QmakeProjectManager::QmakeProFileNode *node, bool success, bool parseInProgress)
{
QmakeProjectManager::QmakeProFileNode *root = m_project->rootQmakeProjectNode();
if (node != root)
return;
m_scope = QLatin1String("contains(ANDROID_TARGET_ARCH,")
+ node->singleVariableValue(QmakeProjectManager::AndroidArchVar)
+ QLatin1Char(')');
if (parseInProgress) {
emit enabledChanged(false);
return;
}
bool enabled;
beginResetModel();
if (success && root->projectType() == QmakeProjectManager::ApplicationTemplate) {
m_entries = node->variableValue(QmakeProjectManager::AndroidExtraLibs);
enabled = true;
} else {
// parsing error or not a application template
m_entries.clear();
enabled = false;
}
endResetModel();
emit enabledChanged(enabled);
}
bool AndroidExtraLibraryListModel::isEnabled() const
{
QmakeProjectManager::QmakeProFileNode *root = m_project->rootQmakeProjectNode();
if (root->parseInProgress())
return false;
if (root->projectType() != QmakeProjectManager::ApplicationTemplate)
return false;
return true;
}
void AndroidExtraLibraryListModel::addEntries(const QStringList &list)
{
if (m_project->rootQmakeProjectNode()->projectType() != QmakeProjectManager::ApplicationTemplate)
return;
beginInsertRows(QModelIndex(), m_entries.size(), m_entries.size() + list.size());
foreach (const QString &path, list)
m_entries += QLatin1String("$$PWD/") + QDir(m_project->projectDirectory().toString()).relativeFilePath(path);
QmakeProjectManager::QmakeProFileNode *node = m_project->rootQmakeProjectNode();
node->setProVariable(QLatin1String("ANDROID_EXTRA_LIBS"), m_entries, m_scope,
QmakeProjectManager::Internal::ProWriter::ReplaceValues
| QmakeProjectManager::Internal::ProWriter::MultiLine);
endInsertRows();
}
bool greaterModelIndexByRow(const QModelIndex &a, const QModelIndex &b)
{
return a.row() > b.row();
}
void AndroidExtraLibraryListModel::removeEntries(QModelIndexList list)
{
if (list.isEmpty() || m_project->rootQmakeProjectNode()->projectType() != QmakeProjectManager::ApplicationTemplate)
return;
std::sort(list.begin(), list.end(), greaterModelIndexByRow);
int i = 0;
while (i < list.size()) {
int lastRow = list.at(i++).row();
int firstRow = lastRow;
while (i < list.size() && firstRow - list.at(i).row() <= 1)
firstRow = list.at(i++).row();
beginRemoveRows(QModelIndex(), firstRow, lastRow);
int count = lastRow - firstRow + 1;
while (count-- > 0)
m_entries.removeAt(firstRow);
endRemoveRows();
}
QmakeProjectManager::QmakeProFileNode *node = m_project->rootQmakeProjectNode();
node->setProVariable(QLatin1String("ANDROID_EXTRA_LIBS"), m_entries, m_scope);
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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 AndroidQtSupport;
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

View File

@@ -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

View File

@@ -1,112 +0,0 @@
/**************************************************************************
**
** 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 "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>
using namespace ProjectExplorer;
namespace Android {
namespace Internal {
AndroidPackageInstallationFactory::AndroidPackageInstallationFactory(QObject *parent)
: IBuildStepFactory(parent)
{
}
QList<Core::Id> AndroidPackageInstallationFactory::availableCreationIds(BuildStepList *parent) const
{
Q_UNUSED(parent);
return QList<Core::Id>();
}
QString AndroidPackageInstallationFactory::displayNameForId(Core::Id id) const
{
if (id == AndroidPackageInstallationStep::Id)
return tr("Deploy to device");
return QString();
}
bool AndroidPackageInstallationFactory::canCreate(BuildStepList *parent, Core::Id id) const
{
Q_UNUSED(parent);
Q_UNUSED(id);
return false;
}
BuildStep *AndroidPackageInstallationFactory::create(BuildStepList *parent, Core::Id id)
{
Q_UNUSED(parent);
Q_UNUSED(id);
return 0;
}
bool AndroidPackageInstallationFactory::canRestore(BuildStepList *parent, const QVariantMap &map) const
{
if (parent->id() != ProjectExplorer::Constants::BUILDSTEPS_DEPLOY)
return false;
if (!AndroidManager::supportsAndroid(parent->target()))
return false;
if (parent->contains(AndroidPackageInstallationStep::Id))
return false;
return ProjectExplorer::idFromMap(map) == AndroidPackageInstallationStep::Id;
}
BuildStep *AndroidPackageInstallationFactory::restore(BuildStepList *parent, const QVariantMap &map)
{
Q_ASSERT(canRestore(parent, map));
AndroidPackageInstallationStep * const step = new AndroidPackageInstallationStep(AndroidPackageInstallationStep::ProjectDirectory, parent);
if (!step->fromMap(map)) {
delete step;
return 0;
}
return step;
}
bool AndroidPackageInstallationFactory::canClone(BuildStepList *parent, BuildStep *product) const
{
return canCreate(parent, product->id());
}
BuildStep *AndroidPackageInstallationFactory::clone(BuildStepList *parent, BuildStep *product)
{
Q_ASSERT(canClone(parent, product));
return new AndroidPackageInstallationStep(parent, static_cast<AndroidPackageInstallationStep*>(product));
}
} // namespace Internal
} // namespace Android

View File

@@ -1,63 +0,0 @@
/**************************************************************************
**
** 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 ANDROIDPACKAGEINSTALLATIONFACTORY_H
#define ANDROIDPACKAGEINSTALLATIONFACTORY_H
#include <projectexplorer/buildstep.h>
namespace Android {
namespace Internal {
class AndroidPackageInstallationFactory: public ProjectExplorer::IBuildStepFactory
{
Q_OBJECT
public:
explicit AndroidPackageInstallationFactory(QObject *parent = 0);
QList<Core::Id> availableCreationIds(ProjectExplorer::BuildStepList *parent) const;
QString displayNameForId(Core::Id id) const;
bool canCreate(ProjectExplorer::BuildStepList *parent, Core::Id id) const;
ProjectExplorer::BuildStep *create(ProjectExplorer::BuildStepList *parent, 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);
};
} // namespace Internal
} // namespace Android
#endif // ANDROIDPACKAGEINSTALLATIONFACTORY_H

View File

@@ -1,168 +0,0 @@
/**************************************************************************
**
** 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 "androidmanager.h"
#include "androidconstants.h"
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/target.h>
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/toolchain.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/gnumakeparser.h>
#include <utils/hostosinfo.h>
#include <qmakeprojectmanager/qmakeparser.h>
#include <QDir>
using namespace Android::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)
{
const QString name = tr("Copy application data");
setDefaultDisplayName(name);
setDisplayName(name);
}
AndroidPackageInstallationStep::AndroidPackageInstallationStep(ProjectExplorer::BuildStepList *bc, AndroidPackageInstallationStep *other)
: AbstractProcessStep(bc, other)
{ }
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();
if (Utils::HostOsInfo::isWindowsHost())
if (bc->environment().searchInPath(QLatin1String("sh.exe")).isEmpty())
dirPath = QDir::toNativeSeparators(dirPath);
ProjectExplorer::ToolChain *tc
= ProjectExplorer::ToolChainKitInformation::toolChain(target()->kit());
ProjectExplorer::ProcessParameters *pp = processParameters();
pp->setMacroExpander(bc->macroExpander());
pp->setWorkingDirectory(bc->buildDirectory().toString());
pp->setCommand(tc->makeCommand(bc->environment()));
Utils::Environment env = bc->environment();
// Force output to english for the parsers. Do this here and not in the toolchain's
// addToEnvironment() to not screw up the users run environment.
env.set(QLatin1String("LC_ALL"), QLatin1String("C"));
pp->setEnvironment(env);
pp->setArguments(QString::fromLatin1("INSTALL_ROOT=\"%1\" install").arg(dirPath));
pp->resolveAll();
setOutputParser(new ProjectExplorer::GnuMakeParser());
ProjectExplorer::IOutputParser *parser = target()->kit()->createOutputParser();
if (parser)
appendOutputParser(parser);
outputParser()->setWorkingDirectory(pp->effectiveWorkingDirectory());
m_androidDirToClean = m_androidDirectory == BuildDirectory ? dirPath : QString();
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;
Utils::FileName androidDir = Utils::FileName::fromString(m_androidDirToClean);
if (!m_androidDirToClean.isEmpty()&& androidDir.toFileInfo().exists()) {
emit addOutput(tr("Removing directory %1").arg(m_androidDirToClean), MessageOutput);
if (!Utils::FileUtils::removeRecursively(androidDir, &error)) {
emit addOutput(error, ErrorOutput);
fi.reportResult(false);
emit finished();
return;
}
}
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);
}
bool AndroidPackageInstallationStep::immutable() const
{
return true;
}
//
// AndroidPackageInstallationStepWidget
//
AndroidPackageInstallationStepWidget::AndroidPackageInstallationStepWidget(AndroidPackageInstallationStep *step)
: m_step(step)
{
}
QString AndroidPackageInstallationStepWidget::summaryText() const
{
return tr("<b>Make install</b>");
}
QString AndroidPackageInstallationStepWidget::displayName() const
{
return tr("Make install");
}
bool AndroidPackageInstallationStepWidget::showWidget() const
{
return false;
}

View File

@@ -1,80 +0,0 @@
/**************************************************************************
**
** 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 ANDROIDPACKAGEINSTALLATIONSTEP_H
#define ANDROIDPACKAGEINSTALLATIONSTEP_H
#include <projectexplorer/buildstep.h>
#include <projectexplorer/abstractprocessstep.h>
namespace Android {
namespace Internal {
class AndroidPackageInstallationStep : public ProjectExplorer::AbstractProcessStep
{
Q_OBJECT
friend class AndroidPackageInstallationFactory;
public:
enum AndroidDirectory { ProjectDirectory, BuildDirectory };
explicit AndroidPackageInstallationStep(AndroidDirectory mode, ProjectExplorer::BuildStepList *bsl);
bool init();
bool fromMap(const QVariantMap &map);
QVariantMap toMap() const;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
bool immutable() const;
void run(QFutureInterface<bool> &fi);
private:
AndroidPackageInstallationStep(ProjectExplorer::BuildStepList *bc,
AndroidPackageInstallationStep *other);
AndroidDirectory m_androidDirectory;
QString m_androidDirToClean;
static const Core::Id Id;
};
class AndroidPackageInstallationStepWidget : public ProjectExplorer::BuildStepConfigWidget
{
Q_OBJECT
public:
AndroidPackageInstallationStepWidget(AndroidPackageInstallationStep *step);
QString summaryText() const;
QString displayName() const;
bool showWidget() const;
private:
AndroidPackageInstallationStep *m_step;
};
} // namespace Internal
} // namespace Android
#endif // ANDROIDPACKAGEINSTALLATIONSTEP_H

View File

@@ -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

View File

@@ -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

View File

@@ -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()

View File

@@ -36,7 +36,6 @@ namespace Android {
class AndroidRunConfiguration;
namespace Internal {
class AndroidRunner;
class AndroidRunControl : public ProjectExplorer::RunControl

View File

@@ -45,7 +45,6 @@ class AndroidRunConfiguration;
namespace Internal {
class AndroidRunner : public QThread
{
Q_OBJECT

View File

@@ -34,9 +34,10 @@
#include <QDialog>
namespace Android {
namespace Internal {
class AndroidConfig;
namespace Internal {
class AvdDialog : public QDialog
{
Q_OBJECT

View File

@@ -1,273 +0,0 @@
/****************************************************************************
**
** 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 "createandroidmanifestwizard.h"
#include <projectexplorer/target.h>
#include <qmakeprojectmanager/qmakeproject.h>
#include <qmakeprojectmanager/qmakenodes.h>
#include <proparser/prowriter.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 QmakeProjectManager::QmakeProject;
using QmakeProjectManager::QmakeProFileNode;
//
// NoApplicationProFilePage
//
NoApplicationProFilePage::NoApplicationProFilePage(CreateAndroidManifestWizard *wizard)
: m_wizard(wizard)
{
QVBoxLayout *layout = new QVBoxLayout(this);
QLabel *label = new QLabel(this);
label->setWordWrap(true);
label->setText(tr("No application .pro file found in this project."));
layout->addWidget(label);
setTitle(tr("No Application .pro File"));
}
//
// ChooseProFilePage
//
ChooseProFilePage::ChooseProFilePage(CreateAndroidManifestWizard *wizard, const QList<QmakeProFileNode *> &nodes)
: m_wizard(wizard)
{
QFormLayout *fl = new QFormLayout(this);
QLabel *label = new QLabel(this);
label->setWordWrap(true);
label->setText(tr("Select the .pro file for which you want to create an AndroidManifest.xml file."));
fl->addRow(label);
m_comboBox = new QComboBox(this);
foreach (QmakeProFileNode *node, nodes)
m_comboBox->addItem(node->displayName(), QVariant::fromValue(static_cast<void *>(node))); // TODO something more?
nodeSelected(0);
connect(m_comboBox, SIGNAL(currentIndexChanged(int)),
this, SLOT(nodeSelected(int)));
fl->addRow(tr(".pro file:"), m_comboBox);
setTitle(tr("Select a .pro File"));
}
void ChooseProFilePage::nodeSelected(int index)
{
Q_UNUSED(index)
m_wizard->setNode(static_cast<QmakeProFileNode *>(m_comboBox->itemData(m_comboBox->currentIndex()).value<void *>()));
}
//
// ChooseDirectoryPage
//
ChooseDirectoryPage::ChooseDirectoryPage(CreateAndroidManifestWizard *wizard)
: m_wizard(wizard), m_androidPackageSourceDir(0), m_complete(true)
{
QString androidPackageDir = m_wizard->node()->singleVariableValue(QmakeProjectManager::AndroidPackageSourceDir);
QFormLayout *fl = new QFormLayout(this);
QLabel *label = new QLabel(this);
label->setWordWrap(true);
fl->addRow(label);
m_sourceDirectoryWarning = new QLabel(this);
m_sourceDirectoryWarning->setVisible(false);
m_sourceDirectoryWarning->setText(tr("The Android package source directory cannot be the same as the project directory."));
m_sourceDirectoryWarning->setWordWrap(true);
m_warningIcon = new QLabel(this);
m_warningIcon->setVisible(false);
m_warningIcon->setPixmap(QPixmap(QLatin1String(Core::Constants::ICON_ERROR)));
m_warningIcon->setWordWrap(true);
m_warningIcon->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
QHBoxLayout *hbox = new QHBoxLayout;
hbox->addWidget(m_warningIcon);
hbox->addWidget(m_sourceDirectoryWarning);
hbox->setAlignment(m_warningIcon, Qt::AlignTop);
fl->addRow(hbox);
m_androidPackageSourceDir = new Utils::PathChooser(this);
m_androidPackageSourceDir->setExpectedKind(Utils::PathChooser::Directory);
fl->addRow(tr("Android package source directory:"), m_androidPackageSourceDir);
if (androidPackageDir.isEmpty()) {
label->setText(tr("Select the Android package source directory.\n\n"
"The files in the Android package source directory are copied to the build directory's "
"Android directory and the default files are overwritten."));
m_androidPackageSourceDir->setPath(QFileInfo(m_wizard->node()->path()).absolutePath().append(QLatin1String("/android")));
connect(m_androidPackageSourceDir, SIGNAL(changed(QString)),
this, SLOT(checkPackageSourceDir()));
} else {
label->setText(tr("The Android manifest file will be created in the ANDROID_PACKAGE_SOURCE_DIR set in the .pro file."));
m_androidPackageSourceDir->setPath(androidPackageDir);
m_androidPackageSourceDir->setReadOnly(true);
}
m_wizard->setDirectory(m_androidPackageSourceDir->path());
connect(m_androidPackageSourceDir, SIGNAL(pathChanged(QString)),
m_wizard, SLOT(setDirectory(QString)));
}
void ChooseDirectoryPage::checkPackageSourceDir()
{
QString projectDir = QFileInfo(m_wizard->node()->path()).absolutePath();
QString newDir = m_androidPackageSourceDir->path();
bool isComplete = QFileInfo(projectDir) != QFileInfo(newDir);
m_sourceDirectoryWarning->setVisible(!isComplete);
m_warningIcon->setVisible(!isComplete);
if (isComplete != m_complete) {
m_complete = isComplete;
emit completeChanged();
}
}
bool ChooseDirectoryPage::isComplete() const
{
return m_complete;
}
//
// CreateAndroidManifestWizard
//
CreateAndroidManifestWizard::CreateAndroidManifestWizard(ProjectExplorer::Target *target)
: m_target(target), m_node(0)
{
setWindowTitle(tr("Create Android Manifest Wizard"));
QmakeProject *project = static_cast<QmakeProject *>(target->project());
QList<QmakeProFileNode *> nodes = project->applicationProFiles();
if (nodes.isEmpty()) {
// oh uhm can't create anything
addPage(new NoApplicationProFilePage(this));
} else if (nodes.size() == 1) {
setNode(nodes.first());
addPage(new ChooseDirectoryPage(this));
} else {
addPage(new ChooseProFilePage(this, nodes));
addPage(new ChooseDirectoryPage(this));
}
}
QmakeProjectManager::QmakeProFileNode *CreateAndroidManifestWizard::node() const
{
return m_node;
}
void CreateAndroidManifestWizard::setNode(QmakeProjectManager::QmakeProFileNode *node)
{
m_node = node;
}
void CreateAndroidManifestWizard::setDirectory(const QString &directory)
{
m_directory = directory;
}
QString CreateAndroidManifestWizard::sourceFileName() const
{
QString result;
QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(m_target->kit());
if (!version)
return result;
Utils::FileName srcPath
= Utils::FileName::fromString(version->qmakeProperty("QT_INSTALL_PREFIX"))
.appendPath(QLatin1String("src/android/java"));
srcPath.appendPath(QLatin1String("AndroidManifest.xml"));
return srcPath.toString();
}
void CreateAndroidManifestWizard::createAndroidManifestFile()
{
if (m_directory.isEmpty())
return;
QDir dir;
if (!QFileInfo(m_directory).exists())
dir.mkpath(m_directory);
QString fileName = m_directory + QLatin1String("/AndroidManifest.xml");
if (QFileInfo(fileName).exists()) {
if (QMessageBox::question(this, tr("Overwrite AndroidManifest.xml"),
tr("Overwrite existing AndroidManifest.xml?"),
QMessageBox::Yes, QMessageBox::No)
== QMessageBox::Yes) {
if (!QFile(m_directory + QLatin1String("/AndroidManifest.xml")).remove()) {
QMessageBox::warning(this, tr("File Removal Error"),
tr("Could not remove file %1.").arg(fileName));
return;
}
} else {
return;
}
}
if (!QFile::copy(sourceFileName(), fileName)) {
QMessageBox::warning(this, tr("File Creation Error"),
tr("Could not create file %1.").arg(fileName));
return;
}
if (m_node->singleVariableValue(QmakeProjectManager::AndroidPackageSourceDir).isEmpty()) {
// and now time for some magic
QString dir = QFileInfo(fileName).absolutePath();
QString value = QLatin1String("$$PWD/")
+ QDir(m_target->project()->projectDirectory().toString()).relativeFilePath(dir);
bool result =
m_node->setProVariable(QLatin1String("ANDROID_PACKAGE_SOURCE_DIR"), QStringList(value));
QStringList unChanged;
m_node->addFiles(QStringList(fileName), &unChanged);
if (result == false
|| !unChanged.isEmpty()) {
QMessageBox::warning(this, tr("Project File not Updated"),
tr("Could not update the .pro file %1.").arg(m_node->path()));
}
}
Core::EditorManager::openEditor(fileName);
}
void CreateAndroidManifestWizard::accept()
{
createAndroidManifestFile();
Utils::Wizard::accept();
}

View File

@@ -1,110 +0,0 @@
/****************************************************************************
**
** 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 CREATEANDROIDMANIFESTWIZARD_H
#define CREATEANDROIDMANIFESTWIZARD_H
#include <utils/pathchooser.h>
#include <utils/wizard.h>
QT_BEGIN_NAMESPACE
class QComboBox;
class QLabel;
QT_END_NAMESPACE
namespace ProjectExplorer { class Target; }
namespace QmakeProjectManager { class QmakeProFileNode; }
namespace Android {
namespace Internal {
class CreateAndroidManifestWizard;
class NoApplicationProFilePage : public QWizardPage
{
Q_OBJECT
public:
NoApplicationProFilePage(CreateAndroidManifestWizard *wizard);
private:
CreateAndroidManifestWizard *m_wizard;
};
class ChooseProFilePage : public QWizardPage
{
Q_OBJECT
public:
ChooseProFilePage(CreateAndroidManifestWizard *wizard, const QList<QmakeProjectManager::QmakeProFileNode *> &nodes);
private slots:
void nodeSelected(int index);
private:
CreateAndroidManifestWizard *m_wizard;
QComboBox *m_comboBox;
};
class ChooseDirectoryPage : public QWizardPage
{
Q_OBJECT
public:
ChooseDirectoryPage(CreateAndroidManifestWizard *wizard);
protected:
bool isComplete() const;
private slots:
void checkPackageSourceDir();
private:
CreateAndroidManifestWizard *m_wizard;
Utils::PathChooser *m_androidPackageSourceDir;
QLabel *m_sourceDirectoryWarning;
QLabel *m_warningIcon;
bool m_complete;
};
class CreateAndroidManifestWizard : public Utils::Wizard
{
Q_OBJECT
public:
CreateAndroidManifestWizard(ProjectExplorer::Target *target);
QmakeProjectManager::QmakeProFileNode *node() const;
void setNode(QmakeProjectManager::QmakeProFileNode *node);
QString sourceFileName() const;
void accept();
public slots:
void setDirectory(const QString &directory);
private:
void createAndroidManifestFile();
ProjectExplorer::Target *m_target;
QmakeProjectManager::QmakeProFileNode *m_node;
QString m_directory;
};
}
}
#endif // CREATEANDROIDMANIFESTWIZARD_H

View File

@@ -1,139 +0,0 @@
/**************************************************************************
**
** 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 "qmakeandroidrunconfiguration.h"
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/target.h>
#include <qtsupport/qtoutputformatter.h>
#include <qtsupport/qtkitinformation.h>
#include <qmakeprojectmanager/qmakeproject.h>
#include <qmakeprojectmanager/qmakenodes.h>
#include <utils/qtcassert.h>
namespace {
QLatin1String PRO_FILE_KEY("QMakeProjectManager.QmakeAndroidRunConfiguration.ProFile");
}
using namespace ProjectExplorer;
using QmakeProjectManager::QmakeProject;
namespace Android {
namespace Internal {
QmakeAndroidRunConfiguration::QmakeAndroidRunConfiguration(Target *parent, Core::Id id, const QString &path)
: AndroidRunConfiguration(parent, id)
, m_proFilePath(path)
{
QmakeProject *project = static_cast<QmakeProject *>(parent->project());
m_parseSuccess = project->validParse(m_proFilePath);
m_parseInProgress = project->parseInProgress(m_proFilePath);
init();
}
QmakeAndroidRunConfiguration::QmakeAndroidRunConfiguration(Target *parent, QmakeAndroidRunConfiguration *source)
: AndroidRunConfiguration(parent, source)
, m_proFilePath(source->m_proFilePath)
, m_parseSuccess(source->m_parseSuccess)
, m_parseInProgress(source->m_parseInProgress)
{
init();
}
void QmakeAndroidRunConfiguration::init()
{
connect(target()->project(), SIGNAL(proFileUpdated(QmakeProjectManager::QmakeProFileNode*,bool,bool)),
this, SLOT(proFileUpdated(QmakeProjectManager::QmakeProFileNode*,bool,bool)));
}
bool QmakeAndroidRunConfiguration::fromMap(const QVariantMap &map)
{
const QDir projectDir = QDir(target()->project()->projectDirectory().toString());
m_proFilePath = QDir::cleanPath(projectDir.filePath(map.value(PRO_FILE_KEY).toString()));
m_parseSuccess = static_cast<QmakeProject *>(target()->project())->validParse(m_proFilePath);
m_parseInProgress = static_cast<QmakeProject *>(target()->project())->parseInProgress(m_proFilePath);
return RunConfiguration::fromMap(map);
}
QVariantMap QmakeAndroidRunConfiguration::toMap() const
{
if (m_proFilePath.isEmpty()) {
if (!target()->project()->rootProjectNode())
return QVariantMap();
m_proFilePath = target()->project()->rootProjectNode()->path();
}
const QDir projectDir = QDir(target()->project()->projectDirectory().toString());
QVariantMap map(RunConfiguration::toMap());
map.insert(PRO_FILE_KEY, projectDir.relativeFilePath(m_proFilePath));
return map;
}
bool QmakeAndroidRunConfiguration::isEnabled() const
{
return m_parseSuccess && !m_parseInProgress;
}
QString QmakeAndroidRunConfiguration::disabledReason() const
{
if (m_parseInProgress)
return tr("The .pro file \"%1\" is currently being parsed.")
.arg(QFileInfo(m_proFilePath).fileName());
if (!m_parseSuccess)
return static_cast<QmakeProject *>(target()->project())->disabledReasonForRunConfiguration(m_proFilePath);
return QString();
}
void QmakeAndroidRunConfiguration::proFileUpdated(QmakeProjectManager::QmakeProFileNode *pro, bool success, bool parseInProgress)
{
if (m_proFilePath.isEmpty() && target()->project()->rootProjectNode()) {
m_proFilePath = target()->project()->rootProjectNode()->path();
}
if (m_proFilePath != pro->path())
return;
bool enabled = isEnabled();
QString reason = disabledReason();
m_parseSuccess = success;
m_parseInProgress = parseInProgress;
if (enabled != isEnabled() || reason != disabledReason())
emit enabledChanged();
}
QString QmakeAndroidRunConfiguration::proFilePath() const
{
return m_proFilePath;
}
} // namespace Internal
} // namespace Android

View File

@@ -1,73 +0,0 @@
/**************************************************************************
**
** 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 QMAKE_ANDROIDRUNCONFIGURATION_H
#define QMAKE_ANDROIDRUNCONFIGURATION_H
#include "androidrunconfiguration.h"
namespace QmakeProjectManager { class QmakeProFileNode; }
namespace Android {
namespace Internal {
class QmakeAndroidRunConfiguration : public Android::AndroidRunConfiguration
{
Q_OBJECT
friend class QmakeAndroidRunConfigurationFactory;
public:
QmakeAndroidRunConfiguration(ProjectExplorer::Target *parent, Core::Id id, const QString &path = QString());
QString proFilePath() const;
bool isEnabled() const;
QString disabledReason() const;
protected:
QmakeAndroidRunConfiguration(ProjectExplorer::Target *parent, QmakeAndroidRunConfiguration *source);
bool fromMap(const QVariantMap &map);
QVariantMap toMap() const;
private slots:
void proFileUpdated(QmakeProjectManager::QmakeProFileNode *pro, bool success, bool parseInProgress);
private:
void init();
mutable QString m_proFilePath;
bool m_parseSuccess;
bool m_parseInProgress;
};
} // namespace Internal
} // namespace Android
#endif // QMAKE_ANDROIDRUNCONFIGURATION_H

View File

@@ -1,148 +0,0 @@
/**************************************************************************
**
** 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 "qmakeandroidrunfactories.h"
#include "qmakeandroidrunconfiguration.h"
#include <android/androidmanager.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/target.h>
#include <debugger/debuggerconstants.h>
#include <qmakeprojectmanager/qmakeproject.h>
#include <qmakeprojectmanager/qmakenodes.h>
#include <qtsupport/customexecutablerunconfiguration.h>
#include <qtsupport/qtkitinformation.h>
#include <qtsupport/qtsupportconstants.h>
using namespace Android;
using namespace ProjectExplorer;
using namespace QmakeProjectManager;
namespace Android {
namespace Internal {
static const char ANDROID_RC_ID_PREFIX[] = "Qt4ProjectManager.AndroidRunConfiguration:";
static QString pathFromId(const Core::Id id)
{
return id.suffixAfter(ANDROID_RC_ID_PREFIX);
}
QmakeAndroidRunConfigurationFactory::QmakeAndroidRunConfigurationFactory(QObject *parent)
: ProjectExplorer::IRunConfigurationFactory(parent)
{
}
QString QmakeAndroidRunConfigurationFactory::displayNameForId(const Core::Id id) const
{
return QFileInfo(pathFromId(id)).completeBaseName();
}
bool QmakeAndroidRunConfigurationFactory::canCreate(Target *parent, const Core::Id id) const
{
if (!canHandle(parent))
return false;
return availableCreationIds(parent).contains(id);
}
bool QmakeAndroidRunConfigurationFactory::canRestore(Target *parent, const QVariantMap &map) const
{
return canCreate(parent, ProjectExplorer::idFromMap(map));
}
bool QmakeAndroidRunConfigurationFactory::canClone(Target *parent, RunConfiguration *source) const
{
return canCreate(parent, source->id());
}
QList<Core::Id> QmakeAndroidRunConfigurationFactory::availableCreationIds(Target *parent, CreationMode mode) const
{
if (!canHandle(parent))
return QList<Core::Id>();
QmakeProject *project = static_cast<QmakeProject *>(parent->project());
QList<QmakeProFileNode *> nodes = project->allProFiles(QList<QmakeProjectType>()
<< ApplicationTemplate
<< LibraryTemplate);
if (mode == AutoCreate)
nodes = QmakeProject::nodesWithQtcRunnable(nodes);
const Core::Id base = Core::Id(ANDROID_RC_ID_PREFIX);
return QmakeProject::idsForNodes(base, nodes);
}
RunConfiguration *QmakeAndroidRunConfigurationFactory::doCreate(Target *parent, const Core::Id id)
{
if (parent->project()->rootProjectNode())
return new QmakeAndroidRunConfiguration(parent, id, parent->project()->rootProjectNode()->path());
return new QmakeAndroidRunConfiguration(parent, id);
}
RunConfiguration *QmakeAndroidRunConfigurationFactory::doRestore(Target *parent,
const QVariantMap &map)
{
Core::Id id = ProjectExplorer::idFromMap(map);
if (parent->project()->rootProjectNode())
return new QmakeAndroidRunConfiguration(parent, id, parent->project()->rootProjectNode()->path());
return new QmakeAndroidRunConfiguration(parent, id);
}
RunConfiguration *QmakeAndroidRunConfigurationFactory::clone(Target *parent, RunConfiguration *source)
{
if (!canClone(parent, source))
return 0;
QmakeAndroidRunConfiguration *old = static_cast<QmakeAndroidRunConfiguration *>(source);
return new QmakeAndroidRunConfiguration(parent, old);
}
bool QmakeAndroidRunConfigurationFactory::canHandle(Target *t) const
{
return t->project()->supportsKit(t->kit())
&& AndroidManager::supportsAndroid(t)
&& qobject_cast<QmakeProject *>(t->project());
}
#warning FIX ME !!!
QList<RunConfiguration *> QmakeAndroidRunConfigurationFactory::runConfigurationsForNode(Target *t, ProjectExplorer::Node *n)
{
QList<ProjectExplorer::RunConfiguration *> result;
foreach (ProjectExplorer::RunConfiguration *rc, t->runConfigurations())
if (QmakeAndroidRunConfiguration *qt4c = qobject_cast<QmakeAndroidRunConfiguration *>(rc))
if (qt4c->proFilePath() == n->path())
result << rc;
return result;
}
} // namespace Internal
} // namespace Android

View File

@@ -1,78 +0,0 @@
/**************************************************************************
**
** 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 QMAKE_ANDROIDRUNFACTORIES_H
#define QMAKE_ANDROIDRUNFACTORIES_H
#include <android/androidrunfactories.h>
#include <projectexplorer/runconfiguration.h>
#include <qmakeprojectmanager/qmakerunconfigurationfactory.h>
namespace ProjectExplorer {
class RunControl;
class RunConfigWidget;
class Target;
class Node;
} // namespace ProjectExplorer
namespace Android {
namespace Internal {
class QmakeAndroidRunConfigurationFactory : public ProjectExplorer::IRunConfigurationFactory
{
Q_OBJECT
public:
explicit QmakeAndroidRunConfigurationFactory(QObject *parent = 0);
QString displayNameForId(const Core::Id id) const;
QList<Core::Id> availableCreationIds(ProjectExplorer::Target *parent, CreationMode mode = UserCreate) const;
bool canCreate(ProjectExplorer::Target *parent, const Core::Id id) const;
bool canRestore(ProjectExplorer::Target *parent, const QVariantMap &map) const;
bool canClone(ProjectExplorer::Target *parent, ProjectExplorer::RunConfiguration *source) const;
ProjectExplorer::RunConfiguration *clone(ProjectExplorer::Target *parent, ProjectExplorer::RunConfiguration *source);
QList<ProjectExplorer::RunConfiguration *> runConfigurationsForNode(ProjectExplorer::Target *t,
ProjectExplorer::Node *n);
private:
bool canHandle(ProjectExplorer::Target *t) const;
ProjectExplorer::RunConfiguration *doCreate(ProjectExplorer::Target *parent, const Core::Id id);
ProjectExplorer::RunConfiguration *doRestore(ProjectExplorer::Target *parent,
const QVariantMap &map);
};
} // namespace Internal
} // namespace Android
#endif // ANDROIDRUNFACTORIES_H

View File

@@ -1,75 +0,0 @@
/**************************************************************************
**
** 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 "qmakeandroidsupport.h"
#include "androidconstants.h"
#include "androidpackageinstallationstep.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>
#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
namespace Android {
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;
}
} // namespace Internal
} // namespace Android

View File

@@ -1,49 +0,0 @@
/**************************************************************************
**
** 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 QMAKEANDROIDSUPPORT_H
#define QMAKEANDROIDSUPPORT_H
#include "androidqtsupport.h"
namespace Android {
namespace Internal {
class QmakeAndroidSupport : public Android::AndroidQtSupport
{
Q_OBJECT
public:
bool canHandle(const ProjectExplorer::Target *target) const;
QStringList soLibSearchPath(const ProjectExplorer::Target *target) const;
};
} // namespace Internal
} // namespace Android
#endif // QMAKEANDROIDSUPPORT_H