forked from qt-creator/qt-creator
Android: Remove Necessitas support
Change-Id: I082acfad3b20d5e096fbb2ca3db775bb527eaf7a Reviewed-by: BogDan Vatra <bogdan@kde.org>
This commit is contained in:
committed by
Daniel Teske
parent
c4451570e7
commit
381b04fa04
@@ -17,12 +17,6 @@ HEADERS += \
|
||||
androidtoolchain.h \
|
||||
androidpackageinstallationstep.h \
|
||||
androidpackageinstallationfactory.h \
|
||||
androidpackagecreationstep.h \
|
||||
androidpackagecreationfactory.h \
|
||||
androidpackagecreationwidget.h \
|
||||
androiddeploystep.h \
|
||||
androiddeploystepwidget.h \
|
||||
androiddeploystepfactory.h \
|
||||
androiderrormessage.h \
|
||||
androidglobal.h \
|
||||
androidrunner.h \
|
||||
@@ -69,12 +63,6 @@ SOURCES += \
|
||||
androidtoolchain.cpp \
|
||||
androidpackageinstallationstep.cpp \
|
||||
androidpackageinstallationfactory.cpp \
|
||||
androidpackagecreationstep.cpp \
|
||||
androidpackagecreationfactory.cpp \
|
||||
androidpackagecreationwidget.cpp \
|
||||
androiddeploystep.cpp \
|
||||
androiddeploystepwidget.cpp \
|
||||
androiddeploystepfactory.cpp \
|
||||
androiderrormessage.cpp \
|
||||
androidrunner.cpp \
|
||||
androiddebugsupport.cpp \
|
||||
@@ -111,8 +99,6 @@ SOURCES += \
|
||||
|
||||
FORMS += \
|
||||
androidsettingswidget.ui \
|
||||
androidpackagecreationwidget.ui \
|
||||
androiddeploystepwidget.ui \
|
||||
addnewavddialog.ui \
|
||||
androidcreatekeystorecertificate.ui \
|
||||
androiddevicedialog.ui \
|
||||
|
||||
@@ -39,13 +39,6 @@ QtcPlugin {
|
||||
"androiddevicedialog.ui",
|
||||
"androiddeployconfiguration.cpp",
|
||||
"androiddeployconfiguration.h",
|
||||
"androiddeploystep.cpp",
|
||||
"androiddeploystep.h",
|
||||
"androiddeploystepfactory.cpp",
|
||||
"androiddeploystepfactory.h",
|
||||
"androiddeploystepwidget.cpp",
|
||||
"androiddeploystepwidget.h",
|
||||
"androiddeploystepwidget.ui",
|
||||
"androiddeployqtwidget.cpp",
|
||||
"androiddeployqtwidget.h",
|
||||
"androiddeployqtwidget.ui",
|
||||
@@ -70,13 +63,6 @@ QtcPlugin {
|
||||
"androidmanifesteditorfactory.h",
|
||||
"androidmanifesteditorwidget.cpp",
|
||||
"androidmanifesteditorwidget.h",
|
||||
"androidpackagecreationfactory.cpp",
|
||||
"androidpackagecreationfactory.h",
|
||||
"androidpackagecreationstep.cpp",
|
||||
"androidpackagecreationstep.h",
|
||||
"androidpackagecreationwidget.cpp",
|
||||
"androidpackagecreationwidget.h",
|
||||
"androidpackagecreationwidget.ui",
|
||||
"androidpackageinstallationfactory.cpp",
|
||||
"androidpackageinstallationfactory.h",
|
||||
"androidpackageinstallationstep.cpp",
|
||||
|
||||
@@ -844,7 +844,7 @@ QString AndroidConfig::bestNdkPlatformMatch(const QString &targetAPI) const
|
||||
if (apiLevel <= target)
|
||||
return QString::fromLatin1("android-%1").arg(apiLevel);
|
||||
}
|
||||
return QLatin1String("android-8");
|
||||
return QLatin1String("android-9");
|
||||
}
|
||||
|
||||
FileName AndroidConfig::sdkLocation() const
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
|
||||
#include "androiddebugsupport.h"
|
||||
|
||||
#include "androiddeploystep.h"
|
||||
#include "androidglobal.h"
|
||||
#include "androidrunner.h"
|
||||
#include "androidmanager.h"
|
||||
|
||||
@@ -29,9 +29,7 @@
|
||||
|
||||
#include "androiddeployconfiguration.h"
|
||||
#include "androidconstants.h"
|
||||
#include "androiddeploystep.h"
|
||||
#include "androidpackageinstallationstep.h"
|
||||
#include "androidpackagecreationstep.h"
|
||||
#include "androiddeployqtstep.h"
|
||||
#include "androidmanager.h"
|
||||
|
||||
@@ -76,14 +74,8 @@ DeployConfiguration *AndroidDeployConfigurationFactory::create(Target *parent, C
|
||||
{
|
||||
AndroidDeployConfiguration *dc = new AndroidDeployConfiguration(parent, id);
|
||||
|
||||
if (id == ANDROID_DEPLOYCONFIGURATION_ID) {
|
||||
dc->stepList()->insertStep(0, new AndroidPackageInstallationStep(AndroidPackageInstallationStep::ProjectDirectory, dc->stepList()));
|
||||
dc->stepList()->insertStep(1, new AndroidPackageCreationStep(dc->stepList()));
|
||||
dc->stepList()->insertStep(2, new AndroidDeployStep(dc->stepList()));
|
||||
} else {
|
||||
dc->stepList()->insertStep(0, new AndroidPackageInstallationStep(AndroidPackageInstallationStep::BuildDirectory, dc->stepList()));
|
||||
dc->stepList()->insertStep(1, new AndroidDeployQtStep(dc->stepList()));
|
||||
}
|
||||
dc->stepList()->insertStep(0, new AndroidPackageInstallationStep(AndroidPackageInstallationStep::BuildDirectory, dc->stepList()));
|
||||
dc->stepList()->insertStep(1, new AndroidDeployQtStep(dc->stepList()));
|
||||
return dc;
|
||||
}
|
||||
|
||||
@@ -136,17 +128,13 @@ QList<Core::Id> AndroidDeployConfigurationFactory::availableCreationIds(Target *
|
||||
QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(parent->kit());
|
||||
if (qt->type() != QLatin1String(Constants::ANDROIDQT))
|
||||
return ids;
|
||||
if (qt->qtVersion() < QtSupport::QtVersionNumber(5, 2, 0))
|
||||
ids << Core::Id(ANDROID_DEPLOYCONFIGURATION_ID);
|
||||
else
|
||||
ids << Core::Id(ANDROID_DEPLOYCONFIGURATION2_ID);
|
||||
ids << Core::Id(ANDROID_DEPLOYCONFIGURATION_ID);
|
||||
return ids;
|
||||
}
|
||||
|
||||
QString AndroidDeployConfigurationFactory::displayNameForId(Core::Id id) const
|
||||
{
|
||||
if (id.name().startsWith(ANDROID_DC_PREFIX)
|
||||
|| id.name().startsWith(ANDROID_DC2_PREFIX))
|
||||
if (id.name().startsWith(ANDROID_DC_PREFIX))
|
||||
return tr("Deploy on Android");
|
||||
return QString();
|
||||
}
|
||||
|
||||
@@ -35,12 +35,9 @@
|
||||
namespace Android {
|
||||
namespace Internal {
|
||||
|
||||
const char ANDROID_DEPLOYCONFIGURATION_ID[] = "Qt4ProjectManager.AndroidDeployConfiguration";
|
||||
const char ANDROID_DC_PREFIX[] = "Qt4ProjectManager.AndroidDeployConfiguration.";
|
||||
|
||||
// Qt 5.2 has a new form of deployment
|
||||
const char ANDROID_DEPLOYCONFIGURATION2_ID[] = "Qt4ProjectManager.AndroidDeployConfiguration2";
|
||||
const char ANDROID_DC2_PREFIX[] = "Qt4ProjectManager.AndroidDeployConfiguration2.";
|
||||
const char ANDROID_DEPLOYCONFIGURATION_ID[] = "Qt4ProjectManager.AndroidDeployConfiguration2";
|
||||
const char ANDROID_DC_PREFIX[] = "Qt4ProjectManager.AndroidDeployConfiguration2.";
|
||||
|
||||
class AndroidDeployConfiguration : public ProjectExplorer::DeployConfiguration
|
||||
{
|
||||
|
||||
@@ -81,9 +81,6 @@ QList<Core::Id> AndroidDeployQtStepFactory::availableCreationIds(ProjectExplorer
|
||||
return QList<Core::Id>();
|
||||
if (parent->contains(AndroidDeployQtStep::Id))
|
||||
return QList<Core::Id>();
|
||||
QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(parent->target()->kit());
|
||||
if (!qtVersion || qtVersion->qtVersion() < QtSupport::QtVersionNumber(5, 2, 0))
|
||||
return QList<Core::Id>();
|
||||
return QList<Core::Id>() << AndroidDeployQtStep::Id;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,501 +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 "androiddeploystep.h"
|
||||
|
||||
#include "androidconstants.h"
|
||||
#include "androiddeploystepwidget.h"
|
||||
#include "androidglobal.h"
|
||||
#include "androidpackagecreationstep.h"
|
||||
#include "androidrunconfiguration.h"
|
||||
#include "androidmanager.h"
|
||||
#include "androidtoolchain.h"
|
||||
#include "androiddevicedialog.h"
|
||||
|
||||
#include <coreplugin/messagemanager.h>
|
||||
#include <projectexplorer/buildconfiguration.h>
|
||||
#include <projectexplorer/deployconfiguration.h>
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
#include <projectexplorer/buildsteplist.h>
|
||||
#include <projectexplorer/target.h>
|
||||
#include <qmakeprojectmanager/qmakebuildconfiguration.h>
|
||||
#include <qmakeprojectmanager/qmakeproject.h>
|
||||
#include <qmakeprojectmanager/qmakenodes.h>
|
||||
|
||||
#include <qtsupport/qtkitinformation.h>
|
||||
|
||||
#include <QDir>
|
||||
|
||||
#define ASSERT_STATE(state) ASSERT_STATE_GENERIC(State, state, m_state)
|
||||
|
||||
using namespace Core;
|
||||
using namespace ProjectExplorer;
|
||||
using namespace QmakeProjectManager;
|
||||
|
||||
namespace Android {
|
||||
namespace Internal {
|
||||
|
||||
static const char USE_LOCAL_QT_KEY[] = "Qt4ProjectManager.AndroidDeployStep.UseLocalQtLibs";
|
||||
static const char DEPLOY_ACTION_KEY[] = "Qt4ProjectManager.AndroidDeployStep.DeployAction";
|
||||
|
||||
const Id AndroidDeployStep::Id("Qt4ProjectManager.AndroidDeployStep");
|
||||
|
||||
AndroidDeployStep::AndroidDeployStep(ProjectExplorer::BuildStepList *parent)
|
||||
: BuildStep(parent, Id)
|
||||
{
|
||||
ctor();
|
||||
}
|
||||
|
||||
AndroidDeployStep::AndroidDeployStep(ProjectExplorer::BuildStepList *parent,
|
||||
AndroidDeployStep *other)
|
||||
: BuildStep(parent, other)
|
||||
{
|
||||
ctor();
|
||||
}
|
||||
|
||||
AndroidDeployStep::~AndroidDeployStep() { }
|
||||
|
||||
void AndroidDeployStep::ctor()
|
||||
{
|
||||
//: AndroidDeployStep default display name
|
||||
setDefaultDisplayName(tr("Deploy to Android device"));
|
||||
m_deployAction = NoDeploy;
|
||||
|
||||
QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(target()->kit());
|
||||
m_bundleQtAvailable = qt && qt->qtVersion() >= QtSupport::QtVersionNumber(5, 0, 0);
|
||||
if (m_bundleQtAvailable)
|
||||
m_deployAction = BundleLibraries;
|
||||
|
||||
|
||||
connect(ProjectExplorer::KitManager::instance(), SIGNAL(kitUpdated(ProjectExplorer::Kit*)),
|
||||
this, SLOT(kitUpdated(ProjectExplorer::Kit*)));
|
||||
}
|
||||
|
||||
bool AndroidDeployStep::init()
|
||||
{
|
||||
m_packageName = AndroidManager::packageName(target());
|
||||
m_deviceAPILevel = AndroidManager::minimumSDK(target());
|
||||
m_targetArch = AndroidManager::targetArch(target());
|
||||
|
||||
AndroidDeviceInfo info = AndroidConfigurations::showDeviceDialog(project(), m_deviceAPILevel, m_targetArch);
|
||||
if (info.serialNumber.isEmpty()) // aborted
|
||||
return false;
|
||||
|
||||
m_deviceAPILevel = info.sdk;
|
||||
m_deviceSerialNumber = info.serialNumber;
|
||||
|
||||
if (info.type == AndroidDeviceInfo::Emulator)
|
||||
m_avdName = m_deviceSerialNumber;
|
||||
|
||||
QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target()->kit());
|
||||
if (!version)
|
||||
return false;
|
||||
|
||||
const QmakeBuildConfiguration *bc = static_cast<QmakeBuildConfiguration *>(target()->activeBuildConfiguration());
|
||||
if (!bc)
|
||||
return false;
|
||||
|
||||
m_signPackage = false;
|
||||
// find AndroidPackageCreationStep
|
||||
foreach (BuildStep *step, target()->activeDeployConfiguration()->stepList()->steps()) {
|
||||
if (AndroidPackageCreationStep *apcs = qobject_cast<AndroidPackageCreationStep *>(step)) {
|
||||
m_signPackage = apcs->signPackage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_qtVersionSourcePath = version->qmakeProperty("QT_INSTALL_PREFIX");
|
||||
m_androidDirPath = AndroidManager::dirPath(target());
|
||||
m_apkPathDebug = AndroidManager::apkPath(target(), AndroidManager::DebugBuild).toString();
|
||||
m_apkPathRelease = AndroidManager::apkPath(target(), AndroidManager::ReleaseBuildSigned).toString();
|
||||
m_buildDirectory = static_cast<QmakeProject *>(target()->project())->rootQmakeProjectNode()->buildDir();
|
||||
m_runDeployAction = m_deployAction;
|
||||
ToolChain *tc = ToolChainKitInformation::toolChain(target()->kit());
|
||||
if (!tc || tc->type() != QLatin1String(Constants::ANDROID_TOOLCHAIN_TYPE)) {
|
||||
raiseError(tr("No Android toolchain selected."));
|
||||
return false;
|
||||
}
|
||||
m_ndkToolChainVersion = static_cast<AndroidToolChain *>(tc)->ndkToolChainVersion();
|
||||
|
||||
QString arch = static_cast<QmakeProject *>(project())->rootQmakeProjectNode()->singleVariableValue(QmakeProjectManager::AndroidArchVar);
|
||||
if (!arch.isEmpty())
|
||||
m_libgnustl = AndroidManager::libGnuStl(arch, m_ndkToolChainVersion);
|
||||
return true;
|
||||
}
|
||||
|
||||
void AndroidDeployStep::run(QFutureInterface<bool> &fi)
|
||||
{
|
||||
fi.reportResult(deployPackage());
|
||||
}
|
||||
|
||||
BuildStepConfigWidget *AndroidDeployStep::createConfigWidget()
|
||||
{
|
||||
return new AndroidDeployStepWidget(this);
|
||||
}
|
||||
|
||||
AndroidDeployStep::AndroidDeployAction AndroidDeployStep::deployAction()
|
||||
{
|
||||
return m_deployAction;
|
||||
}
|
||||
|
||||
bool AndroidDeployStep::fromMap(const QVariantMap &map)
|
||||
{
|
||||
m_deployAction = AndroidDeployAction(map.value(QLatin1String(DEPLOY_ACTION_KEY), NoDeploy).toInt());
|
||||
QVariant useLocalQt = map.value(QLatin1String(USE_LOCAL_QT_KEY));
|
||||
if (useLocalQt.isValid()) { // old settings
|
||||
if (useLocalQt.toBool() && m_deployAction == NoDeploy)
|
||||
m_deployAction = BundleLibraries;
|
||||
}
|
||||
|
||||
if (m_deployAction == InstallQASI)
|
||||
m_deployAction = NoDeploy;
|
||||
QtSupport::BaseQtVersion *qtVersion
|
||||
= QtSupport::QtKitInformation::qtVersion(target()->kit());
|
||||
if (m_deployAction == BundleLibraries)
|
||||
if (!qtVersion || qtVersion->qtVersion() < QtSupport::QtVersionNumber(5, 0, 0))
|
||||
m_deployAction = NoDeploy; // the kit changed to a non qt5 kit
|
||||
|
||||
m_bundleQtAvailable = qtVersion && qtVersion->qtVersion() >= QtSupport::QtVersionNumber(5, 0, 0);
|
||||
|
||||
return ProjectExplorer::BuildStep::fromMap(map);
|
||||
}
|
||||
|
||||
QVariantMap AndroidDeployStep::toMap() const
|
||||
{
|
||||
QVariantMap map = ProjectExplorer::BuildStep::toMap();
|
||||
map.insert(QLatin1String(DEPLOY_ACTION_KEY), m_deployAction);
|
||||
return map;
|
||||
}
|
||||
|
||||
void AndroidDeployStep::kitUpdated(Kit *kit)
|
||||
{
|
||||
if (kit != target()->kit())
|
||||
return;
|
||||
QtSupport::BaseQtVersion *qtVersion
|
||||
= QtSupport::QtKitInformation::qtVersion(target()->kit());
|
||||
|
||||
bool newBundleQtAvailable = qtVersion && qtVersion->qtVersion() >= QtSupport::QtVersionNumber(5, 0, 0);
|
||||
if (m_bundleQtAvailable != newBundleQtAvailable) {
|
||||
m_bundleQtAvailable = newBundleQtAvailable;
|
||||
|
||||
if (!m_bundleQtAvailable && m_deployAction == BundleLibraries)
|
||||
m_deployAction = NoDeploy; // the kit changed to a non qt5 kit
|
||||
|
||||
emit deployOptionsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool AndroidDeployStep::bundleQtOptionAvailable()
|
||||
{
|
||||
return m_bundleQtAvailable;
|
||||
}
|
||||
|
||||
void AndroidDeployStep::setDeployAction(AndroidDeployStep::AndroidDeployAction deploy)
|
||||
{
|
||||
m_deployAction = deploy;
|
||||
|
||||
AndroidManager::updateDeploymentSettings(target());
|
||||
}
|
||||
|
||||
bool AndroidDeployStep::runCommand(QProcess *buildProc,
|
||||
const QString &program, const QStringList &arguments)
|
||||
{
|
||||
writeOutput(tr("Package deploy: Running command '%1 %2'.").arg(program).arg(arguments.join(QLatin1String(" "))), BuildStep::MessageOutput);
|
||||
buildProc->start(program, arguments);
|
||||
if (!buildProc->waitForStarted()) {
|
||||
writeOutput(tr("Packaging error: Could not start command '%1 %2'. Reason: %3")
|
||||
.arg(program).arg(arguments.join(QLatin1String(" "))).arg(buildProc->errorString()), BuildStep::ErrorMessageOutput);
|
||||
return false;
|
||||
}
|
||||
if (!buildProc->waitForFinished(2 * 60 * 1000)
|
||||
|| buildProc->error() != QProcess::UnknownError
|
||||
|| buildProc->exitCode() != 0) {
|
||||
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());
|
||||
else
|
||||
mainMessage += tr("Exit code: %1").arg(buildProc->exitCode());
|
||||
writeOutput(mainMessage, BuildStep::ErrorMessageOutput);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void AndroidDeployStep::handleBuildOutput()
|
||||
{
|
||||
QProcess *const buildProc = qobject_cast<QProcess *>(sender());
|
||||
if (!buildProc)
|
||||
return;
|
||||
emit addOutput(QString::fromLocal8Bit(buildProc->readAllStandardOutput())
|
||||
, BuildStep::NormalOutput);
|
||||
}
|
||||
|
||||
void AndroidDeployStep::handleBuildError()
|
||||
{
|
||||
QProcess *const buildProc = qobject_cast<QProcess *>(sender());
|
||||
if (!buildProc)
|
||||
return;
|
||||
emit addOutput(QString::fromLocal8Bit(buildProc->readAllStandardError())
|
||||
, BuildStep::ErrorOutput);
|
||||
}
|
||||
|
||||
QString AndroidDeployStep::deviceSerialNumber()
|
||||
{
|
||||
return m_deviceSerialNumber;
|
||||
}
|
||||
|
||||
unsigned int AndroidDeployStep::remoteModificationTime(const QString &fullDestination, QHash<QString, unsigned int> *cache)
|
||||
{
|
||||
QString destination = QFileInfo(fullDestination).absolutePath();
|
||||
QProcess process;
|
||||
QHash<QString, unsigned int>::const_iterator it = cache->find(fullDestination);
|
||||
if (it != cache->constEnd())
|
||||
return *it;
|
||||
QStringList arguments = AndroidDeviceInfo::adbSelector(m_deviceSerialNumber);
|
||||
arguments << QLatin1String("ls") << destination;
|
||||
process.start(AndroidConfigurations::currentConfig().adbToolPath().toString(), arguments);
|
||||
if (!process.waitForFinished(10000)
|
||||
|| process.exitCode() != 0)
|
||||
return 0;
|
||||
QByteArray output = process.readAll();
|
||||
output.replace("\r\n", "\n");
|
||||
QList<QByteArray> lines = output.split('\n');
|
||||
foreach (const QByteArray &line, lines) {
|
||||
// do some checks if we got what we expected..
|
||||
if (line.count() < (3 * 8 + 3))
|
||||
continue;
|
||||
if (line.at(8) != ' '
|
||||
|| line.at(17) != ' '
|
||||
|| line.at(26) != ' ')
|
||||
continue;
|
||||
bool ok;
|
||||
int time = line.mid(18, 8).toUInt(&ok, 16);
|
||||
if (!ok)
|
||||
continue;
|
||||
QString fileName = QString::fromLocal8Bit(line.mid(27));
|
||||
cache->insert(destination + QLatin1Char('/') + fileName, time);
|
||||
}
|
||||
it = cache->find(fullDestination);
|
||||
if (it != cache->constEnd())
|
||||
return *it;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AndroidDeployStep::collectFiles(QList<DeployItem> *deployList, const QString &localPath, const QString &remotePath,
|
||||
bool strip, const QStringList &filter)
|
||||
{
|
||||
QDirIterator libsIt(localPath, filter, QDir::NoFilter, QDirIterator::Subdirectories);
|
||||
int pos = localPath.size();
|
||||
while (libsIt.hasNext()) {
|
||||
libsIt.next();
|
||||
const QString destFile(remotePath + libsIt.filePath().mid(pos));
|
||||
if (!libsIt.fileInfo().isDir()) {
|
||||
deployList->append(DeployItem(libsIt.filePath(),
|
||||
libsIt.fileInfo().lastModified().toTime_t(),
|
||||
destFile, strip));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AndroidDeployStep::fetchRemoteModificationTimes(QList<DeployItem> *deployList)
|
||||
{
|
||||
QHash<QString, unsigned int> cache;
|
||||
for (int i = 0; i < deployList->count(); ++i) {
|
||||
DeployItem &item = (*deployList)[i];
|
||||
item.remoteTimeStamp
|
||||
= remoteModificationTime(item.remoteFileName, &cache);
|
||||
}
|
||||
}
|
||||
|
||||
void AndroidDeployStep::filterModificationTimes(QList<DeployItem> *deployList)
|
||||
{
|
||||
QList<DeployItem>::iterator it = deployList->begin();
|
||||
while (it != deployList->end()) {
|
||||
int index = it - deployList->begin();
|
||||
Q_UNUSED(index);
|
||||
if ((*it).localTimeStamp <= (*it).remoteTimeStamp)
|
||||
it = deployList->erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void AndroidDeployStep::copyFilesToTemp(QList<DeployItem> *deployList, const QString &tempDirectory, const QString &sourcePrefix)
|
||||
{
|
||||
QDir dir;
|
||||
|
||||
int pos = sourcePrefix.size();
|
||||
for (int i = 0; i < deployList->count(); ++i) {
|
||||
DeployItem &item = (*deployList)[i];
|
||||
if (!item.needsStrip)
|
||||
continue;
|
||||
const QString destFile(tempDirectory + item.localFileName.mid(pos));
|
||||
dir.mkpath(QFileInfo(destFile).absolutePath());
|
||||
QFile::copy(item.localFileName, destFile);
|
||||
item.localFileName = destFile;
|
||||
}
|
||||
}
|
||||
|
||||
void AndroidDeployStep::stripFiles(const QList<DeployItem> &deployList, Abi::Architecture architecture, const QString &ndkToolchainVersion)
|
||||
{
|
||||
QProcess stripProcess;
|
||||
foreach (const DeployItem &item, deployList) {
|
||||
stripProcess.start(AndroidConfigurations::currentConfig().stripPath(architecture, ndkToolchainVersion).toString(),
|
||||
QStringList()<<QLatin1String("--strip-unneeded") << item.localFileName);
|
||||
stripProcess.waitForStarted();
|
||||
if (!stripProcess.waitForFinished())
|
||||
stripProcess.kill();
|
||||
}
|
||||
}
|
||||
|
||||
void AndroidDeployStep::deployFiles(QProcess *process, const QList<DeployItem> &deployList)
|
||||
{
|
||||
foreach (const DeployItem &item, deployList) {
|
||||
runCommand(process, AndroidConfigurations::currentConfig().adbToolPath().toString(),
|
||||
AndroidDeviceInfo::adbSelector(m_deviceSerialNumber)
|
||||
<< QLatin1String("push") << item.localFileName
|
||||
<< item.remoteFileName);
|
||||
}
|
||||
}
|
||||
|
||||
bool AndroidDeployStep::deployPackage()
|
||||
{
|
||||
if (!m_avdName.isEmpty()) {
|
||||
if (AndroidConfigurations::currentConfig().findAvd(m_deviceAPILevel, m_targetArch).isEmpty()
|
||||
&& !AndroidConfigurations::currentConfig().startAVDAsync(m_avdName))
|
||||
return false;
|
||||
m_deviceSerialNumber = AndroidConfigurations::currentConfig().waitForAvd(m_deviceAPILevel, m_targetArch);
|
||||
}
|
||||
|
||||
QProcess *const deployProc = new QProcess;
|
||||
connect(deployProc, SIGNAL(readyReadStandardOutput()), this,
|
||||
SLOT(handleBuildOutput()));
|
||||
connect(deployProc, SIGNAL(readyReadStandardError()), this,
|
||||
SLOT(handleBuildError()));
|
||||
|
||||
if (m_runDeployAction == DeployLocal) {
|
||||
writeOutput(tr("Deploy Qt libraries. This may take some time, please wait."));
|
||||
const QString tempPath = QDir::tempPath() + QLatin1String("/android_qt_libs_") + m_packageName;
|
||||
AndroidPackageCreationStep::removeDirectory(tempPath);
|
||||
|
||||
const QString remoteRoot = QLatin1String("/data/local/tmp/qt");
|
||||
QList<DeployItem> deployList;
|
||||
collectFiles(&deployList,
|
||||
m_qtVersionSourcePath + QLatin1String("/lib"),
|
||||
remoteRoot + QLatin1String("/lib"),
|
||||
true,
|
||||
QStringList() << QLatin1String("*.so"));
|
||||
|
||||
// don't use the libgnustl_shared.so from the qt directory
|
||||
for (int i = 0; i < deployList.count(); ++i) {
|
||||
if (deployList.at(i).remoteFileName == QLatin1String("/data/local/tmp/qt/lib/libgnustl_shared.so")) {
|
||||
deployList.removeAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We want to deploy that *always*
|
||||
// since even if the timestamps did not change, the toolchain might have changed
|
||||
// leading to a different file
|
||||
deployList.append(DeployItem(m_libgnustl,
|
||||
QDateTime::currentDateTimeUtc().toTime_t(),
|
||||
QLatin1String("/data/local/tmp/qt/lib/libgnustl_shared.so"), false));
|
||||
|
||||
collectFiles(&deployList,
|
||||
m_qtVersionSourcePath + QLatin1String("/plugins"),
|
||||
remoteRoot + QLatin1String("/plugins"),
|
||||
true);
|
||||
collectFiles(&deployList,
|
||||
m_qtVersionSourcePath + QLatin1String("/imports"),
|
||||
remoteRoot + QLatin1String("/imports"),
|
||||
true);
|
||||
collectFiles(&deployList,
|
||||
m_qtVersionSourcePath + QLatin1String("/qml"),
|
||||
remoteRoot + QLatin1String("/qml"),
|
||||
true);
|
||||
collectFiles(&deployList,
|
||||
m_qtVersionSourcePath + QLatin1String("/jar"),
|
||||
remoteRoot + QLatin1String("/jar"),
|
||||
true);
|
||||
|
||||
fetchRemoteModificationTimes(&deployList);
|
||||
filterModificationTimes(&deployList);
|
||||
copyFilesToTemp(&deployList, tempPath, m_qtVersionSourcePath);
|
||||
stripFiles(deployList, target()->activeRunConfiguration()->abi().architecture(), m_ndkToolChainVersion);
|
||||
deployFiles(deployProc, deployList);
|
||||
|
||||
AndroidPackageCreationStep::removeDirectory(tempPath);
|
||||
}
|
||||
|
||||
deployProc->setWorkingDirectory(m_androidDirPath.toString());
|
||||
|
||||
writeOutput(tr("Installing package onto %1.").arg(m_deviceSerialNumber));
|
||||
runCommand(deployProc, AndroidConfigurations::currentConfig().adbToolPath().toString(),
|
||||
AndroidDeviceInfo::adbSelector(m_deviceSerialNumber) << QLatin1String("uninstall") << m_packageName);
|
||||
QString package = m_apkPathDebug;
|
||||
|
||||
if (m_signPackage && QFile::exists(m_apkPathRelease))
|
||||
package = m_apkPathRelease;
|
||||
|
||||
if (!runCommand(deployProc, AndroidConfigurations::currentConfig().adbToolPath().toString(),
|
||||
AndroidDeviceInfo::adbSelector(m_deviceSerialNumber) << QLatin1String("install") << package)) {
|
||||
raiseError(tr("Package installation failed."));
|
||||
disconnect(deployProc, 0, this, 0);
|
||||
deployProc->deleteLater();
|
||||
return false;
|
||||
}
|
||||
|
||||
writeOutput(tr("Pulling files necessary for debugging."));
|
||||
runCommand(deployProc, AndroidConfigurations::currentConfig().adbToolPath().toString(),
|
||||
AndroidDeviceInfo::adbSelector(m_deviceSerialNumber)
|
||||
<< QLatin1String("pull") << QLatin1String("/system/bin/app_process")
|
||||
<< QString::fromLatin1("%1/app_process").arg(m_buildDirectory));
|
||||
runCommand(deployProc, AndroidConfigurations::currentConfig().adbToolPath().toString(),
|
||||
AndroidDeviceInfo::adbSelector(m_deviceSerialNumber) << QLatin1String("pull")
|
||||
<< QLatin1String("/system/lib/libc.so")
|
||||
<< QString::fromLatin1("%1/libc.so").arg(m_buildDirectory));
|
||||
disconnect(deployProc, 0, this, 0);
|
||||
deployProc->deleteLater();
|
||||
return true;
|
||||
}
|
||||
|
||||
void AndroidDeployStep::raiseError(const QString &errorString)
|
||||
{
|
||||
emit addTask(Task(Task::Error, errorString, Utils::FileName::fromString(QString()), -1,
|
||||
ProjectExplorer::Constants::TASK_CATEGORY_DEPLOYMENT));
|
||||
}
|
||||
|
||||
void AndroidDeployStep::writeOutput(const QString &text, OutputFormat format)
|
||||
{
|
||||
emit addOutput(text, format);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Android
|
||||
@@ -1,161 +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 ANDROIDDEPLOYSTEP_H
|
||||
#define ANDROIDDEPLOYSTEP_H
|
||||
|
||||
#include "androidconfigurations.h"
|
||||
|
||||
#include <projectexplorer/buildstep.h>
|
||||
#include <qtsupport/baseqtversion.h>
|
||||
|
||||
#include <QProcess>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QEventLoop;
|
||||
class QTimer;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Android {
|
||||
namespace Internal {
|
||||
class AndroidDeviceConfigListModel;
|
||||
class AndroidPackageCreationStep;
|
||||
|
||||
class DeployItem
|
||||
{
|
||||
public:
|
||||
DeployItem(const QString &_localFileName,
|
||||
unsigned int _localTimeStamp,
|
||||
const QString &_remoteFileName,
|
||||
bool _needsStrip)
|
||||
: localFileName(_localFileName),
|
||||
remoteFileName(_remoteFileName),
|
||||
localTimeStamp(_localTimeStamp),
|
||||
remoteTimeStamp(0),
|
||||
needsStrip(_needsStrip)
|
||||
{}
|
||||
QString localFileName;
|
||||
QString remoteFileName;
|
||||
unsigned int localTimeStamp;
|
||||
unsigned int remoteTimeStamp;
|
||||
bool needsStrip;
|
||||
};
|
||||
|
||||
class AndroidDeployStep : public ProjectExplorer::BuildStep
|
||||
{
|
||||
Q_OBJECT
|
||||
friend class AndroidDeployStepFactory;
|
||||
|
||||
public:
|
||||
enum AndroidDeployAction
|
||||
{
|
||||
NoDeploy, // use ministro
|
||||
DeployLocal,
|
||||
InstallQASI, // unused old value
|
||||
BundleLibraries
|
||||
};
|
||||
|
||||
public:
|
||||
AndroidDeployStep(ProjectExplorer::BuildStepList *bc);
|
||||
|
||||
virtual ~AndroidDeployStep();
|
||||
|
||||
QString deviceSerialNumber();
|
||||
|
||||
AndroidDeployAction deployAction();
|
||||
|
||||
bool fromMap(const QVariantMap &map);
|
||||
QVariantMap toMap() const;
|
||||
|
||||
bool bundleQtOptionAvailable();
|
||||
|
||||
public slots:
|
||||
void setDeployAction(AndroidDeployAction deploy);
|
||||
|
||||
signals:
|
||||
void done();
|
||||
void error();
|
||||
void deployOptionsChanged();
|
||||
|
||||
private slots:
|
||||
bool deployPackage();
|
||||
void handleBuildOutput();
|
||||
void handleBuildError();
|
||||
void kitUpdated(ProjectExplorer::Kit *kit);
|
||||
|
||||
private:
|
||||
AndroidDeployStep(ProjectExplorer::BuildStepList *bc,
|
||||
AndroidDeployStep *other);
|
||||
virtual bool init();
|
||||
virtual void run(QFutureInterface<bool> &fi);
|
||||
virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
|
||||
virtual bool immutable() const { return true; }
|
||||
|
||||
void ctor();
|
||||
void raiseError(const QString &error);
|
||||
void writeOutput(const QString &text, OutputFormat = MessageOutput);
|
||||
bool runCommand(QProcess *buildProc, const QString &program, const QStringList &arguments);
|
||||
unsigned int remoteModificationTime(const QString &fullDestination,
|
||||
QHash<QString, unsigned int> *cache);
|
||||
void collectFiles(QList<DeployItem> *deployList, const QString &localPath,
|
||||
const QString &remotePath, bool strip, const QStringList &filter = QStringList());
|
||||
void filterModificationTimes(QList<DeployItem> *deployList);
|
||||
void copyFilesToTemp(QList<DeployItem> *deployList, const QString &tempDirectory, const QString &sourcePrefix);
|
||||
void fetchRemoteModificationTimes(QList<DeployItem> *deployList);
|
||||
void stripFiles(const QList<DeployItem> &deployList, ProjectExplorer::Abi::Architecture architecture, const QString &ndkToolchainVersion);
|
||||
void deployFiles(QProcess *process, const QList<DeployItem> &deployList);
|
||||
bool checkForQt51Files();
|
||||
|
||||
private:
|
||||
QString m_deviceSerialNumber;
|
||||
int m_deviceAPILevel;
|
||||
QString m_targetArch;
|
||||
|
||||
AndroidDeployAction m_deployAction;
|
||||
|
||||
// members to transfer data from init() to run
|
||||
QString m_avdName;
|
||||
QString m_packageName;
|
||||
QString m_qtVersionSourcePath;
|
||||
bool m_signPackage;
|
||||
Utils::FileName m_androidDirPath;
|
||||
QString m_apkPathDebug;
|
||||
QString m_apkPathRelease;
|
||||
QString m_buildDirectory;
|
||||
AndroidDeployAction m_runDeployAction;
|
||||
QString m_ndkToolChainVersion;
|
||||
QString m_libgnustl;
|
||||
bool m_bundleQtAvailable;
|
||||
static const Core::Id Id;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Android
|
||||
|
||||
#endif // ANDROIDDEPLOYSTEP_H
|
||||
@@ -1,114 +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 "androiddeploystepfactory.h"
|
||||
|
||||
#include "androiddeploystep.h"
|
||||
#include "androidmanager.h"
|
||||
|
||||
#include <projectexplorer/buildsteplist.h>
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
#include <projectexplorer/target.h>
|
||||
#include <qtsupport/qtsupportconstants.h>
|
||||
#include <qtsupport/qtkitinformation.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
namespace Android {
|
||||
namespace Internal {
|
||||
|
||||
AndroidDeployStepFactory::AndroidDeployStepFactory(QObject *parent)
|
||||
: IBuildStepFactory(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QList<Core::Id> AndroidDeployStepFactory::availableCreationIds(BuildStepList *parent) const
|
||||
{
|
||||
if (parent->id() != ProjectExplorer::Constants::BUILDSTEPS_DEPLOY)
|
||||
return QList<Core::Id>();
|
||||
if (!AndroidManager::supportsAndroid(parent->target()))
|
||||
return QList<Core::Id>();
|
||||
if (parent->contains(AndroidDeployStep::Id))
|
||||
return QList<Core::Id>();
|
||||
QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(parent->target()->kit());
|
||||
if (qtVersion && qtVersion->qtVersion() >= QtSupport::QtVersionNumber(5, 2, 0))
|
||||
return QList<Core::Id>();
|
||||
return QList<Core::Id>() << AndroidDeployStep::Id;
|
||||
}
|
||||
|
||||
QString AndroidDeployStepFactory::displayNameForId(Core::Id id) const
|
||||
{
|
||||
if (id == AndroidDeployStep::Id)
|
||||
return tr("Deploy to Android device or emulator");
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool AndroidDeployStepFactory::canCreate(BuildStepList *parent, Core::Id id) const
|
||||
{
|
||||
return availableCreationIds(parent).contains(id);
|
||||
}
|
||||
|
||||
BuildStep *AndroidDeployStepFactory::create(BuildStepList *parent, Core::Id id)
|
||||
{
|
||||
Q_ASSERT(canCreate(parent, id));
|
||||
Q_UNUSED(id);
|
||||
return new AndroidDeployStep(parent);
|
||||
}
|
||||
|
||||
bool AndroidDeployStepFactory::canRestore(BuildStepList *parent, const QVariantMap &map) const
|
||||
{
|
||||
return canCreate(parent, idFromMap(map));
|
||||
}
|
||||
|
||||
BuildStep *AndroidDeployStepFactory::restore(BuildStepList *parent, const QVariantMap &map)
|
||||
{
|
||||
Q_ASSERT(canRestore(parent, map));
|
||||
AndroidDeployStep * const step = new AndroidDeployStep(parent);
|
||||
if (!step->fromMap(map)) {
|
||||
delete step;
|
||||
return 0;
|
||||
}
|
||||
return step;
|
||||
}
|
||||
|
||||
bool AndroidDeployStepFactory::canClone(BuildStepList *parent, BuildStep *product) const
|
||||
{
|
||||
return canCreate(parent, product->id());
|
||||
}
|
||||
|
||||
BuildStep *AndroidDeployStepFactory::clone(BuildStepList *parent, BuildStep *product)
|
||||
{
|
||||
Q_ASSERT(canClone(parent, product));
|
||||
return new AndroidDeployStep(parent, static_cast<AndroidDeployStep *>(product));
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Android
|
||||
@@ -1,62 +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 ANDROIDDEPLOYSTEPFACTORY_H
|
||||
#define ANDROIDDEPLOYSTEPFACTORY_H
|
||||
|
||||
#include <projectexplorer/buildstep.h>
|
||||
|
||||
namespace Android {
|
||||
namespace Internal {
|
||||
|
||||
class AndroidDeployStepFactory : public ProjectExplorer::IBuildStepFactory
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit AndroidDeployStepFactory(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 // ANDROIDDEPLOYSTEPFACTORY_H
|
||||
@@ -1,136 +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 "androiddeploystepwidget.h"
|
||||
#include "ui_androiddeploystepwidget.h"
|
||||
|
||||
#include "androiddeploystep.h"
|
||||
#include "androidmanager.h"
|
||||
#include "androidrunconfiguration.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
#include <QFileDialog>
|
||||
|
||||
namespace Android {
|
||||
namespace Internal {
|
||||
|
||||
AndroidDeployStepWidget::AndroidDeployStepWidget(AndroidDeployStep *step) :
|
||||
ProjectExplorer::BuildStepConfigWidget(),
|
||||
ui(new Ui::AndroidDeployStepWidget),
|
||||
m_step(step)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
deployOptionsChanged();
|
||||
|
||||
connect(ui->ministroOption, SIGNAL(clicked()), SLOT(setMinistro()));
|
||||
connect(ui->temporaryQtOption, SIGNAL(clicked()), SLOT(setDeployLocalQtLibs()));
|
||||
connect(ui->bundleQtOption, SIGNAL(clicked()), SLOT(setBundleQtLibs()));
|
||||
|
||||
connect(ui->chooseButton, SIGNAL(clicked()), SLOT(setQASIPackagePath()));
|
||||
connect(ui->cleanLibsPushButton, SIGNAL(clicked()), SLOT(cleanLibsOnDevice()));
|
||||
connect(ui->resetDefaultDevices, SIGNAL(clicked()), SLOT(resetDefaultDevices()));
|
||||
|
||||
connect(m_step, SIGNAL(deployOptionsChanged()),
|
||||
this, SLOT(deployOptionsChanged()));
|
||||
}
|
||||
|
||||
void AndroidDeployStepWidget::deployOptionsChanged()
|
||||
{
|
||||
switch (m_step->deployAction()) {
|
||||
case AndroidDeployStep::NoDeploy:
|
||||
ui->ministroOption->setChecked(true);
|
||||
break;
|
||||
case AndroidDeployStep::DeployLocal:
|
||||
ui->temporaryQtOption->setChecked(true);
|
||||
break;
|
||||
case AndroidDeployStep::BundleLibraries:
|
||||
ui->bundleQtOption->setChecked(true);
|
||||
break;
|
||||
default:
|
||||
ui->ministroOption->setChecked(true);
|
||||
break;
|
||||
}
|
||||
|
||||
ui->bundleQtOption->setVisible(m_step->bundleQtOptionAvailable());
|
||||
}
|
||||
|
||||
AndroidDeployStepWidget::~AndroidDeployStepWidget()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
QString AndroidDeployStepWidget::displayName() const
|
||||
{
|
||||
return tr("<b>Deploy configurations</b>");
|
||||
}
|
||||
|
||||
QString AndroidDeployStepWidget::summaryText() const
|
||||
{
|
||||
return displayName();
|
||||
}
|
||||
|
||||
void AndroidDeployStepWidget::setMinistro()
|
||||
{
|
||||
m_step->setDeployAction(AndroidDeployStep::NoDeploy);
|
||||
}
|
||||
|
||||
void AndroidDeployStepWidget::setDeployLocalQtLibs()
|
||||
{
|
||||
m_step->setDeployAction(AndroidDeployStep::DeployLocal);
|
||||
}
|
||||
|
||||
void AndroidDeployStepWidget::setBundleQtLibs()
|
||||
{
|
||||
m_step->setDeployAction(AndroidDeployStep::BundleLibraries);
|
||||
}
|
||||
|
||||
void AndroidDeployStepWidget::setQASIPackagePath()
|
||||
{
|
||||
QString packagePath =
|
||||
QFileDialog::getOpenFileName(this, tr("Qt Android Smart Installer"),
|
||||
QDir::homePath(), tr("Android package (*.apk)"));
|
||||
if (!packagePath.isEmpty())
|
||||
AndroidManager::installQASIPackage(m_step->target(), packagePath);
|
||||
}
|
||||
|
||||
|
||||
void AndroidDeployStepWidget::cleanLibsOnDevice()
|
||||
{
|
||||
AndroidManager::cleanLibsOnDevice(m_step->target());
|
||||
}
|
||||
|
||||
void AndroidDeployStepWidget::resetDefaultDevices()
|
||||
{
|
||||
AndroidConfigurations::clearDefaultDevices(m_step->project());
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Android
|
||||
@@ -1,72 +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 ANDROIDDEPLOYSTEPWIDGET_H
|
||||
#define ANDROIDDEPLOYSTEPWIDGET_H
|
||||
|
||||
#include <projectexplorer/buildstep.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui { class AndroidDeployStepWidget; }
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Android {
|
||||
namespace Internal {
|
||||
class AndroidDeployStep;
|
||||
|
||||
class AndroidDeployStepWidget : public ProjectExplorer::BuildStepConfigWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AndroidDeployStepWidget(AndroidDeployStep *step);
|
||||
~AndroidDeployStepWidget();
|
||||
|
||||
private slots:
|
||||
void setMinistro();
|
||||
void setDeployLocalQtLibs();
|
||||
void setBundleQtLibs();
|
||||
|
||||
void setQASIPackagePath();
|
||||
void cleanLibsOnDevice();
|
||||
void resetDefaultDevices();
|
||||
|
||||
void deployOptionsChanged();
|
||||
private:
|
||||
virtual QString summaryText() const;
|
||||
virtual QString displayName() const;
|
||||
|
||||
Ui::AndroidDeployStepWidget *ui;
|
||||
AndroidDeployStep *m_step;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Android
|
||||
|
||||
#endif // ANDROIDDEPLOYSTEPWIDGET_H
|
||||
@@ -1,113 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AndroidDeployStepWidget</class>
|
||||
<widget class="QWidget" name="AndroidDeployStepWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>682</width>
|
||||
<height>183</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<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="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>
|
||||
<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>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Advanced Actions</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QPushButton" name="cleanLibsPushButton">
|
||||
<property name="text">
|
||||
<string>Clean Temporary Libraries Directory on Device</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QPushButton" name="chooseButton">
|
||||
<property name="text">
|
||||
<string>Install Ministro from APK</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<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>
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="resetDefaultDevices">
|
||||
<property name="text">
|
||||
<string>Reset Default Devices</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -31,9 +31,7 @@
|
||||
#include "androiddeployconfiguration.h"
|
||||
#include "androidconfigurations.h"
|
||||
#include "androidrunconfiguration.h"
|
||||
#include "androiddeploystep.h"
|
||||
#include "androidglobal.h"
|
||||
#include "androidpackagecreationstep.h"
|
||||
#include "androidtoolchain.h"
|
||||
#include "androiddeployqtstep.h"
|
||||
|
||||
@@ -66,62 +64,6 @@ namespace {
|
||||
const QLatin1String AndroidLibsFileName("/res/values/libs.xml");
|
||||
const QLatin1String AndroidStringsFileName("/res/values/strings.xml");
|
||||
const QLatin1String AndroidDefaultPropertiesName("project.properties");
|
||||
const QLatin1String AndroidLibraryPrefix("--Managed_by_Qt_Creator--");
|
||||
|
||||
QString cleanPackageName(QString packageName)
|
||||
{
|
||||
QRegExp legalChars(QLatin1String("[a-zA-Z0-9_\\.]"));
|
||||
|
||||
for (int i = 0; i < packageName.length(); ++i)
|
||||
if (!legalChars.exactMatch(packageName.mid(i, 1)))
|
||||
packageName[i] = QLatin1Char('_');
|
||||
|
||||
static QStringList keywords;
|
||||
if (keywords.isEmpty())
|
||||
keywords << QLatin1String("abstract") << QLatin1String("continue") << QLatin1String("for")
|
||||
<< QLatin1String("new") << QLatin1String("switch") << QLatin1String("assert")
|
||||
<< QLatin1String("default") << QLatin1String("if") << QLatin1String("package")
|
||||
<< QLatin1String("synchronized") << QLatin1String("boolean") << QLatin1String("do")
|
||||
<< QLatin1String("goto") << QLatin1String("private") << QLatin1String("this")
|
||||
<< QLatin1String("break") << QLatin1String("double") << QLatin1String("implements")
|
||||
<< QLatin1String("protected") << QLatin1String("throw") << QLatin1String("byte")
|
||||
<< QLatin1String("else") << QLatin1String("import") << QLatin1String("public")
|
||||
<< QLatin1String("throws") << QLatin1String("case") << QLatin1String("enum")
|
||||
<< QLatin1String("instanceof") << QLatin1String("return") << QLatin1String("transient")
|
||||
<< QLatin1String("catch") << QLatin1String("extends") << QLatin1String("int")
|
||||
<< QLatin1String("short") << QLatin1String("try") << QLatin1String("char")
|
||||
<< QLatin1String("final") << QLatin1String("interface") << QLatin1String("static")
|
||||
<< QLatin1String("void") << QLatin1String("class") << QLatin1String("finally")
|
||||
<< QLatin1String("long") << QLatin1String("strictfp") << QLatin1String("volatile")
|
||||
<< QLatin1String("const") << QLatin1String("float") << QLatin1String("native")
|
||||
<< QLatin1String("super") << QLatin1String("while");
|
||||
|
||||
// No keywords
|
||||
int index = -1;
|
||||
while (index != packageName.length()) {
|
||||
int next = packageName.indexOf(QLatin1Char('.'), index + 1);
|
||||
if (next == -1)
|
||||
next = packageName.length();
|
||||
QString word = packageName.mid(index + 1, next - index - 1);
|
||||
if (!word.isEmpty()) {
|
||||
QChar c = word[0];
|
||||
if (c >= QChar(QLatin1Char('0')) && c<= QChar(QLatin1Char('9'))) {
|
||||
packageName.insert(index + 1, QLatin1Char('_'));
|
||||
index = next + 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (keywords.contains(word)) {
|
||||
packageName.insert(next, QLatin1String("_"));
|
||||
index = next + 1;
|
||||
} else {
|
||||
index = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return packageName;
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
namespace Android {
|
||||
@@ -144,48 +86,6 @@ QString AndroidManager::packageName(ProjectExplorer::Target *target)
|
||||
return manifestElem.attribute(QLatin1String("package"));
|
||||
}
|
||||
|
||||
bool AndroidManager::setPackageName(ProjectExplorer::Target *target, const QString &name)
|
||||
{
|
||||
QDomDocument doc;
|
||||
if (!openManifest(target, doc))
|
||||
return false;
|
||||
QDomElement manifestElem = doc.documentElement();
|
||||
manifestElem.setAttribute(QLatin1String("package"), cleanPackageName(name));
|
||||
return saveManifest(target, doc);
|
||||
}
|
||||
|
||||
QString AndroidManager::applicationName(ProjectExplorer::Target *target)
|
||||
{
|
||||
QDomDocument doc;
|
||||
if (!openXmlFile(doc, stringsPath(target)))
|
||||
return QString();
|
||||
QDomElement metadataElem = doc.documentElement().firstChildElement(QLatin1String("string"));
|
||||
while (!metadataElem.isNull()) {
|
||||
if (metadataElem.attribute(QLatin1String("name")) == QLatin1String("app_name"))
|
||||
return metadataElem.text();
|
||||
metadataElem = metadataElem.nextSiblingElement(QLatin1String("string"));
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool AndroidManager::setApplicationName(ProjectExplorer::Target *target, const QString &name)
|
||||
{
|
||||
QDomDocument doc;
|
||||
Utils::FileName path = stringsPath(target);
|
||||
if (!openXmlFile(doc, path))
|
||||
return false;
|
||||
QDomElement metadataElem = doc.documentElement().firstChildElement(QLatin1String("string"));
|
||||
while (!metadataElem.isNull()) {
|
||||
if (metadataElem.attribute(QLatin1String("name")) == QLatin1String("app_name")) {
|
||||
metadataElem.removeChild(metadataElem.firstChild());
|
||||
metadataElem.appendChild(doc.createTextNode(name));
|
||||
break;
|
||||
}
|
||||
metadataElem = metadataElem.nextSiblingElement(QLatin1String("string"));
|
||||
}
|
||||
return saveXmlFile(target, doc, path);
|
||||
}
|
||||
|
||||
QString AndroidManager::intentName(ProjectExplorer::Target *target)
|
||||
{
|
||||
return packageName(target) + QLatin1Char('/') + activityName(target);
|
||||
@@ -220,43 +120,12 @@ int AndroidManager::minimumSDK(ProjectExplorer::Target *target)
|
||||
|
||||
QString AndroidManager::buildTargetSDK(ProjectExplorer::Target *target)
|
||||
{
|
||||
QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(target->kit());
|
||||
if (qt && qt->qtVersion() >= QtSupport::QtVersionNumber(5, 2, 0)) {
|
||||
if (!target->activeDeployConfiguration())
|
||||
return QLatin1String("android-9");
|
||||
AndroidDeployQtStep *step = AndroidGlobal::buildStep<AndroidDeployQtStep>(target->activeDeployConfiguration());
|
||||
if (step)
|
||||
return step->buildTargetSdk();
|
||||
if (!target->activeDeployConfiguration())
|
||||
return QLatin1String("android-9");
|
||||
}
|
||||
|
||||
QVariant v = target->namedSettings(QLatin1String("AndroidManager.TargetSdk"));
|
||||
if (v.isValid())
|
||||
return v.toString();
|
||||
|
||||
QString fallback = QLatin1String("android-8");
|
||||
if (qt && qt->qtVersion() >= QtSupport::QtVersionNumber(5, 0, 0))
|
||||
fallback = QLatin1String("android-9");
|
||||
|
||||
if (!createAndroidTemplatesIfNecessary(target))
|
||||
return fallback;
|
||||
|
||||
QFile file(defaultPropertiesPath(target).toString());
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
return fallback;
|
||||
while (!file.atEnd()) {
|
||||
QByteArray line = file.readLine();
|
||||
if (line.startsWith("target="))
|
||||
return QString::fromLatin1(line.trimmed().mid(7));
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
|
||||
bool AndroidManager::setBuildTargetSDK(ProjectExplorer::Target *target, const QString &sdk)
|
||||
{
|
||||
updateTarget(target, sdk, applicationName(target));
|
||||
target->setNamedSettings(QLatin1String("AndroidManager.TargetSdk"), sdk);
|
||||
return true;
|
||||
AndroidDeployQtStep *step = AndroidGlobal::buildStep<AndroidDeployQtStep>(target->activeDeployConfiguration());
|
||||
if (step)
|
||||
return step->buildTargetSdk();
|
||||
return QLatin1String("android-9");
|
||||
}
|
||||
|
||||
QString AndroidManager::targetArch(ProjectExplorer::Target *target)
|
||||
@@ -272,11 +141,7 @@ QString AndroidManager::targetArch(ProjectExplorer::Target *target)
|
||||
|
||||
Utils::FileName AndroidManager::dirPath(ProjectExplorer::Target *target)
|
||||
{
|
||||
QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(target->kit());
|
||||
if (qtVersion && qtVersion->qtVersion() >= QtSupport::QtVersionNumber(5, 2, 0))
|
||||
return target->activeBuildConfiguration()->buildDirectory().appendPath(QLatin1String(Constants::ANDROID_BUILDDIRECTORY));
|
||||
Utils::FileName dir = target->project()->projectDirectory();
|
||||
return dir.appendPath(AndroidDirName);
|
||||
return target->activeBuildConfiguration()->buildDirectory().appendPath(QLatin1String(Constants::ANDROID_BUILDDIRECTORY));
|
||||
}
|
||||
|
||||
Utils::FileName AndroidManager::manifestPath(ProjectExplorer::Target *target)
|
||||
@@ -289,21 +154,11 @@ Utils::FileName AndroidManager::libsPath(ProjectExplorer::Target *target)
|
||||
return dirPath(target).appendPath(AndroidLibsFileName);
|
||||
}
|
||||
|
||||
Utils::FileName AndroidManager::stringsPath(ProjectExplorer::Target *target)
|
||||
{
|
||||
return dirPath(target).appendString(AndroidStringsFileName);
|
||||
}
|
||||
|
||||
Utils::FileName AndroidManager::defaultPropertiesPath(ProjectExplorer::Target *target)
|
||||
{
|
||||
return dirPath(target).appendPath(AndroidDefaultPropertiesName);
|
||||
}
|
||||
|
||||
Utils::FileName AndroidManager::srcPath(ProjectExplorer::Target *target)
|
||||
{
|
||||
return dirPath(target).appendPath(QLatin1String("/src"));
|
||||
}
|
||||
|
||||
Utils::FileName AndroidManager::apkPath(ProjectExplorer::Target *target, BuildType buildType)
|
||||
{
|
||||
QString packageName = QLatin1String("QtApp");
|
||||
@@ -315,14 +170,6 @@ Utils::FileName AndroidManager::apkPath(ProjectExplorer::Target *target, BuildTy
|
||||
else
|
||||
buildTypeName = QLatin1String("release");
|
||||
|
||||
QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(target->kit());
|
||||
if (!qt || qt->qtVersion() < QtSupport::QtVersionNumber(5, 2, 0)) {
|
||||
// Qt 5.1 and earlier:
|
||||
packageName = applicationName(target);
|
||||
if (buildType == ReleaseBuildSigned)
|
||||
buildTypeName = QLatin1String("signed");
|
||||
}
|
||||
|
||||
return dirPath(target)
|
||||
.appendPath(QLatin1String("bin"))
|
||||
.appendPath(QString::fromLatin1("%1-%2.apk")
|
||||
@@ -349,30 +196,8 @@ QStringList AndroidManager::availableTargetApplications(ProjectExplorer::Target
|
||||
return apps;
|
||||
}
|
||||
|
||||
QString AndroidManager::targetApplication(ProjectExplorer::Target *target)
|
||||
{
|
||||
QDomDocument doc;
|
||||
if (!openManifest(target, doc))
|
||||
return QString();
|
||||
QDomElement metadataElem = doc.documentElement().firstChildElement(QLatin1String("application")).firstChildElement(QLatin1String("activity")).firstChildElement(QLatin1String("meta-data"));
|
||||
while (!metadataElem.isNull()) {
|
||||
if (metadataElem.attribute(QLatin1String("android:name")) == QLatin1String("android.app.lib_name"))
|
||||
return metadataElem.attribute(QLatin1String("android:value"));
|
||||
metadataElem = metadataElem.nextSiblingElement(QLatin1String("meta-data"));
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
// Note, this could be implemented via a base class and a couple of virtuals
|
||||
// but I intend to remove the indirection once we drop support for qt 4.8
|
||||
// and qt 5.1.
|
||||
bool AndroidManager::bundleQt(ProjectExplorer::Target *target)
|
||||
{
|
||||
AndroidDeployStep *androidDeployStep
|
||||
= AndroidGlobal::buildStep<AndroidDeployStep>(target->activeDeployConfiguration());
|
||||
if (androidDeployStep)
|
||||
return androidDeployStep->deployAction() == AndroidDeployStep::BundleLibraries;
|
||||
|
||||
AndroidDeployQtStep *androidDeployQtStep
|
||||
= AndroidGlobal::buildStep<AndroidDeployQtStep>(target->activeDeployConfiguration());
|
||||
if (androidDeployQtStep)
|
||||
@@ -383,13 +208,6 @@ bool AndroidManager::bundleQt(ProjectExplorer::Target *target)
|
||||
|
||||
bool AndroidManager::useLocalLibs(ProjectExplorer::Target *target)
|
||||
{
|
||||
AndroidDeployStep *androidDeployStep
|
||||
= AndroidGlobal::buildStep<AndroidDeployStep>(target->activeDeployConfiguration());
|
||||
if (androidDeployStep) {
|
||||
return androidDeployStep->deployAction() == AndroidDeployStep::DeployLocal
|
||||
|| androidDeployStep->deployAction() == AndroidDeployStep::BundleLibraries;
|
||||
}
|
||||
|
||||
AndroidDeployQtStep *androidDeployQtStep
|
||||
= AndroidGlobal::buildStep<AndroidDeployQtStep>(target->activeDeployConfiguration());
|
||||
if (androidDeployQtStep) {
|
||||
@@ -402,11 +220,6 @@ bool AndroidManager::useLocalLibs(ProjectExplorer::Target *target)
|
||||
|
||||
QString AndroidManager::deviceSerialNumber(ProjectExplorer::Target *target)
|
||||
{
|
||||
AndroidDeployStep *androidDeployStep
|
||||
= AndroidGlobal::buildStep<AndroidDeployStep>(target->activeDeployConfiguration());
|
||||
if (androidDeployStep)
|
||||
return androidDeployStep->deviceSerialNumber();
|
||||
|
||||
AndroidDeployQtStep *androidDeployQtStep
|
||||
= AndroidGlobal::buildStep<AndroidDeployQtStep>(target->activeDeployConfiguration());
|
||||
if (androidDeployQtStep)
|
||||
@@ -414,307 +227,6 @@ QString AndroidManager::deviceSerialNumber(ProjectExplorer::Target *target)
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool AndroidManager::updateDeploymentSettings(ProjectExplorer::Target *target)
|
||||
{
|
||||
// For Qt 4, the "use local libs" options is handled by passing command line arguments to the
|
||||
// app, so no need to alter the AndroidManifest.xml
|
||||
QtSupport::BaseQtVersion *baseQtVersion = QtSupport::QtKitInformation::qtVersion(target->kit());
|
||||
if (baseQtVersion == 0 || baseQtVersion->qtVersion() < QtSupport::QtVersionNumber(5,0,0))
|
||||
return true;
|
||||
|
||||
if (baseQtVersion->qtVersion() >= QtSupport::QtVersionNumber(5, 2, 0))
|
||||
return true;
|
||||
|
||||
ProjectExplorer::RunConfiguration *runConfiguration = target->activeRunConfiguration();
|
||||
AndroidRunConfiguration *androidRunConfiguration = qobject_cast<AndroidRunConfiguration *>(runConfiguration);
|
||||
if (androidRunConfiguration == 0)
|
||||
return false;
|
||||
|
||||
bool useLocalLibs = AndroidManager::useLocalLibs(target);
|
||||
bool bundleQtLibs = AndroidManager::bundleQt(target);
|
||||
|
||||
QDomDocument doc;
|
||||
if (!openManifest(target, doc))
|
||||
return false;
|
||||
|
||||
QDomElement metadataElem = doc.documentElement().firstChildElement(QLatin1String("application")).firstChildElement(QLatin1String("activity")).firstChildElement(QLatin1String("meta-data"));
|
||||
|
||||
// ### Passes -1 for API level, which means it won't work with setups that require
|
||||
// library selection based on API level. Use the old approach (command line argument)
|
||||
// in these cases. Hence the Qt version > 4 condition at the beginning of this function.
|
||||
QString localLibs;
|
||||
QString localJars;
|
||||
QString staticInitClasses;
|
||||
if (useLocalLibs) {
|
||||
localLibs = loadLocalLibs(target, -1);
|
||||
localJars = loadLocalJars(target, -1);
|
||||
staticInitClasses = loadLocalJarsInitClasses(target, -1);
|
||||
}
|
||||
|
||||
bool changedManifest = false;
|
||||
while (!metadataElem.isNull()) {
|
||||
if (metadataElem.attribute(QLatin1String("android:name")) == QLatin1String("android.app.use_local_qt_libs")) {
|
||||
if (metadataElem.attribute(QLatin1String("android:value")).toInt() != int(useLocalLibs)) {
|
||||
metadataElem.setAttribute(QLatin1String("android:value"), int(useLocalLibs));
|
||||
changedManifest = true;
|
||||
}
|
||||
} else if (metadataElem.attribute(QLatin1String("android:name")) == QLatin1String("android.app.load_local_libs")) {
|
||||
if (metadataElem.attribute(QLatin1String("android:value")) != localLibs) {
|
||||
metadataElem.setAttribute(QLatin1String("android:value"), localLibs);
|
||||
changedManifest = true;
|
||||
}
|
||||
} else if (metadataElem.attribute(QLatin1String("android:name")) == QLatin1String("android.app.load_local_jars")) {
|
||||
if (metadataElem.attribute(QLatin1String("android:value")) != localJars) {
|
||||
metadataElem.setAttribute(QLatin1String("android:value"), localJars);
|
||||
changedManifest = true;
|
||||
}
|
||||
} else if (metadataElem.attribute(QLatin1String("android:name")) == QLatin1String("android.app.static_init_classes")) {
|
||||
if (metadataElem.attribute(QLatin1String("android:value")) != staticInitClasses) {
|
||||
metadataElem.setAttribute(QLatin1String("android:value"), staticInitClasses);
|
||||
changedManifest = true;
|
||||
}
|
||||
} else if (metadataElem.attribute(QLatin1String("android:name")) == QLatin1String("android.app.bundle_local_qt_libs")) {
|
||||
if (metadataElem.attribute(QLatin1String("android:value")).toInt() != int(bundleQtLibs)) {
|
||||
metadataElem.setAttribute(QLatin1String("android:value"), int(bundleQtLibs));
|
||||
changedManifest = true;
|
||||
}
|
||||
}
|
||||
|
||||
metadataElem = metadataElem.nextSiblingElement(QLatin1String("meta-data"));
|
||||
}
|
||||
|
||||
if (changedManifest)
|
||||
return saveManifest(target, doc);
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AndroidManager::setTargetApplication(ProjectExplorer::Target *target, const QString &name)
|
||||
{
|
||||
QDomDocument doc;
|
||||
if (!openManifest(target, doc))
|
||||
return false;
|
||||
QDomElement metadataElem = doc.documentElement().firstChildElement(QLatin1String("application")).firstChildElement(QLatin1String("activity")).firstChildElement(QLatin1String("meta-data"));
|
||||
while (!metadataElem.isNull()) {
|
||||
if (metadataElem.attribute(QLatin1String("android:name")) == QLatin1String("android.app.lib_name")) {
|
||||
metadataElem.setAttribute(QLatin1String("android:value"), name);
|
||||
return saveManifest(target, doc);
|
||||
}
|
||||
metadataElem = metadataElem.nextSiblingElement(QLatin1String("meta-data"));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QString AndroidManager::targetApplicationPath(ProjectExplorer::Target *target)
|
||||
{
|
||||
QString selectedApp = targetApplication(target);
|
||||
if (selectedApp.isEmpty())
|
||||
return QString();
|
||||
QmakeProjectManager::QmakeProject *qmakeProject = qobject_cast<QmakeProjectManager::QmakeProject *>(target->project());
|
||||
foreach (QmakeProjectManager::QmakeProFileNode *proFile, qmakeProject->applicationProFiles()) {
|
||||
if (proFile->projectType() == QmakeProjectManager::ApplicationTemplate) {
|
||||
if (proFile->targetInformation().target.startsWith(QLatin1String("lib"))
|
||||
&& proFile->targetInformation().target.endsWith(QLatin1String(".so"))) {
|
||||
if (proFile->targetInformation().target.mid(3, proFile->targetInformation().target.lastIndexOf(QLatin1Char('.')) - 3)
|
||||
== selectedApp)
|
||||
return proFile->targetInformation().buildDir + QLatin1Char('/') + proFile->targetInformation().target;
|
||||
} else {
|
||||
if (proFile->targetInformation().target == selectedApp)
|
||||
return proFile->targetInformation().buildDir + QLatin1String("/lib") + proFile->targetInformation().target + QLatin1String(".so");
|
||||
}
|
||||
}
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool AndroidManager::createAndroidTemplatesIfNecessary(ProjectExplorer::Target *target)
|
||||
{
|
||||
QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target->kit());
|
||||
QmakeProjectManager::QmakeProject *qmakeProject = qobject_cast<QmakeProjectManager::QmakeProject*>(target->project());
|
||||
if (!qmakeProject || !qmakeProject->rootProjectNode() || !version)
|
||||
return false;
|
||||
|
||||
// TODO we should create the AndroidManifest.xml file for that version
|
||||
if (version->qtVersion() >= QtSupport::QtVersionNumber(5, 2, 0))
|
||||
return true;
|
||||
|
||||
Utils::FileName javaSrcPath
|
||||
= Utils::FileName::fromString(version->qmakeProperty("QT_INSTALL_PREFIX"))
|
||||
.appendPath(QLatin1String("src/android/java"));
|
||||
QDir projectDir(qmakeProject->projectDirectory().toString());
|
||||
Utils::FileName androidPath = dirPath(target);
|
||||
|
||||
QStringList m_ignoreFiles;
|
||||
bool forceUpdate = false;
|
||||
QDomDocument srcVersionDoc;
|
||||
Utils::FileName srcVersionPath = javaSrcPath;
|
||||
srcVersionPath.appendPath(QLatin1String("version.xml"));
|
||||
if (openXmlFile(srcVersionDoc, srcVersionPath)) {
|
||||
QDomDocument dstVersionDoc;
|
||||
Utils::FileName dstVersionPath=androidPath;
|
||||
dstVersionPath.appendPath(QLatin1String("version.xml"));
|
||||
if (openXmlFile(dstVersionDoc, dstVersionPath))
|
||||
forceUpdate = (srcVersionDoc.documentElement().attribute(QLatin1String("value")).toDouble()
|
||||
> dstVersionDoc.documentElement().attribute(QLatin1String("value")).toDouble());
|
||||
else
|
||||
forceUpdate = true;
|
||||
|
||||
if (forceUpdate && androidPath.toFileInfo().exists()) {
|
||||
QDomElement ignoreFile = srcVersionDoc.documentElement().firstChildElement(QLatin1String("ignore")).firstChildElement(QLatin1String("file"));
|
||||
while (!ignoreFile.isNull()) {
|
||||
m_ignoreFiles << ignoreFile.text();
|
||||
ignoreFile = ignoreFile.nextSiblingElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Utils::FileName src = androidPath;
|
||||
src.appendPath(QLatin1String("src"));
|
||||
Utils::FileName res = androidPath;
|
||||
res.appendPath(QLatin1String("res"));
|
||||
|
||||
if (!forceUpdate && androidPath.toFileInfo().exists()
|
||||
&& manifestPath(target).toFileInfo().exists()
|
||||
&& src.toFileInfo().exists()
|
||||
&& res.toFileInfo().exists())
|
||||
return true;
|
||||
|
||||
forceUpdate &= androidPath.toFileInfo().exists();
|
||||
|
||||
if (!dirPath(target).toFileInfo().exists() && !projectDir.mkdir(AndroidDirName)) {
|
||||
raiseError(tr("Error creating Android directory \"%1\".").arg(AndroidDirName));
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList androidFiles;
|
||||
QDirIterator it(javaSrcPath.toString(), QDirIterator::Subdirectories);
|
||||
int pos = it.path().size();
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
if (it.fileInfo().isDir()) {
|
||||
projectDir.mkpath(AndroidDirName + it.filePath().mid(pos));
|
||||
} else {
|
||||
Utils::FileName dstFile = androidPath;
|
||||
dstFile.appendPath(it.filePath().mid(pos));
|
||||
if (m_ignoreFiles.contains(it.fileName())) {
|
||||
continue;
|
||||
} else {
|
||||
if (dstFile.toFileInfo().exists())
|
||||
QFile::remove(dstFile.toString());
|
||||
else
|
||||
androidFiles << dstFile.toString();
|
||||
}
|
||||
QFile::copy(it.filePath(), dstFile.toString());
|
||||
}
|
||||
}
|
||||
if (!androidFiles.isEmpty())
|
||||
qmakeProject->rootProjectNode()->addFiles(androidFiles);
|
||||
|
||||
int minApiLevel = 4;
|
||||
if (QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(target->kit()))
|
||||
if (qt->qtVersion() >= QtSupport::QtVersionNumber(5, 0, 0))
|
||||
minApiLevel = 9;
|
||||
|
||||
QStringList sdks = AndroidConfig::apiLevelNamesFor(AndroidConfigurations::currentConfig().sdkTargets(minApiLevel));
|
||||
if (sdks.isEmpty()) {
|
||||
raiseError(tr("No Qt for Android SDKs were found.\nPlease install at least one SDK."));
|
||||
return false;
|
||||
}
|
||||
|
||||
updateTarget(target, sdks.first());
|
||||
QStringList apps = availableTargetApplications(target);
|
||||
if (!apps.isEmpty())
|
||||
setTargetApplication(target, apps.at(0));
|
||||
|
||||
QString applicationName = target->project()->displayName();
|
||||
if (!applicationName.isEmpty()) {
|
||||
setPackageName(target, packageName(target) + QLatin1Char('.') + applicationName);
|
||||
applicationName[0] = applicationName[0].toUpper();
|
||||
setApplicationName(target, applicationName);
|
||||
}
|
||||
|
||||
if (forceUpdate)
|
||||
QMessageBox::warning(Core::ICore::dialogParent(), tr("Warning"), tr("Android files have been updated automatically."));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AndroidManager::updateTarget(ProjectExplorer::Target *target, const QString &targetSDK, const QString &name)
|
||||
{
|
||||
QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(target->kit());
|
||||
if (qtVersion && qtVersion->qtVersion() >= QtSupport::QtVersionNumber(5,2,0))
|
||||
return;
|
||||
|
||||
QString androidDir = dirPath(target).toString();
|
||||
|
||||
Utils::Environment env = Utils::Environment::systemEnvironment();
|
||||
QString javaHome = AndroidConfigurations::currentConfig().openJDKLocation().toString();
|
||||
if (!javaHome.isEmpty())
|
||||
env.set(QLatin1String("JAVA_HOME"), javaHome);
|
||||
// clean previous build
|
||||
QProcess androidProc;
|
||||
androidProc.setWorkingDirectory(androidDir);
|
||||
androidProc.setProcessEnvironment(env.toProcessEnvironment());
|
||||
androidProc.start(AndroidConfigurations::currentConfig().antToolPath().toString(),
|
||||
QStringList() << QLatin1String("clean"));
|
||||
if (!androidProc.waitForFinished(-1))
|
||||
androidProc.terminate();
|
||||
// clean previous build
|
||||
|
||||
int targetSDKNumber = targetSDK.mid(targetSDK.lastIndexOf(QLatin1Char('-')) + 1).toInt();
|
||||
bool commentLines = false;
|
||||
QDirIterator it(androidDir, QStringList() << QLatin1String("*.java"), QDir::Files, QDirIterator::Subdirectories);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
QFile file(it.filePath());
|
||||
if (!file.open(QIODevice::ReadWrite))
|
||||
continue;
|
||||
QList<QByteArray> lines = file.readAll().trimmed().split('\n');
|
||||
|
||||
bool modified = false;
|
||||
bool comment = false;
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
QByteArray trimmed = lines[i].trimmed();
|
||||
if (trimmed.contains("@ANDROID-")) {
|
||||
commentLines = targetSDKNumber < trimmed.mid(trimmed.lastIndexOf('-') + 1).toInt();
|
||||
comment = !comment;
|
||||
continue;
|
||||
}
|
||||
if (!comment)
|
||||
continue;
|
||||
if (commentLines) {
|
||||
if (!trimmed.startsWith("//QtCreator")) {
|
||||
lines[i] = "//QtCreator " + lines[i];
|
||||
modified = true;
|
||||
}
|
||||
} else { if (trimmed.startsWith("//QtCreator")) {
|
||||
lines[i] = lines[i].mid(12);
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (modified) {
|
||||
file.resize(0);
|
||||
foreach (const QByteArray &line, lines) {
|
||||
file.write(line);
|
||||
file.write("\n");
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
QStringList params;
|
||||
params << QLatin1String("update") << QLatin1String("project") << QLatin1String("-p") << androidDir;
|
||||
if (!targetSDK.isEmpty())
|
||||
params << QLatin1String("-t") << targetSDK;
|
||||
if (!name.isEmpty())
|
||||
params << QLatin1String("-n") << name;
|
||||
androidProc.setProcessEnvironment(AndroidConfigurations::currentConfig().androidToolEnvironment().toProcessEnvironment());
|
||||
androidProc.start(AndroidConfigurations::currentConfig().androidToolPath().toString(), params);
|
||||
if (!androidProc.waitForFinished(-1))
|
||||
androidProc.terminate();
|
||||
}
|
||||
|
||||
Utils::FileName AndroidManager::localLibsRulesFilePath(ProjectExplorer::Target *target)
|
||||
{
|
||||
QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target->kit());
|
||||
@@ -728,11 +240,6 @@ QString AndroidManager::loadLocalLibs(ProjectExplorer::Target *target, int apiLe
|
||||
return loadLocal(target, apiLevel, Lib);
|
||||
}
|
||||
|
||||
QString AndroidManager::loadLocalBundledFiles(ProjectExplorer::Target *target, int apiLevel)
|
||||
{
|
||||
return loadLocal(target, apiLevel, BundledFile);
|
||||
}
|
||||
|
||||
QString AndroidManager::loadLocalJars(ProjectExplorer::Target *target, int apiLevel)
|
||||
{
|
||||
ItemType type = bundleQt(target) ? BundledJar : Jar;
|
||||
@@ -745,17 +252,9 @@ QString AndroidManager::loadLocalJarsInitClasses(ProjectExplorer::Target *target
|
||||
return loadLocal(target, apiLevel, type, QLatin1String("initClass"));
|
||||
}
|
||||
|
||||
QPair<int, int> AndroidManager::apiLevelRange(ProjectExplorer::Target *target)
|
||||
QPair<int, int> AndroidManager::apiLevelRange()
|
||||
{
|
||||
// 4 is the minimum version on which qt is supported
|
||||
// 19 and 20 are not yet released, but allow the user
|
||||
// to set them
|
||||
int minApiLevel = 4;
|
||||
QtSupport::BaseQtVersion *qt;
|
||||
if (target && (qt = QtSupport::QtKitInformation::qtVersion(target->kit())))
|
||||
if (qt->qtVersion() >= QtSupport::QtVersionNumber(5, 0, 0))
|
||||
minApiLevel = 9;
|
||||
return qMakePair(minApiLevel, 20);
|
||||
return qMakePair(9, 20);
|
||||
}
|
||||
|
||||
QString AndroidManager::androidNameForApiLevel(int x)
|
||||
@@ -800,139 +299,16 @@ QString AndroidManager::androidNameForApiLevel(int x)
|
||||
}
|
||||
}
|
||||
|
||||
QVector<AndroidManager::Library> AndroidManager::availableQtLibsWithDependencies(ProjectExplorer::Target *target)
|
||||
{
|
||||
QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target->kit());
|
||||
if (!target->activeRunConfiguration())
|
||||
return QVector<AndroidManager::Library>();
|
||||
|
||||
ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainKitInformation::toolChain(target->kit());
|
||||
if (tc->type() != QLatin1String(Constants::ANDROID_TOOLCHAIN_TYPE))
|
||||
return QVector<AndroidManager::Library>();
|
||||
|
||||
QmakeProjectManager::QmakeProject *project = static_cast<QmakeProjectManager::QmakeProject *>(target->project());
|
||||
QString arch = project->rootQmakeProjectNode()->singleVariableValue(QmakeProjectManager::AndroidArchVar);
|
||||
|
||||
AndroidToolChain *atc = static_cast<AndroidToolChain *>(tc);
|
||||
QString libgnustl = libGnuStl(arch, atc->ndkToolChainVersion());
|
||||
|
||||
Utils::FileName readelfPath = AndroidConfigurations::currentConfig().readelfPath(target->activeRunConfiguration()->abi().architecture(),
|
||||
atc->ndkToolChainVersion());
|
||||
const QmakeProjectManager::QmakeProject *const qmakeProject
|
||||
= qobject_cast<const QmakeProjectManager::QmakeProject *>(target->project());
|
||||
if (!qmakeProject || !version)
|
||||
return QVector<AndroidManager::Library>();
|
||||
QString qtLibsPath = version->qmakeProperty("QT_INSTALL_LIBS");
|
||||
if (!readelfPath.toFileInfo().exists())
|
||||
return QVector<AndroidManager::Library>();
|
||||
LibrariesMap mapLibs;
|
||||
QDir libPath;
|
||||
QDirIterator it(qtLibsPath, QStringList() << QLatin1String("*.so"), QDir::Files, QDirIterator::Subdirectories);
|
||||
while (it.hasNext()) {
|
||||
libPath = it.next();
|
||||
const QString library = libPath.absolutePath().mid(libPath.absolutePath().lastIndexOf(QLatin1Char('/')) + 1);
|
||||
mapLibs[library].dependencies = dependencies(readelfPath, libPath.absolutePath());
|
||||
}
|
||||
|
||||
const QString library = libgnustl.mid(libgnustl.lastIndexOf(QLatin1Char('/')) + 1);
|
||||
mapLibs[library] = Library();
|
||||
|
||||
// clean dependencies
|
||||
const LibrariesMap::Iterator lend = mapLibs.end();
|
||||
for (LibrariesMap::Iterator lit = mapLibs.begin(); lit != lend; ++lit) {
|
||||
Library &library = lit.value();
|
||||
int it = 0;
|
||||
while (it < library.dependencies.size()) {
|
||||
const QString &dependName = library.dependencies[it];
|
||||
if (!mapLibs.contains(dependName) && dependName.startsWith(QLatin1String("lib")) && dependName.endsWith(QLatin1String(".so")))
|
||||
library.dependencies.removeAt(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
if (library.dependencies.isEmpty())
|
||||
library.level = 0;
|
||||
}
|
||||
|
||||
QVector<Library> qtLibraries;
|
||||
// calculate the level for every library
|
||||
for (LibrariesMap::Iterator lit = mapLibs.begin(); lit != lend; ++lit) {
|
||||
Library &library = lit.value();
|
||||
const QString &key = lit.key();
|
||||
if (library.level < 0)
|
||||
setLibraryLevel(key, mapLibs);
|
||||
|
||||
if (library.name.isEmpty() && key.startsWith(QLatin1String("lib")) && key.endsWith(QLatin1String(".so")))
|
||||
library.name = key.mid(3, key.length() - 6);
|
||||
|
||||
for (int it = 0; it < library.dependencies.size(); it++) {
|
||||
const QString &libName = library.dependencies[it];
|
||||
if (libName.startsWith(QLatin1String("lib")) && libName.endsWith(QLatin1String(".so")))
|
||||
library.dependencies[it] = libName.mid(3, libName.length() - 6);
|
||||
}
|
||||
qtLibraries.push_back(library);
|
||||
}
|
||||
Utils::sort(qtLibraries, [](const Library &a, const Library &b) -> bool {
|
||||
if (a.level == b.level)
|
||||
return a.name < b.name;
|
||||
return a.level < b.level;
|
||||
});
|
||||
|
||||
return qtLibraries;
|
||||
|
||||
}
|
||||
|
||||
QStringList AndroidManager::availableQtLibs(ProjectExplorer::Target *target)
|
||||
{
|
||||
QStringList libs;
|
||||
QVector<Library> qtLibraries = availableQtLibsWithDependencies(target);
|
||||
foreach (Library lib, qtLibraries)
|
||||
libs.push_back(lib.name);
|
||||
return libs;
|
||||
}
|
||||
|
||||
QStringList AndroidManager::qtLibs(ProjectExplorer::Target *target)
|
||||
{
|
||||
return libsXml(target, QLatin1String("qt_libs"));
|
||||
}
|
||||
|
||||
bool AndroidManager::setQtLibs(ProjectExplorer::Target *target, const QStringList &libs)
|
||||
{
|
||||
return setLibsXml(target, libs, QLatin1String("qt_libs"));
|
||||
}
|
||||
|
||||
bool AndroidManager::setBundledInAssets(ProjectExplorer::Target *target, const QStringList &fileList)
|
||||
{
|
||||
return setLibsXml(target, fileList, QLatin1String("bundled_in_assets"));
|
||||
}
|
||||
|
||||
bool AndroidManager::setBundledInLib(ProjectExplorer::Target *target, const QStringList &fileList)
|
||||
{
|
||||
return setLibsXml(target, fileList, QLatin1String("bundled_in_lib"));
|
||||
}
|
||||
|
||||
QStringList AndroidManager::availablePrebundledLibs(ProjectExplorer::Target *target)
|
||||
{
|
||||
QStringList libs;
|
||||
QmakeProjectManager::QmakeProject *qmakeProject = qobject_cast<QmakeProjectManager::QmakeProject *>(target->project());
|
||||
if (!qmakeProject)
|
||||
return libs;
|
||||
|
||||
foreach (QmakeProjectManager::QmakeProFileNode *node, qmakeProject->allProFiles())
|
||||
if (node->projectType() == QmakeProjectManager::LibraryTemplate)
|
||||
libs << node->targetInformation().target;
|
||||
return libs;
|
||||
}
|
||||
|
||||
QStringList AndroidManager::prebundledLibs(ProjectExplorer::Target *target)
|
||||
{
|
||||
return libsXml(target, QLatin1String("bundled_libs"));
|
||||
}
|
||||
|
||||
bool AndroidManager::setPrebundledLibs(ProjectExplorer::Target *target, const QStringList &libs)
|
||||
{
|
||||
return setLibsXml(target, libs, QLatin1String("bundled_libs"));
|
||||
}
|
||||
|
||||
bool AndroidManager::openLibsXml(ProjectExplorer::Target *target, QDomDocument &doc)
|
||||
{
|
||||
return openXmlFile(doc, libsPath(target));
|
||||
@@ -940,7 +316,7 @@ bool AndroidManager::openLibsXml(ProjectExplorer::Target *target, QDomDocument &
|
||||
|
||||
bool AndroidManager::saveLibsXml(ProjectExplorer::Target *target, QDomDocument &doc)
|
||||
{
|
||||
return saveXmlFile(target, doc, libsPath(target));
|
||||
return saveXmlFile(doc, libsPath(target));
|
||||
}
|
||||
|
||||
void AndroidManager::raiseError(const QString &reason)
|
||||
@@ -1060,11 +436,8 @@ bool AndroidManager::openXmlFile(QDomDocument &doc, const Utils::FileName &fileN
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AndroidManager::saveXmlFile(ProjectExplorer::Target *target, QDomDocument &doc, const Utils::FileName &fileName)
|
||||
bool AndroidManager::saveXmlFile(QDomDocument &doc, const Utils::FileName &fileName)
|
||||
{
|
||||
if (!createAndroidTemplatesIfNecessary(target))
|
||||
return false;
|
||||
|
||||
QFile f(fileName.toString());
|
||||
if (!f.open(QIODevice::WriteOnly)) {
|
||||
raiseError(tr("Cannot open \"%1\".").arg(fileName.toUserOutput()));
|
||||
@@ -1081,7 +454,7 @@ bool AndroidManager::openManifest(ProjectExplorer::Target *target, QDomDocument
|
||||
bool AndroidManager::saveManifest(ProjectExplorer::Target *target, QDomDocument &doc)
|
||||
{
|
||||
Core::FileChangeBlocker blocker(manifestPath(target).toString());
|
||||
return saveXmlFile(target, doc, manifestPath(target));
|
||||
return saveXmlFile(doc, manifestPath(target));
|
||||
}
|
||||
|
||||
QStringList AndroidManager::libsXml(ProjectExplorer::Target *target, const QString &tag)
|
||||
@@ -1178,21 +551,6 @@ int AndroidManager::setLibraryLevel(const QString &library, LibrariesMap &mapLib
|
||||
return maxlevel + 1;
|
||||
}
|
||||
|
||||
QString AndroidManager::libGnuStl(const QString &arch, const QString &ndkToolChainVersion)
|
||||
{
|
||||
return AndroidConfigurations::currentConfig().ndkLocation().toString()
|
||||
+ QLatin1String("/sources/cxx-stl/gnu-libstdc++/")
|
||||
+ ndkToolChainVersion + QLatin1String("/libs/")
|
||||
+ arch
|
||||
+ QLatin1String("/libgnustl_shared.so");
|
||||
}
|
||||
|
||||
QString AndroidManager::libraryPrefix()
|
||||
{
|
||||
return AndroidLibraryPrefix;
|
||||
}
|
||||
|
||||
|
||||
void AndroidManager::cleanLibsOnDevice(ProjectExplorer::Target *target)
|
||||
{
|
||||
const QString targetArch = AndroidManager::targetArch(target);
|
||||
|
||||
@@ -57,26 +57,17 @@ public:
|
||||
static bool supportsAndroid(ProjectExplorer::Target *target);
|
||||
|
||||
static QString packageName(ProjectExplorer::Target *target);
|
||||
static bool setPackageName(ProjectExplorer::Target *target, const QString &name);
|
||||
|
||||
static QString applicationName(ProjectExplorer::Target *target);
|
||||
static bool setApplicationName(ProjectExplorer::Target *target, const QString &name);
|
||||
|
||||
static QString intentName(ProjectExplorer::Target *target);
|
||||
static QString activityName(ProjectExplorer::Target *target);
|
||||
|
||||
static QStringList availableTargetApplications(ProjectExplorer::Target *target);
|
||||
static QString targetApplication(ProjectExplorer::Target *target);
|
||||
static bool setTargetApplication(ProjectExplorer::Target *target, const QString &name);
|
||||
static QString targetApplicationPath(ProjectExplorer::Target *target);
|
||||
|
||||
static bool updateDeploymentSettings(ProjectExplorer::Target *target);
|
||||
static bool bundleQt(ProjectExplorer::Target *target);
|
||||
static bool useLocalLibs(ProjectExplorer::Target *target);
|
||||
static QString deviceSerialNumber(ProjectExplorer::Target *target);
|
||||
|
||||
static QString buildTargetSDK(ProjectExplorer::Target *target);
|
||||
static bool setBuildTargetSDK(ProjectExplorer::Target *target, const QString &sdk);
|
||||
static int minimumSDK(ProjectExplorer::Target *target);
|
||||
|
||||
static QString targetArch(ProjectExplorer::Target *target);
|
||||
@@ -84,22 +75,15 @@ public:
|
||||
static Utils::FileName dirPath(ProjectExplorer::Target *target);
|
||||
static Utils::FileName manifestPath(ProjectExplorer::Target *target);
|
||||
static Utils::FileName libsPath(ProjectExplorer::Target *target);
|
||||
static Utils::FileName stringsPath(ProjectExplorer::Target *target);
|
||||
static Utils::FileName defaultPropertiesPath(ProjectExplorer::Target *target);
|
||||
static Utils::FileName srcPath(ProjectExplorer::Target *target);
|
||||
static Utils::FileName apkPath(ProjectExplorer::Target *target, BuildType buildType);
|
||||
|
||||
static bool createAndroidTemplatesIfNecessary(ProjectExplorer::Target *target);
|
||||
static void updateTarget(ProjectExplorer::Target *target, const QString &buildTargetSDK,
|
||||
const QString &name = QString());
|
||||
|
||||
static Utils::FileName localLibsRulesFilePath(ProjectExplorer::Target *target);
|
||||
static QString loadLocalLibs(ProjectExplorer::Target *target, int apiLevel = -1);
|
||||
static QString loadLocalJars(ProjectExplorer::Target *target, int apiLevel = -1);
|
||||
static QString loadLocalBundledFiles(ProjectExplorer::Target *target, int apiLevel = -1);
|
||||
static QString loadLocalJarsInitClasses(ProjectExplorer::Target *target, int apiLevel = -1);
|
||||
|
||||
static QPair<int, int> apiLevelRange(ProjectExplorer::Target *target);
|
||||
static QPair<int, int> apiLevelRange();
|
||||
static QString androidNameForApiLevel(int x);
|
||||
|
||||
class Library
|
||||
@@ -113,22 +97,8 @@ public:
|
||||
};
|
||||
typedef QMap<QString, Library> LibrariesMap;
|
||||
|
||||
static QVector<AndroidManager::Library> availableQtLibsWithDependencies(ProjectExplorer::Target *target);
|
||||
static QStringList availableQtLibs(ProjectExplorer::Target *target);
|
||||
static QStringList qtLibs(ProjectExplorer::Target *target);
|
||||
static bool setQtLibs(ProjectExplorer::Target *target, const QStringList &libs);
|
||||
|
||||
static bool setBundledInLib(ProjectExplorer::Target *target,
|
||||
const QStringList &fileList);
|
||||
static bool setBundledInAssets(ProjectExplorer::Target *target,
|
||||
const QStringList &fileList);
|
||||
|
||||
static QStringList availablePrebundledLibs(ProjectExplorer::Target *target);
|
||||
static QStringList prebundledLibs(ProjectExplorer::Target *target);
|
||||
static bool setPrebundledLibs(ProjectExplorer::Target *target, const QStringList &libs);
|
||||
|
||||
static QString libGnuStl(const QString &arch, const QString &ndkToolChainVersion);
|
||||
static QString libraryPrefix();
|
||||
|
||||
static void cleanLibsOnDevice(ProjectExplorer::Target *target);
|
||||
static void installQASIPackage(ProjectExplorer::Target *target, const QString &packagePath);
|
||||
@@ -139,7 +109,7 @@ public:
|
||||
private:
|
||||
static void raiseError(const QString &reason);
|
||||
static bool openXmlFile(QDomDocument &doc, const Utils::FileName &fileName);
|
||||
static bool saveXmlFile(ProjectExplorer::Target *target, QDomDocument &doc, const Utils::FileName &fileName);
|
||||
static bool saveXmlFile(QDomDocument &doc, const Utils::FileName &fileName);
|
||||
static bool openManifest(ProjectExplorer::Target *target, QDomDocument &doc);
|
||||
static bool saveManifest(ProjectExplorer::Target *target, QDomDocument &doc);
|
||||
static bool openLibsXml(ProjectExplorer::Target *target, QDomDocument &doc);
|
||||
|
||||
@@ -690,8 +690,7 @@ void AndroidManifestEditorWidget::updateInfoBar()
|
||||
void AndroidManifestEditorWidget::updateSdkVersions()
|
||||
{
|
||||
const QString docPath(m_textEditorWidget->baseTextDocument()->filePath());
|
||||
Project *project = androidProject(docPath);
|
||||
QPair<int, int> apiLevels = AndroidManager::apiLevelRange(project ? project->activeTarget() : 0);
|
||||
QPair<int, int> apiLevels = AndroidManager::apiLevelRange();
|
||||
for (int i = apiLevels.first; i < apiLevels.second + 1; ++i)
|
||||
m_androidMinSdkVersion->addItem(tr("API %1: %2")
|
||||
.arg(i)
|
||||
|
||||
@@ -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 "androidpackagecreationfactory.h"
|
||||
|
||||
#include "androidpackagecreationstep.h"
|
||||
#include "androidmanager.h"
|
||||
|
||||
#include <projectexplorer/buildsteplist.h>
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
#include <projectexplorer/target.h>
|
||||
|
||||
#include <qtsupport/qtkitinformation.h>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
namespace Android {
|
||||
namespace Internal {
|
||||
|
||||
AndroidPackageCreationFactory::AndroidPackageCreationFactory(QObject *parent)
|
||||
: IBuildStepFactory(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QList<Core::Id> AndroidPackageCreationFactory::availableCreationIds(BuildStepList *parent) const
|
||||
{
|
||||
if (parent->id() != Constants::BUILDSTEPS_DEPLOY)
|
||||
return QList<Core::Id>();
|
||||
if (!AndroidManager::supportsAndroid(parent->target()))
|
||||
return QList<Core::Id>();
|
||||
if (parent->contains(AndroidPackageCreationStep::CreatePackageId))
|
||||
return QList<Core::Id>();
|
||||
QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(parent->target()->kit());
|
||||
if (qtVersion && qtVersion->qtVersion() >= QtSupport::QtVersionNumber(5, 2, 0))
|
||||
return QList<Core::Id>();
|
||||
return QList<Core::Id>() << AndroidPackageCreationStep::CreatePackageId;
|
||||
}
|
||||
|
||||
QString AndroidPackageCreationFactory::displayNameForId(Core::Id id) const
|
||||
{
|
||||
if (id == AndroidPackageCreationStep::CreatePackageId)
|
||||
return tr("Create Android (.apk) Package");
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool AndroidPackageCreationFactory::canCreate(BuildStepList *parent, Core::Id id) const
|
||||
{
|
||||
return availableCreationIds(parent).contains(id);
|
||||
}
|
||||
|
||||
BuildStep *AndroidPackageCreationFactory::create(BuildStepList *parent, Core::Id id)
|
||||
{
|
||||
Q_ASSERT(canCreate(parent, id));
|
||||
Q_UNUSED(id);
|
||||
return new AndroidPackageCreationStep(parent);
|
||||
}
|
||||
|
||||
bool AndroidPackageCreationFactory::canRestore(BuildStepList *parent, const QVariantMap &map) const
|
||||
{
|
||||
return canCreate(parent, idFromMap(map));
|
||||
}
|
||||
|
||||
BuildStep *AndroidPackageCreationFactory::restore(BuildStepList *parent, const QVariantMap &map)
|
||||
{
|
||||
Q_ASSERT(canRestore(parent, map));
|
||||
AndroidPackageCreationStep *const step = new AndroidPackageCreationStep(parent);
|
||||
if (!step->fromMap(map)) {
|
||||
delete step;
|
||||
return 0;
|
||||
}
|
||||
return step;
|
||||
}
|
||||
|
||||
bool AndroidPackageCreationFactory::canClone(BuildStepList *parent, BuildStep *product) const
|
||||
{
|
||||
return canCreate(parent, product->id());
|
||||
}
|
||||
|
||||
BuildStep *AndroidPackageCreationFactory::clone(BuildStepList *parent, BuildStep *product)
|
||||
{
|
||||
Q_ASSERT(canClone(parent, product));
|
||||
return new AndroidPackageCreationStep(parent, static_cast<AndroidPackageCreationStep *>(product));
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Android
|
||||
@@ -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 ANDROIDPACKAGECREATIONFACTORY_H
|
||||
#define ANDROIDPACKAGECREATIONFACTORY_H
|
||||
|
||||
#include <projectexplorer/buildstep.h>
|
||||
|
||||
namespace Android {
|
||||
namespace Internal {
|
||||
|
||||
class AndroidPackageCreationFactory : public ProjectExplorer::IBuildStepFactory
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit AndroidPackageCreationFactory(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 // ANDROIDPACKAGECREATIONFACTORY_H
|
||||
@@ -1,883 +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 "androidpackagecreationstep.h"
|
||||
|
||||
#include "androidconstants.h"
|
||||
#include "androiddeploystep.h"
|
||||
#include "androidglobal.h"
|
||||
#include "androidpackagecreationwidget.h"
|
||||
#include "androidmanager.h"
|
||||
#include "androidgdbserverkitinformation.h"
|
||||
#include "androidtoolchain.h"
|
||||
#include "certificatesmodel.h"
|
||||
|
||||
#include <projectexplorer/buildsteplist.h>
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
#include <projectexplorer/runconfiguration.h>
|
||||
#include <projectexplorer/target.h>
|
||||
#include <qmakeprojectmanager/qmakebuildconfiguration.h>
|
||||
#include <qmakeprojectmanager/qmakeproject.h>
|
||||
#include <qmakeprojectmanager/qmakenodes.h>
|
||||
#include <qtsupport/qtkitinformation.h>
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/fileutils.h>
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QProcess>
|
||||
#include <QVector>
|
||||
#include <QPair>
|
||||
#include <QWidget>
|
||||
#include <QMessageBox>
|
||||
#include <QInputDialog>
|
||||
#include <QMainWindow>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
using namespace ProjectExplorer::Constants;
|
||||
|
||||
namespace Android {
|
||||
namespace Internal {
|
||||
|
||||
namespace {
|
||||
const QLatin1String KeystoreLocationKey("KeystoreLocation");
|
||||
const QLatin1String SignPackageKey("SignPackage");
|
||||
const QLatin1String AliasString("Alias name:");
|
||||
const QLatin1String CertificateSeparator("*******************************************");
|
||||
}
|
||||
|
||||
using namespace QmakeProjectManager;
|
||||
|
||||
AndroidPackageCreationStep::AndroidPackageCreationStep(BuildStepList *bsl)
|
||||
: BuildStep(bsl, CreatePackageId)
|
||||
{
|
||||
ctor();
|
||||
}
|
||||
|
||||
AndroidPackageCreationStep::AndroidPackageCreationStep(BuildStepList *bsl,
|
||||
AndroidPackageCreationStep *other)
|
||||
: BuildStep(bsl, other)
|
||||
{
|
||||
ctor();
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::ctor()
|
||||
{
|
||||
setDefaultDisplayName(tr("Packaging for Android"));
|
||||
m_openPackageLocation = true;
|
||||
m_bundleQt = false;
|
||||
m_signPackage = false;
|
||||
connect(&m_outputParser, SIGNAL(addTask(ProjectExplorer::Task)), this, SIGNAL(addTask(ProjectExplorer::Task)));
|
||||
}
|
||||
|
||||
bool AndroidPackageCreationStep::init()
|
||||
{
|
||||
const QmakeBuildConfiguration *bc = qobject_cast<QmakeBuildConfiguration *>(target()->activeBuildConfiguration());
|
||||
if (!bc) {
|
||||
raiseError(tr("Cannot create Android package: current build configuration is not Qt 4."));
|
||||
return false;
|
||||
}
|
||||
QmakeProject *project = static_cast<QmakeProject *>(target()->project());
|
||||
m_outputParser.setProjectFileList(project->files(Project::AllFiles));
|
||||
|
||||
// Copying
|
||||
m_androidDir = AndroidManager::dirPath(target());
|
||||
Utils::FileName path = m_androidDir;
|
||||
QString androidTargetArch = project->rootQmakeProjectNode()->singleVariableValue(QmakeProjectManager::AndroidArchVar);
|
||||
if (androidTargetArch.isEmpty()) {
|
||||
raiseError(tr("Cannot create Android package: No ANDROID_TARGET_ARCH set in make spec."));
|
||||
return false;
|
||||
}
|
||||
|
||||
Utils::FileName androidLibPath = path.appendPath(QLatin1String("libs/") + androidTargetArch);
|
||||
m_gdbServerDestination = androidLibPath.appendPath(QLatin1String("gdbserver"));
|
||||
m_gdbServerSource = AndroidGdbServerKitInformation::gdbServer(target()->kit());
|
||||
|
||||
if (!AndroidManager::createAndroidTemplatesIfNecessary(target()))
|
||||
return false;
|
||||
|
||||
AndroidManager::updateTarget(target(), AndroidManager::buildTargetSDK(target()), AndroidManager::applicationName(target()));
|
||||
m_antToolPath = AndroidConfigurations::currentConfig().antToolPath();
|
||||
m_apkPathUnsigned = AndroidManager::apkPath(target(), AndroidManager::ReleaseBuildUnsigned);
|
||||
m_apkPathSigned = AndroidManager::apkPath(target(), AndroidManager::ReleaseBuildSigned);
|
||||
m_signPackageForRun = m_signPackage;
|
||||
m_keystorePathForRun = m_keystorePath;
|
||||
m_certificatePasswdForRun = m_certificatePasswd;
|
||||
m_jarSigner = AndroidConfigurations::currentConfig().jarsignerPath();
|
||||
m_zipAligner = AndroidConfigurations::currentConfig().zipalignPath();
|
||||
m_environment = bc->environment();
|
||||
|
||||
ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainKitInformation::toolChain(target()->kit());
|
||||
if (tc->type() != QLatin1String(Constants::ANDROID_TOOLCHAIN_TYPE))
|
||||
return false;
|
||||
|
||||
initCheckRequiredLibrariesForRun();
|
||||
|
||||
if (m_signPackage && (bc->qmakeBuildConfiguration() & QtSupport::BaseQtVersion::DebugBuild))
|
||||
emit addOutput(tr("Warning: Signing a debug package."), BuildStep::ErrorMessageOutput);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::run(QFutureInterface<bool> &fi)
|
||||
{
|
||||
fi.reportResult(createPackage());
|
||||
}
|
||||
|
||||
BuildStepConfigWidget *AndroidPackageCreationStep::createConfigWidget()
|
||||
{
|
||||
return new AndroidPackageCreationWidget(this);
|
||||
}
|
||||
|
||||
static inline QString msgCannotFindElfInformation()
|
||||
{
|
||||
return AndroidPackageCreationStep::tr("Cannot find ELF information");
|
||||
}
|
||||
|
||||
static inline QString msgCannotFindExecutable(const QString &appPath)
|
||||
{
|
||||
return AndroidPackageCreationStep::tr("Cannot find \"%1\".\n"
|
||||
"Please make sure your application is "
|
||||
"built successfully and is selected in Application tab ('Run option').").arg(appPath);
|
||||
}
|
||||
|
||||
static void parseSharedLibs(const QByteArray &buffer, QStringList *libs)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
QList<QByteArray> lines = buffer.trimmed().split('\r');
|
||||
#else
|
||||
QList<QByteArray> lines = buffer.trimmed().split('\n');
|
||||
#endif
|
||||
foreach (const QByteArray &line, lines) {
|
||||
if (line.contains("(NEEDED)") && line.contains("Shared library:") ) {
|
||||
const int pos = line.lastIndexOf('[') + 1;
|
||||
(*libs) << QString::fromLatin1(line.mid(pos, line.length() - pos - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void markNeeded(const QString &library,
|
||||
const QVector<AndroidManager::Library> &dependencies,
|
||||
QMap<QString, bool> *neededMap)
|
||||
{
|
||||
if (!neededMap->contains(library))
|
||||
return;
|
||||
if (neededMap->value(library))
|
||||
return;
|
||||
neededMap->insert(library, true);
|
||||
for (int i = 0; i < dependencies.size(); ++i) {
|
||||
if (dependencies.at(i).name == library) {
|
||||
foreach (const QString &dependency, dependencies.at(i).dependencies)
|
||||
markNeeded(dependency, dependencies, neededMap);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QStringList requiredLibraries(QVector<AndroidManager::Library> availableLibraries,
|
||||
const QStringList &checkedLibs, const QStringList &dependencies)
|
||||
{
|
||||
QMap<QString, bool> neededLibraries;
|
||||
QVector<AndroidManager::Library>::const_iterator it, end;
|
||||
it = availableLibraries.constBegin();
|
||||
end = availableLibraries.constEnd();
|
||||
|
||||
for (; it != end; ++it)
|
||||
neededLibraries[(*it).name] = false;
|
||||
|
||||
// Checked items are always needed
|
||||
foreach (const QString &lib, checkedLibs)
|
||||
markNeeded(lib, availableLibraries, &neededLibraries);
|
||||
|
||||
foreach (const QString &lib, dependencies) {
|
||||
if (lib.startsWith(QLatin1String("lib"))
|
||||
&& lib.endsWith(QLatin1String(".so")))
|
||||
markNeeded(lib.mid(3, lib.size() - 6), availableLibraries, &neededLibraries);
|
||||
}
|
||||
|
||||
for (int i = availableLibraries.size() - 1; i>= 0; --i)
|
||||
if (!neededLibraries.value(availableLibraries.at(i).name))
|
||||
availableLibraries.remove(i);
|
||||
|
||||
QStringList requiredLibraries;
|
||||
foreach (const AndroidManager::Library &lib, availableLibraries) {
|
||||
if (neededLibraries.value(lib.name))
|
||||
requiredLibraries << lib.name;
|
||||
}
|
||||
return requiredLibraries;
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::checkRequiredLibraries()
|
||||
{
|
||||
QProcess readelfProc;
|
||||
QString appPath = AndroidManager::targetApplicationPath(target());
|
||||
if (!QFile::exists(appPath)) {
|
||||
raiseError(msgCannotFindElfInformation(), msgCannotFindExecutable(appPath));
|
||||
return;
|
||||
}
|
||||
|
||||
ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainKitInformation::toolChain(target()->kit());
|
||||
if (tc->type() != QLatin1String(Constants::ANDROID_TOOLCHAIN_TYPE))
|
||||
return;
|
||||
AndroidToolChain *atc = static_cast<AndroidToolChain *>(tc);
|
||||
|
||||
readelfProc.start(AndroidConfigurations::currentConfig().readelfPath(target()->activeRunConfiguration()->abi().architecture(), atc->ndkToolChainVersion()).toString(),
|
||||
QStringList() << QLatin1String("-d") << QLatin1String("-W") << appPath);
|
||||
if (!readelfProc.waitForFinished(-1)) {
|
||||
readelfProc.kill();
|
||||
return;
|
||||
}
|
||||
QStringList libs;
|
||||
parseSharedLibs(readelfProc.readAll(), &libs);
|
||||
AndroidManager::setQtLibs(target(), requiredLibraries(AndroidManager::availableQtLibsWithDependencies(target()),
|
||||
AndroidManager::qtLibs(target()), libs));
|
||||
emit updateRequiredLibrariesModels();
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::initCheckRequiredLibrariesForRun()
|
||||
{
|
||||
ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainKitInformation::toolChain(target()->kit());
|
||||
if (tc->type() != QLatin1String(Constants::ANDROID_TOOLCHAIN_TYPE))
|
||||
return;
|
||||
AndroidToolChain *atc = static_cast<AndroidToolChain *>(tc);
|
||||
|
||||
m_appPath = Utils::FileName::fromString(AndroidManager::targetApplicationPath(target()));
|
||||
m_readElf = AndroidConfigurations::currentConfig().readelfPath(target()->activeRunConfiguration()->abi().architecture(),
|
||||
atc->ndkToolChainVersion());
|
||||
m_qtLibs = AndroidManager::qtLibs(target());
|
||||
m_availableQtLibs = AndroidManager::availableQtLibsWithDependencies(target());
|
||||
m_prebundledLibs = AndroidManager::prebundledLibs(target());
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::getBundleInformation()
|
||||
{
|
||||
m_bundleQt = AndroidManager::bundleQt(target());
|
||||
if (m_bundleQt) {
|
||||
m_bundledJars = AndroidManager::loadLocalJars(target()).split(QLatin1Char(':'),
|
||||
QString::SkipEmptyParts);
|
||||
m_otherBundledFiles = AndroidManager::loadLocalBundledFiles(target()).split(QLatin1Char(':'),
|
||||
QString::SkipEmptyParts);
|
||||
}
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::checkRequiredLibrariesForRun()
|
||||
{
|
||||
QProcess readelfProc;
|
||||
if (!m_appPath.toFileInfo().exists()) {
|
||||
raiseError(msgCannotFindElfInformation(), msgCannotFindExecutable(m_appPath.toUserOutput()));
|
||||
return;
|
||||
}
|
||||
readelfProc.start(m_readElf.toString(), QStringList() << QLatin1String("-d") << QLatin1String("-W") << m_appPath.toUserOutput());
|
||||
if (!readelfProc.waitForFinished(-1)) {
|
||||
readelfProc.kill();
|
||||
return;
|
||||
}
|
||||
QStringList libs;
|
||||
parseSharedLibs(readelfProc.readAll(), &libs);
|
||||
|
||||
m_qtLibsWithDependencies = requiredLibraries(m_availableQtLibs, m_qtLibs, libs);
|
||||
QMetaObject::invokeMethod(this, "setQtLibs",Qt::BlockingQueuedConnection,
|
||||
Q_ARG(QStringList, m_qtLibsWithDependencies));
|
||||
|
||||
QMetaObject::invokeMethod(this, "getBundleInformation", Qt::BlockingQueuedConnection);
|
||||
|
||||
emit updateRequiredLibrariesModels();
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::setQtLibs(const QStringList &qtLibs)
|
||||
{
|
||||
AndroidManager::setQtLibs(target(), qtLibs);
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::setPrebundledLibs(const QStringList &prebundledLibs)
|
||||
{
|
||||
AndroidManager::setPrebundledLibs(target(), prebundledLibs);
|
||||
}
|
||||
|
||||
Utils::FileName AndroidPackageCreationStep::keystorePath()
|
||||
{
|
||||
return m_keystorePath;
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::setKeystorePath(const Utils::FileName &path)
|
||||
{
|
||||
m_keystorePath = path;
|
||||
m_certificatePasswd.clear();
|
||||
m_keystorePasswd.clear();
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::setKeystorePassword(const QString &pwd)
|
||||
{
|
||||
m_keystorePasswd = pwd;
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::setCertificateAlias(const QString &alias)
|
||||
{
|
||||
m_certificateAlias = alias;
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::setCertificatePassword(const QString &pwd)
|
||||
{
|
||||
m_certificatePasswd = pwd;
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::setOpenPackageLocation(bool open)
|
||||
{
|
||||
m_openPackageLocation = open;
|
||||
}
|
||||
|
||||
QAbstractItemModel *AndroidPackageCreationStep::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 AndroidPackageCreationStep::signPackage() const
|
||||
{
|
||||
return m_signPackage;
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::setSignPackage(bool b)
|
||||
{
|
||||
m_signPackage = b;
|
||||
}
|
||||
|
||||
bool AndroidPackageCreationStep::fromMap(const QVariantMap &map)
|
||||
{
|
||||
if (!BuildStep::fromMap(map))
|
||||
return false;
|
||||
m_keystorePath = Utils::FileName::fromString(map.value(KeystoreLocationKey).toString());
|
||||
m_signPackage = map.value(SignPackageKey).toBool();
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariantMap AndroidPackageCreationStep::toMap() const
|
||||
{
|
||||
QVariantMap map(BuildStep::toMap());
|
||||
map.insert(KeystoreLocationKey, m_keystorePath.toString());
|
||||
map.insert(SignPackageKey, m_signPackage);
|
||||
return map;
|
||||
}
|
||||
|
||||
QStringList AndroidPackageCreationStep::collectRelativeFilePaths(const QString &parentPath)
|
||||
{
|
||||
QStringList relativeFilePaths;
|
||||
|
||||
QDirIterator libsIt(parentPath, QDir::NoFilter, QDirIterator::Subdirectories);
|
||||
int pos = parentPath.size();
|
||||
while (libsIt.hasNext()) {
|
||||
libsIt.next();
|
||||
if (!libsIt.fileInfo().isDir())
|
||||
relativeFilePaths.append(libsIt.filePath().mid(pos));
|
||||
}
|
||||
|
||||
return relativeFilePaths;
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::collectFiles(QList<DeployItem> *deployList,
|
||||
QList<DeployItem> *pluginsAndImportsList)
|
||||
{
|
||||
Q_ASSERT(deployList != 0);
|
||||
QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target()->kit());
|
||||
if (!version)
|
||||
return;
|
||||
|
||||
QmakeProject *project = static_cast<QmakeProject *>(target()->project());
|
||||
QString androidTargetArch = project->rootQmakeProjectNode()->singleVariableValue(QmakeProjectManager::AndroidArchVar);
|
||||
|
||||
QString androidAssetsPath = m_androidDir.toString() + QLatin1String("/assets/");
|
||||
QString androidJarPath = m_androidDir.toString() + QLatin1String("/libs/");
|
||||
QString androidLibPath = m_androidDir.toString() + QLatin1String("/libs/") + androidTargetArch;
|
||||
|
||||
QString qtVersionSourcePath = version->sourcePath().toString();
|
||||
|
||||
foreach (QString qtLib, m_qtLibsWithDependencies) {
|
||||
QString fullPath = qtVersionSourcePath
|
||||
+ QLatin1String("/lib/lib")
|
||||
+ qtLib
|
||||
+ QLatin1String(".so");
|
||||
QString destinationPath = androidLibPath
|
||||
+ QLatin1String("/lib")
|
||||
+ qtLib
|
||||
+ QLatin1String(".so");
|
||||
|
||||
// If the Qt lib/ folder contains libgnustl_shared.so, don't deploy it from there, since
|
||||
// it will be deployed directly from the NDK instead.
|
||||
if (qtLib != QLatin1String("gnustl_shared")) {
|
||||
DeployItem deployItem(fullPath, 0, destinationPath, true);
|
||||
deployList->append(deployItem);
|
||||
}
|
||||
}
|
||||
|
||||
if (!androidTargetArch.isEmpty()) {
|
||||
ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainKitInformation::toolChain(target()->kit());
|
||||
if (tc->type() != QLatin1String(Constants::ANDROID_TOOLCHAIN_TYPE))
|
||||
return;
|
||||
|
||||
AndroidToolChain *atc = static_cast<AndroidToolChain *>(tc);
|
||||
|
||||
QString libgnustl = AndroidManager::libGnuStl(androidTargetArch, atc->ndkToolChainVersion());
|
||||
DeployItem deployItem(libgnustl, 0, androidLibPath + QLatin1String("/libgnustl_shared.so"), false);
|
||||
deployList->append(deployItem);
|
||||
}
|
||||
|
||||
foreach (QString jar, m_bundledJars) {
|
||||
QString fullPath = qtVersionSourcePath + QLatin1Char('/') + jar;
|
||||
QFileInfo fileInfo(fullPath);
|
||||
if (fileInfo.exists()) {
|
||||
QString destinationPath = androidJarPath
|
||||
+ AndroidManager::libraryPrefix()
|
||||
+ fileInfo.fileName();
|
||||
deployList->append(DeployItem(fullPath, 0, destinationPath, true));
|
||||
}
|
||||
}
|
||||
|
||||
QSet<QString> alreadyListed;
|
||||
foreach (QString bundledFile, m_otherBundledFiles) {
|
||||
QStringList allFiles;
|
||||
if (QFileInfo(qtVersionSourcePath + QLatin1Char('/') + bundledFile).isDir()) {
|
||||
if (!bundledFile.endsWith(QLatin1Char('/')))
|
||||
bundledFile.append(QLatin1Char('/'));
|
||||
|
||||
allFiles = collectRelativeFilePaths(qtVersionSourcePath + QLatin1Char('/') + bundledFile);
|
||||
} else {
|
||||
// If we need to bundle a specific file, we just add an empty string and the file
|
||||
// names and data will be prepared correctly in the loop below.
|
||||
allFiles = QStringList(QString());
|
||||
}
|
||||
|
||||
foreach (QString file, allFiles) {
|
||||
QString fullPath = qtVersionSourcePath + QLatin1Char('/') + bundledFile + file;
|
||||
if (alreadyListed.contains(fullPath))
|
||||
continue;
|
||||
|
||||
alreadyListed.insert(fullPath);
|
||||
|
||||
QString garbledFileName;
|
||||
QString destinationPath;
|
||||
bool shouldStrip = false;
|
||||
|
||||
QString fullFileName = bundledFile + file;
|
||||
if (fullFileName.endsWith(QLatin1String(".so"))) {
|
||||
if (fullFileName.startsWith(QLatin1String("lib/"))) {
|
||||
// Special case when the destination folder is lib/
|
||||
// Since this is also the source folder, there is no need to garble the file
|
||||
// name and copy it. We also won't have write access to this folder, so we
|
||||
// couldn't if we wanted to.
|
||||
garbledFileName = fullFileName.mid(sizeof("lib/") - 1);
|
||||
} else {
|
||||
garbledFileName = QLatin1String("lib")
|
||||
+ AndroidManager::libraryPrefix()
|
||||
+ QString(fullFileName).replace(QLatin1Char('/'), QLatin1Char('_'));
|
||||
}
|
||||
destinationPath = androidLibPath + QLatin1Char('/') + garbledFileName;
|
||||
shouldStrip = true;
|
||||
} else {
|
||||
garbledFileName = AndroidManager::libraryPrefix() + QLatin1Char('/') + fullFileName;
|
||||
destinationPath = androidAssetsPath + garbledFileName;
|
||||
}
|
||||
|
||||
deployList->append(DeployItem(fullPath, 0, destinationPath, shouldStrip));
|
||||
pluginsAndImportsList->append(DeployItem(garbledFileName,
|
||||
0,
|
||||
fullFileName,
|
||||
shouldStrip));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::removeManagedFilesFromPackage(const Utils::FileName &qtLibraryDir)
|
||||
{
|
||||
// Clean up all files managed by Qt Creator
|
||||
{
|
||||
QString androidLibPath = m_androidDir.toString() + QLatin1String("/libs/");
|
||||
QDirIterator dirIt(m_androidDir.toString(), QDirIterator::Subdirectories);
|
||||
while (dirIt.hasNext()) {
|
||||
dirIt.next();
|
||||
|
||||
if (!dirIt.fileInfo().isDir()) {
|
||||
bool isQtLibrary = dirIt.fileInfo().path().startsWith(androidLibPath)
|
||||
&& dirIt.fileName().startsWith(QLatin1String("libQt5"))
|
||||
&& dirIt.fileName().endsWith(QLatin1String(".so"));
|
||||
|
||||
if (isQtLibrary) {
|
||||
Utils::FileName qtLibraryFile = qtLibraryDir;
|
||||
qtLibraryFile.appendPath(dirIt.fileName());
|
||||
isQtLibrary = qtLibraryFile.toFileInfo().exists();
|
||||
}
|
||||
|
||||
if (dirIt.filePath().contains(AndroidManager::libraryPrefix()) || isQtLibrary)
|
||||
QFile::remove(dirIt.filePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
removeDirectory(m_androidDir.toString() + QLatin1String("/assets/") + AndroidManager::libraryPrefix());
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::copyFilesIntoPackage(const QList<DeployItem> &deployList)
|
||||
{
|
||||
foreach (DeployItem item, deployList) {
|
||||
QFileInfo info(item.remoteFileName);
|
||||
if (info.exists())
|
||||
QFile::remove(item.remoteFileName);
|
||||
else
|
||||
QDir().mkpath(info.absolutePath());
|
||||
|
||||
QFile::copy(item.localFileName, item.remoteFileName);
|
||||
}
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::stripFiles(const QList<DeployItem> &deployList)
|
||||
{
|
||||
|
||||
QStringList fileList;
|
||||
foreach (DeployItem item, deployList)
|
||||
if (item.needsStrip)
|
||||
fileList.append(item.remoteFileName);
|
||||
|
||||
ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainKitInformation::toolChain(target()->kit());
|
||||
if (tc->type() != QLatin1String(Constants::ANDROID_TOOLCHAIN_TYPE))
|
||||
return;
|
||||
|
||||
AndroidToolChain *atc = static_cast<AndroidToolChain *>(tc);
|
||||
stripAndroidLibs(fileList,
|
||||
target()->activeRunConfiguration()->abi().architecture(),
|
||||
atc->ndkToolChainVersion());
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::updateXmlForFiles(const QStringList &inLibList,
|
||||
const QStringList &inAssetsList)
|
||||
{
|
||||
AndroidManager::setBundledInLib(target(), inLibList);
|
||||
AndroidManager::setBundledInAssets(target(), inAssetsList);
|
||||
}
|
||||
|
||||
|
||||
bool AndroidPackageCreationStep::createPackage()
|
||||
{
|
||||
checkRequiredLibrariesForRun();
|
||||
|
||||
emit addOutput(tr("Copy Qt app & libs to Android package ..."), MessageOutput);
|
||||
|
||||
QStringList build;
|
||||
// build << QLatin1String("-silent"); //TODO depends on ant 1.9.0, enabled, not *now*
|
||||
build << QLatin1String("clean");
|
||||
QFile::remove(m_gdbServerDestination.toString());
|
||||
if (m_signPackageForRun) {
|
||||
build << QLatin1String("release");
|
||||
} else {
|
||||
build << QLatin1String("debug");
|
||||
QDir dir;
|
||||
dir.mkpath(m_gdbServerDestination.toFileInfo().absolutePath());
|
||||
if (!QFile::copy(m_gdbServerSource.toString(), m_gdbServerDestination.toString())) {
|
||||
raiseError(tr("Can't copy gdbserver from \"%1\" to \"%2\"").arg(m_gdbServerSource.toUserOutput())
|
||||
.arg(m_gdbServerDestination.toUserOutput()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
QList<DeployItem> deployFiles;
|
||||
QList<DeployItem> importsAndPlugins;
|
||||
|
||||
QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target()->kit());
|
||||
|
||||
// Qt 5 supports bundling libraries inside the apk. We guard the code for Qt 5 to be sure we
|
||||
// do not disrupt existing projects.
|
||||
if (version && version->qtVersion() >= QtSupport::QtVersionNumber(5, 0, 0)) {
|
||||
bool bundleQt = AndroidManager::bundleQt(target());
|
||||
|
||||
// Collect the files to bundle in the package
|
||||
if (bundleQt)
|
||||
collectFiles(&deployFiles, &importsAndPlugins);
|
||||
|
||||
// Remove files from package if they are not needed
|
||||
removeManagedFilesFromPackage(version->libraryPath());
|
||||
|
||||
// Deploy files to package
|
||||
if (bundleQt) {
|
||||
copyFilesIntoPackage(deployFiles);
|
||||
stripFiles(deployFiles);
|
||||
|
||||
QStringList inLibList;
|
||||
QStringList inAssetsList;
|
||||
foreach (DeployItem deployItem, importsAndPlugins) {
|
||||
QString conversionInfo = deployItem.localFileName
|
||||
+ QLatin1Char(':')
|
||||
+ deployItem.remoteFileName;
|
||||
|
||||
if (deployItem.localFileName.endsWith(QLatin1String(".so")))
|
||||
inLibList.append(conversionInfo);
|
||||
else
|
||||
inAssetsList.append(conversionInfo);
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod(this,
|
||||
"updateXmlForFiles",
|
||||
Qt::BlockingQueuedConnection,
|
||||
Q_ARG(QStringList, inLibList),
|
||||
Q_ARG(QStringList, inAssetsList));
|
||||
}
|
||||
}
|
||||
|
||||
emit addOutput(tr("Creating package file ..."), MessageOutput);
|
||||
|
||||
QProcess *const buildProc = new QProcess;
|
||||
buildProc->setProcessEnvironment(m_environment.toProcessEnvironment());
|
||||
|
||||
connect(buildProc, SIGNAL(readyReadStandardOutput()), this,
|
||||
SLOT(handleBuildStdOutOutput()), Qt::DirectConnection);
|
||||
connect(buildProc, SIGNAL(readyReadStandardError()), this,
|
||||
SLOT(handleBuildStdErrOutput()), Qt::DirectConnection);
|
||||
|
||||
buildProc->setWorkingDirectory(m_androidDir.toString());
|
||||
|
||||
if (!runCommand(buildProc, m_antToolPath.toString(), build)) {
|
||||
disconnect(buildProc, 0, this, 0);
|
||||
buildProc->deleteLater();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_signPackageForRun) {
|
||||
emit addOutput(tr("Signing package ..."), MessageOutput);
|
||||
while (true) {
|
||||
if (m_certificatePasswdForRun.isEmpty())
|
||||
QMetaObject::invokeMethod(this, "certificatePassword", Qt::BlockingQueuedConnection);
|
||||
|
||||
if (m_certificatePasswdForRun.isEmpty()) {
|
||||
disconnect(buildProc, 0, this, 0);
|
||||
buildProc->deleteLater();
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray keyPass = m_certificatePasswdForRun.toUtf8();
|
||||
build.clear();
|
||||
build << QLatin1String("-verbose") << QLatin1String("-digestalg") << QLatin1String("SHA1")
|
||||
<< QLatin1String("-sigalg") << QLatin1String("MD5withRSA")
|
||||
<< QLatin1String("-keystore") << m_keystorePathForRun.toUserOutput()
|
||||
<< QLatin1String("-storepass") << m_keystorePasswd
|
||||
<< m_apkPathUnsigned.toUserOutput()
|
||||
<< m_certificateAlias;
|
||||
buildProc->start(m_jarSigner.toString(), build);
|
||||
if (!buildProc->waitForStarted()) {
|
||||
disconnect(buildProc, 0, this, 0);
|
||||
buildProc->deleteLater();
|
||||
return false;
|
||||
}
|
||||
|
||||
keyPass += '\n';
|
||||
buildProc->write(keyPass);
|
||||
buildProc->waitForBytesWritten();
|
||||
buildProc->waitForFinished();
|
||||
|
||||
if (!buildProc->exitCode())
|
||||
break;
|
||||
emit addOutput(tr("Failed, try again"), ErrorMessageOutput);
|
||||
m_certificatePasswdForRun.clear();
|
||||
}
|
||||
build.clear();
|
||||
build << QLatin1String("-f") << QLatin1String("-v") << QLatin1String("4") << m_apkPathUnsigned.toString() << m_apkPathSigned.toString();
|
||||
buildProc->start(m_zipAligner.toString(), build);
|
||||
buildProc->waitForFinished();
|
||||
if (!buildProc->exitCode()) {
|
||||
QFile::remove(m_apkPathUnsigned.toString());
|
||||
emit addOutput(tr("Release signed package created to %1")
|
||||
.arg(m_apkPathSigned.toUserOutput())
|
||||
, MessageOutput);
|
||||
|
||||
if (m_openPackageLocation)
|
||||
QMetaObject::invokeMethod(this, "showInGraphicalShell", Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
emit addOutput(tr("Package created."), BuildStep::MessageOutput);
|
||||
disconnect(buildProc, 0, this, 0);
|
||||
buildProc->deleteLater();
|
||||
return true;
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::stripAndroidLibs(const QStringList & files, Abi::Architecture architecture, const QString &ndkToolchainVersion)
|
||||
{
|
||||
QProcess stripProcess;
|
||||
foreach (const QString &file, files) {
|
||||
stripProcess.start(AndroidConfigurations::currentConfig().stripPath(architecture, ndkToolchainVersion).toString(),
|
||||
QStringList()<<QLatin1String("--strip-unneeded") << file);
|
||||
stripProcess.waitForStarted();
|
||||
if (!stripProcess.waitForFinished())
|
||||
stripProcess.kill();
|
||||
}
|
||||
}
|
||||
|
||||
bool AndroidPackageCreationStep::removeDirectory(const QString &dirPath)
|
||||
{
|
||||
QDir dir(dirPath);
|
||||
if (!dir.exists())
|
||||
return true;
|
||||
|
||||
const QStringList &files
|
||||
= dir.entryList(QDir::Files | QDir::Hidden | QDir::System);
|
||||
foreach (const QString &fileName, files) {
|
||||
if (!dir.remove(fileName))
|
||||
return false;
|
||||
}
|
||||
|
||||
const QStringList &subDirs
|
||||
= dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
foreach (const QString &subDirName, subDirs) {
|
||||
if (!removeDirectory(dirPath + QLatin1Char('/') + subDirName))
|
||||
return false;
|
||||
}
|
||||
|
||||
return dir.rmdir(dirPath);
|
||||
}
|
||||
|
||||
bool AndroidPackageCreationStep::runCommand(QProcess *buildProc
|
||||
, const QString &program, const QStringList &arguments)
|
||||
{
|
||||
emit addOutput(tr("Package deploy: Running command '%1 %2'.").arg(program).arg(arguments.join(QLatin1String(" "))), BuildStep::MessageOutput);
|
||||
buildProc->start(program, arguments);
|
||||
if (!buildProc->waitForStarted()) {
|
||||
raiseError(tr("Packaging failed."),
|
||||
tr("Packaging error: Could not start command '%1 %2'. Reason: %3")
|
||||
.arg(program).arg(arguments.join(QLatin1String(" "))).arg(buildProc->errorString()));
|
||||
return false;
|
||||
}
|
||||
buildProc->waitForFinished(-1);
|
||||
|
||||
handleProcessOutput(buildProc, false);
|
||||
handleProcessOutput(buildProc, true);
|
||||
|
||||
if (buildProc->error() != QProcess::UnknownError
|
||||
|| buildProc->exitCode() != 0) {
|
||||
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());
|
||||
else
|
||||
mainMessage += tr("Exit code: %1").arg(buildProc->exitCode());
|
||||
raiseError(mainMessage);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::handleBuildStdOutOutput()
|
||||
{
|
||||
QProcess *const process = qobject_cast<QProcess *>(sender());
|
||||
if (!process)
|
||||
return;
|
||||
handleProcessOutput(process, false);
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::handleBuildStdErrOutput()
|
||||
{
|
||||
QProcess *const process = qobject_cast<QProcess *>(sender());
|
||||
if (!process)
|
||||
return;
|
||||
|
||||
handleProcessOutput(process, true);
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::handleProcessOutput(QProcess *process, bool stdErr)
|
||||
{
|
||||
process->setReadChannel(stdErr ? QProcess::StandardError : QProcess::StandardOutput);
|
||||
while (process->canReadLine()) {
|
||||
QString line = QString::fromLocal8Bit(process->readLine());
|
||||
if (stdErr)
|
||||
m_outputParser.stdError(line);
|
||||
else
|
||||
m_outputParser.stdOutput(line);
|
||||
emit addOutput(line, stdErr ? BuildStep::ErrorOutput
|
||||
: BuildStep::NormalOutput,
|
||||
BuildStep::DontAppendNewline);
|
||||
}
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::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;
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::certificatePassword()
|
||||
{
|
||||
m_certificatePasswdForRun.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_certificatePasswdForRun = text;
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::showInGraphicalShell()
|
||||
{
|
||||
Core::FileUtils::showInGraphicalShell(Core::ICore::mainWindow(), m_apkPathSigned.toString());
|
||||
}
|
||||
|
||||
void AndroidPackageCreationStep::raiseError(const QString &shortMsg,
|
||||
const QString &detailedMsg)
|
||||
{
|
||||
emit addOutput(detailedMsg.isNull() ? shortMsg : detailedMsg, BuildStep::ErrorOutput);
|
||||
emit addTask(Task(Task::Error, shortMsg, Utils::FileName::fromString(QString()), -1,
|
||||
TASK_CATEGORY_DEPLOYMENT));
|
||||
}
|
||||
|
||||
const Core::Id AndroidPackageCreationStep::CreatePackageId("Qt4ProjectManager.AndroidPackageCreationStep");
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Android
|
||||
@@ -1,156 +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 ANDROIDPACKAGECREATIONSTEP_H
|
||||
#define ANDROIDPACKAGECREATIONSTEP_H
|
||||
|
||||
#include "javaparser.h"
|
||||
#include "androidmanager.h"
|
||||
|
||||
#include <projectexplorer/abi.h>
|
||||
#include <projectexplorer/buildstep.h>
|
||||
#include <utils/environment.h>
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QProcess;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Android {
|
||||
namespace Internal {
|
||||
|
||||
class DeployItem;
|
||||
|
||||
class AndroidPackageCreationStep : public ProjectExplorer::BuildStep
|
||||
{
|
||||
Q_OBJECT
|
||||
friend class AndroidPackageCreationFactory;
|
||||
|
||||
public:
|
||||
AndroidPackageCreationStep(ProjectExplorer::BuildStepList *bsl);
|
||||
|
||||
static bool removeDirectory(const QString &dirPath);
|
||||
static void stripAndroidLibs(const QStringList &files, ProjectExplorer::Abi::Architecture architecture, const QString &ndkToolchainVersion);
|
||||
|
||||
static const QLatin1String DefaultVersionNumber;
|
||||
|
||||
void checkRequiredLibraries();
|
||||
void initCheckRequiredLibrariesForRun();
|
||||
void checkRequiredLibrariesForRun();
|
||||
|
||||
Utils::FileName keystorePath();
|
||||
void setKeystorePath(const Utils::FileName &path);
|
||||
void setKeystorePassword(const QString &pwd);
|
||||
void setCertificateAlias(const QString &alias);
|
||||
void setCertificatePassword(const QString &pwd);
|
||||
void setOpenPackageLocation(bool open);
|
||||
QAbstractItemModel *keystoreCertificates();
|
||||
bool signPackage() const;
|
||||
void setSignPackage(bool b);
|
||||
|
||||
protected:
|
||||
bool fromMap(const QVariantMap &map);
|
||||
QVariantMap toMap() const;
|
||||
|
||||
private slots:
|
||||
void handleBuildStdOutOutput();
|
||||
void handleBuildStdErrOutput();
|
||||
void keystorePassword();
|
||||
void certificatePassword();
|
||||
void showInGraphicalShell();
|
||||
void setQtLibs(const QStringList &qtLibs);
|
||||
void setPrebundledLibs(const QStringList &prebundledLibs);
|
||||
void updateXmlForFiles(const QStringList &inLibList, const QStringList &inAssetsList);
|
||||
void getBundleInformation();
|
||||
|
||||
signals:
|
||||
void updateRequiredLibrariesModels();
|
||||
|
||||
private:
|
||||
AndroidPackageCreationStep(ProjectExplorer::BuildStepList *buildConfig,
|
||||
AndroidPackageCreationStep *other);
|
||||
|
||||
void ctor();
|
||||
virtual bool init();
|
||||
virtual void run(QFutureInterface<bool> &fi);
|
||||
virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
|
||||
virtual bool immutable() const { return true; }
|
||||
bool createPackage();
|
||||
bool runCommand(QProcess *buildProc, const QString &program, const QStringList &arguments);
|
||||
void raiseError(const QString &shortMsg,
|
||||
const QString &detailedMsg = QString());
|
||||
|
||||
QStringList collectRelativeFilePaths(const QString &parentPath);
|
||||
void collectFiles(QList<DeployItem> *deployList, QList<DeployItem> *pluginsAndImports);
|
||||
void removeManagedFilesFromPackage(const Utils::FileName &qtLibraryDir);
|
||||
void copyFilesIntoPackage(const QList<DeployItem> &deployList);
|
||||
void stripFiles(const QList<DeployItem> &deployList);
|
||||
|
||||
static const Core::Id CreatePackageId;
|
||||
|
||||
private:
|
||||
void handleProcessOutput(QProcess *process, bool stdErr);
|
||||
bool m_signPackage;
|
||||
Utils::FileName m_keystorePath;
|
||||
QString m_keystorePasswd;
|
||||
QString m_certificateAlias;
|
||||
QString m_certificatePasswd;
|
||||
bool m_openPackageLocation;
|
||||
JavaParser m_outputParser;
|
||||
|
||||
// members to pass data from init() to run()
|
||||
Utils::FileName m_androidDir;
|
||||
Utils::FileName m_gdbServerSource;
|
||||
Utils::FileName m_gdbServerDestination;
|
||||
Utils::FileName m_antToolPath;
|
||||
Utils::FileName m_apkPathUnsigned;
|
||||
Utils::FileName m_apkPathSigned;
|
||||
bool m_signPackageForRun;
|
||||
Utils::FileName m_keystorePathForRun;
|
||||
QString m_certificatePasswdForRun;
|
||||
Utils::FileName m_jarSigner;
|
||||
Utils::FileName m_zipAligner;
|
||||
// more for checkLibraries
|
||||
Utils::FileName m_appPath;
|
||||
Utils::FileName m_readElf;
|
||||
QStringList m_qtLibs;
|
||||
QStringList m_qtLibsWithDependencies;
|
||||
QVector<AndroidManager::Library> m_availableQtLibs;
|
||||
QStringList m_prebundledLibs;
|
||||
QStringList m_bundledJars;
|
||||
QStringList m_otherBundledFiles;
|
||||
bool m_bundleQt;
|
||||
Utils::Environment m_environment;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Android
|
||||
|
||||
#endif // ANDROIDPACKAGECREATIONSTEP_H
|
||||
@@ -1,394 +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 "androidpackagecreationwidget.h"
|
||||
#include "androidpackagecreationstep.h"
|
||||
#include "androidconfigurations.h"
|
||||
#include "androidcreatekeystorecertificate.h"
|
||||
#include "androidmanager.h"
|
||||
#include "androiddeploystep.h"
|
||||
#include "androidglobal.h"
|
||||
#include "ui_androidpackagecreationwidget.h"
|
||||
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/target.h>
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
#include <projectexplorer/buildmanager.h>
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
#include <qmakeprojectmanager/qmakebuildconfiguration.h>
|
||||
#include <qmakeprojectmanager/qmakestep.h>
|
||||
#include <utils/pathchooser.h>
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QFileSystemWatcher>
|
||||
#include <QMessageBox>
|
||||
#include <qtsupport/baseqtversion.h>
|
||||
#include <qtsupport/qtkitinformation.h>
|
||||
|
||||
namespace Android {
|
||||
namespace Internal {
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
using namespace QmakeProjectManager;
|
||||
|
||||
///////////////////////////// CheckModel /////////////////////////////
|
||||
|
||||
CheckModel::CheckModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void CheckModel::setAvailableItems(const QStringList &items)
|
||||
{
|
||||
beginResetModel();
|
||||
m_availableItems = items;
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void CheckModel::setCheckedItems(const QStringList &items)
|
||||
{
|
||||
m_checkedItems = items;
|
||||
if (rowCount())
|
||||
emit dataChanged(index(0), index(rowCount()-1));
|
||||
}
|
||||
|
||||
const QStringList &CheckModel::checkedItems()
|
||||
{
|
||||
return m_checkedItems;
|
||||
}
|
||||
|
||||
QVariant CheckModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
switch (role) {
|
||||
case Qt::CheckStateRole:
|
||||
return m_checkedItems.contains(m_availableItems.at(index.row())) ? Qt::Checked : Qt::Unchecked;
|
||||
case Qt::DisplayRole:
|
||||
return m_availableItems.at(index.row());
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void CheckModel::moveUp(int index)
|
||||
{
|
||||
beginMoveRows(QModelIndex(), index, index, QModelIndex(), index - 1);
|
||||
const QString &item1 = m_availableItems[index];
|
||||
const QString &item2 = m_availableItems[index - 1];
|
||||
m_availableItems.swap(index, index - 1);
|
||||
index = m_checkedItems.indexOf(item1);
|
||||
int index2 = m_checkedItems.indexOf(item2);
|
||||
if (index > -1 && index2 > -1)
|
||||
m_checkedItems.swap(index, index2);
|
||||
endMoveRows();
|
||||
}
|
||||
|
||||
bool CheckModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if (role != Qt::CheckStateRole || !index.isValid())
|
||||
return false;
|
||||
if (value.toInt() == Qt::Checked)
|
||||
m_checkedItems.append(m_availableItems.at(index.row()));
|
||||
else
|
||||
m_checkedItems.removeAll(m_availableItems.at(index.row()));
|
||||
emit dataChanged(index, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
int CheckModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid())
|
||||
return 0;
|
||||
return m_availableItems.count();
|
||||
}
|
||||
|
||||
Qt::ItemFlags CheckModel::flags(const QModelIndex &/*index*/) const
|
||||
{
|
||||
return Qt::ItemIsSelectable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled;
|
||||
}
|
||||
|
||||
///////////////////////////// AndroidPackageCreationWidget /////////////////////////////
|
||||
|
||||
AndroidPackageCreationWidget::AndroidPackageCreationWidget(AndroidPackageCreationStep *step)
|
||||
: ProjectExplorer::BuildStepConfigWidget(),
|
||||
m_step(step),
|
||||
m_ui(new Ui::AndroidPackageCreationWidget),
|
||||
m_fileSystemWatcher(new QFileSystemWatcher(this)),
|
||||
m_currentBuildConfiguration(0)
|
||||
{
|
||||
m_qtLibsModel = new CheckModel(this);
|
||||
m_prebundledLibs = new CheckModel(this);
|
||||
|
||||
m_ui->setupUi(this);
|
||||
m_ui->KeystoreLocationPushButton->setText(Utils::PathChooser::browseButtonLabel());
|
||||
m_ui->signingDebugWarningIcon->hide();
|
||||
m_ui->signingDebugWarningLabel->hide();
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
QTimer::singleShot(50, this, SLOT(initGui()));
|
||||
connect(m_step, SIGNAL(updateRequiredLibrariesModels()), SLOT(updateRequiredLibrariesModels()));
|
||||
}
|
||||
|
||||
void AndroidPackageCreationWidget::initGui()
|
||||
{
|
||||
updateAndroidProjectInfo();
|
||||
ProjectExplorer::Target *target = m_step->target();
|
||||
|
||||
m_fileSystemWatcher->addPath(AndroidManager::dirPath(target).toString());
|
||||
m_fileSystemWatcher->addPath(AndroidManager::manifestPath(target).toString());
|
||||
m_fileSystemWatcher->addPath(AndroidManager::srcPath(target).toString());
|
||||
connect(m_fileSystemWatcher, SIGNAL(directoryChanged(QString)),
|
||||
this, SLOT(updateAndroidProjectInfo()));
|
||||
connect(m_fileSystemWatcher, SIGNAL(fileChanged(QString)), this,
|
||||
SLOT(updateAndroidProjectInfo()));
|
||||
|
||||
connect(m_ui->targetSDKComboBox, SIGNAL(activated(QString)), SLOT(setTargetSDK(QString)));
|
||||
connect(m_qtLibsModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), SLOT(setQtLibs(QModelIndex,QModelIndex)));
|
||||
connect(m_prebundledLibs, SIGNAL(dataChanged(QModelIndex,QModelIndex)), SLOT(setPrebundledLibs(QModelIndex,QModelIndex)));
|
||||
connect(m_ui->prebundledLibsListView, SIGNAL(activated(QModelIndex)), SLOT(prebundledLibSelected(QModelIndex)));
|
||||
connect(m_ui->prebundledLibsListView, SIGNAL(clicked(QModelIndex)), SLOT(prebundledLibSelected(QModelIndex)));
|
||||
connect(m_ui->upPushButton, SIGNAL(clicked()), SLOT(prebundledLibMoveUp()));
|
||||
connect(m_ui->downPushButton, SIGNAL(clicked()), SLOT(prebundledLibMoveDown()));
|
||||
connect(m_ui->readInfoPushButton, SIGNAL(clicked()), SLOT(readElfInfo()));
|
||||
|
||||
m_ui->qtLibsListView->setModel(m_qtLibsModel);
|
||||
m_ui->prebundledLibsListView->setModel(m_prebundledLibs);
|
||||
m_ui->KeystoreLocationLineEdit->setText(m_step->keystorePath().toUserOutput());
|
||||
|
||||
// Make the buildconfiguration emit a evironmentChanged() signal
|
||||
// TODO find a better way
|
||||
QmakeBuildConfiguration *bc = qobject_cast<QmakeBuildConfiguration *>(m_step->target()->activeBuildConfiguration());
|
||||
if (!bc)
|
||||
return;
|
||||
bool use = bc->useSystemEnvironment();
|
||||
bc->setUseSystemEnvironment(!use);
|
||||
bc->setUseSystemEnvironment(use);
|
||||
|
||||
activeBuildConfigurationChanged();
|
||||
connect(m_step->target(), SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
|
||||
this, SLOT(activeBuildConfigurationChanged()));
|
||||
}
|
||||
|
||||
void AndroidPackageCreationWidget::updateSigningWarning()
|
||||
{
|
||||
QmakeBuildConfiguration *bc = qobject_cast<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 AndroidPackageCreationWidget::activeBuildConfigurationChanged()
|
||||
{
|
||||
if (m_currentBuildConfiguration)
|
||||
disconnect(m_currentBuildConfiguration, SIGNAL(qmakeBuildConfigurationChanged()),
|
||||
this, SLOT(updateSigningWarning()));
|
||||
updateSigningWarning();
|
||||
QmakeBuildConfiguration *bc = qobject_cast<QmakeBuildConfiguration *>(m_step->target()->activeBuildConfiguration());
|
||||
m_currentBuildConfiguration = bc;
|
||||
if (bc)
|
||||
connect(bc, SIGNAL(qmakeBuildConfigurationChanged()), this, SLOT(updateSigningWarning()));
|
||||
m_currentBuildConfiguration = bc;
|
||||
}
|
||||
|
||||
void AndroidPackageCreationWidget::updateAndroidProjectInfo()
|
||||
{
|
||||
ProjectExplorer::Target *target = m_step->target();
|
||||
m_ui->targetSDKComboBox->clear();
|
||||
|
||||
int minApiLevel = 4;
|
||||
if (QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(target->kit()))
|
||||
if (qt->qtVersion() >= QtSupport::QtVersionNumber(5, 0, 0))
|
||||
minApiLevel = 9;
|
||||
|
||||
QStringList targets = AndroidConfig::apiLevelNamesFor(AndroidConfigurations::currentConfig().sdkTargets(minApiLevel));
|
||||
m_ui->targetSDKComboBox->addItems(targets);
|
||||
m_ui->targetSDKComboBox->setCurrentIndex(targets.indexOf(AndroidManager::buildTargetSDK(target)));
|
||||
|
||||
m_qtLibsModel->setAvailableItems(AndroidManager::availableQtLibs(target));
|
||||
m_qtLibsModel->setCheckedItems(AndroidManager::qtLibs(target));
|
||||
m_prebundledLibs->setAvailableItems(AndroidManager::availablePrebundledLibs(target));
|
||||
m_prebundledLibs->setCheckedItems(AndroidManager::prebundledLibs(target));
|
||||
}
|
||||
|
||||
void AndroidPackageCreationWidget::setTargetSDK(const QString &sdk)
|
||||
{
|
||||
AndroidManager::setBuildTargetSDK(m_step->target(), sdk);
|
||||
QmakeBuildConfiguration *bc = qobject_cast<QmakeBuildConfiguration *>(m_step->target()->activeBuildConfiguration());
|
||||
if (!bc)
|
||||
return;
|
||||
QMakeStep *qs = bc->qmakeStep();
|
||||
if (!qs)
|
||||
return;
|
||||
|
||||
qs->setForced(true);
|
||||
|
||||
BuildManager::buildList(bc->stepList(ProjectExplorer::Constants::BUILDSTEPS_CLEAN),
|
||||
ProjectExplorerPlugin::displayNameForStepId(ProjectExplorer::Constants::BUILDSTEPS_CLEAN));
|
||||
BuildManager::appendStep(qs, ProjectExplorerPlugin::displayNameForStepId(ProjectExplorer::Constants::BUILDSTEPS_CLEAN));
|
||||
bc->setSubNodeBuild(0);
|
||||
// Make the buildconfiguration emit a evironmentChanged() signal
|
||||
// TODO find a better way
|
||||
bool use = bc->useSystemEnvironment();
|
||||
bc->setUseSystemEnvironment(!use);
|
||||
bc->setUseSystemEnvironment(use);
|
||||
}
|
||||
|
||||
void AndroidPackageCreationWidget::setQtLibs(QModelIndex, QModelIndex)
|
||||
{
|
||||
AndroidManager::setQtLibs(m_step->target(), m_qtLibsModel->checkedItems());
|
||||
AndroidDeployStep * const deployStep = AndroidGlobal::buildStep<AndroidDeployStep>(m_step->target()->activeDeployConfiguration());
|
||||
if (deployStep->deployAction() == AndroidDeployStep::DeployLocal
|
||||
|| deployStep->deployAction() == AndroidDeployStep::BundleLibraries)
|
||||
AndroidManager::updateDeploymentSettings(m_step->target());
|
||||
}
|
||||
|
||||
void AndroidPackageCreationWidget::setPrebundledLibs(QModelIndex, QModelIndex)
|
||||
{
|
||||
AndroidManager::setPrebundledLibs(m_step->target(), m_prebundledLibs->checkedItems());
|
||||
AndroidDeployStep * const deployStep = AndroidGlobal::buildStep<AndroidDeployStep>(m_step->target()->activeDeployConfiguration());
|
||||
if (deployStep->deployAction() == AndroidDeployStep::DeployLocal
|
||||
|| deployStep->deployAction() == AndroidDeployStep::BundleLibraries)
|
||||
AndroidManager::updateDeploymentSettings(m_step->target());
|
||||
}
|
||||
|
||||
void AndroidPackageCreationWidget::prebundledLibSelected(const QModelIndex &index)
|
||||
{
|
||||
m_ui->upPushButton->setEnabled(false);
|
||||
m_ui->downPushButton->setEnabled(false);
|
||||
if (!index.isValid())
|
||||
return;
|
||||
if (index.row() > 0)
|
||||
m_ui->upPushButton->setEnabled(true);
|
||||
if (index.row() < m_prebundledLibs->rowCount(QModelIndex()) - 1)
|
||||
m_ui->downPushButton->setEnabled(true);
|
||||
}
|
||||
|
||||
void AndroidPackageCreationWidget::prebundledLibMoveUp()
|
||||
{
|
||||
const QModelIndex &index = m_ui->prebundledLibsListView->currentIndex();
|
||||
if (index.isValid())
|
||||
m_prebundledLibs->moveUp(index.row());
|
||||
}
|
||||
|
||||
void AndroidPackageCreationWidget::prebundledLibMoveDown()
|
||||
{
|
||||
const QModelIndex &index = m_ui->prebundledLibsListView->currentIndex();
|
||||
if (index.isValid())
|
||||
m_prebundledLibs->moveUp(index.row() + 1);
|
||||
}
|
||||
|
||||
void AndroidPackageCreationWidget::updateRequiredLibrariesModels()
|
||||
{
|
||||
m_qtLibsModel->setCheckedItems(AndroidManager::qtLibs(m_step->target()));
|
||||
m_prebundledLibs->setCheckedItems(AndroidManager::prebundledLibs(m_step->target()));
|
||||
}
|
||||
|
||||
void AndroidPackageCreationWidget::readElfInfo()
|
||||
{
|
||||
m_step->checkRequiredLibraries();
|
||||
}
|
||||
|
||||
QString AndroidPackageCreationWidget::summaryText() const
|
||||
{
|
||||
return tr("<b>Package configurations</b>");
|
||||
}
|
||||
|
||||
QString AndroidPackageCreationWidget::displayName() const
|
||||
{
|
||||
return m_step->displayName();
|
||||
}
|
||||
|
||||
void AndroidPackageCreationWidget::setCertificates()
|
||||
{
|
||||
QAbstractItemModel *certificates = m_step->keystoreCertificates();
|
||||
m_ui->signPackageCheckBox->setChecked(certificates);
|
||||
m_ui->certificatesAliasComboBox->setModel(certificates);
|
||||
}
|
||||
|
||||
void AndroidPackageCreationWidget::on_signPackageCheckBox_toggled(bool checked)
|
||||
{
|
||||
m_step->setSignPackage(checked);
|
||||
updateSigningWarning();
|
||||
if (!checked)
|
||||
return;
|
||||
if (!m_step->keystorePath().isEmpty())
|
||||
setCertificates();
|
||||
}
|
||||
|
||||
void AndroidPackageCreationWidget::on_KeystoreCreatePushButton_clicked()
|
||||
{
|
||||
AndroidCreateKeystoreCertificate d;
|
||||
if (d.exec() != QDialog::Accepted)
|
||||
return;
|
||||
m_ui->KeystoreLocationLineEdit->setText(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 AndroidPackageCreationWidget::on_KeystoreLocationPushButton_clicked()
|
||||
{
|
||||
Utils::FileName keystorePath = m_step->keystorePath();
|
||||
if (keystorePath.isEmpty())
|
||||
keystorePath = Utils::FileName::fromString(QDir::homePath());
|
||||
Utils::FileName file = Utils::FileName::fromString(QFileDialog::getOpenFileName(this, tr("Select keystore file"), keystorePath.toString(), tr("Keystore files (*.keystore *.jks)")));
|
||||
if (file.isEmpty())
|
||||
return;
|
||||
m_ui->KeystoreLocationLineEdit->setText(file.toUserOutput());
|
||||
m_step->setKeystorePath(file);
|
||||
m_ui->signPackageCheckBox->setChecked(false);
|
||||
}
|
||||
|
||||
void AndroidPackageCreationWidget::on_certificatesAliasComboBox_activated(const QString &alias)
|
||||
{
|
||||
if (alias.length())
|
||||
m_step->setCertificateAlias(alias);
|
||||
}
|
||||
|
||||
void AndroidPackageCreationWidget::on_certificatesAliasComboBox_currentIndexChanged(const QString &alias)
|
||||
{
|
||||
if (alias.length())
|
||||
m_step->setCertificateAlias(alias);
|
||||
}
|
||||
|
||||
void AndroidPackageCreationWidget::on_openPackageLocationCheckBox_toggled(bool checked)
|
||||
{
|
||||
m_step->setOpenPackageLocation(checked);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Android
|
||||
@@ -1,121 +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 ANDROIDPACKAGECREATIONWIDGET_H
|
||||
#define ANDROIDPACKAGECREATIONWIDGET_H
|
||||
|
||||
#include <projectexplorer/buildstep.h>
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QStringList>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QFileSystemWatcher;
|
||||
|
||||
namespace Ui { class AndroidPackageCreationWidget; }
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace QmakeProjectManager { class QmakeBuildConfiguration; }
|
||||
|
||||
namespace Android {
|
||||
namespace Internal {
|
||||
class AndroidPackageCreationStep;
|
||||
|
||||
class CheckModel: public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CheckModel(QObject *parent = 0);
|
||||
void setAvailableItems(const QStringList &items);
|
||||
void setCheckedItems(const QStringList &items);
|
||||
const QStringList &checkedItems();
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
void moveUp(int index);
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
|
||||
protected:
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role);
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
private:
|
||||
QStringList m_availableItems;
|
||||
QStringList m_checkedItems;
|
||||
};
|
||||
|
||||
class AndroidPackageCreationWidget : public ProjectExplorer::BuildStepConfigWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AndroidPackageCreationWidget(AndroidPackageCreationStep *step);
|
||||
|
||||
virtual QString summaryText() const;
|
||||
virtual QString displayName() const;
|
||||
|
||||
public slots:
|
||||
void readElfInfo();
|
||||
|
||||
private:
|
||||
void setEnabledSaveDiscardButtons(bool enabled);
|
||||
void setCertificates();
|
||||
|
||||
private slots:
|
||||
void initGui();
|
||||
void updateAndroidProjectInfo();
|
||||
|
||||
void setTargetSDK(const QString &sdk);
|
||||
|
||||
void setQtLibs(QModelIndex, QModelIndex);
|
||||
void setPrebundledLibs(QModelIndex, QModelIndex);
|
||||
void prebundledLibSelected(const QModelIndex &index);
|
||||
void prebundledLibMoveUp();
|
||||
void prebundledLibMoveDown();
|
||||
|
||||
void updateRequiredLibrariesModels();
|
||||
void on_signPackageCheckBox_toggled(bool checked);
|
||||
void on_KeystoreCreatePushButton_clicked();
|
||||
void on_KeystoreLocationPushButton_clicked();
|
||||
void on_certificatesAliasComboBox_activated(const QString &alias);
|
||||
void on_certificatesAliasComboBox_currentIndexChanged(const QString &alias);
|
||||
|
||||
void on_openPackageLocationCheckBox_toggled(bool checked);
|
||||
|
||||
void updateSigningWarning();
|
||||
void activeBuildConfigurationChanged();
|
||||
private:
|
||||
AndroidPackageCreationStep *const m_step;
|
||||
Ui::AndroidPackageCreationWidget *const m_ui;
|
||||
CheckModel *m_qtLibsModel;
|
||||
CheckModel *m_prebundledLibs;
|
||||
QFileSystemWatcher *m_fileSystemWatcher;
|
||||
QmakeProjectManager::QmakeBuildConfiguration *m_currentBuildConfiguration;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Android
|
||||
|
||||
#endif // ANDROIDPACKAGECREATIONWIDGET_H
|
||||
@@ -1,323 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AndroidPackageCreationWidget</class>
|
||||
<widget class="QWidget" name="AndroidPackageCreationWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>688</width>
|
||||
<height>553</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Application</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="editDebianFileLabel_4">
|
||||
<property name="text">
|
||||
<string><b>Android target SDK:</b></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="targetSDKComboBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="librariesGroupBox">
|
||||
<property name="title">
|
||||
<string>Libraries</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="readInfoPushButton">
|
||||
<property name="toolTip">
|
||||
<string>Automatically check required Qt libraries from compiled application.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Read information from application (must be compiled)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Required Qt libraries</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListView" name="qtLibsListView"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QFrame" name="frame_2">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string><center>Prebundled libraries</center>
|
||||
<p align="justify">Please be aware that the order is very important: If library <i>A</i> depends on library <i>B</i>, <i>B</i> <b>must</b> go before <i>A</i>.</p></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QListView" name="prebundledLibsListView"/>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<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>
|
||||
<item>
|
||||
<widget class="QPushButton" name="upPushButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Up</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="downPushButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Down</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<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>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<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="QLineEdit" name="KeystoreLocationLineEdit">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="KeystoreCreatePushButton">
|
||||
<property name="text">
|
||||
<string>Create</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="KeystoreLocationPushButton">
|
||||
<property name="text">
|
||||
<string>Browse</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>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="openPackageLocationCheckBox">
|
||||
<property name="text">
|
||||
<string>Open package location after is complete</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</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>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../projectexplorer/projectexplorer.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>signPackageCheckBox</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>certificatesAliasComboBox</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>138</x>
|
||||
<y>93</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>184</x>
|
||||
<y>139</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<slots>
|
||||
<slot>addFile()</slot>
|
||||
<slot>removeFile()</slot>
|
||||
<slot>handleSkipButtonToggled(bool)</slot>
|
||||
<slot>versionInfoChanged()</slot>
|
||||
<slot>editDebianFile()</slot>
|
||||
<slot>setPackageManagerIcon()</slot>
|
||||
</slots>
|
||||
</ui>
|
||||
@@ -31,12 +31,10 @@
|
||||
|
||||
#include "androidconstants.h"
|
||||
#include "androidconfigurations.h"
|
||||
#include "androiddeploystepfactory.h"
|
||||
#include "androiddeployqtstep.h"
|
||||
#include "androiddevice.h"
|
||||
#include "androiddevicefactory.h"
|
||||
#include "androidmanager.h"
|
||||
#include "androidpackagecreationfactory.h"
|
||||
#include "androidpackageinstallationfactory.h"
|
||||
#include "androidrunfactories.h"
|
||||
#include "androidsettingspage.h"
|
||||
@@ -77,8 +75,6 @@ bool AndroidPlugin::initialize(const QStringList &arguments, QString *errorMessa
|
||||
addAutoReleasedObject(new Internal::AndroidRunControlFactory);
|
||||
addAutoReleasedObject(new Internal::AndroidRunConfigurationFactory);
|
||||
addAutoReleasedObject(new Internal::AndroidPackageInstallationFactory);
|
||||
addAutoReleasedObject(new Internal::AndroidPackageCreationFactory);
|
||||
addAutoReleasedObject(new Internal::AndroidDeployStepFactory);
|
||||
addAutoReleasedObject(new Internal::AndroidDeployQtStepFactory);
|
||||
addAutoReleasedObject(new Internal::AndroidSettingsPage);
|
||||
addAutoReleasedObject(new Internal::AndroidQtVersionFactory);
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "androidrunconfiguration.h"
|
||||
#include "androiddeploystep.h"
|
||||
#include "androidglobal.h"
|
||||
#include "androidtoolchain.h"
|
||||
#include "androidmanager.h"
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
|
||||
#include "androidruncontrol.h"
|
||||
|
||||
#include "androiddeploystep.h"
|
||||
#include "androidglobal.h"
|
||||
#include "androidrunconfiguration.h"
|
||||
#include "androidrunner.h"
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
|
||||
#include "androidrunner.h"
|
||||
|
||||
#include "androiddeploystep.h"
|
||||
#include "androiddeployqtstep.h"
|
||||
#include "androidconfigurations.h"
|
||||
#include "androidglobal.h"
|
||||
|
||||
Reference in New Issue
Block a user