forked from qt-creator/qt-creator
ios: preliminary support for ios
first work in progress support for ios * separate iosTool using xml communication used for device info and run * iossim tool to handle the simulator * debug prepared but not working * separate gcc toolchain detection fix for simulator 1) add a QT built for ios 2) open a project, for example qtbase/examples/widgets/animation/animatedtiles/animatedtiles.pro 3) build/run... Change-Id: I7e01604e416338cbe4692dfb34f5d3f31312702d Reviewed-by: Eike Ziller <eike.ziller@digia.com>
This commit is contained in:
committed by
Eike Ziller
parent
3a7d91ca44
commit
8d96ce557e
17
src/plugins/ios/Ios.pluginspec.in
Normal file
17
src/plugins/ios/Ios.pluginspec.in
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<plugin name=\"Ios\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\" experimental=\"true\">
|
||||||
|
<vendor>Digia Plc</vendor>
|
||||||
|
<copyright>(C) 2013 Digia Plc</copyright>
|
||||||
|
<license>
|
||||||
|
Commercial Usage
|
||||||
|
|
||||||
|
Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and Digia.
|
||||||
|
|
||||||
|
GNU Lesser General Public License Usage
|
||||||
|
|
||||||
|
Alternatively, this plugin may be used under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation. 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.
|
||||||
|
</license>
|
||||||
|
<description>Support for deployment to and execution on iOS Devices</description>
|
||||||
|
<category>Device Support</category>
|
||||||
|
<url>http://www.qt-project.org</url>
|
||||||
|
$$dependencyList
|
||||||
|
</plugin>
|
BIN
src/plugins/ios/images/QtIos.png
Executable file
BIN
src/plugins/ios/images/QtIos.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
69
src/plugins/ios/ios.pro
Normal file
69
src/plugins/ios/ios.pro
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
TEMPLATE = lib
|
||||||
|
TARGET = Ios
|
||||||
|
|
||||||
|
include(../../qtcreatorplugin.pri)
|
||||||
|
|
||||||
|
QT += xml network
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
iosconstants.h \
|
||||||
|
iosconfigurations.h \
|
||||||
|
iosmanager.h \
|
||||||
|
iosrunconfiguration.h \
|
||||||
|
iosruncontrol.h \
|
||||||
|
iosrunfactories.h \
|
||||||
|
iossettingspage.h \
|
||||||
|
iossettingswidget.h \
|
||||||
|
iosrunner.h \
|
||||||
|
iosdebugsupport.h \
|
||||||
|
iosqtversionfactory.h \
|
||||||
|
iosqtversion.h \
|
||||||
|
iosplugin.h \
|
||||||
|
iosdevicefactory.h \
|
||||||
|
iosdevice.h \
|
||||||
|
iossimulator.h \
|
||||||
|
iossimulatorfactory.h \
|
||||||
|
iosprobe.h \
|
||||||
|
iosbuildstep.h \
|
||||||
|
iostoolhandler.h \
|
||||||
|
iosdeployconfiguration.h \
|
||||||
|
iosdeploystep.h \
|
||||||
|
iosdeploystepfactory.h \
|
||||||
|
iosdeploystepwidget.h
|
||||||
|
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
iosconfigurations.cpp \
|
||||||
|
iosmanager.cpp \
|
||||||
|
iosrunconfiguration.cpp \
|
||||||
|
iosruncontrol.cpp \
|
||||||
|
iosrunfactories.cpp \
|
||||||
|
iossettingspage.cpp \
|
||||||
|
iossettingswidget.cpp \
|
||||||
|
iosrunner.cpp \
|
||||||
|
iosdebugsupport.cpp \
|
||||||
|
iosqtversionfactory.cpp \
|
||||||
|
iosqtversion.cpp \
|
||||||
|
iosplugin.cpp \
|
||||||
|
iosdevicefactory.cpp \
|
||||||
|
iosdevice.cpp \
|
||||||
|
iossimulator.cpp \
|
||||||
|
iossimulatorfactory.cpp \
|
||||||
|
iosprobe.cpp \
|
||||||
|
iosbuildstep.cpp \
|
||||||
|
iostoolhandler.cpp \
|
||||||
|
iosdeployconfiguration.cpp \
|
||||||
|
iosdeploystep.cpp \
|
||||||
|
iosdeploystepfactory.cpp \
|
||||||
|
iosdeploystepwidget.cpp
|
||||||
|
|
||||||
|
FORMS += \
|
||||||
|
iossettingswidget.ui \
|
||||||
|
iosbuildstep.ui \
|
||||||
|
iosrunconfiguration.ui \
|
||||||
|
iosdeploystepwidget.ui
|
||||||
|
|
||||||
|
DEFINES += IOS_LIBRARY
|
||||||
|
|
||||||
|
RESOURCES += ios.qrc
|
||||||
|
|
73
src/plugins/ios/ios.qbs
Normal file
73
src/plugins/ios/ios.qbs
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
import qbs.base 1.0
|
||||||
|
|
||||||
|
import "../QtcPlugin.qbs" as QtcPlugin
|
||||||
|
|
||||||
|
QtcPlugin {
|
||||||
|
name: "Ios"
|
||||||
|
condition: qbs.targetOS.contains("osx")
|
||||||
|
|
||||||
|
Depends { name: "Core" }
|
||||||
|
Depends { name: "ProjectExplorer" }
|
||||||
|
Depends { name: "Qt4ProjectManager" }
|
||||||
|
Depends { name: "Debugger" }
|
||||||
|
Depends { name: "QtSupport" }
|
||||||
|
Depends { name: "Qt"; submodules: ["widgets", "xml", "network"] }
|
||||||
|
|
||||||
|
cpp.includePaths: base.concat("../../shared")
|
||||||
|
cpp.frameworks: base.concat(["CoreFoundation", "IOKit"])
|
||||||
|
|
||||||
|
files: [
|
||||||
|
"ios.qrc",
|
||||||
|
"iosbuildstep.cpp",
|
||||||
|
"iosbuildstep.h",
|
||||||
|
"iosbuildstep.ui",
|
||||||
|
"iosconfigurations.cpp",
|
||||||
|
"iosconfigurations.h",
|
||||||
|
"iosconstants.h",
|
||||||
|
"iosdebugsupport.cpp",
|
||||||
|
"iosdebugsupport.h",
|
||||||
|
"iosdeployconfiguration.cpp",
|
||||||
|
"iosdeployconfiguration.h",
|
||||||
|
"iosdeploystep.cpp",
|
||||||
|
"iosdeploystep.h",
|
||||||
|
"iosdeploystepfactory.cpp",
|
||||||
|
"iosdeploystepfactory.h",
|
||||||
|
"iosdeploystepwidget.cpp",
|
||||||
|
"iosdeploystepwidget.h",
|
||||||
|
"iosdeploystepwidget.ui",
|
||||||
|
"iosdevice.cpp",
|
||||||
|
"iosdevice.h",
|
||||||
|
"iosdevicefactory.cpp",
|
||||||
|
"iosdevicefactory.h",
|
||||||
|
"iosmanager.cpp",
|
||||||
|
"iosmanager.h",
|
||||||
|
"iosplugin.cpp",
|
||||||
|
"iosplugin.h",
|
||||||
|
"iosprobe.cpp",
|
||||||
|
"iosprobe.h",
|
||||||
|
"iosqtversion.cpp",
|
||||||
|
"iosqtversion.h",
|
||||||
|
"iosqtversionfactory.cpp",
|
||||||
|
"iosqtversionfactory.h",
|
||||||
|
"iosrunconfiguration.cpp",
|
||||||
|
"iosrunconfiguration.h",
|
||||||
|
"iosrunconfiguration.ui",
|
||||||
|
"iosruncontrol.cpp",
|
||||||
|
"iosruncontrol.h",
|
||||||
|
"iosrunfactories.cpp",
|
||||||
|
"iosrunfactories.h",
|
||||||
|
"iosrunner.cpp",
|
||||||
|
"iosrunner.h",
|
||||||
|
"iossettingspage.cpp",
|
||||||
|
"iossettingspage.h",
|
||||||
|
"iossettingswidget.cpp",
|
||||||
|
"iossettingswidget.h",
|
||||||
|
"iossettingswidget.ui",
|
||||||
|
"iossimulator.cpp",
|
||||||
|
"iossimulator.h",
|
||||||
|
"iossimulatorfactory.cpp",
|
||||||
|
"iossimulatorfactory.h",
|
||||||
|
"iostoolhandler.cpp",
|
||||||
|
"iostoolhandler.h"
|
||||||
|
]
|
||||||
|
}
|
5
src/plugins/ios/ios.qrc
Normal file
5
src/plugins/ios/ios.qrc
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<RCC>
|
||||||
|
<qresource prefix="/ios">
|
||||||
|
<file>images/QtIos.png</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
8
src/plugins/ios/ios_dependencies.pri
Normal file
8
src/plugins/ios/ios_dependencies.pri
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
QTC_PLUGIN_NAME = Ios
|
||||||
|
QTC_LIB_DEPENDS += \
|
||||||
|
utils
|
||||||
|
QTC_PLUGIN_DEPENDS += \
|
||||||
|
coreplugin \
|
||||||
|
debugger \
|
||||||
|
projectexplorer \
|
||||||
|
qt4projectmanager
|
433
src/plugins/ios/iosbuildstep.cpp
Normal file
433
src/plugins/ios/iosbuildstep.cpp
Normal file
@@ -0,0 +1,433 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "iosbuildstep.h"
|
||||||
|
#include "iosconstants.h"
|
||||||
|
#include "ui_iosbuildstep.h"
|
||||||
|
#include "iosmanager.h"
|
||||||
|
|
||||||
|
#include <extensionsystem/pluginmanager.h>
|
||||||
|
#include <projectexplorer/target.h>
|
||||||
|
#include <projectexplorer/project.h>
|
||||||
|
#include <projectexplorer/buildsteplist.h>
|
||||||
|
#include <projectexplorer/gnumakeparser.h>
|
||||||
|
#include <projectexplorer/kitinformation.h>
|
||||||
|
#include <projectexplorer/projectexplorer.h>
|
||||||
|
#include <projectexplorer/buildconfiguration.h>
|
||||||
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
|
#include <projectexplorer/toolchain.h>
|
||||||
|
#include <projectexplorer/gcctoolchain.h>
|
||||||
|
#include <qt4projectmanager/qt4buildconfiguration.h>
|
||||||
|
#include <qt4projectmanager/qt4projectmanagerconstants.h>
|
||||||
|
#include <qt4projectmanager/qt4projectmanager.h>
|
||||||
|
#include <qt4projectmanager/qt4project.h>
|
||||||
|
#include <qt4projectmanager/qt4nodes.h>
|
||||||
|
#include <qtsupport/qtkitinformation.h>
|
||||||
|
#include <qtsupport/qtparser.h>
|
||||||
|
#include <coreplugin/variablemanager.h>
|
||||||
|
#include <utils/stringutils.h>
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/qtcprocess.h>
|
||||||
|
|
||||||
|
using namespace Core;
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
using namespace Qt4ProjectManager;
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
const char IOS_BUILD_STEP_ID[] = "Ios.IosBuildStep";
|
||||||
|
const char IOS_BUILD_STEP_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("Ios::Internal::IosBuildStep",
|
||||||
|
"xcodebuild");
|
||||||
|
|
||||||
|
const char BUILD_USE_DEFAULT_ARGS_KEY[] = "Ios.IosBuildStep.XcodeArgumentsUseDefault";
|
||||||
|
const char BUILD_ARGUMENTS_KEY[] = "Ios.IosBuildStep.XcodeArguments";
|
||||||
|
const char CLEAN_KEY[] = "Ios.IosBuildStep.Clean";
|
||||||
|
|
||||||
|
IosBuildStep::IosBuildStep(BuildStepList *parent) :
|
||||||
|
AbstractProcessStep(parent, Id(IOS_BUILD_STEP_ID)),
|
||||||
|
m_useDefaultArguments(true),
|
||||||
|
m_clean(false)
|
||||||
|
{
|
||||||
|
ctor();
|
||||||
|
}
|
||||||
|
|
||||||
|
IosBuildStep::IosBuildStep(BuildStepList *parent, const Id id) :
|
||||||
|
AbstractProcessStep(parent, id),
|
||||||
|
m_useDefaultArguments(true),
|
||||||
|
m_clean(false)
|
||||||
|
{
|
||||||
|
ctor();
|
||||||
|
}
|
||||||
|
|
||||||
|
IosBuildStep::IosBuildStep(BuildStepList *parent, IosBuildStep *bs) :
|
||||||
|
AbstractProcessStep(parent, bs),
|
||||||
|
m_baseBuildArguments(bs->m_baseBuildArguments),
|
||||||
|
m_useDefaultArguments(bs->m_useDefaultArguments),
|
||||||
|
m_clean(bs->m_clean)
|
||||||
|
{
|
||||||
|
ctor();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosBuildStep::ctor()
|
||||||
|
{
|
||||||
|
setDefaultDisplayName(QCoreApplication::translate("GenericProjectManager::Internal::IosBuildStep",
|
||||||
|
IOS_BUILD_STEP_DISPLAY_NAME));
|
||||||
|
}
|
||||||
|
|
||||||
|
IosBuildStep::~IosBuildStep()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosBuildStep::init()
|
||||||
|
{
|
||||||
|
BuildConfiguration *bc = buildConfiguration();
|
||||||
|
if (!bc)
|
||||||
|
bc = target()->activeBuildConfiguration();
|
||||||
|
|
||||||
|
m_tasks.clear();
|
||||||
|
ToolChain *tc = ToolChainKitInformation::toolChain(target()->kit());
|
||||||
|
if (!tc) {
|
||||||
|
Task t = Task(Task::Error, tr("Qt Creator needs a compiler set up to build. Configure a compiler in the kit preferences."),
|
||||||
|
Utils::FileName(), -1,
|
||||||
|
Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
|
||||||
|
m_tasks.append(t);
|
||||||
|
emit addTask(t);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ProcessParameters *pp = processParameters();
|
||||||
|
pp->setMacroExpander(bc->macroExpander());
|
||||||
|
pp->setWorkingDirectory(bc->buildDirectory().toString());
|
||||||
|
Utils::Environment env = bc->environment();
|
||||||
|
// Force output to english for the parsers. Do this here and not in the toolchain's
|
||||||
|
// addToEnvironment() to not screw up the users run environment.
|
||||||
|
env.set(QLatin1String("LC_ALL"), QLatin1String("C"));
|
||||||
|
pp->setEnvironment(env);
|
||||||
|
pp->setCommand(buildCommand());
|
||||||
|
pp->setArguments(Utils::QtcProcess::joinArgs(allArguments()));
|
||||||
|
pp->resolveAll();
|
||||||
|
|
||||||
|
// If we are cleaning, then build can fail with an error code, but that doesn't mean
|
||||||
|
// we should stop the clean queue
|
||||||
|
// That is mostly so that rebuild works on an already clean project
|
||||||
|
setIgnoreReturnValue(m_clean);
|
||||||
|
|
||||||
|
setOutputParser(new GnuMakeParser());
|
||||||
|
IOutputParser *parser = target()->kit()->createOutputParser();
|
||||||
|
if (parser)
|
||||||
|
appendOutputParser(parser);
|
||||||
|
outputParser()->setWorkingDirectory(pp->effectiveWorkingDirectory());
|
||||||
|
|
||||||
|
return AbstractProcessStep::init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosBuildStep::setClean(bool clean)
|
||||||
|
{
|
||||||
|
m_clean = clean;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosBuildStep::isClean() const
|
||||||
|
{
|
||||||
|
return m_clean;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap IosBuildStep::toMap() const
|
||||||
|
{
|
||||||
|
QVariantMap map(AbstractProcessStep::toMap());
|
||||||
|
|
||||||
|
map.insert(QLatin1String(BUILD_ARGUMENTS_KEY), m_baseBuildArguments);
|
||||||
|
map.insert(QLatin1String(BUILD_USE_DEFAULT_ARGS_KEY), m_useDefaultArguments);
|
||||||
|
map.insert(QLatin1String(CLEAN_KEY), m_clean);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosBuildStep::fromMap(const QVariantMap &map)
|
||||||
|
{
|
||||||
|
QVariant bArgs = map.value(QLatin1String(BUILD_ARGUMENTS_KEY));
|
||||||
|
m_baseBuildArguments = bArgs.toStringList();
|
||||||
|
m_useDefaultArguments = map.value(QLatin1String(BUILD_USE_DEFAULT_ARGS_KEY)).toBool();
|
||||||
|
m_clean = map.value(QLatin1String(CLEAN_KEY)).toBool();
|
||||||
|
|
||||||
|
return BuildStep::fromMap(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList IosBuildStep::allArguments() const
|
||||||
|
{
|
||||||
|
return baseArguments() + m_extraArguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList IosBuildStep::defaultArguments() const
|
||||||
|
{
|
||||||
|
QStringList res;
|
||||||
|
Kit *kit = target()->kit();
|
||||||
|
ToolChain *tc = ToolChainKitInformation::toolChain(kit);
|
||||||
|
switch (target()->activeBuildConfiguration()->buildType()) {
|
||||||
|
case BuildConfiguration::Debug :
|
||||||
|
res << QLatin1String("-configuration") << QLatin1String("Debug");
|
||||||
|
break;
|
||||||
|
case BuildConfiguration::Release :
|
||||||
|
res << QLatin1String("-configuration") << QLatin1String("Release");
|
||||||
|
break;
|
||||||
|
case BuildConfiguration::Unknown :
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qDebug() << "IosBuildStep had an unknown buildType "
|
||||||
|
<< target()->activeBuildConfiguration()->buildType();
|
||||||
|
}
|
||||||
|
if (tc->type() == QLatin1String("gcc") || tc->type() == QLatin1String("clang")) {
|
||||||
|
GccToolChain *gtc = static_cast<GccToolChain *>(tc);
|
||||||
|
res << gtc->platformCodeGenFlags();
|
||||||
|
}
|
||||||
|
if (!SysRootKitInformation::sysRoot(kit).isEmpty())
|
||||||
|
res << QLatin1String("-sdk") << SysRootKitInformation::sysRoot(kit).toString();
|
||||||
|
res << QLatin1String("SYMROOT=") + IosManager::resDirForTarget(target());
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosBuildStep::buildCommand() const
|
||||||
|
{
|
||||||
|
return QLatin1String("xcodebuild"); // add path?
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosBuildStep::run(QFutureInterface<bool> &fi)
|
||||||
|
{
|
||||||
|
bool canContinue = true;
|
||||||
|
foreach (const Task &t, m_tasks) {
|
||||||
|
addTask(t);
|
||||||
|
canContinue = false;
|
||||||
|
}
|
||||||
|
if (!canContinue) {
|
||||||
|
emit addOutput(tr("Configuration is faulty. Check the Issues output pane for details."),
|
||||||
|
BuildStep::MessageOutput);
|
||||||
|
fi.reportResult(false);
|
||||||
|
emit finished();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractProcessStep::run(fi);
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildStepConfigWidget *IosBuildStep::createConfigWidget()
|
||||||
|
{
|
||||||
|
return new IosBuildStepConfigWidget(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosBuildStep::immutable() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosBuildStep::setBaseArguments(const QStringList &args)
|
||||||
|
{
|
||||||
|
m_baseBuildArguments = args;
|
||||||
|
m_useDefaultArguments = (args == defaultArguments());
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosBuildStep::setExtraArguments(const QStringList &extraArgs)
|
||||||
|
{
|
||||||
|
m_extraArguments = extraArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList IosBuildStep::baseArguments() const
|
||||||
|
{
|
||||||
|
if (m_useDefaultArguments)
|
||||||
|
return defaultArguments();
|
||||||
|
return m_baseBuildArguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// IosBuildStepConfigWidget
|
||||||
|
//
|
||||||
|
|
||||||
|
IosBuildStepConfigWidget::IosBuildStepConfigWidget(IosBuildStep *buildStep)
|
||||||
|
: m_buildStep(buildStep)
|
||||||
|
{
|
||||||
|
m_ui = new Ui::IosBuildStep;
|
||||||
|
m_ui->setupUi(this);
|
||||||
|
|
||||||
|
Project *pro = m_buildStep->target()->project();
|
||||||
|
|
||||||
|
m_ui->buildArgumentsTextEdit->setPlainText(Utils::QtcProcess::joinArgs(
|
||||||
|
m_buildStep->baseArguments()));
|
||||||
|
m_ui->extraArgumentsLineEdit->setText(Utils::QtcProcess::joinArgs(
|
||||||
|
m_buildStep->m_extraArguments));
|
||||||
|
m_ui->resetDefaultsButton->setEnabled(!m_buildStep->m_useDefaultArguments);
|
||||||
|
updateDetails();
|
||||||
|
|
||||||
|
connect(m_ui->buildArgumentsTextEdit, SIGNAL(textChanged()),
|
||||||
|
this, SLOT(buildArgumentsChanged()));
|
||||||
|
connect(m_ui->resetDefaultsButton, SIGNAL(clicked()),
|
||||||
|
this, SLOT(resetDefaultArguments()));
|
||||||
|
connect(m_ui->extraArgumentsLineEdit, SIGNAL(editingFinished()),
|
||||||
|
this, SLOT(extraArgumentsChanged()));
|
||||||
|
|
||||||
|
connect(ProjectExplorerPlugin::instance(), SIGNAL(settingsChanged()),
|
||||||
|
this, SLOT(updateDetails()));
|
||||||
|
connect(m_buildStep->target(), SIGNAL(kitChanged()),
|
||||||
|
this, SLOT(updateDetails()));
|
||||||
|
connect(pro, SIGNAL(environmentChanged()),
|
||||||
|
this, SLOT(updateDetails()));
|
||||||
|
}
|
||||||
|
|
||||||
|
IosBuildStepConfigWidget::~IosBuildStepConfigWidget()
|
||||||
|
{
|
||||||
|
delete m_ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosBuildStepConfigWidget::displayName() const
|
||||||
|
{
|
||||||
|
return tr("iOS build", "iOS BuildStep display name.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosBuildStepConfigWidget::updateDetails()
|
||||||
|
{
|
||||||
|
BuildConfiguration *bc = m_buildStep->buildConfiguration();
|
||||||
|
if (!bc)
|
||||||
|
bc = m_buildStep->target()->activeBuildConfiguration();
|
||||||
|
|
||||||
|
ProcessParameters param;
|
||||||
|
param.setMacroExpander(bc->macroExpander());
|
||||||
|
param.setWorkingDirectory(bc->buildDirectory().toString());
|
||||||
|
param.setEnvironment(bc->environment());
|
||||||
|
param.setCommand(m_buildStep->buildCommand());
|
||||||
|
param.setArguments(Utils::QtcProcess::joinArgs(m_buildStep->allArguments()));
|
||||||
|
m_summaryText = param.summary(displayName());
|
||||||
|
emit updateSummary();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosBuildStepConfigWidget::summaryText() const
|
||||||
|
{
|
||||||
|
return m_summaryText;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosBuildStepConfigWidget::buildArgumentsChanged()
|
||||||
|
{
|
||||||
|
m_buildStep->setBaseArguments(Utils::QtcProcess::splitArgs(
|
||||||
|
m_ui->buildArgumentsTextEdit->toPlainText()));
|
||||||
|
m_ui->resetDefaultsButton->setEnabled(!m_buildStep->m_useDefaultArguments);
|
||||||
|
updateDetails();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosBuildStepConfigWidget::resetDefaultArguments()
|
||||||
|
{
|
||||||
|
m_buildStep->setBaseArguments(m_buildStep->defaultArguments());
|
||||||
|
m_ui->buildArgumentsTextEdit->setPlainText(Utils::QtcProcess::joinArgs(
|
||||||
|
m_buildStep->baseArguments()));
|
||||||
|
m_ui->resetDefaultsButton->setEnabled(!m_buildStep->m_useDefaultArguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosBuildStepConfigWidget::extraArgumentsChanged()
|
||||||
|
{
|
||||||
|
m_buildStep->setExtraArguments(Utils::QtcProcess::splitArgs(
|
||||||
|
m_ui->extraArgumentsLineEdit->text()));
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// IosBuildStepFactory
|
||||||
|
//
|
||||||
|
|
||||||
|
IosBuildStepFactory::IosBuildStepFactory(QObject *parent) :
|
||||||
|
IBuildStepFactory(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosBuildStepFactory::canCreate(BuildStepList *parent, const Id) const
|
||||||
|
{
|
||||||
|
if (parent->id() != ProjectExplorer::Constants::BUILDSTEPS_CLEAN
|
||||||
|
&& parent->id() != ProjectExplorer::Constants::BUILDSTEPS_BUILD)
|
||||||
|
return false;
|
||||||
|
Kit *kit = parent->target()->kit();
|
||||||
|
Core::Id deviceType = DeviceTypeKitInformation::deviceTypeId(kit);
|
||||||
|
return (deviceType == Constants::IOS_DEVICE_TYPE
|
||||||
|
|| deviceType == Constants::IOS_SIMULATOR_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildStep *IosBuildStepFactory::create(BuildStepList *parent, const Id id)
|
||||||
|
{
|
||||||
|
if (!canCreate(parent, id))
|
||||||
|
return 0;
|
||||||
|
IosBuildStep *step = new IosBuildStep(parent);
|
||||||
|
if (parent->id() == ProjectExplorer::Constants::BUILDSTEPS_CLEAN) {
|
||||||
|
step->setClean(true);
|
||||||
|
step->setExtraArguments(QStringList(QLatin1String("clean")));
|
||||||
|
} else if (parent->id() == ProjectExplorer::Constants::BUILDSTEPS_BUILD) {
|
||||||
|
// nomal setup
|
||||||
|
}
|
||||||
|
return step;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosBuildStepFactory::canClone(BuildStepList *parent, BuildStep *source) const
|
||||||
|
{
|
||||||
|
return canCreate(parent, source->id());
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildStep *IosBuildStepFactory::clone(BuildStepList *parent, BuildStep *source)
|
||||||
|
{
|
||||||
|
if (!canClone(parent, source))
|
||||||
|
return 0;
|
||||||
|
IosBuildStep *old(qobject_cast<IosBuildStep *>(source));
|
||||||
|
Q_ASSERT(old);
|
||||||
|
return new IosBuildStep(parent, old);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosBuildStepFactory::canRestore(BuildStepList *parent, const QVariantMap &map) const
|
||||||
|
{
|
||||||
|
return canCreate(parent, idFromMap(map));
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildStep *IosBuildStepFactory::restore(BuildStepList *parent, const QVariantMap &map)
|
||||||
|
{
|
||||||
|
if (!canRestore(parent, map))
|
||||||
|
return 0;
|
||||||
|
IosBuildStep *bs(new IosBuildStep(parent));
|
||||||
|
if (bs->fromMap(map))
|
||||||
|
return bs;
|
||||||
|
delete bs;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<Id> IosBuildStepFactory::availableCreationIds(BuildStepList *parent) const
|
||||||
|
{
|
||||||
|
Kit *kit = parent->target()->kit();
|
||||||
|
Core::Id deviceType = DeviceTypeKitInformation::deviceTypeId(kit);
|
||||||
|
if (deviceType == Constants::IOS_DEVICE_TYPE
|
||||||
|
|| deviceType == Constants::IOS_SIMULATOR_TYPE)
|
||||||
|
return QList<Id>() << Id(IOS_BUILD_STEP_ID);
|
||||||
|
return QList<Id>();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosBuildStepFactory::displayNameForId(const Id id) const
|
||||||
|
{
|
||||||
|
if (id == IOS_BUILD_STEP_ID)
|
||||||
|
return QCoreApplication::translate("GenericProjectManager::Internal::IosBuildStep",
|
||||||
|
IOS_BUILD_STEP_DISPLAY_NAME);
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
134
src/plugins/ios/iosbuildstep.h
Normal file
134
src/plugins/ios/iosbuildstep.h
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef IOSBUILDSTEP_H
|
||||||
|
#define IOSBUILDSTEP_H
|
||||||
|
|
||||||
|
#include <projectexplorer/abstractprocessstep.h>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QListWidgetItem;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class IosBuildStepConfigWidget;
|
||||||
|
class IosBuildStepFactory;
|
||||||
|
namespace Ui { class IosBuildStep; }
|
||||||
|
|
||||||
|
class IosBuildStep : public ProjectExplorer::AbstractProcessStep
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
friend class IosBuildStepConfigWidget;
|
||||||
|
friend class IosBuildStepFactory;
|
||||||
|
|
||||||
|
public:
|
||||||
|
IosBuildStep(ProjectExplorer::BuildStepList *parent);
|
||||||
|
~IosBuildStep();
|
||||||
|
|
||||||
|
bool init();
|
||||||
|
void run(QFutureInterface<bool> &fi);
|
||||||
|
|
||||||
|
ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
|
||||||
|
bool immutable() const;
|
||||||
|
void setBaseArguments(const QStringList &args);
|
||||||
|
void setExtraArguments(const QStringList &extraArgs);
|
||||||
|
QStringList baseArguments() const;
|
||||||
|
QStringList allArguments() const;
|
||||||
|
QStringList defaultArguments() const;
|
||||||
|
QString buildCommand() const;
|
||||||
|
|
||||||
|
void setClean(bool clean);
|
||||||
|
bool isClean() const;
|
||||||
|
|
||||||
|
QVariantMap toMap() const;
|
||||||
|
protected:
|
||||||
|
IosBuildStep(ProjectExplorer::BuildStepList *parent, IosBuildStep *bs);
|
||||||
|
IosBuildStep(ProjectExplorer::BuildStepList *parent, const Core::Id id);
|
||||||
|
bool fromMap(const QVariantMap &map);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void ctor();
|
||||||
|
|
||||||
|
QStringList m_baseBuildArguments;
|
||||||
|
QStringList m_extraArguments;
|
||||||
|
QString m_buildCommand;
|
||||||
|
bool m_useDefaultArguments;
|
||||||
|
bool m_clean;
|
||||||
|
QList<ProjectExplorer::Task> m_tasks;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IosBuildStepConfigWidget : public ProjectExplorer::BuildStepConfigWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
IosBuildStepConfigWidget(IosBuildStep *buildStep);
|
||||||
|
~IosBuildStepConfigWidget();
|
||||||
|
QString displayName() const;
|
||||||
|
QString summaryText() const;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void buildArgumentsChanged();
|
||||||
|
void resetDefaultArguments();
|
||||||
|
void extraArgumentsChanged();
|
||||||
|
void updateDetails();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::IosBuildStep *m_ui;
|
||||||
|
IosBuildStep *m_buildStep;
|
||||||
|
QString m_summaryText;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IosBuildStepFactory : public ProjectExplorer::IBuildStepFactory
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit IosBuildStepFactory(QObject *parent = 0);
|
||||||
|
|
||||||
|
bool canCreate(ProjectExplorer::BuildStepList *parent, const Core::Id id) const;
|
||||||
|
ProjectExplorer::BuildStep *create(ProjectExplorer::BuildStepList *parent, const Core::Id id);
|
||||||
|
bool canClone(ProjectExplorer::BuildStepList *parent,
|
||||||
|
ProjectExplorer::BuildStep *source) const;
|
||||||
|
ProjectExplorer::BuildStep *clone(ProjectExplorer::BuildStepList *parent,
|
||||||
|
ProjectExplorer::BuildStep *source);
|
||||||
|
bool canRestore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) const;
|
||||||
|
ProjectExplorer::BuildStep *restore(ProjectExplorer::BuildStepList *parent,
|
||||||
|
const QVariantMap &map);
|
||||||
|
|
||||||
|
QList<Core::Id> availableCreationIds(ProjectExplorer::BuildStepList *bc) const;
|
||||||
|
QString displayNameForId(const Core::Id id) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#endif // IOSBUILDSTEP_H
|
65
src/plugins/ios/iosbuildstep.ui
Normal file
65
src/plugins/ios/iosbuildstep.ui
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Ios::Internal::IosBuildStep</class>
|
||||||
|
<widget class="QWidget" name="Ios::Internal::IosBuildStep">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>756</width>
|
||||||
|
<height>183</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="buildArgumentsLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Base arguments:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1" rowspan="2">
|
||||||
|
<widget class="QPlainTextEdit" name="buildArgumentsTextEdit"/>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QPushButton" name="resetDefaultsButton">
|
||||||
|
<property name="layoutDirection">
|
||||||
|
<enum>Qt::RightToLeft</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Reset defaults</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="extraArgumentsLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Extra arguments:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLineEdit" name="extraArgumentsLineEdit"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
<zorder>buildArgumentsTextEdit</zorder>
|
||||||
|
<zorder>resetDefaultsButton</zorder>
|
||||||
|
<zorder>extraArgumentsLabel</zorder>
|
||||||
|
<zorder>extraArgumentsLineEdit</zorder>
|
||||||
|
<zorder>buildArgumentsLabel</zorder>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
448
src/plugins/ios/iosconfigurations.cpp
Normal file
448
src/plugins/ios/iosconfigurations.cpp
Normal file
@@ -0,0 +1,448 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "iosconfigurations.h"
|
||||||
|
#include "iosconstants.h"
|
||||||
|
#include "iosdevice.h"
|
||||||
|
#include "iossimulator.h"
|
||||||
|
#include "iosprobe.h"
|
||||||
|
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
|
#include <utils/hostosinfo.h>
|
||||||
|
#include <utils/persistentsettings.h>
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
#include <projectexplorer/kitmanager.h>
|
||||||
|
#include <projectexplorer/kitinformation.h>
|
||||||
|
#include <projectexplorer/devicesupport/devicemanager.h>
|
||||||
|
#include <projectexplorer/toolchainmanager.h>
|
||||||
|
#include <projectexplorer/toolchain.h>
|
||||||
|
#include <projectexplorer/gcctoolchain.h>
|
||||||
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
|
#include <qt4projectmanager/qmakekitinformation.h>
|
||||||
|
#include <debugger/debuggerkitinformation.h>
|
||||||
|
#include <qtsupport/baseqtversion.h>
|
||||||
|
#include <qtsupport/qtkitinformation.h>
|
||||||
|
#include <qtsupport/qtversionmanager.h>
|
||||||
|
#include <qtsupport/qtversionfactory.h>
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QSettings>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QDirIterator>
|
||||||
|
#include <QMetaObject>
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
#include <QStringListModel>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
using namespace Utils;
|
||||||
|
|
||||||
|
static const bool debugProbe = true;
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
const QLatin1String SettingsGroup("IosConfigurations");
|
||||||
|
const QLatin1String developerPathKey("DeveloperPath");
|
||||||
|
const QLatin1String ignoreAllDevicesKey("IgnoreAllDevices");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
IosConfig::IosConfig(const QSettings &settings)
|
||||||
|
{
|
||||||
|
developerPath = FileName::fromString(settings.value(developerPathKey).toString());
|
||||||
|
ignoreAllDevices = settings.value(ignoreAllDevicesKey, false).toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
IosConfig::IosConfig() : ignoreAllDevices(false)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void IosConfig::save(QSettings &settings) const
|
||||||
|
{
|
||||||
|
settings.setValue(developerPathKey, developerPath.toString());
|
||||||
|
settings.setValue(ignoreAllDevicesKey, ignoreAllDevices);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosConfigurations::setConfig(const IosConfig &devConfigs)
|
||||||
|
{
|
||||||
|
m_config = devConfigs;
|
||||||
|
save();
|
||||||
|
updateAutomaticKitList();
|
||||||
|
emit updated();
|
||||||
|
}
|
||||||
|
|
||||||
|
FileName IosConfigurations::iosToolPath() const
|
||||||
|
{
|
||||||
|
FileName res = FileName::fromString(QCoreApplication::applicationDirPath()
|
||||||
|
+ QLatin1String("/iosTool"));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool equalKits(Kit *a, Kit *b)
|
||||||
|
{
|
||||||
|
return ToolChainKitInformation::toolChain(a) == ToolChainKitInformation::toolChain(b)
|
||||||
|
&& QtSupport::QtKitInformation::qtVersion(a) == QtSupport::QtKitInformation::qtVersion(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosConfigurations::updateAutomaticKitList()
|
||||||
|
{
|
||||||
|
QMap<QString, Platform> platforms = IosProbe::detectPlatforms(m_config.developerPath.toString());
|
||||||
|
QMap<QString, ProjectExplorer::GccToolChain *> platformToolchainMap;
|
||||||
|
// check existing toolchains (and remove old ones)
|
||||||
|
foreach (ProjectExplorer::ToolChain *tc, ProjectExplorer::ToolChainManager::toolChains()) {
|
||||||
|
if (!tc->isAutoDetected()) // use also user toolchains?
|
||||||
|
continue;
|
||||||
|
if (tc->type() != QLatin1String("clang") && tc->type() != QLatin1String("gcc"))
|
||||||
|
continue;
|
||||||
|
ProjectExplorer::GccToolChain *toolchain = static_cast<ProjectExplorer::GccToolChain *>(tc);
|
||||||
|
QMapIterator<QString, Platform> iter(platforms);
|
||||||
|
bool found = false;
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
iter.next();
|
||||||
|
const Platform &p = iter.value();
|
||||||
|
if (p.compilerPath == toolchain->compilerCommand()
|
||||||
|
&& p.backendFlags == toolchain->platformCodeGenFlags()) {
|
||||||
|
platformToolchainMap[p.name] = toolchain;
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iter.toFront();
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
iter.next();
|
||||||
|
const Platform &p = iter.value();
|
||||||
|
if (p.platformKind)
|
||||||
|
continue;
|
||||||
|
if (p.compilerPath == toolchain->compilerCommand()
|
||||||
|
&& p.backendFlags == toolchain->platformCodeGenFlags()) {
|
||||||
|
platformToolchainMap[p.name] = toolchain;
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found && (tc->displayName().startsWith(QLatin1String("iphone"))
|
||||||
|
|| tc->displayName().startsWith(QLatin1String("mac")))) {
|
||||||
|
qDebug() << "removing toolchain" << tc->displayName();
|
||||||
|
ProjectExplorer::ToolChainManager::deregisterToolChain(tc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// add missing toolchains
|
||||||
|
{
|
||||||
|
QMapIterator<QString, Platform> iter(platforms);
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
iter.next();
|
||||||
|
const Platform &p = iter.value();
|
||||||
|
if (platformToolchainMap.contains(p.name)
|
||||||
|
|| (p.platformKind & Platform::BasePlatform) == 0
|
||||||
|
|| (p.name.startsWith(QLatin1String("iphone"))
|
||||||
|
&& (p.platformKind & Platform::Cxx11Support) != 0))
|
||||||
|
continue;
|
||||||
|
ProjectExplorer::GccToolChain *toolchain;
|
||||||
|
if (p.compilerPath.toFileInfo().baseName().startsWith(QLatin1String("clang")))
|
||||||
|
toolchain = new ProjectExplorer::ClangToolChain(
|
||||||
|
ProjectExplorer::ToolChain::AutoDetection);
|
||||||
|
else
|
||||||
|
toolchain = new ProjectExplorer::GccToolChain(
|
||||||
|
QLatin1String(ProjectExplorer::Constants::GCC_TOOLCHAIN_ID),
|
||||||
|
ProjectExplorer::ToolChain::AutoDetection);
|
||||||
|
QString baseDisplayName = p.name;
|
||||||
|
QString displayName = baseDisplayName;
|
||||||
|
for (int iVers = 1; iVers < 100; ++iVers) {
|
||||||
|
bool unique = true;
|
||||||
|
foreach (ProjectExplorer::ToolChain *existingTC, ProjectExplorer::ToolChainManager::toolChains()) {
|
||||||
|
if (existingTC->displayName() == displayName) {
|
||||||
|
unique = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (unique) break;
|
||||||
|
displayName = baseDisplayName + QLatin1String("-") + QString::number(iVers);
|
||||||
|
}
|
||||||
|
toolchain->setDisplayName(displayName);
|
||||||
|
toolchain->setPlatformCodeGenFlags(p.backendFlags);
|
||||||
|
toolchain->setPlatformLinkerFlags(p.backendFlags);
|
||||||
|
toolchain->setCompilerCommand(p.compilerPath);
|
||||||
|
ProjectExplorer::ToolChainManager::registerToolChain(toolchain);
|
||||||
|
platformToolchainMap.insert(p.name, toolchain);
|
||||||
|
QMapIterator<QString, Platform> iter2(iter);
|
||||||
|
while (iter2.hasNext()) {
|
||||||
|
iter2.next();
|
||||||
|
const Platform &p2 = iter2.value();
|
||||||
|
if (!platformToolchainMap.contains(p2.name)
|
||||||
|
&& p2.compilerPath == toolchain->compilerCommand()
|
||||||
|
&& p2.backendFlags == toolchain->platformCodeGenFlags()) {
|
||||||
|
platformToolchainMap[p2.name] = toolchain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// filter out all non iphone, non base, non clang or cxx11 platforms, as we don't set up kits for those
|
||||||
|
{
|
||||||
|
QStringList toRemove;
|
||||||
|
QMapIterator<QString, Platform> iter(platforms);
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
iter.next();
|
||||||
|
const Platform &p = iter.value();
|
||||||
|
if (!p.name.startsWith(QLatin1String("iphone")) || (p.platformKind & Platform::BasePlatform) == 0
|
||||||
|
|| (p.platformKind & Platform::Cxx11Support) != 0
|
||||||
|
|| !p.compilerPath.toString().contains(QLatin1String("clang")))
|
||||||
|
toRemove.append(p.name);
|
||||||
|
}
|
||||||
|
foreach (const QString &pName, toRemove) {
|
||||||
|
if (debugProbe)
|
||||||
|
qDebug() << "filtering out " << pName;
|
||||||
|
platforms.remove(pName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QMap<ProjectExplorer::Abi::Architecture, QList<QtSupport::BaseQtVersion *> > qtVersionsForArch;
|
||||||
|
foreach (QtSupport::BaseQtVersion *qtVersion, QtSupport::QtVersionManager::versions()) {
|
||||||
|
if (debugProbe)
|
||||||
|
qDebug() << "qt type " << qtVersion->type();
|
||||||
|
if (qtVersion->type() != QLatin1String(Constants::IOSQT)) {
|
||||||
|
if (qtVersion->qmakeProperty("QMAKE_PLATFORM").contains(QLatin1String("ios"))
|
||||||
|
|| qtVersion->qmakeProperty("QMAKE_XSPEC").contains(QLatin1String("ios"))) {
|
||||||
|
// replace with an ios version
|
||||||
|
QtSupport::BaseQtVersion *iosVersion =
|
||||||
|
QtSupport::QtVersionFactory::createQtVersionFromQMakePath(
|
||||||
|
qtVersion->qmakeCommand(),
|
||||||
|
qtVersion->isAutodetected(),
|
||||||
|
qtVersion->autodetectionSource());
|
||||||
|
if (iosVersion && iosVersion->type() == QLatin1String(Constants::IOSQT)) {
|
||||||
|
if (debugProbe)
|
||||||
|
qDebug() << "converting QT to iOS QT for " << qtVersion->qmakeCommand().toUserOutput();
|
||||||
|
QtSupport::QtVersionManager::removeVersion(qtVersion);
|
||||||
|
QtSupport::QtVersionManager::addVersion(iosVersion);
|
||||||
|
qtVersion = iosVersion;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!qtVersion->isValid())
|
||||||
|
continue;
|
||||||
|
QList<ProjectExplorer::Abi> qtAbis = qtVersion->qtAbis();
|
||||||
|
if (qtAbis.empty())
|
||||||
|
continue;
|
||||||
|
if (debugProbe)
|
||||||
|
qDebug() << "qt arch " << qtAbis.first().architecture();
|
||||||
|
foreach (const ProjectExplorer::Abi &abi, qtAbis)
|
||||||
|
qtVersionsForArch[abi.architecture()].append(qtVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<ProjectExplorer::Kit *> existingKits;
|
||||||
|
QList<bool> kitMatched;
|
||||||
|
foreach (ProjectExplorer::Kit *k, ProjectExplorer::KitManager::kits()) {
|
||||||
|
Core::Id deviceKind=ProjectExplorer::DeviceTypeKitInformation::deviceTypeId(k);
|
||||||
|
if (deviceKind != Core::Id(Constants::IOS_DEVICE_TYPE)
|
||||||
|
&& deviceKind != Core::Id(Constants::IOS_SIMULATOR_TYPE)
|
||||||
|
&& deviceKind != Core::Id(ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE)){
|
||||||
|
if (debugProbe)
|
||||||
|
qDebug() << "skipping existing kit with deviceKind " << deviceKind.toString();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!k->isAutoDetected()) // use also used set kits?
|
||||||
|
continue;
|
||||||
|
existingKits << k;
|
||||||
|
kitMatched << false;
|
||||||
|
}
|
||||||
|
// create missing kits
|
||||||
|
{
|
||||||
|
QMapIterator<QString, Platform> iter(platforms);
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
iter.next();
|
||||||
|
const Platform &p = iter.value();
|
||||||
|
ProjectExplorer::GccToolChain *pToolchain = platformToolchainMap.value(p.name, 0);
|
||||||
|
if (!pToolchain)
|
||||||
|
continue;
|
||||||
|
Core::Id pDeviceType, pDeviceId;
|
||||||
|
if (debugProbe)
|
||||||
|
qDebug() << "guaranteeing kit for " << p.name ;
|
||||||
|
if (p.name.startsWith(QLatin1String("iphoneos-"))) {
|
||||||
|
pDeviceType = Core::Id(Constants::IOS_DEVICE_TYPE);
|
||||||
|
} else if (p.name.startsWith(QLatin1String("iphonesimulator-"))) {
|
||||||
|
pDeviceType = Core::Id(Constants::IOS_SIMULATOR_TYPE);
|
||||||
|
if (debugProbe)
|
||||||
|
qDebug() << "pDeviceType " << pDeviceType.toString();
|
||||||
|
} else {
|
||||||
|
if (debugProbe)
|
||||||
|
qDebug() << "skipping non ios kit " << p.name;
|
||||||
|
// we looked up only the ios qt build above...
|
||||||
|
continue;
|
||||||
|
//pDeviceType = Core::Id(ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE);
|
||||||
|
}
|
||||||
|
ProjectExplorer::Abi::Architecture arch = pToolchain->targetAbi().architecture();
|
||||||
|
|
||||||
|
QList<QtSupport::BaseQtVersion *> qtVersions = qtVersionsForArch.value(arch);
|
||||||
|
foreach (QtSupport::BaseQtVersion *qt, qtVersions) {
|
||||||
|
bool kitExists = false;
|
||||||
|
for (int i = 0; i < existingKits.size(); ++i) {
|
||||||
|
Kit *k = existingKits.at(i);
|
||||||
|
if (DeviceTypeKitInformation::deviceTypeId(k) == pDeviceType
|
||||||
|
&& ToolChainKitInformation::toolChain(k) == pToolchain
|
||||||
|
&& SysRootKitInformation::sysRoot(k) == p.sdkPath
|
||||||
|
&& QtSupport::QtKitInformation::qtVersion(k) == qt)
|
||||||
|
{
|
||||||
|
kitExists = true;
|
||||||
|
if (debugProbe)
|
||||||
|
qDebug() << "found existing kit " << k->displayName() << " for " << p.name
|
||||||
|
<< "," << qt->displayName();
|
||||||
|
if (i<kitMatched.size())
|
||||||
|
kitMatched.replace(i, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (kitExists)
|
||||||
|
continue;
|
||||||
|
if (debugProbe)
|
||||||
|
qDebug() << "setting up new kit for " << p.name;
|
||||||
|
Kit *newKit = new Kit;
|
||||||
|
newKit->setAutoDetected(true);
|
||||||
|
QString baseDisplayName = tr("%1 %2").arg(p.name, qt->displayName());
|
||||||
|
QString displayName = baseDisplayName;
|
||||||
|
for (int iVers = 1; iVers < 100; ++iVers) {
|
||||||
|
bool unique = true;
|
||||||
|
foreach (const ProjectExplorer::Kit *k, existingKits) {
|
||||||
|
if (k->displayName() == displayName) {
|
||||||
|
unique = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (unique) break;
|
||||||
|
displayName = baseDisplayName + QLatin1String("-") + QString::number(iVers);
|
||||||
|
}
|
||||||
|
newKit->setDisplayName(displayName);
|
||||||
|
//newKit->setIconPath(QLatin1String(Constants::IOS_SETTINGS_CATEGORY_ICON));
|
||||||
|
//DeviceKitInformation::setDevice(newKit, pDeviceType);
|
||||||
|
DeviceTypeKitInformation::setDeviceTypeId(newKit, pDeviceType);
|
||||||
|
ToolChainKitInformation::setToolChain(newKit, pToolchain);
|
||||||
|
QtSupport::QtKitInformation::setQtVersion(newKit, qt);
|
||||||
|
//DeviceKitInformation::setDevice(newKit, device);
|
||||||
|
Debugger::DebuggerKitInformation::setDebugger(newKit, pToolchain->suggestedDebugger());
|
||||||
|
SysRootKitInformation::setSysRoot(newKit, p.sdkPath);
|
||||||
|
//Qt4ProjectManager::QmakeKitInformation::setMkspec(newKit,
|
||||||
|
// Utils::FileName::fromString(QLatin1String("macx-ios-clang")));
|
||||||
|
KitManager::registerKit(newKit);
|
||||||
|
existingKits << newKit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// deleting extra (old) kits
|
||||||
|
for (int i = 0; i < kitMatched.size(); ++i) {
|
||||||
|
if (!kitMatched.at(i) && !existingKits.at(i)->isValid()) {
|
||||||
|
qDebug() << "deleting kit " << existingKits.at(i)->displayName();
|
||||||
|
KitManager::deregisterKit(existingKits.at(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IosConfigurations &IosConfigurations::instance()
|
||||||
|
{
|
||||||
|
if (m_instance == 0) {
|
||||||
|
m_instance = new IosConfigurations(0);
|
||||||
|
m_instance->updateSimulators();
|
||||||
|
connect(&(m_instance->m_updateAvailableDevices),SIGNAL(timeout()),
|
||||||
|
IosDeviceManager::instance(),SLOT(monitorAvailableDevices()));
|
||||||
|
m_instance->m_updateAvailableDevices.setSingleShot(true);
|
||||||
|
m_instance->m_updateAvailableDevices.start(10000);
|
||||||
|
}
|
||||||
|
return *m_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosConfigurations::save()
|
||||||
|
{
|
||||||
|
QSettings *settings = Core::ICore::instance()->settings();
|
||||||
|
settings->beginGroup(SettingsGroup);
|
||||||
|
m_config.save(*settings);
|
||||||
|
settings->endGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
IosConfigurations::IosConfigurations(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosConfigurations::load()
|
||||||
|
{
|
||||||
|
QSettings *settings = Core::ICore::instance()->settings();
|
||||||
|
settings->beginGroup(SettingsGroup);
|
||||||
|
m_config = IosConfig(*settings);
|
||||||
|
settings->endGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
IosConfigurations *IosConfigurations::m_instance = 0;
|
||||||
|
|
||||||
|
QStringList IosConfigurations::sdkTargets()
|
||||||
|
{
|
||||||
|
QStringList res;
|
||||||
|
QTC_CHECK(false);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosConfigurations::updateSimulators() {
|
||||||
|
// currently we have just one simulator
|
||||||
|
DeviceManager *devManager = DeviceManager::instance();
|
||||||
|
Core::Id devId(Constants::IOS_SIMULATOR_DEVICE_ID);
|
||||||
|
QMap<QString, Platform> platforms = IosProbe::detectPlatforms(m_config.developerPath.toString());
|
||||||
|
QMapIterator<QString, Platform> iter(platforms);
|
||||||
|
Utils::FileName simulatorPath;
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
iter.next();
|
||||||
|
const Platform &p = iter.value();
|
||||||
|
if (p.name.startsWith(QLatin1String("iphonesimulator-"))) {
|
||||||
|
simulatorPath = p.platformPath;
|
||||||
|
simulatorPath.appendPath(QLatin1String(
|
||||||
|
"/Developer/Applications/iPhone Simulator.app/Contents/MacOS/iPhone Simulator"));
|
||||||
|
if (simulatorPath.toFileInfo().exists())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IDevice::ConstPtr dev = devManager->find(devId);
|
||||||
|
if (!simulatorPath.isEmpty() && simulatorPath.toFileInfo().exists()) {
|
||||||
|
if (!dev.isNull()) {
|
||||||
|
if (static_cast<const IosSimulator*>(dev.data())->simulatorPath() == simulatorPath)
|
||||||
|
return;
|
||||||
|
devManager->removeDevice(devId);
|
||||||
|
}
|
||||||
|
IosSimulator *newDev = new IosSimulator(devId, simulatorPath);
|
||||||
|
devManager->addDevice(IDevice::ConstPtr(newDev));
|
||||||
|
} else if (!dev.isNull()) {
|
||||||
|
devManager->removeDevice(devId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
90
src/plugins/ios/iosconfigurations.h
Normal file
90
src/plugins/ios/iosconfigurations.h
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef IOSCONFIGURATIONS_H
|
||||||
|
#define IOSCONFIGURATIONS_H
|
||||||
|
|
||||||
|
#include <projectexplorer/abi.h>
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
|
#include <QMap>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QSettings;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class IosConfig
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IosConfig();
|
||||||
|
IosConfig(const QSettings &settings);
|
||||||
|
void save(QSettings &settings) const;
|
||||||
|
|
||||||
|
Utils::FileName developerPath;
|
||||||
|
bool ignoreAllDevices;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IosConfigurations : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
static IosConfigurations &instance();
|
||||||
|
IosConfig config() const { return m_config; }
|
||||||
|
void setConfig(const IosConfig &config);
|
||||||
|
Utils::FileName iosToolPath() const;
|
||||||
|
|
||||||
|
QStringList sdkTargets();
|
||||||
|
void updateSimulators();
|
||||||
|
signals:
|
||||||
|
void updated();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void updateAutomaticKitList();
|
||||||
|
|
||||||
|
private:
|
||||||
|
IosConfigurations(QObject *parent);
|
||||||
|
void load();
|
||||||
|
void save();
|
||||||
|
|
||||||
|
static IosConfigurations *m_instance;
|
||||||
|
IosConfig m_config;
|
||||||
|
QTimer m_updateAvailableDevices;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#endif // IOSCONFIGURATIONS_H
|
67
src/plugins/ios/iosconstants.h
Normal file
67
src/plugins/ios/iosconstants.h
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef IOSCONSTANTS_H
|
||||||
|
#define IOSCONSTANTS_H
|
||||||
|
|
||||||
|
#include <QtGlobal>
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
enum IosQemuStatus {
|
||||||
|
IosQemuStarting,
|
||||||
|
IosQemuFailedToStart,
|
||||||
|
IosQemuFinished,
|
||||||
|
IosQemuCrashed,
|
||||||
|
IosQemuUserReason
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
#define IOS_BAT_SUFFIX ".bat"
|
||||||
|
#else
|
||||||
|
#define IOS_BAT_SUFFIX ""
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
|
||||||
|
namespace Constants {
|
||||||
|
const char IOS_SETTINGS_ID[] = "ZZ.Ios Configurations";
|
||||||
|
const char IOS_SETTINGS_CATEGORY[] = "XA.Ios";
|
||||||
|
const char IOS_SETTINGS_TR_CATEGORY[] = QT_TRANSLATE_NOOP("Ios", "iOS");
|
||||||
|
const char IOS_SETTINGS_CATEGORY_ICON[] = ":/ios/images/QtIos.png";
|
||||||
|
const char IOSQT[] = "Qt4ProjectManager.QtVersion.Ios";
|
||||||
|
|
||||||
|
const char IOS_DEVICE_TYPE[] = "Ios.Device.Type";
|
||||||
|
const char IOS_SIMULATOR_TYPE[] = "Ios.Simulator.Type";
|
||||||
|
const char IOS_DEVICE_ID[] = "iOS Device ";
|
||||||
|
const char IOS_SIMULATOR_DEVICE_ID[] = "iOS Simulator Device ";
|
||||||
|
} // namespace Constants;
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#endif // IOSCONSTANTS_H
|
136
src/plugins/ios/iosdebugsupport.cpp
Normal file
136
src/plugins/ios/iosdebugsupport.cpp
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "iosdebugsupport.h"
|
||||||
|
|
||||||
|
#include "iosrunner.h"
|
||||||
|
#include "iosmanager.h"
|
||||||
|
|
||||||
|
#include <debugger/debuggerengine.h>
|
||||||
|
#include <debugger/debuggerplugin.h>
|
||||||
|
#include <debugger/debuggerkitinformation.h>
|
||||||
|
#include <debugger/debuggerrunner.h>
|
||||||
|
#include <debugger/debuggerstartparameters.h>
|
||||||
|
|
||||||
|
#include <projectexplorer/target.h>
|
||||||
|
#include <qt4projectmanager/qt4buildconfiguration.h>
|
||||||
|
#include <qt4projectmanager/qt4nodes.h>
|
||||||
|
#include <qt4projectmanager/qt4project.h>
|
||||||
|
#include <qtsupport/qtkitinformation.h>
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
|
using namespace Debugger;
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
using namespace Qt4ProjectManager;
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
static const char * const qMakeVariables[] = {
|
||||||
|
"QT_INSTALL_LIBS",
|
||||||
|
"QT_INSTALL_PLUGINS",
|
||||||
|
"QT_INSTALL_IMPORTS"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
RunControl *IosDebugSupport::createDebugRunControl(IosRunConfiguration *runConfig,
|
||||||
|
QString *errorMessage)
|
||||||
|
{
|
||||||
|
//Target *target = runConfig->target();
|
||||||
|
//Qt4Project *project = static_cast<Qt4Project *>(target->project());
|
||||||
|
|
||||||
|
DebuggerStartParameters params;
|
||||||
|
params.startMode = AttachToRemoteServer;
|
||||||
|
//params.displayName = IosManager::packageName(target);
|
||||||
|
params.remoteSetupNeeded = true;
|
||||||
|
|
||||||
|
DebuggerRunControl * const debuggerRunControl
|
||||||
|
= DebuggerPlugin::createDebugger(params, runConfig, errorMessage);
|
||||||
|
new IosDebugSupport(runConfig, debuggerRunControl);
|
||||||
|
return debuggerRunControl;
|
||||||
|
}
|
||||||
|
|
||||||
|
IosDebugSupport::IosDebugSupport(IosRunConfiguration *runConfig,
|
||||||
|
DebuggerRunControl *runControl)
|
||||||
|
: QObject(runControl), m_runControl(runControl),
|
||||||
|
m_runner(new IosRunner(this, runConfig, true)),
|
||||||
|
m_gdbServerPort(0), m_qmlPort(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
connect(m_runControl->engine(), SIGNAL(requestRemoteSetup()),
|
||||||
|
m_runner, SLOT(start()));
|
||||||
|
connect(m_runControl, SIGNAL(finished()),
|
||||||
|
m_runner, SLOT(stop()));
|
||||||
|
|
||||||
|
connect(m_runner, SIGNAL(gotGdbSocket(int)),
|
||||||
|
SLOT(handleGdbServerFd(int)));
|
||||||
|
connect(m_runner, SIGNAL(finished(bool)),
|
||||||
|
SLOT(handleRemoteProcessFinished(bool)));
|
||||||
|
|
||||||
|
connect(m_runner, SIGNAL(errorMsg(QString)),
|
||||||
|
SLOT(handleRemoteErrorOutput(QString)));
|
||||||
|
connect(m_runner, SIGNAL(appOutput(QString)),
|
||||||
|
SLOT(handleRemoteOutput(QString)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosDebugSupport::handleGdbServerFd(int gdbServerFd)
|
||||||
|
{
|
||||||
|
QTC_CHECK(false); // to do transfer fd to debugger
|
||||||
|
//m_runControl->engine()->notifyEngineRemoteSetupDone(gdbServerPort, qmlPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosDebugSupport::handleRemoteProcessFinished(bool cleanEnd)
|
||||||
|
{
|
||||||
|
if (!cleanEnd && m_runControl)
|
||||||
|
m_runControl->showMessage(tr("Run failed unexpectedly."), AppStuff);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosDebugSupport::handleRemoteOutput(const QString &output)
|
||||||
|
{
|
||||||
|
if (m_runControl) {
|
||||||
|
if (m_runControl->engine())
|
||||||
|
m_runControl->engine()->showMessage(output, AppOutput);
|
||||||
|
else
|
||||||
|
m_runControl->showMessage(output, AppOutput);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosDebugSupport::handleRemoteErrorOutput(const QString &output)
|
||||||
|
{
|
||||||
|
if (m_runControl) {
|
||||||
|
if (m_runControl->engine())
|
||||||
|
m_runControl->engine()->showMessage(output + QLatin1Char('\n'), AppError);
|
||||||
|
else
|
||||||
|
m_runControl->showMessage(output + QLatin1Char('\n'), AppError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
73
src/plugins/ios/iosdebugsupport.h
Normal file
73
src/plugins/ios/iosdebugsupport.h
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef IOSDEBUGSUPPORT_H
|
||||||
|
#define IOSDEBUGSUPPORT_H
|
||||||
|
|
||||||
|
#include "iosrunconfiguration.h"
|
||||||
|
|
||||||
|
namespace Debugger { class DebuggerRunControl; }
|
||||||
|
namespace ProjectExplorer { class RunControl; }
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class IosRunConfiguration;
|
||||||
|
class IosRunner;
|
||||||
|
|
||||||
|
class IosDebugSupport : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
static ProjectExplorer::RunControl *createDebugRunControl(IosRunConfiguration *runConfig,
|
||||||
|
QString *errorMessage);
|
||||||
|
|
||||||
|
IosDebugSupport(IosRunConfiguration *runConfig,
|
||||||
|
Debugger::DebuggerRunControl *runControl);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void handleGdbServerFd(int gdbServerFd);
|
||||||
|
void handleRemoteProcessFinished(bool cleanEnd);
|
||||||
|
|
||||||
|
void handleRemoteOutput(const QString &output);
|
||||||
|
void handleRemoteErrorOutput(const QString &output);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Debugger::DebuggerRunControl *m_runControl;
|
||||||
|
IosRunner * const m_runner;
|
||||||
|
const QString m_dumperLib;
|
||||||
|
|
||||||
|
int m_gdbServerPort;
|
||||||
|
int m_qmlPort;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#endif // IOSDEBUGSUPPORT_H
|
138
src/plugins/ios/iosdeployconfiguration.cpp
Normal file
138
src/plugins/ios/iosdeployconfiguration.cpp
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "iosconstants.h"
|
||||||
|
#include "iosdeploystep.h"
|
||||||
|
#include "iosdeployconfiguration.h"
|
||||||
|
#include "iosmanager.h"
|
||||||
|
|
||||||
|
#include <projectexplorer/buildsteplist.h>
|
||||||
|
#include <projectexplorer/target.h>
|
||||||
|
|
||||||
|
#include <qt4projectmanager/qt4project.h>
|
||||||
|
#include <qtsupport/qtkitinformation.h>
|
||||||
|
#include <qtsupport/qtsupportconstants.h>
|
||||||
|
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
IosDeployConfiguration::IosDeployConfiguration(Target *parent, Core::Id id)
|
||||||
|
: DeployConfiguration(parent, id)
|
||||||
|
{
|
||||||
|
setDisplayName(tr("Deploy to iOS"));
|
||||||
|
setDefaultDisplayName(displayName());
|
||||||
|
}
|
||||||
|
|
||||||
|
IosDeployConfiguration::IosDeployConfiguration(Target *parent, DeployConfiguration *source)
|
||||||
|
: DeployConfiguration(parent, source)
|
||||||
|
{
|
||||||
|
cloneSteps(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
IosDeployConfigurationFactory::IosDeployConfigurationFactory(QObject *parent)
|
||||||
|
: DeployConfigurationFactory(parent)
|
||||||
|
{
|
||||||
|
setObjectName(QLatin1String("IosDeployConfigurationFactory"));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosDeployConfigurationFactory::canCreate(Target *parent, const Core::Id id) const
|
||||||
|
{
|
||||||
|
return availableCreationIds(parent).contains(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
DeployConfiguration *IosDeployConfigurationFactory::create(Target *parent, const Core::Id id)
|
||||||
|
{
|
||||||
|
IosDeployConfiguration *dc = new IosDeployConfiguration(parent, id);
|
||||||
|
if (!dc)
|
||||||
|
return 0;
|
||||||
|
dc->stepList()->insertStep(0, new IosDeployStep(dc->stepList()));
|
||||||
|
return dc;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosDeployConfigurationFactory::canRestore(Target *parent, const QVariantMap &map) const
|
||||||
|
{
|
||||||
|
return canCreate(parent, idFromMap(map));
|
||||||
|
}
|
||||||
|
|
||||||
|
DeployConfiguration *IosDeployConfigurationFactory::restore(Target *parent, const QVariantMap &map)
|
||||||
|
{
|
||||||
|
if (!canRestore(parent, map))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
IosDeployConfiguration *dc = new IosDeployConfiguration(parent, idFromMap(map));
|
||||||
|
if (dc->fromMap(map))
|
||||||
|
return dc;
|
||||||
|
|
||||||
|
delete dc;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosDeployConfigurationFactory::canClone(Target *parent, DeployConfiguration *source) const
|
||||||
|
{
|
||||||
|
if (!IosManager::supportsIos(parent))
|
||||||
|
return false;
|
||||||
|
return source->id() == IOS_DEPLOYCONFIGURATION_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeployConfiguration *IosDeployConfigurationFactory::clone(Target *parent, DeployConfiguration *source)
|
||||||
|
{
|
||||||
|
if (!canClone(parent, source))
|
||||||
|
return 0;
|
||||||
|
return new IosDeployConfiguration(parent, source);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<Core::Id> IosDeployConfigurationFactory::availableCreationIds(Target *parent) const
|
||||||
|
{
|
||||||
|
QList<Core::Id> ids;
|
||||||
|
if (!qobject_cast<Qt4ProjectManager::Qt4Project *>(parent->project()))
|
||||||
|
return ids;
|
||||||
|
if (!parent->project()->supportsKit(parent->kit()))
|
||||||
|
return ids;
|
||||||
|
if (!IosManager::supportsIos(parent))
|
||||||
|
return ids;
|
||||||
|
ids << Core::Id(IOS_DEPLOYCONFIGURATION_ID);
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosDeployConfigurationFactory::displayNameForId(const Core::Id id) const
|
||||||
|
{
|
||||||
|
if (id.name().startsWith(IOS_DC_PREFIX))
|
||||||
|
return tr("Deploy on iOS");
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosDeployConfigurationFactory::canHandle(Target *parent) const
|
||||||
|
{
|
||||||
|
return IosManager::supportsIos(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
82
src/plugins/ios/iosdeployconfiguration.h
Normal file
82
src/plugins/ios/iosdeployconfiguration.h
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef IOSDEPLOYCONFIGURATION_H
|
||||||
|
#define IOSDEPLOYCONFIGURATION_H
|
||||||
|
|
||||||
|
#include <projectexplorer/deployconfiguration.h>
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
const char IOS_DEPLOYCONFIGURATION_ID[] = "Qt4ProjectManager.IosDeployConfiguration";
|
||||||
|
const char IOS_DC_PREFIX[] = "Qt4ProjectManager.IosDeployConfiguration.";
|
||||||
|
|
||||||
|
class IosDeployConfiguration : public ProjectExplorer::DeployConfiguration
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
friend class IosDeployConfigurationFactory;
|
||||||
|
|
||||||
|
public:
|
||||||
|
IosDeployConfiguration(ProjectExplorer::Target *parent, Core::Id id);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
IosDeployConfiguration(ProjectExplorer::Target *parent,
|
||||||
|
ProjectExplorer::DeployConfiguration *source);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class IosDeployConfigurationFactory : public ProjectExplorer::DeployConfigurationFactory
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit IosDeployConfigurationFactory(QObject *parent = 0);
|
||||||
|
|
||||||
|
bool canCreate(ProjectExplorer::Target *parent, const Core::Id id) const;
|
||||||
|
ProjectExplorer::DeployConfiguration *create(ProjectExplorer::Target *parent, const Core::Id id);
|
||||||
|
bool canRestore(ProjectExplorer::Target *parent, const QVariantMap &map) const;
|
||||||
|
ProjectExplorer::DeployConfiguration *restore(ProjectExplorer::Target *parent,
|
||||||
|
const QVariantMap &map);
|
||||||
|
bool canClone(ProjectExplorer::Target *parent,
|
||||||
|
ProjectExplorer::DeployConfiguration *source) const;
|
||||||
|
ProjectExplorer::DeployConfiguration *clone(ProjectExplorer::Target *parent,
|
||||||
|
ProjectExplorer::DeployConfiguration *source);
|
||||||
|
|
||||||
|
QList<Core::Id> availableCreationIds(ProjectExplorer::Target *parent) const;
|
||||||
|
// used to translate the ids to names to display to the user
|
||||||
|
QString displayNameForId(const Core::Id id) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool canHandle(ProjectExplorer::Target *parent) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#endif // IOSDEPLOYCONFIGURATION_H
|
231
src/plugins/ios/iosdeploystep.cpp
Normal file
231
src/plugins/ios/iosdeploystep.cpp
Normal file
@@ -0,0 +1,231 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "iosdeploystepwidget.h"
|
||||||
|
#include "iosdeploystep.h"
|
||||||
|
#include "iosbuildstep.h"
|
||||||
|
#include "iosconstants.h"
|
||||||
|
#include "iosrunconfiguration.h"
|
||||||
|
#include "iosmanager.h"
|
||||||
|
#include "iostoolhandler.h"
|
||||||
|
|
||||||
|
#include <coreplugin/messagemanager.h>
|
||||||
|
#include <projectexplorer/buildconfiguration.h>
|
||||||
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
|
#include <projectexplorer/target.h>
|
||||||
|
#include <qt4projectmanager/qt4buildconfiguration.h>
|
||||||
|
#include <qt4projectmanager/qt4project.h>
|
||||||
|
#include <qt4projectmanager/qt4nodes.h>
|
||||||
|
|
||||||
|
#include <qtsupport/qtkitinformation.h>
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
|
#define ASSERT_STATE(state) ASSERT_STATE_GENERIC(State, state, m_state)
|
||||||
|
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
using namespace Qt4ProjectManager;
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
static const char USE_LOCAL_QT_KEY[] = "Qt4ProjectManager.IosDeployStep.UseLocalQtLibs";
|
||||||
|
|
||||||
|
const Core::Id IosDeployStep::Id("Qt4ProjectManager.IosDeployStep");
|
||||||
|
|
||||||
|
IosDeployStep::IosDeployStep(ProjectExplorer::BuildStepList *parent)
|
||||||
|
: BuildStep(parent, Id)
|
||||||
|
{
|
||||||
|
ctor();
|
||||||
|
}
|
||||||
|
|
||||||
|
IosDeployStep::IosDeployStep(ProjectExplorer::BuildStepList *parent,
|
||||||
|
IosDeployStep *other)
|
||||||
|
: BuildStep(parent, other)
|
||||||
|
{
|
||||||
|
ctor();
|
||||||
|
}
|
||||||
|
|
||||||
|
IosDeployStep::~IosDeployStep() { }
|
||||||
|
|
||||||
|
void IosDeployStep::ctor()
|
||||||
|
{
|
||||||
|
m_transferStatus = NoTransfer;
|
||||||
|
m_device = ProjectExplorer::DeviceKitInformation::device(target()->kit());
|
||||||
|
QString devName;
|
||||||
|
if (!m_device.isNull())
|
||||||
|
devName = m_device->displayName();
|
||||||
|
if (devName.isEmpty())
|
||||||
|
devName = tr("iOS device");
|
||||||
|
setDefaultDisplayName(tr("Deploy to %1").arg(devName));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosDeployStep::init()
|
||||||
|
{
|
||||||
|
QTC_CHECK(m_transferStatus == NoTransfer);
|
||||||
|
m_device = ProjectExplorer::DeviceKitInformation::device(target()->kit());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosDeployStep::run(QFutureInterface<bool> &fi)
|
||||||
|
{
|
||||||
|
m_futureInterface = fi;
|
||||||
|
QTC_CHECK(m_transferStatus == NoTransfer);
|
||||||
|
if (iosdevice().isNull()) {
|
||||||
|
m_futureInterface.reportResult(!iossimulator().isNull());
|
||||||
|
cleanup();
|
||||||
|
m_futureInterface.reportFinished();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_transferStatus = TransferInProgress;
|
||||||
|
IosToolHandler *toolHandler = new IosToolHandler(IosToolHandler::IosDeviceType, this);
|
||||||
|
m_futureInterface.setProgressRange(0, 200);
|
||||||
|
m_futureInterface.setProgressValueAndText(0, QLatin1String("Transferring application"));
|
||||||
|
m_futureInterface.reportStarted();
|
||||||
|
connect(toolHandler, SIGNAL(isTransferringApp(Ios::IosToolHandler*,QString,QString,int,int,QString)),
|
||||||
|
SLOT(handleIsTransferringApp(Ios::IosToolHandler*,QString,QString,int,int,QString)));
|
||||||
|
connect(toolHandler, SIGNAL(didTransferApp(Ios::IosToolHandler*,QString,QString,Ios::IosToolHandler::OpStatus)),
|
||||||
|
SLOT(handleDidTransferApp(Ios::IosToolHandler*,QString,QString,Ios::IosToolHandler::OpStatus)));
|
||||||
|
connect(toolHandler, SIGNAL(finished(Ios::IosToolHandler*)),
|
||||||
|
SLOT(handleFinished(Ios::IosToolHandler*)));
|
||||||
|
toolHandler->requestTransferApp(appBundle(), deviceId());
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosDeployStep::cancel()
|
||||||
|
{
|
||||||
|
if (m_toolHandler)
|
||||||
|
m_toolHandler->stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosDeployStep::cleanup()
|
||||||
|
{
|
||||||
|
QTC_CHECK(m_transferStatus != TransferInProgress);
|
||||||
|
m_transferStatus = NoTransfer;
|
||||||
|
m_device.clear();
|
||||||
|
m_toolHandler = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosDeployStep::handleIsTransferringApp(IosToolHandler *handler, const QString &bundlePath,
|
||||||
|
const QString &deviceId, int progress, int maxProgress,
|
||||||
|
const QString &info)
|
||||||
|
{
|
||||||
|
Q_UNUSED(handler); Q_UNUSED(bundlePath); Q_UNUSED(deviceId);
|
||||||
|
QTC_CHECK(m_transferStatus == TransferInProgress);
|
||||||
|
m_futureInterface.setProgressRange(0, maxProgress);
|
||||||
|
m_futureInterface.setProgressValueAndText(progress, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosDeployStep::handleDidTransferApp(IosToolHandler *handler, const QString &bundlePath,
|
||||||
|
const QString &deviceId, IosToolHandler::OpStatus status)
|
||||||
|
{
|
||||||
|
Q_UNUSED(handler); Q_UNUSED(bundlePath); Q_UNUSED(deviceId);
|
||||||
|
QTC_CHECK(m_transferStatus == TransferInProgress);
|
||||||
|
if (status == IosToolHandler::Success)
|
||||||
|
m_transferStatus = TransferOk;
|
||||||
|
else
|
||||||
|
m_transferStatus = TransferFailed;
|
||||||
|
m_futureInterface.reportResult(status == IosToolHandler::Success);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosDeployStep::handleFinished(IosToolHandler *handler)
|
||||||
|
{
|
||||||
|
switch (m_transferStatus) {
|
||||||
|
case TransferInProgress:
|
||||||
|
m_transferStatus = TransferFailed;
|
||||||
|
m_futureInterface.reportResult(false);
|
||||||
|
break;
|
||||||
|
case NoTransfer:
|
||||||
|
case TransferOk:
|
||||||
|
case TransferFailed:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cleanup();
|
||||||
|
handler->deleteLater();
|
||||||
|
// move it when result is reported? (would need care to avoid problems with concurrent runs)
|
||||||
|
m_futureInterface.reportFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildStepConfigWidget *IosDeployStep::createConfigWidget()
|
||||||
|
{
|
||||||
|
return new IosDeployStepWidget(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosDeployStep::fromMap(const QVariantMap &map)
|
||||||
|
{
|
||||||
|
return ProjectExplorer::BuildStep::fromMap(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap IosDeployStep::toMap() const
|
||||||
|
{
|
||||||
|
QVariantMap map = ProjectExplorer::BuildStep::toMap();
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosDeployStep::deviceId() const
|
||||||
|
{
|
||||||
|
if (iosdevice().isNull())
|
||||||
|
return QString();
|
||||||
|
return iosdevice()->uniqueDeviceID();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosDeployStep::appBundle() const
|
||||||
|
{
|
||||||
|
IosRunConfiguration * runConfig = qobject_cast<IosRunConfiguration *>(
|
||||||
|
this->target()->activeRunConfiguration());
|
||||||
|
return runConfig->bundleDir().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosDeployStep::raiseError(const QString &errorString)
|
||||||
|
{
|
||||||
|
emit addTask(Task(Task::Error, errorString, Utils::FileName::fromString(QString()), -1,
|
||||||
|
ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosDeployStep::writeOutput(const QString &text, OutputFormat format)
|
||||||
|
{
|
||||||
|
emit addOutput(text, format);
|
||||||
|
}
|
||||||
|
|
||||||
|
IDevice::ConstPtr IosDeployStep::device() const
|
||||||
|
{
|
||||||
|
return m_device;
|
||||||
|
}
|
||||||
|
|
||||||
|
IosDevice::ConstPtr IosDeployStep::iosdevice() const
|
||||||
|
{
|
||||||
|
return m_device.dynamicCast<const IosDevice>();
|
||||||
|
}
|
||||||
|
|
||||||
|
IosSimulator::ConstPtr IosDeployStep::iossimulator() const
|
||||||
|
{
|
||||||
|
return m_device.dynamicCast<const IosSimulator>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Qt4ProjectManager
|
135
src/plugins/ios/iosdeploystep.h
Normal file
135
src/plugins/ios/iosdeploystep.h
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef IOSDEPLOYSTEP_H
|
||||||
|
#define IOSDEPLOYSTEP_H
|
||||||
|
|
||||||
|
#include "iosconfigurations.h"
|
||||||
|
#include "iosdevice.h"
|
||||||
|
#include "iossimulator.h"
|
||||||
|
|
||||||
|
#include <projectexplorer/buildstep.h>
|
||||||
|
#include <projectexplorer/devicesupport/idevice.h>
|
||||||
|
#include <qtsupport/baseqtversion.h>
|
||||||
|
|
||||||
|
#include <QFutureInterface>
|
||||||
|
#include <QProcess>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QEventLoop;
|
||||||
|
class QTimer;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
class IosToolHandler;
|
||||||
|
namespace Internal {
|
||||||
|
class IosDeviceConfigListModel;
|
||||||
|
class IosPackageCreationStep;
|
||||||
|
|
||||||
|
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 IosDeployStep : public ProjectExplorer::BuildStep
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum TransferStatus {
|
||||||
|
NoTransfer,
|
||||||
|
TransferInProgress,
|
||||||
|
TransferOk,
|
||||||
|
TransferFailed
|
||||||
|
};
|
||||||
|
|
||||||
|
friend class IosDeployStepFactory;
|
||||||
|
IosDeployStep(ProjectExplorer::BuildStepList *bc);
|
||||||
|
|
||||||
|
virtual ~IosDeployStep();
|
||||||
|
|
||||||
|
bool fromMap(const QVariantMap &map);
|
||||||
|
QVariantMap toMap() const;
|
||||||
|
|
||||||
|
virtual void run(QFutureInterface<bool> &fi);
|
||||||
|
void cleanup();
|
||||||
|
ProjectExplorer::IDevice::ConstPtr device() const;
|
||||||
|
IosDevice::ConstPtr iosdevice() const;
|
||||||
|
IosSimulator::ConstPtr iossimulator() const;
|
||||||
|
void cancel();
|
||||||
|
signals:
|
||||||
|
//void done();
|
||||||
|
//void error();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void handleIsTransferringApp(Ios::IosToolHandler *handler, const QString &bundlePath,
|
||||||
|
const QString &deviceId, int progress, int maxProgress,
|
||||||
|
const QString &info);
|
||||||
|
void handleDidTransferApp(Ios::IosToolHandler *handler, const QString &bundlePath, const QString &deviceId,
|
||||||
|
Ios::IosToolHandler::OpStatus status);
|
||||||
|
void handleFinished(Ios::IosToolHandler *handler);
|
||||||
|
|
||||||
|
private:
|
||||||
|
IosDeployStep(ProjectExplorer::BuildStepList *bc,
|
||||||
|
IosDeployStep *other);
|
||||||
|
bool init();
|
||||||
|
ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
|
||||||
|
bool immutable() const { return true; }
|
||||||
|
bool runInGuiThread() const { return true; }
|
||||||
|
|
||||||
|
void ctor();
|
||||||
|
QString deviceId() const;
|
||||||
|
QString appBundle() const;
|
||||||
|
void raiseError(const QString &error);
|
||||||
|
void writeOutput(const QString &text, OutputFormat = MessageOutput);
|
||||||
|
private:
|
||||||
|
TransferStatus m_transferStatus;
|
||||||
|
IosToolHandler *m_toolHandler;
|
||||||
|
QFutureInterface<bool> m_futureInterface;
|
||||||
|
ProjectExplorer::IDevice::ConstPtr m_device;
|
||||||
|
static const Core::Id Id;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#endif // IOSDEPLOYSTEP_H
|
111
src/plugins/ios/iosdeploystepfactory.cpp
Normal file
111
src/plugins/ios/iosdeploystepfactory.cpp
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "iosdeploystepfactory.h"
|
||||||
|
|
||||||
|
#include "iosdeploystep.h"
|
||||||
|
#include "iosmanager.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 Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
IosDeployStepFactory::IosDeployStepFactory(QObject *parent)
|
||||||
|
: IBuildStepFactory(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<Core::Id> IosDeployStepFactory::availableCreationIds(BuildStepList *parent) const
|
||||||
|
{
|
||||||
|
if (parent->id() != ProjectExplorer::Constants::BUILDSTEPS_DEPLOY)
|
||||||
|
return QList<Core::Id>();
|
||||||
|
if (!IosManager::supportsIos(parent->target()))
|
||||||
|
return QList<Core::Id>();
|
||||||
|
if (parent->contains(IosDeployStep::Id))
|
||||||
|
return QList<Core::Id>();
|
||||||
|
return QList<Core::Id>() << IosDeployStep::Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosDeployStepFactory::displayNameForId(const Core::Id id) const
|
||||||
|
{
|
||||||
|
if (id == IosDeployStep::Id)
|
||||||
|
return tr("Deploy to iOS device or emulator");
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosDeployStepFactory::canCreate(BuildStepList *parent, const Core::Id id) const
|
||||||
|
{
|
||||||
|
return availableCreationIds(parent).contains(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildStep *IosDeployStepFactory::create(BuildStepList *parent, const Core::Id id)
|
||||||
|
{
|
||||||
|
Q_ASSERT(canCreate(parent, id));
|
||||||
|
Q_UNUSED(id);
|
||||||
|
return new IosDeployStep(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosDeployStepFactory::canRestore(BuildStepList *parent, const QVariantMap &map) const
|
||||||
|
{
|
||||||
|
return canCreate(parent, idFromMap(map));
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildStep *IosDeployStepFactory::restore(BuildStepList *parent, const QVariantMap &map)
|
||||||
|
{
|
||||||
|
Q_ASSERT(canRestore(parent, map));
|
||||||
|
IosDeployStep * const step = new IosDeployStep(parent);
|
||||||
|
if (!step->fromMap(map)) {
|
||||||
|
delete step;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return step;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosDeployStepFactory::canClone(BuildStepList *parent, BuildStep *product) const
|
||||||
|
{
|
||||||
|
return canCreate(parent, product->id());
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildStep *IosDeployStepFactory::clone(BuildStepList *parent, BuildStep *product)
|
||||||
|
{
|
||||||
|
Q_ASSERT(canClone(parent, product));
|
||||||
|
return new IosDeployStep(parent, static_cast<IosDeployStep *>(product));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
62
src/plugins/ios/iosdeploystepfactory.h
Normal file
62
src/plugins/ios/iosdeploystepfactory.h
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef IOSDEPLOYSTEPFACTORY_H
|
||||||
|
#define IOSDEPLOYSTEPFACTORY_H
|
||||||
|
|
||||||
|
#include <projectexplorer/buildstep.h>
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class IosDeployStepFactory : public ProjectExplorer::IBuildStepFactory
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit IosDeployStepFactory(QObject *parent = 0);
|
||||||
|
|
||||||
|
QList<Core::Id> availableCreationIds(ProjectExplorer::BuildStepList *parent) const;
|
||||||
|
QString displayNameForId(const Core::Id id) const;
|
||||||
|
|
||||||
|
bool canCreate(ProjectExplorer::BuildStepList *parent,
|
||||||
|
const Core::Id id) const;
|
||||||
|
ProjectExplorer::BuildStep *create(ProjectExplorer::BuildStepList *parent, const Core::Id id);
|
||||||
|
|
||||||
|
bool canRestore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) const;
|
||||||
|
ProjectExplorer::BuildStep *restore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map);
|
||||||
|
|
||||||
|
bool canClone(ProjectExplorer::BuildStepList *parent,
|
||||||
|
ProjectExplorer::BuildStep *product) const;
|
||||||
|
ProjectExplorer::BuildStep *clone(ProjectExplorer::BuildStepList *parent,
|
||||||
|
ProjectExplorer::BuildStep *product);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#endif // IOSDEPLOYSTEPFACTORY_H
|
70
src/plugins/ios/iosdeploystepwidget.cpp
Normal file
70
src/plugins/ios/iosdeploystepwidget.cpp
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "iosdeploystepwidget.h"
|
||||||
|
#include "ui_iosdeploystepwidget.h"
|
||||||
|
|
||||||
|
#include "iosdeploystep.h"
|
||||||
|
#include "iosrunconfiguration.h"
|
||||||
|
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
|
|
||||||
|
#include <QFileDialog>
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
IosDeployStepWidget::IosDeployStepWidget(IosDeployStep *step) :
|
||||||
|
ProjectExplorer::BuildStepConfigWidget(),
|
||||||
|
ui(new Ui::IosDeployStepWidget),
|
||||||
|
m_step(step)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
IosDeployStepWidget::~IosDeployStepWidget()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosDeployStepWidget::displayName() const
|
||||||
|
{
|
||||||
|
QString deviceName = tr("iOS Device");
|
||||||
|
if (!m_step->device().isNull())
|
||||||
|
deviceName = m_step->device()->displayName();
|
||||||
|
return tr("<b>Deploy to %1</b>").arg(deviceName);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosDeployStepWidget::summaryText() const
|
||||||
|
{
|
||||||
|
return displayName();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Qt4ProjectManager
|
61
src/plugins/ios/iosdeploystepwidget.h
Normal file
61
src/plugins/ios/iosdeploystepwidget.h
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef IOSDEPLOYSTEPWIDGET_H
|
||||||
|
#define IOSDEPLOYSTEPWIDGET_H
|
||||||
|
|
||||||
|
#include <projectexplorer/buildstep.h>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
namespace Ui { class IosDeployStepWidget; }
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
class IosDeployStep;
|
||||||
|
|
||||||
|
class IosDeployStepWidget : public ProjectExplorer::BuildStepConfigWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
IosDeployStepWidget(IosDeployStep *step);
|
||||||
|
~IosDeployStepWidget();
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual QString summaryText() const;
|
||||||
|
virtual QString displayName() const;
|
||||||
|
|
||||||
|
Ui::IosDeployStepWidget *ui;
|
||||||
|
IosDeployStep *m_step;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#endif // IOSDEPLOYSTEPWIDGET_H
|
26
src/plugins/ios/iosdeploystepwidget.ui
Normal file
26
src/plugins/ios/iosdeploystepwidget.ui
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>IosDeployStepWidget</class>
|
||||||
|
<widget class="QWidget" name="IosDeployStepWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>479</width>
|
||||||
|
<height>76</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="QGridLayout" name="gridLayout"/>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
519
src/plugins/ios/iosdevice.cpp
Normal file
519
src/plugins/ios/iosdevice.cpp
Normal file
@@ -0,0 +1,519 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "iosdevice.h"
|
||||||
|
#include "iosconstants.h"
|
||||||
|
#include "iosconfigurations.h"
|
||||||
|
#include "iostoolhandler.h"
|
||||||
|
#include <projectexplorer/devicesupport/devicemanager.h>
|
||||||
|
#include <projectexplorer/kitinformation.h>
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QVariant>
|
||||||
|
#include <QVariantMap>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
#include <IOKit/IOKitLib.h>
|
||||||
|
#include <IOKit/usb/IOUSBLib.h>
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
|
||||||
|
static bool debugDeviceDetection = false;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
QString CFStringRef2QString(CFStringRef s)
|
||||||
|
{
|
||||||
|
unsigned char buf[250];
|
||||||
|
CFIndex len = CFStringGetLength(s);
|
||||||
|
CFIndex usedBufLen;
|
||||||
|
CFIndex converted = CFStringGetBytes(s, CFRangeMake(0,len), kCFStringEncodingUTF8,
|
||||||
|
'?', false, &buf[0], sizeof(buf), &usedBufLen);
|
||||||
|
if (converted == len)
|
||||||
|
return QString::fromUtf8(reinterpret_cast<char *>(&buf[0]), usedBufLen);
|
||||||
|
size_t bufSize = sizeof(buf)
|
||||||
|
+ CFStringGetMaximumSizeForEncoding(len - converted, kCFStringEncodingUTF8);
|
||||||
|
unsigned char *bigBuf = new unsigned char[bufSize];
|
||||||
|
memcpy(bigBuf, buf, usedBufLen);
|
||||||
|
CFIndex newUseBufLen;
|
||||||
|
CFStringGetBytes(s, CFRangeMake(converted,len), kCFStringEncodingUTF8,
|
||||||
|
'?', false, &bigBuf[usedBufLen], bufSize, &newUseBufLen);
|
||||||
|
QString res = QString::fromUtf8(reinterpret_cast<char *>(bigBuf), usedBufLen + newUseBufLen);
|
||||||
|
delete[] bigBuf;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
const char extraInfoKey[] = "extraInfo";
|
||||||
|
|
||||||
|
IosDevice::IosDevice()
|
||||||
|
: IDevice(Core::Id(Constants::IOS_DEVICE_TYPE),
|
||||||
|
IDevice::AutoDetected,
|
||||||
|
IDevice::Hardware,
|
||||||
|
Constants::IOS_DEVICE_ID)
|
||||||
|
{
|
||||||
|
setDisplayName(QCoreApplication::translate("Ios::Internal::IosDevice", "iOS Device"));
|
||||||
|
setDeviceState(DeviceStateUnknown);
|
||||||
|
}
|
||||||
|
|
||||||
|
IosDevice::IosDevice(const IosDevice &other)
|
||||||
|
: IDevice(other), m_extraInfo(other.m_extraInfo), m_ignoreDevice(other.m_ignoreDevice)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
IosDevice::IosDevice(const QString &uid)
|
||||||
|
: IDevice(Core::Id(Constants::IOS_DEVICE_TYPE),
|
||||||
|
IDevice::AutoDetected,
|
||||||
|
IDevice::Hardware,
|
||||||
|
Core::Id(Constants::IOS_DEVICE_ID).withSuffix(uid))
|
||||||
|
{
|
||||||
|
setDisplayName(QCoreApplication::translate("Ios::Internal::IosDevice", "iOS Device"));
|
||||||
|
setDeviceState(DeviceStateUnknown);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IDevice::DeviceInfo IosDevice::deviceInformation() const
|
||||||
|
{
|
||||||
|
IDevice::DeviceInfo res;
|
||||||
|
QMapIterator<QString, QString> i(m_extraInfo);
|
||||||
|
while (i.hasNext()) {
|
||||||
|
i.next();
|
||||||
|
IosDeviceManager::TranslationMap tMap = IosDeviceManager::translationMap();
|
||||||
|
if (tMap.contains(i.key()))
|
||||||
|
res.append(DeviceInfoItem(tMap.value(i.key()), tMap.value(i.value(), i.value())));
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosDevice::displayType() const
|
||||||
|
{
|
||||||
|
return QCoreApplication::translate("Ios::Internal::IosDevice", "iOS");
|
||||||
|
}
|
||||||
|
|
||||||
|
IDeviceWidget *IosDevice::createWidget()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<Core::Id> IosDevice::actionIds() const
|
||||||
|
{
|
||||||
|
return QList<Core::Id>(); // add activation action?
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosDevice::displayNameForActionId(Core::Id actionId) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(actionId)
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosDevice::executeAction(Core::Id actionId, QWidget *parent)
|
||||||
|
{
|
||||||
|
Q_UNUSED(actionId)
|
||||||
|
Q_UNUSED(parent)
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceProcessSignalOperation::Ptr IosDevice::signalOperation() const
|
||||||
|
{
|
||||||
|
return DeviceProcessSignalOperation::Ptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
IDevice::Ptr IosDevice::clone() const
|
||||||
|
{
|
||||||
|
return IDevice::Ptr(new IosDevice(*this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosDevice::fromMap(const QVariantMap &map)
|
||||||
|
{
|
||||||
|
IDevice::fromMap(map);
|
||||||
|
QVariantMap vMap = map.value(QLatin1String(extraInfoKey)).toMap();
|
||||||
|
QMapIterator<QString, QVariant> i(vMap);
|
||||||
|
m_extraInfo.clear();
|
||||||
|
while (i.hasNext()) {
|
||||||
|
i.next();
|
||||||
|
m_extraInfo.insert(i.key(), i.value().toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap IosDevice::toMap() const
|
||||||
|
{
|
||||||
|
QVariantMap res = IDevice::toMap();
|
||||||
|
QVariantMap vMap;
|
||||||
|
QMapIterator<QString, QString> i(m_extraInfo);
|
||||||
|
while (i.hasNext()) {
|
||||||
|
i.next();
|
||||||
|
vMap.insert(i.key(), i.value());
|
||||||
|
}
|
||||||
|
res.insert(QLatin1String(extraInfoKey), vMap);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosDevice::uniqueDeviceID() const
|
||||||
|
{
|
||||||
|
return id().suffixAfter(Core::Id(Constants::IOS_DEVICE_ID));
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
// add back?
|
||||||
|
|
||||||
|
QString IosDevice::cpuArchitecure() const
|
||||||
|
{
|
||||||
|
return m_extraInfo.value(QLatin1String("deviceInfo")).toMap()
|
||||||
|
.value(QLatin1String("CPUArchitecture")).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosDevice::productType() const
|
||||||
|
{
|
||||||
|
return m_extraInfo.value(QLatin1String("deviceInfo")).toMap()
|
||||||
|
.value(QLatin1String("ProductType")).toString();
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
|
// IosDeviceManager
|
||||||
|
|
||||||
|
IosDeviceManager::TranslationMap IosDeviceManager::translationMap()
|
||||||
|
{
|
||||||
|
static TranslationMap *translationMap = 0;
|
||||||
|
if (translationMap)
|
||||||
|
return *translationMap;
|
||||||
|
TranslationMap &tMap = *new TranslationMap;
|
||||||
|
tMap[QLatin1String("deviceName")] = tr("Device name");
|
||||||
|
tMap[QLatin1String("developerStatus")] = tr("Developer status");
|
||||||
|
tMap[QLatin1String("deviceConnected")] = tr("Connected");
|
||||||
|
tMap[QLatin1String("YES")] = tr("yes");
|
||||||
|
tMap[QLatin1String("NO")] = tr("no");
|
||||||
|
tMap[QLatin1String("YES")] = tr("yes");
|
||||||
|
tMap[QLatin1String("*unknown*")] = tr("unknown");
|
||||||
|
translationMap = &tMap;
|
||||||
|
return tMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosDeviceManager::deviceConnected(const QString &uid, const QString &name)
|
||||||
|
{
|
||||||
|
DeviceManager *devManager = DeviceManager::instance();
|
||||||
|
Core::Id baseDevId(Constants::IOS_DEVICE_ID);
|
||||||
|
Core::Id devType(Constants::IOS_DEVICE_TYPE);
|
||||||
|
Core::Id devId = baseDevId.withSuffix(uid);
|
||||||
|
IDevice::ConstPtr dev = devManager->find(devId);
|
||||||
|
if (dev.isNull()) {
|
||||||
|
IosDevice *newDev = new IosDevice(uid);
|
||||||
|
if (!name.isNull())
|
||||||
|
newDev->setDisplayName(name);
|
||||||
|
if (debugDeviceDetection)
|
||||||
|
qDebug() << "adding ios device " << uid;
|
||||||
|
devManager->addDevice(IDevice::ConstPtr(newDev));
|
||||||
|
} else if (dev->deviceState() != IDevice::DeviceConnected &&
|
||||||
|
dev->deviceState() != IDevice::DeviceReadyToUse) {
|
||||||
|
if (debugDeviceDetection)
|
||||||
|
qDebug() << "updating ios device " << uid;
|
||||||
|
IosDevice *newDev = 0;
|
||||||
|
if (dev->type() == devType) {
|
||||||
|
const IosDevice *iosDev = static_cast<const IosDevice *>(dev.data());
|
||||||
|
newDev = new IosDevice(*iosDev);
|
||||||
|
} else {
|
||||||
|
newDev = new IosDevice(uid);
|
||||||
|
}
|
||||||
|
devManager->addDevice(IDevice::ConstPtr(newDev));
|
||||||
|
}
|
||||||
|
updateInfo(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosDeviceManager::deviceDisconnected(const QString &uid)
|
||||||
|
{
|
||||||
|
if (debugDeviceDetection)
|
||||||
|
qDebug() << "detected disconnection of ios device " << uid;
|
||||||
|
DeviceManager *devManager = DeviceManager::instance();
|
||||||
|
Core::Id baseDevId(Constants::IOS_DEVICE_ID);
|
||||||
|
Core::Id devType(Constants::IOS_DEVICE_TYPE);
|
||||||
|
Core::Id devId = baseDevId.withSuffix(uid);
|
||||||
|
IDevice::ConstPtr dev = devManager->find(devId);
|
||||||
|
if (dev.isNull() || dev->type() != devType) {
|
||||||
|
qDebug() << "ignoring disconnection of ios device " << uid; // should neve happen
|
||||||
|
} else {
|
||||||
|
const IosDevice *iosDev = static_cast<const IosDevice *>(dev.data());
|
||||||
|
if (iosDev->deviceState() != IDevice::DeviceDisconnected) {
|
||||||
|
if (debugDeviceDetection)
|
||||||
|
qDebug() << "disconnecting device " << iosDev->uniqueDeviceID();
|
||||||
|
devManager->setDeviceState(iosDev->id(), IDevice::DeviceDisconnected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosDeviceManager::updateInfo(const QString &devId)
|
||||||
|
{
|
||||||
|
IosToolHandler *requester = new IosToolHandler(IosToolHandler::IosDeviceType, this);
|
||||||
|
connect(requester, SIGNAL(deviceInfo(Ios::IosToolHandler*,QString,Ios::IosToolHandler::Dict)),
|
||||||
|
SLOT(deviceInfo(Ios::IosToolHandler *,QString,Ios::IosToolHandler::Dict)));
|
||||||
|
connect(requester, SIGNAL(finished(Ios::IosToolHandler*)),
|
||||||
|
SLOT(infoGathererFinished(Ios::IosToolHandler*)));
|
||||||
|
requester->requestDeviceInfo(devId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosDeviceManager::deviceInfo(IosToolHandler *, const QString &uid,
|
||||||
|
const Ios::IosToolHandler::Dict &info)
|
||||||
|
{
|
||||||
|
DeviceManager *devManager = DeviceManager::instance();
|
||||||
|
Core::Id baseDevId(Constants::IOS_DEVICE_ID);
|
||||||
|
Core::Id devType(Constants::IOS_DEVICE_TYPE);
|
||||||
|
Core::Id devId = baseDevId.withSuffix(uid);
|
||||||
|
IDevice::ConstPtr dev = devManager->find(devId);
|
||||||
|
bool skipUpdate = false;
|
||||||
|
IosDevice *newDev = 0;
|
||||||
|
if (!dev.isNull() && dev->type() == devType) {
|
||||||
|
const IosDevice *iosDev = static_cast<const IosDevice *>(dev.data());
|
||||||
|
if (iosDev->m_extraInfo == info) {
|
||||||
|
skipUpdate = true;
|
||||||
|
newDev = const_cast<IosDevice *>(iosDev);
|
||||||
|
} else {
|
||||||
|
newDev = new IosDevice(*iosDev);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
newDev = new IosDevice(uid);
|
||||||
|
}
|
||||||
|
if (!skipUpdate) {
|
||||||
|
QString devNameKey = QLatin1String("deviceName");
|
||||||
|
if (info.contains(devNameKey))
|
||||||
|
newDev->setDisplayName(info.value(devNameKey));
|
||||||
|
newDev->m_extraInfo = info;
|
||||||
|
if (debugDeviceDetection)
|
||||||
|
qDebug() << "updated info of ios device " << uid;
|
||||||
|
dev = IDevice::ConstPtr(newDev);
|
||||||
|
devManager->addDevice(dev);
|
||||||
|
}
|
||||||
|
QLatin1String devStatusKey = QLatin1String("developerStatus");
|
||||||
|
if (info.contains(devStatusKey)) {
|
||||||
|
QString devStatus = info.value(devStatusKey);
|
||||||
|
if (devStatus == QLatin1String("*off*")) {
|
||||||
|
devManager->setDeviceState(newDev->id(), IDevice::DeviceConnected);
|
||||||
|
if (!newDev->m_ignoreDevice && !IosConfigurations::instance().config().ignoreAllDevices) {
|
||||||
|
QMessageBox mBox;
|
||||||
|
mBox.setText(tr("An iOS device in user mode has been detected."));
|
||||||
|
mBox.setInformativeText(tr("Do you want to see how to set it up for development?"));
|
||||||
|
mBox.setStandardButtons(QMessageBox::NoAll | QMessageBox::No | QMessageBox::Yes);
|
||||||
|
mBox.setDefaultButton(QMessageBox::No);
|
||||||
|
int ret = mBox.exec();
|
||||||
|
switch (ret) {
|
||||||
|
case QMessageBox::Yes:
|
||||||
|
// open doc
|
||||||
|
break;
|
||||||
|
case QMessageBox::No:
|
||||||
|
newDev->m_ignoreDevice = true;
|
||||||
|
break;
|
||||||
|
case QMessageBox::NoAll:
|
||||||
|
{
|
||||||
|
IosConfig conf = IosConfigurations::instance().config();
|
||||||
|
conf.ignoreAllDevices = true;
|
||||||
|
IosConfigurations::instance().setConfig(conf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (devStatus == QLatin1String("Development")) {
|
||||||
|
devManager->setDeviceState(newDev->id(), IDevice::DeviceReadyToUse);
|
||||||
|
} else {
|
||||||
|
devManager->setDeviceState(newDev->id(), IDevice::DeviceConnected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosDeviceManager::infoGathererFinished(IosToolHandler *gatherer)
|
||||||
|
{
|
||||||
|
gatherer->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
io_iterator_t gAddedIter;
|
||||||
|
io_iterator_t gRemovedIter;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
void deviceConnectedCallback(void *refCon, io_iterator_t iterator)
|
||||||
|
{
|
||||||
|
kern_return_t kr;
|
||||||
|
io_service_t usbDevice;
|
||||||
|
(void) refCon;
|
||||||
|
|
||||||
|
while ((usbDevice = IOIteratorNext(iterator))) {
|
||||||
|
io_name_t deviceName;
|
||||||
|
|
||||||
|
// Get the USB device's name.
|
||||||
|
kr = IORegistryEntryGetName(usbDevice, deviceName);
|
||||||
|
QString name;
|
||||||
|
if (KERN_SUCCESS == kr)
|
||||||
|
name = QString::fromLocal8Bit(deviceName);
|
||||||
|
if (debugDeviceDetection)
|
||||||
|
qDebug() << "ios device " << name << " in deviceAddedCallback";
|
||||||
|
|
||||||
|
CFStringRef cfUid = static_cast<CFStringRef>(IORegistryEntryCreateCFProperty(
|
||||||
|
usbDevice,
|
||||||
|
CFSTR(kUSBSerialNumberString),
|
||||||
|
kCFAllocatorDefault, 0));
|
||||||
|
QString uid = CFStringRef2QString(cfUid);
|
||||||
|
CFRelease(cfUid);
|
||||||
|
IosDeviceManager::instance()->deviceConnected(uid, name);
|
||||||
|
|
||||||
|
// Done with this USB device; release the reference added by IOIteratorNext
|
||||||
|
kr = IOObjectRelease(usbDevice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void deviceDisconnectedCallback(void *refCon, io_iterator_t iterator)
|
||||||
|
{
|
||||||
|
kern_return_t kr;
|
||||||
|
io_service_t usbDevice;
|
||||||
|
(void) refCon;
|
||||||
|
|
||||||
|
while ((usbDevice = IOIteratorNext(iterator))) {
|
||||||
|
io_name_t deviceName;
|
||||||
|
|
||||||
|
// Get the USB device's name.
|
||||||
|
kr = IORegistryEntryGetName(usbDevice, deviceName);
|
||||||
|
if (KERN_SUCCESS != kr)
|
||||||
|
deviceName[0] = '\0';
|
||||||
|
if (debugDeviceDetection)
|
||||||
|
qDebug() << "ios device " << deviceName << " in deviceDisconnectedCallback";
|
||||||
|
|
||||||
|
{
|
||||||
|
CFStringRef cfUid = static_cast<CFStringRef>(IORegistryEntryCreateCFProperty(
|
||||||
|
usbDevice,
|
||||||
|
CFSTR(kUSBSerialNumberString),
|
||||||
|
kCFAllocatorDefault, 0));
|
||||||
|
QString uid = CFStringRef2QString(cfUid);
|
||||||
|
CFRelease(cfUid);
|
||||||
|
IosDeviceManager::instance()->deviceDisconnected(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Done with this USB device; release the reference added by IOIteratorNext
|
||||||
|
kr = IOObjectRelease(usbDevice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // extern C
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
void IosDeviceManager::monitorAvailableDevices()
|
||||||
|
{
|
||||||
|
CFMutableDictionaryRef matchingDictionary =
|
||||||
|
IOServiceMatching("IOUSBDevice" );
|
||||||
|
{
|
||||||
|
UInt32 vendorId = 0x05ac;
|
||||||
|
CFNumberRef cfVendorValue = CFNumberCreate( kCFAllocatorDefault, kCFNumberSInt32Type,
|
||||||
|
&vendorId );
|
||||||
|
CFDictionaryAddValue( matchingDictionary, CFSTR( kUSBVendorID ), cfVendorValue);
|
||||||
|
CFRelease( cfVendorValue );
|
||||||
|
UInt32 productId = 0x1280;
|
||||||
|
CFNumberRef cfProductIdValue = CFNumberCreate( kCFAllocatorDefault, kCFNumberSInt32Type,
|
||||||
|
&productId );
|
||||||
|
CFDictionaryAddValue( matchingDictionary, CFSTR( kUSBProductID ), cfProductIdValue);
|
||||||
|
CFRelease( cfProductIdValue );
|
||||||
|
UInt32 productIdMask = 0xFFC0;
|
||||||
|
CFNumberRef cfProductIdMaskValue = CFNumberCreate( kCFAllocatorDefault, kCFNumberSInt32Type,
|
||||||
|
&productIdMask );
|
||||||
|
CFDictionaryAddValue( matchingDictionary, CFSTR( kUSBProductIDMask ), cfProductIdMaskValue);
|
||||||
|
CFRelease( cfProductIdMaskValue );
|
||||||
|
}
|
||||||
|
|
||||||
|
IONotificationPortRef notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
|
||||||
|
CFRunLoopSourceRef runLoopSource = IONotificationPortGetRunLoopSource(notificationPort);
|
||||||
|
|
||||||
|
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode);
|
||||||
|
|
||||||
|
// IOServiceAddMatchingNotification releases this, so we retain for the next call
|
||||||
|
CFRetain(matchingDictionary);
|
||||||
|
|
||||||
|
// Now set up a notification to be called when a device is first matched by I/O Kit.
|
||||||
|
kern_return_t kr;
|
||||||
|
kr = IOServiceAddMatchingNotification(notificationPort,
|
||||||
|
kIOMatchedNotification,
|
||||||
|
matchingDictionary,
|
||||||
|
deviceConnectedCallback,
|
||||||
|
NULL,
|
||||||
|
&gAddedIter);
|
||||||
|
|
||||||
|
|
||||||
|
kr = IOServiceAddMatchingNotification(notificationPort,
|
||||||
|
kIOTerminatedNotification,
|
||||||
|
matchingDictionary,
|
||||||
|
deviceDisconnectedCallback,
|
||||||
|
NULL,
|
||||||
|
&gRemovedIter);
|
||||||
|
|
||||||
|
// Iterate once to get already-present devices and arm the notification
|
||||||
|
deviceConnectedCallback(NULL, gAddedIter);
|
||||||
|
deviceDisconnectedCallback(NULL, gRemovedIter);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IosDeviceManager::IosDeviceManager(QObject *parent) :
|
||||||
|
QObject(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
IosDeviceManager *IosDeviceManager::instance()
|
||||||
|
{
|
||||||
|
static IosDeviceManager obj;
|
||||||
|
return &obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosDeviceManager::updateAvailableDevices(const QStringList &devices)
|
||||||
|
{
|
||||||
|
foreach (const QString &uid, devices)
|
||||||
|
deviceConnected(uid);
|
||||||
|
|
||||||
|
DeviceManager *devManager = DeviceManager::instance();
|
||||||
|
for (int iDevice = 0; iDevice < devManager->deviceCount(); ++iDevice) {
|
||||||
|
IDevice::ConstPtr dev = devManager->deviceAt(iDevice);
|
||||||
|
Core::Id devType(Constants::IOS_DEVICE_TYPE);
|
||||||
|
if (dev.isNull() || dev->type() != devType)
|
||||||
|
continue;
|
||||||
|
const IosDevice *iosDev = static_cast<const IosDevice *>(dev.data());
|
||||||
|
if (devices.contains(iosDev->uniqueDeviceID()))
|
||||||
|
continue;
|
||||||
|
if (iosDev->deviceState() != IDevice::DeviceDisconnected) {
|
||||||
|
if (debugDeviceDetection)
|
||||||
|
qDebug() << "disconnecting device " << iosDev->uniqueDeviceID();
|
||||||
|
devManager->setDeviceState(iosDev->id(), IDevice::DeviceDisconnected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IosDevice::ConstPtr IosKitInformation::device(Kit *kit)
|
||||||
|
{
|
||||||
|
if (!kit)
|
||||||
|
return IosDevice::ConstPtr();
|
||||||
|
ProjectExplorer::IDevice::ConstPtr dev = ProjectExplorer::DeviceKitInformation::device(kit);
|
||||||
|
IosDevice::ConstPtr res = dev.dynamicCast<const IosDevice>();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
111
src/plugins/ios/iosdevice.h
Normal file
111
src/plugins/ios/iosdevice.h
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef IOSDEVICE_H
|
||||||
|
#define IOSDEVICE_H
|
||||||
|
|
||||||
|
#include <projectexplorer/devicesupport/idevice.h>
|
||||||
|
#include <QVariantMap>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QString>
|
||||||
|
#include "iostoolhandler.h"
|
||||||
|
#include <QSharedPointer>
|
||||||
|
|
||||||
|
namespace ProjectExplorer{
|
||||||
|
class Kit;
|
||||||
|
}
|
||||||
|
namespace Ios {
|
||||||
|
class IosConfigurations;
|
||||||
|
|
||||||
|
namespace Internal {
|
||||||
|
class IosDeviceManager;
|
||||||
|
|
||||||
|
class IosDevice : public ProjectExplorer::IDevice
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef QMap<QString, QString> Dict;
|
||||||
|
typedef QSharedPointer<const IosDevice> ConstPtr;
|
||||||
|
typedef QSharedPointer<IosDevice> Ptr;
|
||||||
|
|
||||||
|
ProjectExplorer::IDevice::DeviceInfo deviceInformation() const;
|
||||||
|
ProjectExplorer::IDeviceWidget *createWidget();
|
||||||
|
QList<Core::Id> actionIds() const;
|
||||||
|
QString displayNameForActionId(Core::Id actionId) const;
|
||||||
|
void executeAction(Core::Id actionId, QWidget *parent = 0);
|
||||||
|
ProjectExplorer::DeviceProcessSignalOperation::Ptr signalOperation() const;
|
||||||
|
QString displayType() const;
|
||||||
|
|
||||||
|
ProjectExplorer::IDevice::Ptr clone() const;
|
||||||
|
void fromMap(const QVariantMap &map);
|
||||||
|
QVariantMap toMap() const;
|
||||||
|
QString uniqueDeviceID() const;
|
||||||
|
IosDevice(const QString &uid);
|
||||||
|
// add back? currently unused...
|
||||||
|
//QString cpuArchitecure() const;
|
||||||
|
//QString productType() const;
|
||||||
|
protected:
|
||||||
|
friend class IosDeviceFactory;
|
||||||
|
friend class Ios::Internal::IosDeviceManager;
|
||||||
|
IosDevice();
|
||||||
|
IosDevice(const IosDevice &other);
|
||||||
|
Dict m_extraInfo;
|
||||||
|
bool m_ignoreDevice;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IosDeviceManager : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
typedef QHash<QString, QString> TranslationMap;
|
||||||
|
|
||||||
|
static TranslationMap translationMap();
|
||||||
|
static IosDeviceManager *instance();
|
||||||
|
|
||||||
|
void updateAvailableDevices(const QStringList &devices);
|
||||||
|
void deviceConnected(const QString &uid, const QString &name = QString());
|
||||||
|
void deviceDisconnected(const QString &uid);
|
||||||
|
friend class IosConfigurations;
|
||||||
|
public slots:
|
||||||
|
void updateInfo(const QString &devId);
|
||||||
|
//private slots:
|
||||||
|
void deviceInfo(Ios::IosToolHandler *gatherer, const QString &deviceId,
|
||||||
|
const Ios::IosToolHandler::Dict &info);
|
||||||
|
void infoGathererFinished(Ios::IosToolHandler *gatherer);
|
||||||
|
void monitorAvailableDevices();
|
||||||
|
private:
|
||||||
|
IosDeviceManager(QObject *parent = 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace IosKitInformation {
|
||||||
|
IosDevice::ConstPtr device(ProjectExplorer::Kit *);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#endif // IOSDEVICE_H
|
81
src/plugins/ios/iosdevicefactory.cpp
Normal file
81
src/plugins/ios/iosdevicefactory.cpp
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "iosdevicefactory.h"
|
||||||
|
#include "iosdevice.h"
|
||||||
|
|
||||||
|
#include "iosconstants.h"
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
IosDeviceFactory::IosDeviceFactory()
|
||||||
|
{
|
||||||
|
setObjectName(QLatin1String("IosDeviceFactory"));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosDeviceFactory::displayNameForId(Core::Id type) const
|
||||||
|
{
|
||||||
|
if (type == Constants::IOS_DEVICE_TYPE)
|
||||||
|
return tr("iOS Device");
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<Core::Id> IosDeviceFactory::availableCreationIds() const
|
||||||
|
{
|
||||||
|
return QList<Core::Id>() << Core::Id(Constants::IOS_DEVICE_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosDeviceFactory::canCreate() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectExplorer::IDevice::Ptr IosDeviceFactory::create(Core::Id id) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(id)
|
||||||
|
return ProjectExplorer::IDevice::Ptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosDeviceFactory::canRestore(const QVariantMap &map) const
|
||||||
|
{
|
||||||
|
return ProjectExplorer::IDevice::typeFromMap(map) == Constants::IOS_DEVICE_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectExplorer::IDevice::Ptr IosDeviceFactory::restore(const QVariantMap &map) const
|
||||||
|
{
|
||||||
|
IosDevice *newDev = new IosDevice;
|
||||||
|
newDev->fromMap(map);
|
||||||
|
// updating the active ones should be enough...
|
||||||
|
//IosDeviceManager::instance()->updateInfo(newDev->uniqueDeviceID());
|
||||||
|
return ProjectExplorer::IDevice::Ptr(newDev);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
58
src/plugins/ios/iosdevicefactory.h
Normal file
58
src/plugins/ios/iosdevicefactory.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef IOSDEVICEFACTORY_H
|
||||||
|
#define IOSDEVICEFACTORY_H
|
||||||
|
|
||||||
|
#include <projectexplorer/devicesupport/idevicefactory.h>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class IosDeviceFactory : public ProjectExplorer::IDeviceFactory
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
IosDeviceFactory();
|
||||||
|
|
||||||
|
QString displayNameForId(Core::Id type) const;
|
||||||
|
QList<Core::Id> availableCreationIds() const;
|
||||||
|
|
||||||
|
bool canCreate() const;
|
||||||
|
ProjectExplorer::IDevice::Ptr create(Core::Id id) const;
|
||||||
|
bool canRestore(const QVariantMap &map) const;
|
||||||
|
ProjectExplorer::IDevice::Ptr restore(const QVariantMap &map) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#endif // IOSDEVICEFACTORY_H
|
76
src/plugins/ios/iosmanager.cpp
Normal file
76
src/plugins/ios/iosmanager.cpp
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "iosmanager.h"
|
||||||
|
#include "iosconfigurations.h"
|
||||||
|
#include "iosrunconfiguration.h"
|
||||||
|
|
||||||
|
#include <projectexplorer/projectexplorer.h>
|
||||||
|
#include <projectexplorer/session.h>
|
||||||
|
#include <projectexplorer/target.h>
|
||||||
|
#include <projectexplorer/toolchain.h>
|
||||||
|
#include <qt4projectmanager/qt4nodes.h>
|
||||||
|
#include <qt4projectmanager/qt4project.h>
|
||||||
|
#include <qt4projectmanager/qt4projectmanagerconstants.h>
|
||||||
|
#include <qt4projectmanager/qt4buildconfiguration.h>
|
||||||
|
#include <qtsupport/customexecutablerunconfiguration.h>
|
||||||
|
#include <qtsupport/qtkitinformation.h>
|
||||||
|
#include <qtsupport/qtsupportconstants.h>
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFileSystemWatcher>
|
||||||
|
#include <QList>
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QDomDocument>
|
||||||
|
|
||||||
|
using namespace Qt4ProjectManager;
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
bool IosManager::supportsIos(ProjectExplorer::Target *target)
|
||||||
|
{
|
||||||
|
if (!qobject_cast<Qt4ProjectManager::Qt4Project *>(target->project()))
|
||||||
|
return false;
|
||||||
|
QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target->kit());
|
||||||
|
return version && version->type() == QLatin1String(Ios::Constants::IOSQT);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosManager::resDirForTarget(Target *target)
|
||||||
|
{
|
||||||
|
Qt4BuildConfiguration *bc =
|
||||||
|
qobject_cast<Qt4BuildConfiguration *>(target->activeBuildConfiguration());
|
||||||
|
return bc->buildDirectory().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Qt4ProjectManager
|
55
src/plugins/ios/iosmanager.h
Normal file
55
src/plugins/ios/iosmanager.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef IOSMANAGER_H
|
||||||
|
#define IOSMANAGER_H
|
||||||
|
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
|
#include <QDomDocument>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
namespace ProjectExplorer { class Target; }
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class IosManager : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
static bool supportsIos(ProjectExplorer::Target *target);
|
||||||
|
static QString resDirForTarget(ProjectExplorer::Target *target);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#endif // IOSMANAGER_H
|
96
src/plugins/ios/iosplugin.cpp
Normal file
96
src/plugins/ios/iosplugin.cpp
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "iosplugin.h"
|
||||||
|
|
||||||
|
#include "iosconstants.h"
|
||||||
|
#include "iosconfigurations.h"
|
||||||
|
#include "iosdevicefactory.h"
|
||||||
|
#include "iossimulator.h"
|
||||||
|
#include "iossimulatorfactory.h"
|
||||||
|
#include "iosconfigurations.h"
|
||||||
|
#include "iosmanager.h"
|
||||||
|
#include "iosrunfactories.h"
|
||||||
|
#include "iossettingspage.h"
|
||||||
|
#include "iosqtversionfactory.h"
|
||||||
|
#include "iosbuildstep.h"
|
||||||
|
#include "iosdeploystepfactory.h"
|
||||||
|
#include "iosdeployconfiguration.h"
|
||||||
|
#include <projectexplorer/kitmanager.h>
|
||||||
|
#include <qtsupport/qtversionmanager.h>
|
||||||
|
|
||||||
|
#include <QtPlugin>
|
||||||
|
|
||||||
|
#include <projectexplorer/devicesupport/devicemanager.h>
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
|
||||||
|
IosPlugin::IosPlugin()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
bool IosPlugin::initialize(const QStringList &arguments, QString *errorMessage)
|
||||||
|
{
|
||||||
|
Q_UNUSED(arguments);
|
||||||
|
Q_UNUSED(errorMessage);
|
||||||
|
|
||||||
|
Internal::IosConfigurations::instance();
|
||||||
|
|
||||||
|
addAutoReleasedObject(new Internal::IosRunControlFactory);
|
||||||
|
addAutoReleasedObject(new Internal::IosRunConfigurationFactory);
|
||||||
|
addAutoReleasedObject(new Internal::IosSettingsPage);
|
||||||
|
addAutoReleasedObject(new Internal::IosQtVersionFactory);
|
||||||
|
addAutoReleasedObject(new Internal::IosDeviceFactory);
|
||||||
|
addAutoReleasedObject(new Internal::IosSimulatorFactory);
|
||||||
|
addAutoReleasedObject(new Internal::IosBuildStepFactory);
|
||||||
|
addAutoReleasedObject(new Internal::IosDeployStepFactory);
|
||||||
|
addAutoReleasedObject(new Internal::IosDeployConfigurationFactory);
|
||||||
|
//ProjectExplorer::KitManager::instance()->registerKitInformation(new Internal::IosGdbServerKitInformation);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosPlugin::extensionsInitialized()
|
||||||
|
{
|
||||||
|
connect(ProjectExplorer::KitManager::instance(), SIGNAL(kitsLoaded()),
|
||||||
|
this, SLOT(kitsRestored()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosPlugin::kitsRestored()
|
||||||
|
{
|
||||||
|
disconnect(ProjectExplorer::KitManager::instance(), SIGNAL(kitsLoaded()),
|
||||||
|
this, SLOT(kitsRestored()));
|
||||||
|
Internal::IosConfigurations::instance().updateAutomaticKitList();
|
||||||
|
connect(QtSupport::QtVersionManager::instance(),
|
||||||
|
SIGNAL(qtVersionsChanged(QList<int>,QList<int>,QList<int>)),
|
||||||
|
&Internal::IosConfigurations::instance(),
|
||||||
|
SLOT(updateAutomaticKitList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
Q_EXPORT_PLUGIN(Ios::IosPlugin)
|
52
src/plugins/ios/iosplugin.h
Normal file
52
src/plugins/ios/iosplugin.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef IOSPLUGIN_H
|
||||||
|
#define IOSPLUGIN_H
|
||||||
|
|
||||||
|
#include <extensionsystem/iplugin.h>
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
|
||||||
|
class IosPlugin : public ExtensionSystem::IPlugin
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Ios.json")
|
||||||
|
|
||||||
|
public:
|
||||||
|
IosPlugin();
|
||||||
|
|
||||||
|
bool initialize(const QStringList &arguments, QString *errorMessage);
|
||||||
|
void extensionsInitialized();
|
||||||
|
private slots:
|
||||||
|
void kitsRestored();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#endif // IOSPLUGIN_H
|
355
src/plugins/ios/iosprobe.cpp
Normal file
355
src/plugins/ios/iosprobe.cpp
Normal file
@@ -0,0 +1,355 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "iosprobe.h"
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFileInfoList>
|
||||||
|
|
||||||
|
static const bool debugProbe = false;
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
|
||||||
|
static QString qsystem(const QString &exe, const QStringList &args = QStringList())
|
||||||
|
{
|
||||||
|
QProcess p;
|
||||||
|
p.setProcessChannelMode(QProcess::MergedChannels);
|
||||||
|
p.start(exe, args);
|
||||||
|
p.waitForFinished();
|
||||||
|
return QString::fromLocal8Bit(p.readAll());
|
||||||
|
}
|
||||||
|
|
||||||
|
QMap<QString, Platform> IosProbe::detectPlatforms(const QString &devPath)
|
||||||
|
{
|
||||||
|
IosProbe probe;
|
||||||
|
probe.addDeveloperPath(devPath);
|
||||||
|
probe.detectAll();
|
||||||
|
return probe.detectedPlatforms();
|
||||||
|
}
|
||||||
|
|
||||||
|
int IosProbe::compareVersions(const QString &v1, const QString &v2)
|
||||||
|
{
|
||||||
|
QStringList v1L = v1.split(QLatin1Char('.'));
|
||||||
|
QStringList v2L = v2.split(QLatin1Char('.'));
|
||||||
|
int i = 0;
|
||||||
|
while (v1.length() > i && v1.length() > i) {
|
||||||
|
bool n1Ok, n2Ok;
|
||||||
|
int n1 = v1L.value(i).toInt(&n1Ok);
|
||||||
|
int n2 = v2L.value(i).toInt(&n2Ok);
|
||||||
|
if (!(n1Ok && n2Ok)) {
|
||||||
|
qDebug() << QString::fromLatin1("Failed to compare version %1 and %2").arg(v1,v2);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (n1 > n2)
|
||||||
|
return -1;
|
||||||
|
else if (n1 < n2)
|
||||||
|
return 1;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
if (v1.length() > v2.length())
|
||||||
|
return -1;
|
||||||
|
if (v1.length() < v2.length())
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosProbe::addDeveloperPath(const QString &path)
|
||||||
|
{
|
||||||
|
if (path.isEmpty())
|
||||||
|
return false;
|
||||||
|
QFileInfo pInfo(path);
|
||||||
|
if (!pInfo.exists() || !pInfo.isDir())
|
||||||
|
return false;
|
||||||
|
if (m_developerPaths.contains(path))
|
||||||
|
return false;
|
||||||
|
m_developerPaths.append(path);
|
||||||
|
if (debugProbe)
|
||||||
|
qDebug() << QString::fromLatin1("Added developer path %1").arg(path);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosProbe::detectDeveloperPaths()
|
||||||
|
{
|
||||||
|
QProcess selectedXcode;
|
||||||
|
QString program = QLatin1String("/usr/bin/xcode-select");
|
||||||
|
QStringList arguments(QLatin1String("--print-path"));
|
||||||
|
selectedXcode.start(program, arguments, QProcess::ReadOnly);
|
||||||
|
if (!selectedXcode.waitForFinished() || selectedXcode.exitCode()) {
|
||||||
|
qDebug() << QString::fromLatin1("Could not detect selected xcode with /usr/bin/xcode-select");
|
||||||
|
} else {
|
||||||
|
QString path = QString::fromLocal8Bit(selectedXcode.readAllStandardOutput());
|
||||||
|
addDeveloperPath(path);
|
||||||
|
}
|
||||||
|
addDeveloperPath(QLatin1String("/Applications/Xcode.app/Contents/Developer"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosProbe::setArch(Platform *platform, const QString &pathToGcc, const QStringList &extraFlags)
|
||||||
|
{
|
||||||
|
if (!extraFlags.isEmpty())
|
||||||
|
platform->backendFlags = extraFlags;
|
||||||
|
// setting architecture and endianness only here, bercause the same compiler
|
||||||
|
// can support several ones
|
||||||
|
QStringList flags(extraFlags);
|
||||||
|
flags << QLatin1String("-dumpmachine");
|
||||||
|
QString compilerTriplet = qsystem(pathToGcc, flags).simplified();
|
||||||
|
QStringList compilerTripletl = compilerTriplet.split(QLatin1Char('-'));
|
||||||
|
if (compilerTripletl.count() < 2) {
|
||||||
|
qDebug() << QString::fromLatin1("Detected '%1', but I don't understand "
|
||||||
|
"its architecture '%2'.")
|
||||||
|
.arg(pathToGcc, compilerTriplet);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString endianness, architecture;
|
||||||
|
architecture = compilerTripletl.at(0);
|
||||||
|
endianness = QLatin1String("little");
|
||||||
|
|
||||||
|
if (debugProbe)
|
||||||
|
qDebug() << QString::fromLatin1(" Toolchain %1 detected:\n"
|
||||||
|
" binary: %2\n"
|
||||||
|
" triplet: %3\n"
|
||||||
|
" arch: %4").arg(platform->name, pathToGcc,
|
||||||
|
compilerTriplet, architecture);
|
||||||
|
|
||||||
|
platform->architecture = architecture;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosProbe::setupDefaultToolchains(const QString &devPath, const QString &xCodeName)
|
||||||
|
{
|
||||||
|
if (debugProbe)
|
||||||
|
qDebug() << QString::fromLatin1("Setting up platform '%1'.").arg(xCodeName);
|
||||||
|
QString indent = QLatin1String(" ");
|
||||||
|
|
||||||
|
// detect clang (default toolchain)
|
||||||
|
QFileInfo clangFileInfo(devPath
|
||||||
|
+ QLatin1String("/Toolchains/XcodeDefault.xctoolchain/usr/bin")
|
||||||
|
+ QLatin1String("/clang++"));
|
||||||
|
bool hasClang = clangFileInfo.exists();
|
||||||
|
QSettingsPtr toolchainInfo;
|
||||||
|
if (hasClang)
|
||||||
|
toolchainInfo = QSettingsPtr(new QSettings(
|
||||||
|
devPath + QLatin1String("/Toolchains/XcodeDefault.xctoolchain/ToolchainInfo.plist")
|
||||||
|
, QSettings::NativeFormat));
|
||||||
|
else
|
||||||
|
qDebug() << indent << QString::fromLatin1("Default toolchain %1 not found.")
|
||||||
|
.arg(clangFileInfo.canonicalFilePath());
|
||||||
|
// Platforms
|
||||||
|
QDir platformsDir(devPath + QLatin1String("/Platforms"));
|
||||||
|
QFileInfoList platforms = platformsDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||||
|
foreach (const QFileInfo &fInfo, platforms) {
|
||||||
|
if (fInfo.isDir() && fInfo.suffix() == QLatin1String("platform")) {
|
||||||
|
if (debugProbe)
|
||||||
|
qDebug() << indent << QString::fromLatin1("Setting up %1").arg(fInfo.fileName());
|
||||||
|
QSettingsPtr infoSettings(new QSettings(
|
||||||
|
fInfo.absoluteFilePath() + QLatin1String("/Info.plist")
|
||||||
|
, QSettings::NativeFormat));
|
||||||
|
if (!infoSettings->contains(QLatin1String("Name"))) {
|
||||||
|
qDebug() << indent << QString::fromLatin1("Missing platform name in Info.plist of %1")
|
||||||
|
.arg(fInfo.absoluteFilePath());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
QString targetOS;
|
||||||
|
QString name = infoSettings->value(QLatin1String("Name")).toString();
|
||||||
|
if (name != QLatin1String("macosx") && name != QLatin1String("iphoneos")
|
||||||
|
&& name != QLatin1String("iphonesimulator"))
|
||||||
|
{
|
||||||
|
qDebug() << indent << QString::fromLatin1("Skipping unknown platform %1").arg(name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepare default platform properties
|
||||||
|
QVariantMap defaultProp = infoSettings->value(QLatin1String("DefaultProperties"))
|
||||||
|
.toMap();
|
||||||
|
QVariantMap overrideProp = infoSettings->value(QLatin1String("OverrideProperties"))
|
||||||
|
.toMap();
|
||||||
|
QMapIterator<QString, QVariant> i(overrideProp);
|
||||||
|
while (i.hasNext()) {
|
||||||
|
i.next();
|
||||||
|
// use unite? might lead to double insertions...
|
||||||
|
defaultProp[i.key()] = i.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString clangFullName = name + QLatin1String("-clang") + xCodeName;
|
||||||
|
QString clang11FullName = name + QLatin1String("-clang11") + xCodeName;
|
||||||
|
// detect gcc
|
||||||
|
QFileInfo gccFileInfo(fInfo.absoluteFilePath() + QLatin1String("/Developer/usr/bin/g++"));
|
||||||
|
QString gccFullName = name + QLatin1String("-gcc") + xCodeName;
|
||||||
|
if (!gccFileInfo.exists())
|
||||||
|
gccFileInfo = QFileInfo(devPath + QLatin1String("/usr/bin/g++"));
|
||||||
|
bool hasGcc = gccFileInfo.exists();
|
||||||
|
|
||||||
|
QStringList extraFlags;
|
||||||
|
if (defaultProp.contains(QLatin1String("ARCHS"))) {
|
||||||
|
QString arch = defaultProp.value(QLatin1String("ARCHS")).toString();
|
||||||
|
if (arch == QLatin1String("$(NATIVE_ARCH_32_BIT)"))
|
||||||
|
extraFlags << QLatin1String("-arch") << QLatin1String("i386");
|
||||||
|
}
|
||||||
|
if (defaultProp.contains(QLatin1String("NATIVE_ARCH"))) {
|
||||||
|
QString arch = defaultProp.value(QLatin1String("NATIVE_ARCH")).toString();
|
||||||
|
if (!arch.startsWith(QLatin1String("arm")))
|
||||||
|
qDebug() << indent << QString::fromLatin1("Expected arm architecture, not %1").arg(arch);
|
||||||
|
extraFlags << QLatin1String("-arch") << arch;
|
||||||
|
}
|
||||||
|
if (hasClang) {
|
||||||
|
Platform clangProfile;
|
||||||
|
clangProfile.platformKind = 0;
|
||||||
|
clangProfile.name = clangFullName;
|
||||||
|
clangProfile.platformPath = Utils::FileName(fInfo);
|
||||||
|
clangProfile.platformInfo = infoSettings;
|
||||||
|
clangProfile.compilerPath = Utils::FileName(clangFileInfo);
|
||||||
|
setArch(&clangProfile, clangFileInfo.canonicalFilePath(), extraFlags);
|
||||||
|
if (debugProbe)
|
||||||
|
qDebug() << indent << QString::fromLatin1("* adding profile %1").arg(clangProfile.name);
|
||||||
|
this->m_platforms[clangProfile.name] = clangProfile;
|
||||||
|
clangProfile.platformKind |= Platform::Cxx11Support;
|
||||||
|
clangProfile.backendFlags.append(QLatin1String("-std=c++11"));
|
||||||
|
clangProfile.backendFlags.append(QLatin1String("-stdlib=libc++"));
|
||||||
|
clangProfile.name = clang11FullName;
|
||||||
|
this->m_platforms[clangProfile.name] = clangProfile;
|
||||||
|
}
|
||||||
|
if (hasGcc) {
|
||||||
|
Platform gccProfile;
|
||||||
|
gccProfile.name = gccFullName;
|
||||||
|
gccProfile.platformKind = 0;
|
||||||
|
// use the arm-apple-darwin10-llvm-* variant and avoid the extraFlags if available???
|
||||||
|
gccProfile.platformPath = Utils::FileName(fInfo);
|
||||||
|
gccProfile.platformInfo = infoSettings;
|
||||||
|
gccProfile.compilerPath = Utils::FileName(gccFileInfo);
|
||||||
|
setArch(&gccProfile, gccFileInfo.canonicalFilePath(), extraFlags);
|
||||||
|
if (debugProbe)
|
||||||
|
qDebug() << indent << QString::fromLatin1("* adding profile %1").arg(gccProfile.name);
|
||||||
|
this->m_platforms[gccProfile.name] = gccProfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set SDKs/sysroot
|
||||||
|
QString sysRoot;
|
||||||
|
QSettingsPtr sdkSettings;
|
||||||
|
{
|
||||||
|
QString sdkName;
|
||||||
|
if (defaultProp.contains(QLatin1String("SDKROOT")))
|
||||||
|
sdkName = defaultProp.value(QLatin1String("SDKROOT")).toString();
|
||||||
|
QString sdkPath;
|
||||||
|
QDir sdks(fInfo.absoluteFilePath() + QLatin1String("/Developer/SDKs"));
|
||||||
|
QString maxVersion;
|
||||||
|
foreach (const QFileInfo &sdkDirInfo, sdks.entryInfoList(QDir::Dirs
|
||||||
|
| QDir::NoDotAndDotDot)) {
|
||||||
|
indent = QLatin1String(" ");
|
||||||
|
QSettingsPtr sdkInfo(new QSettings(sdkDirInfo.absoluteFilePath()
|
||||||
|
+ QLatin1String("/SDKSettings.plist")
|
||||||
|
, QSettings::NativeFormat));
|
||||||
|
QString versionStr = sdkInfo->value(QLatin1String("Version")).toString();
|
||||||
|
QVariant currentSdkName = sdkInfo->value(QLatin1String("CanonicalName"));
|
||||||
|
bool isBaseSdk = sdkInfo->value((QLatin1String("isBaseSDK"))).toString()
|
||||||
|
.toLower() != QLatin1String("no");
|
||||||
|
if (!isBaseSdk) {
|
||||||
|
if (debugProbe)
|
||||||
|
qDebug() << indent << QString::fromLatin1("Skipping non base Sdk %1")
|
||||||
|
.arg(currentSdkName.toString());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
QString safeName = currentSdkName.toString().replace(QLatin1Char('-'), QLatin1Char('_'))
|
||||||
|
.replace(QRegExp(QLatin1String("[^-a-zA-Z0-9]")),QLatin1String("-"));
|
||||||
|
if (sdkName.isEmpty()) {
|
||||||
|
if (compareVersions(maxVersion,versionStr) > 0) {
|
||||||
|
maxVersion = versionStr;
|
||||||
|
sdkPath = sdkDirInfo.canonicalFilePath();
|
||||||
|
sdkSettings = sdkInfo;
|
||||||
|
}
|
||||||
|
} else if (currentSdkName == sdkName) {
|
||||||
|
sdkPath = sdkDirInfo.canonicalFilePath();
|
||||||
|
sdkSettings = sdkInfo;
|
||||||
|
}
|
||||||
|
if (hasClang){
|
||||||
|
Platform pSdk;
|
||||||
|
pSdk = this->m_platforms[clangFullName];
|
||||||
|
pSdk.name = safeName + QLatin1String("-clang") + xCodeName;
|
||||||
|
pSdk.sdkPath = Utils::FileName(sdkDirInfo);
|
||||||
|
pSdk.sdkSettings = sdkInfo;
|
||||||
|
if (debugProbe)
|
||||||
|
qDebug() << indent << QString::fromLatin1("* adding profile %1").arg(pSdk.name);
|
||||||
|
this->m_platforms[pSdk.name] = pSdk;
|
||||||
|
pSdk.backendFlags.append(QLatin1String("-std=c++11"));
|
||||||
|
pSdk.backendFlags.append(QLatin1String("-stdlib=libc++"));
|
||||||
|
pSdk.name = safeName + QLatin1String("-clang11") + xCodeName;
|
||||||
|
this->m_platforms[pSdk.name] = pSdk;
|
||||||
|
}
|
||||||
|
if (hasGcc) {
|
||||||
|
Platform pSdk;
|
||||||
|
pSdk = this->m_platforms[gccFullName];
|
||||||
|
pSdk.name = safeName + QLatin1String("-gcc") + xCodeName;
|
||||||
|
pSdk.sdkPath = Utils::FileName(sdkDirInfo);
|
||||||
|
pSdk.sdkSettings = sdkInfo;
|
||||||
|
if (debugProbe)
|
||||||
|
qDebug() << indent << QString::fromLatin1("* adding profile %1").arg(pSdk.name);
|
||||||
|
this->m_platforms[pSdk.name] = pSdk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!sdkPath.isEmpty())
|
||||||
|
sysRoot = sdkPath;
|
||||||
|
else if (!sdkName.isEmpty())
|
||||||
|
qDebug() << indent << QString::fromLatin1("Failed to find sysroot %1").arg(sdkName);
|
||||||
|
}
|
||||||
|
//this->m_platforms.remove(clangFullName);
|
||||||
|
if (hasClang && !sysRoot.isEmpty()) {
|
||||||
|
this->m_platforms[clangFullName].platformKind |= Platform::BasePlatform;
|
||||||
|
this->m_platforms[clangFullName].sdkPath = Utils::FileName::fromString(sysRoot);
|
||||||
|
this->m_platforms[clangFullName].sdkSettings = sdkSettings;
|
||||||
|
this->m_platforms[clang11FullName].platformKind |= Platform::BasePlatform;
|
||||||
|
this->m_platforms[clang11FullName].sdkPath = Utils::FileName::fromString(sysRoot);
|
||||||
|
this->m_platforms[clang11FullName].sdkSettings = sdkSettings;
|
||||||
|
}
|
||||||
|
//this->m_platforms.remove(gccFullName);
|
||||||
|
if (hasGcc && !sysRoot.isEmpty()) {
|
||||||
|
this->m_platforms[gccFullName].platformKind |= Platform::BasePlatform;
|
||||||
|
this->m_platforms[gccFullName].sdkPath = Utils::FileName::fromString(sysRoot);
|
||||||
|
this->m_platforms[gccFullName].sdkSettings = sdkSettings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
indent = QLatin1String(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosProbe::detectAll()
|
||||||
|
{
|
||||||
|
detectDeveloperPaths();
|
||||||
|
QString xcodeName = QLatin1String("");
|
||||||
|
for (int iXcode = 0; iXcode < m_developerPaths.count(); ++iXcode) {
|
||||||
|
setupDefaultToolchains(m_developerPaths.value(iXcode), xcodeName);
|
||||||
|
xcodeName = QString::fromLatin1("-%1").arg(iXcode + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QMap<QString, Platform> IosProbe::detectedPlatforms()
|
||||||
|
{
|
||||||
|
return m_platforms;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
84
src/plugins/ios/iosprobe.h
Normal file
84
src/plugins/ios/iosprobe.h
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef IOSPROBE_H
|
||||||
|
#define IOSPROBE_H
|
||||||
|
#include <QSettings>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
|
||||||
|
typedef QSharedPointer<QSettings> QSettingsPtr;
|
||||||
|
|
||||||
|
class Platform
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum PlatformKind {
|
||||||
|
BasePlatform = 1 << 0,
|
||||||
|
Cxx11Support = 1 << 1
|
||||||
|
};
|
||||||
|
|
||||||
|
quint32 platformKind;
|
||||||
|
QString name;
|
||||||
|
Utils::FileName developerPath;
|
||||||
|
Utils::FileName platformPath;
|
||||||
|
Utils::FileName sdkPath;
|
||||||
|
Utils::FileName defaultToolchainPath;
|
||||||
|
Utils::FileName compilerPath;
|
||||||
|
QString architecture;
|
||||||
|
QStringList backendFlags;
|
||||||
|
QSettingsPtr platformInfo;
|
||||||
|
QSettingsPtr sdkSettings;
|
||||||
|
QSettingsPtr toolchainInfo;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IosProbe
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static QMap<QString, Platform> detectPlatforms(const QString &devPath);
|
||||||
|
IosProbe()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static int compareVersions(const QString &v1, const QString &v2);
|
||||||
|
bool addDeveloperPath(const QString &path);
|
||||||
|
void detectDeveloperPaths();
|
||||||
|
void setArch(Platform *platform, const QString &pathToGcc, const QStringList &extraFlags);
|
||||||
|
void setupDefaultToolchains(const QString &devPath, const QString &xCodeName);
|
||||||
|
void detectAll();
|
||||||
|
QMap<QString, Platform> detectedPlatforms();
|
||||||
|
private:
|
||||||
|
QMap<QString, Platform> m_platforms;
|
||||||
|
QStringList m_developerPaths;
|
||||||
|
};
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#endif // IOSPROBE_H
|
131
src/plugins/ios/iosqtversion.cpp
Normal file
131
src/plugins/ios/iosqtversion.cpp
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "iosqtversion.h"
|
||||||
|
#include "iosconstants.h"
|
||||||
|
#include "iosconfigurations.h"
|
||||||
|
#include "iosmanager.h"
|
||||||
|
|
||||||
|
#include <utils/environment.h>
|
||||||
|
#include <utils/hostosinfo.h>
|
||||||
|
|
||||||
|
#include <qt4projectmanager/qt4project.h>
|
||||||
|
#include <qt4projectmanager/qt4projectmanagerconstants.h>
|
||||||
|
|
||||||
|
#include <qtsupport/qtkitinformation.h>
|
||||||
|
#include <qtsupport/qtsupportconstants.h>
|
||||||
|
#include <qtsupport/qtversionmanager.h>
|
||||||
|
|
||||||
|
#include <projectexplorer/kit.h>
|
||||||
|
#include <projectexplorer/projectexplorer.h>
|
||||||
|
|
||||||
|
using namespace Ios::Internal;
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
using namespace Qt4ProjectManager;
|
||||||
|
|
||||||
|
IosQtVersion::IosQtVersion()
|
||||||
|
: QtSupport::BaseQtVersion()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
IosQtVersion::IosQtVersion(const Utils::FileName &path, bool isAutodetected,
|
||||||
|
const QString &autodetectionSource)
|
||||||
|
: QtSupport::BaseQtVersion(path, isAutodetected, autodetectionSource)
|
||||||
|
{
|
||||||
|
setDisplayName(defaultDisplayName(qtVersionString(), path, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
IosQtVersion *IosQtVersion::clone() const
|
||||||
|
{
|
||||||
|
return new IosQtVersion(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosQtVersion::type() const
|
||||||
|
{
|
||||||
|
return QLatin1String(Constants::IOSQT);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosQtVersion::isValid() const
|
||||||
|
{
|
||||||
|
if (!BaseQtVersion::isValid())
|
||||||
|
return false;
|
||||||
|
if (qtAbis().isEmpty())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosQtVersion::invalidReason() const
|
||||||
|
{
|
||||||
|
QString tmp = BaseQtVersion::invalidReason();
|
||||||
|
if (tmp.isEmpty() && qtAbis().isEmpty())
|
||||||
|
return tr("Failed to detect the ABIs used by the Qt version.");
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<ProjectExplorer::Abi> IosQtVersion::detectQtAbis() const
|
||||||
|
{
|
||||||
|
QList<ProjectExplorer::Abi> abis = qtAbisFromLibrary(qtCorePath(versionInfo(), qtVersionString()));
|
||||||
|
for (int i = 0; i < abis.count(); ++i) {
|
||||||
|
abis[i] = Abi(abis.at(i).architecture(),
|
||||||
|
abis.at(i).os(),
|
||||||
|
ProjectExplorer::Abi::GenericMacFlavor,
|
||||||
|
abis.at(i).binaryFormat(),
|
||||||
|
abis.at(i).wordWidth());
|
||||||
|
}
|
||||||
|
return abis;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosQtVersion::addToEnvironment(const ProjectExplorer::Kit *k, Utils::Environment &env) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(k);
|
||||||
|
Q_UNUSED(env);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosQtVersion::description() const
|
||||||
|
{
|
||||||
|
//: Qt Version is meant for Ios
|
||||||
|
return tr("iOS");
|
||||||
|
}
|
||||||
|
|
||||||
|
Core::FeatureSet IosQtVersion::availableFeatures() const
|
||||||
|
{
|
||||||
|
Core::FeatureSet features = QtSupport::BaseQtVersion::availableFeatures();
|
||||||
|
features |= Core::FeatureSet(QtSupport::Constants::FEATURE_MOBILE);
|
||||||
|
return features;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosQtVersion::platformName() const
|
||||||
|
{
|
||||||
|
return QLatin1String(QtSupport::Constants::IOS_PLATFORM);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosQtVersion::platformDisplayName() const
|
||||||
|
{
|
||||||
|
return QLatin1String(QtSupport::Constants::IOS_PLATFORM_TR);
|
||||||
|
}
|
67
src/plugins/ios/iosqtversion.h
Normal file
67
src/plugins/ios/iosqtversion.h
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef IOSQTVERSION_H
|
||||||
|
#define IOSQTVERSION_H
|
||||||
|
|
||||||
|
#include <qtsupport/baseqtversion.h>
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class IosQtVersion : public QtSupport::BaseQtVersion
|
||||||
|
{
|
||||||
|
Q_DECLARE_TR_FUNCTIONS(Ios::Internal::IosQtVersion)
|
||||||
|
|
||||||
|
public:
|
||||||
|
IosQtVersion();
|
||||||
|
IosQtVersion(const Utils::FileName &path, bool isAutodetected = false,
|
||||||
|
const QString &autodetectionSource = QString());
|
||||||
|
|
||||||
|
IosQtVersion *clone() const;
|
||||||
|
QString type() const;
|
||||||
|
bool isValid() const;
|
||||||
|
QString invalidReason() const;
|
||||||
|
|
||||||
|
QList<ProjectExplorer::Abi> detectQtAbis() const;
|
||||||
|
|
||||||
|
void addToEnvironment(const ProjectExplorer::Kit *k, Utils::Environment &env) const;
|
||||||
|
|
||||||
|
Core::FeatureSet availableFeatures() const;
|
||||||
|
QString platformName() const;
|
||||||
|
QString platformDisplayName() const;
|
||||||
|
|
||||||
|
QString description() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#endif // IOSQTVERSION_H
|
78
src/plugins/ios/iosqtversionfactory.cpp
Normal file
78
src/plugins/ios/iosqtversionfactory.cpp
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "iosqtversionfactory.h"
|
||||||
|
#include "iosqtversion.h"
|
||||||
|
#include "iosconstants.h"
|
||||||
|
#include <qtsupport/qtsupportconstants.h>
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
#include <proparser/profileevaluator.h>
|
||||||
|
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
IosQtVersionFactory::IosQtVersionFactory(QObject *parent)
|
||||||
|
: QtSupport::QtVersionFactory(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosQtVersionFactory::canRestore(const QString &type)
|
||||||
|
{
|
||||||
|
return type == QLatin1String(Constants::IOSQT);
|
||||||
|
}
|
||||||
|
|
||||||
|
QtSupport::BaseQtVersion *IosQtVersionFactory::restore(const QString &type,
|
||||||
|
const QVariantMap &data)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(canRestore(type), return 0);
|
||||||
|
IosQtVersion *v = new IosQtVersion;
|
||||||
|
v->fromMap(data);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
int IosQtVersionFactory::priority() const
|
||||||
|
{
|
||||||
|
return 90;
|
||||||
|
}
|
||||||
|
|
||||||
|
QtSupport::BaseQtVersion *IosQtVersionFactory::create(const Utils::FileName &qmakePath,
|
||||||
|
ProFileEvaluator *evaluator,
|
||||||
|
bool isAutoDetected,
|
||||||
|
const QString &autoDetectionSource)
|
||||||
|
{
|
||||||
|
if (!(evaluator->values(QLatin1String("QMAKE_PLATFORM")).contains(QLatin1String("ios"))))
|
||||||
|
return 0;
|
||||||
|
return new IosQtVersion(qmakePath, isAutoDetected, autoDetectionSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Internal
|
||||||
|
} // Ios
|
54
src/plugins/ios/iosqtversionfactory.h
Normal file
54
src/plugins/ios/iosqtversionfactory.h
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef IOSQTVERSIONFACTORY_H
|
||||||
|
#define IOSQTVERSIONFACTORY_H
|
||||||
|
|
||||||
|
#include <qtsupport/qtversionfactory.h>
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class IosQtVersionFactory : public QtSupport::QtVersionFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit IosQtVersionFactory(QObject *parent = 0);
|
||||||
|
|
||||||
|
bool canRestore(const QString &type);
|
||||||
|
QtSupport::BaseQtVersion *restore(const QString &type, const QVariantMap &data);
|
||||||
|
|
||||||
|
int priority() const;
|
||||||
|
QtSupport::BaseQtVersion *create(const Utils::FileName &qmakePath, ProFileEvaluator *evaluator,
|
||||||
|
bool isAutoDetected = false,
|
||||||
|
const QString &autoDetectionSource = QString());
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#endif // IOSQTVERSIONFACTORY_H
|
275
src/plugins/ios/iosrunconfiguration.cpp
Normal file
275
src/plugins/ios/iosrunconfiguration.cpp
Normal file
@@ -0,0 +1,275 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "iosrunconfiguration.h"
|
||||||
|
#include "iosmanager.h"
|
||||||
|
#include "iosdeploystep.h"
|
||||||
|
|
||||||
|
#include <projectexplorer/kitinformation.h>
|
||||||
|
#include <projectexplorer/target.h>
|
||||||
|
#include <projectexplorer/deployconfiguration.h>
|
||||||
|
#include <projectexplorer/buildstep.h>
|
||||||
|
#include <projectexplorer/buildsteplist.h>
|
||||||
|
#include <qt4projectmanager/qt4buildconfiguration.h>
|
||||||
|
#include <qt4projectmanager/qt4project.h>
|
||||||
|
#include <qt4projectmanager/qt4nodes.h>
|
||||||
|
#include <qtsupport/qtoutputformatter.h>
|
||||||
|
#include <qtsupport/qtkitinformation.h>
|
||||||
|
#include "ui_iosrunconfiguration.h"
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
#include <utils/qtcprocess.h>
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
using namespace Qt4ProjectManager;
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class IosRunConfigurationWidget : public RunConfigWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
IosRunConfigurationWidget(IosRunConfiguration *runConfiguration);
|
||||||
|
~IosRunConfigurationWidget();
|
||||||
|
QString argListToString(const QStringList &args) const;
|
||||||
|
QStringList stringToArgList(const QString &args) const;
|
||||||
|
QString displayName() const;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void argumentsLineEditTextEdited();
|
||||||
|
void updateValues();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::IosRunConfiguration *m_ui;
|
||||||
|
IosRunConfiguration *m_runConfiguration;
|
||||||
|
};
|
||||||
|
|
||||||
|
IosRunConfiguration::IosRunConfiguration(Target *parent, Core::Id id, const QString &path)
|
||||||
|
: RunConfiguration(parent, id)
|
||||||
|
, m_profilePath(path)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
IosRunConfiguration::IosRunConfiguration(Target *parent, IosRunConfiguration *source)
|
||||||
|
: RunConfiguration(parent, source)
|
||||||
|
, m_profilePath(source->m_profilePath)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosRunConfiguration::init()
|
||||||
|
{
|
||||||
|
setDefaultDisplayName(defaultDisplayName());
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget *IosRunConfiguration::createConfigurationWidget()
|
||||||
|
{
|
||||||
|
return new IosRunConfigurationWidget(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Utils::OutputFormatter *IosRunConfiguration::createOutputFormatter() const
|
||||||
|
{
|
||||||
|
return new QtSupport::QtOutputFormatter(target()->project());
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList IosRunConfiguration::commandLineArguments()
|
||||||
|
{
|
||||||
|
return m_arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosRunConfiguration::defaultDisplayName()
|
||||||
|
{
|
||||||
|
ProjectExplorer::IDevice::ConstPtr dev =
|
||||||
|
ProjectExplorer::DeviceKitInformation::device(target()->kit());
|
||||||
|
QString devName;
|
||||||
|
if (!dev.isNull())
|
||||||
|
devName = dev->displayName();
|
||||||
|
if (devName.isEmpty())
|
||||||
|
devName = tr("iOS device");
|
||||||
|
return tr("Run on %1").arg(devName);
|
||||||
|
}
|
||||||
|
|
||||||
|
IosDeployStep *IosRunConfiguration::deployStep() const
|
||||||
|
{
|
||||||
|
IosDeployStep * step = 0;
|
||||||
|
DeployConfiguration *config = target()->activeDeployConfiguration();
|
||||||
|
ProjectExplorer::BuildStepList *bsl = config->stepList();
|
||||||
|
if (bsl) {
|
||||||
|
const QList<ProjectExplorer::BuildStep *> &buildSteps = bsl->steps();
|
||||||
|
for (int i = buildSteps.count() - 1; i >= 0; --i) {
|
||||||
|
step = qobject_cast<IosDeployStep *>(buildSteps.at(i));
|
||||||
|
if (step)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Q_ASSERT_X(step, Q_FUNC_INFO, "Impossible: iOS build configuration without deploy step.");
|
||||||
|
return step;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosRunConfiguration::profilePath() const
|
||||||
|
{
|
||||||
|
return m_profilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosRunConfiguration::appName() const
|
||||||
|
{
|
||||||
|
Qt4Project *pro = qobject_cast<Qt4Project *>(target()->project());
|
||||||
|
if (pro) {
|
||||||
|
const Qt4ProFileNode *node = pro->rootQt4ProjectNode()->findProFileFor(profilePath());
|
||||||
|
if (node) {
|
||||||
|
TargetInformation ti = node->targetInformation();
|
||||||
|
if (ti.valid) {
|
||||||
|
return ti.target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qDebug() << "IosRunConfiguration::appName failed";
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
Utils::FileName IosRunConfiguration::bundleDir() const
|
||||||
|
{
|
||||||
|
Utils::FileName res;
|
||||||
|
Core::Id devType = ProjectExplorer::DeviceTypeKitInformation::deviceTypeId(target()->kit());
|
||||||
|
bool isDevice = (devType == Constants::IOS_DEVICE_TYPE);
|
||||||
|
if (!isDevice && devType != Constants::IOS_SIMULATOR_TYPE) {
|
||||||
|
qDebug() << "unexpected device type in bundleDirForTarget: " << devType.toString();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
Qt4BuildConfiguration *bc =
|
||||||
|
qobject_cast<Qt4BuildConfiguration *>(target()->activeBuildConfiguration());
|
||||||
|
if (bc) {
|
||||||
|
res = bc->buildDirectory();
|
||||||
|
switch (bc->buildType()) {
|
||||||
|
case BuildConfiguration::Debug :
|
||||||
|
case BuildConfiguration::Unknown :
|
||||||
|
if (isDevice)
|
||||||
|
res.appendPath(QLatin1String("Debug-iphoneos"));
|
||||||
|
else
|
||||||
|
res.appendPath(QLatin1String("Debug-iphonesimulator"));
|
||||||
|
break;
|
||||||
|
case BuildConfiguration::Release :
|
||||||
|
if (isDevice)
|
||||||
|
res.appendPath(QLatin1String("Release-iphoneos"));
|
||||||
|
else
|
||||||
|
res.appendPath(QLatin1String("/Release-iphonesimulator"));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qDebug() << "IosBuildStep had an unknown buildType "
|
||||||
|
<< target()->activeBuildConfiguration()->buildType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res.appendPath(appName() + QLatin1String(".app"));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
Utils::FileName IosRunConfiguration::exePath() const
|
||||||
|
{
|
||||||
|
return bundleDir().appendPath(appName());
|
||||||
|
}
|
||||||
|
|
||||||
|
IosRunConfigurationWidget::IosRunConfigurationWidget(IosRunConfiguration *runConfiguration) :
|
||||||
|
m_ui(new Ui::IosRunConfiguration), m_runConfiguration(runConfiguration)
|
||||||
|
{
|
||||||
|
m_ui->setupUi(this);
|
||||||
|
|
||||||
|
updateValues();
|
||||||
|
connect(m_ui->argumentsLineEdit, SIGNAL(editingFinished()),
|
||||||
|
this, SLOT(argumentsLineEditTextEdited()));
|
||||||
|
}
|
||||||
|
|
||||||
|
IosRunConfigurationWidget::~IosRunConfigurationWidget()
|
||||||
|
{
|
||||||
|
delete m_ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosRunConfigurationWidget::argListToString(const QStringList &args) const
|
||||||
|
{
|
||||||
|
return Utils::QtcProcess::joinArgs(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList IosRunConfigurationWidget::stringToArgList(const QString &args) const
|
||||||
|
{
|
||||||
|
Utils::QtcProcess::SplitError err;
|
||||||
|
QStringList res = Utils::QtcProcess::splitArgs(args, false, &err);
|
||||||
|
switch (err) {
|
||||||
|
case Utils::QtcProcess::SplitOk:
|
||||||
|
break;
|
||||||
|
case Utils::QtcProcess::BadQuoting:
|
||||||
|
if (args.at(args.size()-1) == QLatin1Char('\\')) {
|
||||||
|
res = Utils::QtcProcess::splitArgs(args + QLatin1Char('\\'), false, &err);
|
||||||
|
if (err != Utils::QtcProcess::SplitOk)
|
||||||
|
res = Utils::QtcProcess::splitArgs(args + QLatin1Char('\\') + QLatin1Char('\''),
|
||||||
|
false, &err);
|
||||||
|
if (err != Utils::QtcProcess::SplitOk)
|
||||||
|
res = Utils::QtcProcess::splitArgs(args + QLatin1Char('\\') + QLatin1Char('\"'),
|
||||||
|
false, &err);
|
||||||
|
}
|
||||||
|
if (err != Utils::QtcProcess::SplitOk)
|
||||||
|
res = Utils::QtcProcess::splitArgs(args + QLatin1Char('\''), false, &err);
|
||||||
|
if (err != Utils::QtcProcess::SplitOk)
|
||||||
|
res = Utils::QtcProcess::splitArgs(args + QLatin1Char('\"'), false, &err);
|
||||||
|
break;
|
||||||
|
case Utils::QtcProcess::FoundMeta:
|
||||||
|
qDebug() << "IosRunConfigurationWidget FoundMeta (should not happen)";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosRunConfigurationWidget::displayName() const
|
||||||
|
{
|
||||||
|
return tr("iOS run settings");
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosRunConfigurationWidget::argumentsLineEditTextEdited()
|
||||||
|
{
|
||||||
|
QString argsString = m_ui->argumentsLineEdit->text();
|
||||||
|
QStringList args = stringToArgList(argsString);
|
||||||
|
m_runConfiguration->m_arguments = args;
|
||||||
|
m_ui->argumentsLineEdit->setText(argListToString(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosRunConfigurationWidget::updateValues()
|
||||||
|
{
|
||||||
|
QStringList args = m_runConfiguration->m_arguments;
|
||||||
|
QString argsString = argListToString(args);
|
||||||
|
m_ui->argumentsLineEdit->setText(argsString);
|
||||||
|
m_ui->executableLineEdit->setText(m_runConfiguration->exePath().toUserOutput());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#include "iosrunconfiguration.moc"
|
78
src/plugins/ios/iosrunconfiguration.h
Normal file
78
src/plugins/ios/iosrunconfiguration.h
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef IOSRUNCONFIGURATION_H
|
||||||
|
#define IOSRUNCONFIGURATION_H
|
||||||
|
|
||||||
|
#include "iosconstants.h"
|
||||||
|
#include "iosconfigurations.h"
|
||||||
|
|
||||||
|
#include <projectexplorer/runconfiguration.h>
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class IosDeployStep;
|
||||||
|
class IosRunConfigurationFactory;
|
||||||
|
class IosRunConfigurationWidget;
|
||||||
|
|
||||||
|
class IosRunConfiguration : public ProjectExplorer::RunConfiguration
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
friend class IosRunConfigurationFactory;
|
||||||
|
|
||||||
|
public:
|
||||||
|
IosRunConfiguration(ProjectExplorer::Target *parent, Core::Id id, const QString &path);
|
||||||
|
|
||||||
|
QWidget *createConfigurationWidget();
|
||||||
|
Utils::OutputFormatter *createOutputFormatter() const;
|
||||||
|
IosDeployStep *deployStep() const;
|
||||||
|
|
||||||
|
QStringList commandLineArguments();
|
||||||
|
QString profilePath() const;
|
||||||
|
QString appName() const;
|
||||||
|
Utils::FileName bundleDir() const;
|
||||||
|
Utils::FileName exePath() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
IosRunConfiguration(ProjectExplorer::Target *parent, IosRunConfiguration *source);
|
||||||
|
QString defaultDisplayName();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void init();
|
||||||
|
friend class IosRunConfigurationWidget;
|
||||||
|
|
||||||
|
QString m_profilePath;
|
||||||
|
QStringList m_arguments;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#endif // IOSRUNCONFIGURATION_H
|
51
src/plugins/ios/iosrunconfiguration.ui
Normal file
51
src/plugins/ios/iosrunconfiguration.ui
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>IosRunConfiguration</class>
|
||||||
|
<widget class="QWidget" name="IosRunConfiguration">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>571</width>
|
||||||
|
<height>76</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLineEdit" name="argumentsLineEdit"/>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="argumentsLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Aguments:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="exeLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Executable:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="executableLineEdit">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
112
src/plugins/ios/iosruncontrol.cpp
Normal file
112
src/plugins/ios/iosruncontrol.cpp
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "iosruncontrol.h"
|
||||||
|
|
||||||
|
#include "iosrunconfiguration.h"
|
||||||
|
#include "iosrunner.h"
|
||||||
|
|
||||||
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
|
#include <QIcon>
|
||||||
|
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
IosRunControl::IosRunControl(IosRunConfiguration *rc)
|
||||||
|
: RunControl(rc, NormalRunMode)
|
||||||
|
, m_runner(new IosRunner(this, rc, false))
|
||||||
|
, m_running(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
IosRunControl::~IosRunControl()
|
||||||
|
{
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosRunControl::start()
|
||||||
|
{
|
||||||
|
m_running = true;
|
||||||
|
emit started();
|
||||||
|
disconnect(m_runner, 0, this, 0);
|
||||||
|
|
||||||
|
connect(m_runner, SIGNAL(errorMsg(QString)),
|
||||||
|
SLOT(handleRemoteErrorOutput(QString)));
|
||||||
|
connect(m_runner, SIGNAL(appOutput(QString)),
|
||||||
|
SLOT(handleRemoteOutput(QString)));
|
||||||
|
connect(m_runner, SIGNAL(finished(bool)),
|
||||||
|
SLOT(handleRemoteProcessFinished(bool)));
|
||||||
|
appendMessage(tr("Starting remote process.\n"), Utils::NormalMessageFormat);
|
||||||
|
m_runner->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
RunControl::StopResult IosRunControl::stop()
|
||||||
|
{
|
||||||
|
m_runner->stop();
|
||||||
|
return StoppedSynchronously;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosRunControl::handleRemoteProcessFinished(bool cleanEnd)
|
||||||
|
{
|
||||||
|
if (!cleanEnd)
|
||||||
|
appendMessage(tr("Run ended unexpectedly."), Utils::ErrorMessageFormat);
|
||||||
|
disconnect(m_runner, 0, this, 0);
|
||||||
|
m_running = false;
|
||||||
|
emit finished();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosRunControl::handleRemoteOutput(const QString &output)
|
||||||
|
{
|
||||||
|
appendMessage(output, Utils::StdOutFormatSameLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosRunControl::handleRemoteErrorOutput(const QString &output)
|
||||||
|
{
|
||||||
|
appendMessage(output, Utils::StdErrFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosRunControl::isRunning() const
|
||||||
|
{
|
||||||
|
return m_running;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosRunControl::displayName() const
|
||||||
|
{
|
||||||
|
return m_runner->displayName();
|
||||||
|
}
|
||||||
|
|
||||||
|
QIcon IosRunControl::icon() const
|
||||||
|
{
|
||||||
|
return QIcon(QLatin1String(ProjectExplorer::Constants::ICON_DEBUG_SMALL));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Qt4ProjectManager
|
69
src/plugins/ios/iosruncontrol.h
Normal file
69
src/plugins/ios/iosruncontrol.h
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef IOSRUNCONTROL_H
|
||||||
|
#define IOSRUNCONTROL_H
|
||||||
|
|
||||||
|
#include <projectexplorer/runconfiguration.h>
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class IosRunConfiguration;
|
||||||
|
class IosRunner;
|
||||||
|
|
||||||
|
class IosRunControl : public ProjectExplorer::RunControl
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit IosRunControl(IosRunConfiguration *runConfig);
|
||||||
|
~IosRunControl();
|
||||||
|
|
||||||
|
|
||||||
|
void start();
|
||||||
|
StopResult stop();
|
||||||
|
bool isRunning() const;
|
||||||
|
QString displayName() const;
|
||||||
|
QIcon icon() const;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void handleRemoteProcessFinished(bool cleanEnd);
|
||||||
|
void handleRemoteOutput(const QString &output);
|
||||||
|
void handleRemoteErrorOutput(const QString &output);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
IosRunner * const m_runner;
|
||||||
|
bool m_running;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#endif // IOSRUNCONTROL_H
|
202
src/plugins/ios/iosrunfactories.cpp
Normal file
202
src/plugins/ios/iosrunfactories.cpp
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "iosrunfactories.h"
|
||||||
|
|
||||||
|
#include "iosconstants.h"
|
||||||
|
#include "iosdebugsupport.h"
|
||||||
|
#include "iosrunconfiguration.h"
|
||||||
|
#include "iosruncontrol.h"
|
||||||
|
#include "iosmanager.h"
|
||||||
|
|
||||||
|
#include <projectexplorer/project.h>
|
||||||
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
|
#include <projectexplorer/target.h>
|
||||||
|
#include <debugger/debuggerconstants.h>
|
||||||
|
#include <qt4projectmanager/qt4project.h>
|
||||||
|
#include <qt4projectmanager/qt4nodes.h>
|
||||||
|
#include <qtsupport/customexecutablerunconfiguration.h>
|
||||||
|
#include <qtsupport/qtkitinformation.h>
|
||||||
|
#include <qtsupport/qtsupportconstants.h>
|
||||||
|
#include <coreplugin/id.h>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
using namespace Qt4ProjectManager;
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
#define IOS_PREFIX "Qt4ProjectManager.IosRunConfiguration"
|
||||||
|
#define IOS_RC_ID_PREFIX IOS_PREFIX ":"
|
||||||
|
|
||||||
|
static QString pathFromId(const Core::Id id)
|
||||||
|
{
|
||||||
|
QString pathStr = id.toString();
|
||||||
|
const QString prefix = QLatin1String(IOS_RC_ID_PREFIX);
|
||||||
|
if (!pathStr.startsWith(prefix))
|
||||||
|
return QString();
|
||||||
|
return pathStr.mid(prefix.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
IosRunConfigurationFactory::IosRunConfigurationFactory(QObject *parent)
|
||||||
|
: QmakeRunConfigurationFactory(parent)
|
||||||
|
{
|
||||||
|
setObjectName(QLatin1String("IosRunConfigurationFactory"));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosRunConfigurationFactory::canCreate(Target *parent, const Core::Id id) const
|
||||||
|
{
|
||||||
|
if (!canHandle(parent))
|
||||||
|
return false;
|
||||||
|
return availableCreationIds(parent).contains(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosRunConfigurationFactory::canRestore(Target *parent, const QVariantMap &map) const
|
||||||
|
{
|
||||||
|
if (!canHandle(parent))
|
||||||
|
return false;
|
||||||
|
QString id = ProjectExplorer::idFromMap(map).toString();
|
||||||
|
return id.startsWith(QLatin1String(IOS_RC_ID_PREFIX));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosRunConfigurationFactory::canClone(Target *parent, RunConfiguration *source) const
|
||||||
|
{
|
||||||
|
return canCreate(parent, source->id());
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<Core::Id> IosRunConfigurationFactory::availableCreationIds(Target *parent) const
|
||||||
|
{
|
||||||
|
QList<Core::Id> ids;
|
||||||
|
if (!IosManager::supportsIos(parent))
|
||||||
|
return ids;
|
||||||
|
Core::Id baseId(IOS_RC_ID_PREFIX);
|
||||||
|
QList<Qt4ProFileNode *> nodes = static_cast<Qt4Project *>(parent->project())->allProFiles();
|
||||||
|
foreach (Qt4ProFileNode *node, nodes)
|
||||||
|
if (node->projectType() == ApplicationTemplate || node->projectType() == LibraryTemplate
|
||||||
|
|| node->projectType() == AuxTemplate)
|
||||||
|
ids << baseId.withSuffix(node->path());
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosRunConfigurationFactory::displayNameForId(const Core::Id id) const
|
||||||
|
{
|
||||||
|
return QFileInfo(pathFromId(id)).completeBaseName();
|
||||||
|
}
|
||||||
|
|
||||||
|
RunConfiguration *IosRunConfigurationFactory::create(Target *parent, const Core::Id id)
|
||||||
|
{
|
||||||
|
if (!canCreate(parent, id))
|
||||||
|
return 0;
|
||||||
|
return new IosRunConfiguration(parent, id, pathFromId(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
RunConfiguration *IosRunConfigurationFactory::restore(Target *parent,
|
||||||
|
const QVariantMap &map)
|
||||||
|
{
|
||||||
|
if (!canRestore(parent, map))
|
||||||
|
return 0;
|
||||||
|
Core::Id id = ProjectExplorer::idFromMap(map);
|
||||||
|
IosRunConfiguration *rc = new IosRunConfiguration(parent, id, pathFromId(id));
|
||||||
|
if (rc->fromMap(map))
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
delete rc;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
RunConfiguration *IosRunConfigurationFactory::clone(Target *parent, RunConfiguration *source)
|
||||||
|
{
|
||||||
|
if (!canClone(parent, source))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
IosRunConfiguration *old = qobject_cast<IosRunConfiguration *>(source);
|
||||||
|
return new IosRunConfiguration(parent, old);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosRunConfigurationFactory::canHandle(Target *t) const
|
||||||
|
{
|
||||||
|
if (!t->project()->supportsKit(t->kit()))
|
||||||
|
return false;
|
||||||
|
return IosManager::supportsIos(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<RunConfiguration *> IosRunConfigurationFactory::runConfigurationsForNode(Target *t, ProjectExplorer::Node *n)
|
||||||
|
{
|
||||||
|
QList<ProjectExplorer::RunConfiguration *> result;
|
||||||
|
foreach (ProjectExplorer::RunConfiguration *rc, t->runConfigurations())
|
||||||
|
if (IosRunConfiguration *qt4c = qobject_cast<IosRunConfiguration *>(rc))
|
||||||
|
if (qt4c->profilePath() == n->path())
|
||||||
|
result << rc;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
RunConfiguration *IosRunConfigurationFactory::doCreate(Target *parent, const Core::Id id)
|
||||||
|
{
|
||||||
|
return new IosRunConfiguration(parent, id, pathFromId(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
RunConfiguration *IosRunConfigurationFactory::doRestore(Target *parent, const QVariantMap &map)
|
||||||
|
{
|
||||||
|
Core::Id id = ProjectExplorer::idFromMap(map);
|
||||||
|
return new IosRunConfiguration(parent, id, pathFromId(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
IosRunControlFactory::IosRunControlFactory(QObject *parent)
|
||||||
|
: IRunControlFactory(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosRunControlFactory::canRun(RunConfiguration *runConfiguration,
|
||||||
|
ProjectExplorer::RunMode mode) const
|
||||||
|
{
|
||||||
|
if (mode != NormalRunMode && mode != DebugRunMode)
|
||||||
|
return false;
|
||||||
|
return qobject_cast<IosRunConfiguration *>(runConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
|
RunControl *IosRunControlFactory::create(RunConfiguration *runConfig,
|
||||||
|
ProjectExplorer::RunMode mode, QString *errorMessage)
|
||||||
|
{
|
||||||
|
Q_ASSERT(canRun(runConfig, mode));
|
||||||
|
IosRunConfiguration *rc = qobject_cast<IosRunConfiguration *>(runConfig);
|
||||||
|
Q_ASSERT(rc);
|
||||||
|
if (mode == NormalRunMode)
|
||||||
|
return new Ios::Internal::IosRunControl(rc);
|
||||||
|
else
|
||||||
|
return IosDebugSupport::createDebugRunControl(rc, errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosRunControlFactory::displayName() const
|
||||||
|
{
|
||||||
|
return tr("Run on iOS device or simulator.");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Qt4ProjectManager
|
97
src/plugins/ios/iosrunfactories.h
Normal file
97
src/plugins/ios/iosrunfactories.h
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef IOSRUNFACTORIES_H
|
||||||
|
#define IOSRUNFACTORIES_H
|
||||||
|
|
||||||
|
#include <projectexplorer/runconfiguration.h>
|
||||||
|
#include <qt4projectmanager/qmakerunconfigurationfactory.h>
|
||||||
|
#include <qcompilerdetection.h>
|
||||||
|
|
||||||
|
namespace ProjectExplorer {
|
||||||
|
class RunControl;
|
||||||
|
class RunConfigWidget;
|
||||||
|
class Target;
|
||||||
|
class Node;
|
||||||
|
} // namespace ProjectExplorer
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class IosRunConfigurationFactory : public Qt4ProjectManager::QmakeRunConfigurationFactory
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit IosRunConfigurationFactory(QObject *parent = 0);
|
||||||
|
|
||||||
|
Q_DECL_OVERRIDE QString displayNameForId(const Core::Id id) const;
|
||||||
|
Q_DECL_OVERRIDE QList<Core::Id> availableCreationIds(ProjectExplorer::Target *parent) const;
|
||||||
|
|
||||||
|
Q_DECL_OVERRIDE bool canCreate(ProjectExplorer::Target *parent, const Core::Id id) const;
|
||||||
|
Q_DECL_OVERRIDE ProjectExplorer::RunConfiguration *create(ProjectExplorer::Target *parent,
|
||||||
|
const Core::Id id);
|
||||||
|
|
||||||
|
Q_DECL_OVERRIDE bool canRestore(ProjectExplorer::Target *parent, const QVariantMap &map) const;
|
||||||
|
Q_DECL_OVERRIDE ProjectExplorer::RunConfiguration *restore(ProjectExplorer::Target *parent,
|
||||||
|
const QVariantMap &map);
|
||||||
|
|
||||||
|
Q_DECL_OVERRIDE bool canClone(ProjectExplorer::Target *parent,
|
||||||
|
ProjectExplorer::RunConfiguration *source) const;
|
||||||
|
Q_DECL_OVERRIDE ProjectExplorer::RunConfiguration *clone(ProjectExplorer::Target *parent,
|
||||||
|
ProjectExplorer::RunConfiguration *source);
|
||||||
|
|
||||||
|
Q_DECL_OVERRIDE bool canHandle(ProjectExplorer::Target *t) const;
|
||||||
|
Q_DECL_OVERRIDE QList<ProjectExplorer::RunConfiguration *> runConfigurationsForNode(ProjectExplorer::Target *t,
|
||||||
|
ProjectExplorer::Node *n);
|
||||||
|
private:
|
||||||
|
ProjectExplorer::RunConfiguration *doCreate(ProjectExplorer::Target *parent, const Core::Id id);
|
||||||
|
ProjectExplorer::RunConfiguration *doRestore(ProjectExplorer::Target *parent,
|
||||||
|
const QVariantMap &map);
|
||||||
|
};
|
||||||
|
|
||||||
|
class IosRunControlFactory : public ProjectExplorer::IRunControlFactory
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit IosRunControlFactory(QObject *parent = 0);
|
||||||
|
|
||||||
|
QString displayName() const;
|
||||||
|
|
||||||
|
bool canRun(ProjectExplorer::RunConfiguration *runConfiguration,
|
||||||
|
ProjectExplorer::RunMode mode) const;
|
||||||
|
ProjectExplorer::RunControl *create(ProjectExplorer::RunConfiguration *runConfiguration,
|
||||||
|
ProjectExplorer::RunMode mode,
|
||||||
|
QString *errorMessage);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#endif // IOSRUNFACTORIES_H
|
195
src/plugins/ios/iosrunner.cpp
Normal file
195
src/plugins/ios/iosrunner.cpp
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "iosbuildstep.h"
|
||||||
|
#include "iosconfigurations.h"
|
||||||
|
#include "iosdevice.h"
|
||||||
|
#include "iosmanager.h"
|
||||||
|
#include "iosrunconfiguration.h"
|
||||||
|
#include "iosrunner.h"
|
||||||
|
#include "iossimulator.h"
|
||||||
|
|
||||||
|
#include <projectexplorer/devicesupport/deviceapplicationrunner.h>
|
||||||
|
#include <projectexplorer/kitinformation.h>
|
||||||
|
#include <projectexplorer/target.h>
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QTime>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
IosRunner::IosRunner(QObject *parent, IosRunConfiguration *runConfig, bool debuggingMode)
|
||||||
|
: QObject(parent), m_toolHandler(0), m_bundleDir(runConfig->bundleDir().toString()),
|
||||||
|
m_arguments(runConfig->commandLineArguments()),
|
||||||
|
m_device(ProjectExplorer::DeviceKitInformation::device(runConfig->target()->kit())),
|
||||||
|
m_debuggingMode(debuggingMode), m_cleanExit(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
IosRunner::~IosRunner()
|
||||||
|
{
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosRunner::bundlePath()
|
||||||
|
{
|
||||||
|
return m_bundleDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList IosRunner::extraArgs()
|
||||||
|
{
|
||||||
|
return m_arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosRunner::deviceId()
|
||||||
|
{
|
||||||
|
IosDevice::ConstPtr dev = m_device.dynamicCast<const IosDevice>();
|
||||||
|
if (!dev)
|
||||||
|
return QString();
|
||||||
|
return dev->uniqueDeviceID();
|
||||||
|
}
|
||||||
|
|
||||||
|
IosToolHandler::RunKind IosRunner::runType()
|
||||||
|
{
|
||||||
|
if (m_debuggingMode)
|
||||||
|
return IosToolHandler::DebugRun;
|
||||||
|
return IosToolHandler::NormalRun;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosRunner::start()
|
||||||
|
{
|
||||||
|
if (m_toolHandler) {
|
||||||
|
m_toolHandler->stop();
|
||||||
|
emit finished(m_cleanExit);
|
||||||
|
}
|
||||||
|
m_cleanExit = false;
|
||||||
|
IosToolHandler::DeviceType devType = IosToolHandler::IosDeviceType;
|
||||||
|
if (m_device->type() != Ios::Constants::IOS_DEVICE_TYPE) {
|
||||||
|
IosSimulator::ConstPtr sim = m_device.dynamicCast<const IosSimulator>();
|
||||||
|
if (sim.isNull()) {
|
||||||
|
emit finished(m_cleanExit);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
devType = IosToolHandler::IosSimulatedIphoneRetina4InchType; // store type in sim?
|
||||||
|
}
|
||||||
|
m_toolHandler = new IosToolHandler(devType, this);
|
||||||
|
connect(m_toolHandler, SIGNAL(appOutput(Ios::IosToolHandler*,QString)),
|
||||||
|
SLOT(handleAppOutput(Ios::IosToolHandler*,QString)));
|
||||||
|
connect(m_toolHandler,
|
||||||
|
SIGNAL(didStartApp(Ios::IosToolHandler*,QString,QString,Ios::IosToolHandler::OpStatus)),
|
||||||
|
SLOT(handleDidStartApp(Ios::IosToolHandler*,QString,QString,Ios::IosToolHandler::OpStatus)));
|
||||||
|
connect(m_toolHandler, SIGNAL(errorMsg(Ios::IosToolHandler*,QString)),
|
||||||
|
SLOT(handleErrorMsg(Ios::IosToolHandler*,QString)));
|
||||||
|
connect(m_toolHandler, SIGNAL(gotGdbserverSocket(Ios::IosToolHandler*,QString,QString,int)),
|
||||||
|
SLOT(handleGotGdbserverSocket(Ios::IosToolHandler*,QString,QString,int)));
|
||||||
|
connect(m_toolHandler, SIGNAL(gotInferiorPid(Ios::IosToolHandler*,QString,QString,pid_t)),
|
||||||
|
SLOT(handleGotInferiorPid(Ios::IosToolHandler*,QString,QString,pid_t)));
|
||||||
|
connect(m_toolHandler, SIGNAL(toolExited(Ios::IosToolHandler*,int)),
|
||||||
|
SLOT(handleToolExited(Ios::IosToolHandler*,int)));
|
||||||
|
connect(m_toolHandler, SIGNAL(finished(Ios::IosToolHandler*)),
|
||||||
|
SLOT(handleFinished(Ios::IosToolHandler*)));
|
||||||
|
m_toolHandler->requestRunApp(bundlePath(), extraArgs(), runType(), deviceId());
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosRunner::stop()
|
||||||
|
{
|
||||||
|
if (m_toolHandler)
|
||||||
|
m_toolHandler->stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosRunner::handleDidStartApp(IosToolHandler *handler, const QString &bundlePath,
|
||||||
|
const QString &deviceId, IosToolHandler::OpStatus status)
|
||||||
|
{
|
||||||
|
Q_UNUSED(bundlePath); Q_UNUSED(deviceId);
|
||||||
|
if (m_toolHandler == handler)
|
||||||
|
emit didStartApp(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosRunner::handleGotGdbserverSocket(IosToolHandler *handler, const QString &bundlePath,
|
||||||
|
const QString &deviceId, int gdbFd)
|
||||||
|
{
|
||||||
|
Q_UNUSED(bundlePath); Q_UNUSED(deviceId);
|
||||||
|
if (m_toolHandler == handler)
|
||||||
|
emit gotGdbserverSocket(gdbFd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosRunner::handleGotInferiorPid(IosToolHandler *handler, const QString &bundlePath,
|
||||||
|
const QString &deviceId, pid_t pid)
|
||||||
|
{
|
||||||
|
Q_UNUSED(bundlePath); Q_UNUSED(deviceId);
|
||||||
|
if (m_toolHandler == handler)
|
||||||
|
emit gotInferiorPid(pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosRunner::handleAppOutput(IosToolHandler *handler, const QString &output)
|
||||||
|
{
|
||||||
|
Q_UNUSED(handler);
|
||||||
|
emit appOutput(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosRunner::handleErrorMsg(IosToolHandler *handler, const QString &msg)
|
||||||
|
{
|
||||||
|
if (msg.contains(QLatin1String("AMDeviceStartService returned -402653150"))) {
|
||||||
|
QMessageBox mBox;
|
||||||
|
mBox.setText(tr("Running on iOS device failed"));
|
||||||
|
mBox.setInformativeText(tr("This might be due to not up-to date certificates in Xcode or the device, go to the organizer window of Xcode to ensure that all certificates are up to date and try again."));
|
||||||
|
mBox.setStandardButtons(QMessageBox::Ok);
|
||||||
|
mBox.setDefaultButton(QMessageBox::Ok);
|
||||||
|
mBox.setIcon(QMessageBox::Information);
|
||||||
|
mBox.exec();
|
||||||
|
}
|
||||||
|
Q_UNUSED(handler);
|
||||||
|
emit errorMsg(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosRunner::handleToolExited(IosToolHandler *handler, int code)
|
||||||
|
{
|
||||||
|
Q_UNUSED(handler);
|
||||||
|
m_cleanExit = (code == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosRunner::handleFinished(IosToolHandler *handler)
|
||||||
|
{
|
||||||
|
if (m_toolHandler == handler) {
|
||||||
|
emit finished(m_cleanExit);
|
||||||
|
m_toolHandler = 0;
|
||||||
|
}
|
||||||
|
handler->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosRunner::displayName() const
|
||||||
|
{
|
||||||
|
return QString::fromLatin1("Run on %1").arg(m_device.isNull() ? QString()
|
||||||
|
: m_device->displayName());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Qt4ProjectManager
|
95
src/plugins/ios/iosrunner.h
Normal file
95
src/plugins/ios/iosrunner.h
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef IOSRUNNER_H
|
||||||
|
#define IOSRUNNER_H
|
||||||
|
|
||||||
|
#include "iosconfigurations.h"
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QThread>
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QMutex>
|
||||||
|
#include "iostoolhandler.h"
|
||||||
|
#include <projectexplorer/devicesupport/idevice.h>
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class IosRunConfiguration;
|
||||||
|
|
||||||
|
class IosRunner : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
IosRunner(QObject *parent, IosRunConfiguration *m_runConfig, bool m_debuggingMode);
|
||||||
|
~IosRunner();
|
||||||
|
|
||||||
|
QString displayName() const;
|
||||||
|
|
||||||
|
QString bundlePath();
|
||||||
|
QStringList extraArgs();
|
||||||
|
QString deviceId();
|
||||||
|
IosToolHandler::RunKind runType();
|
||||||
|
public slots:
|
||||||
|
void start();
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void didStartApp(Ios::IosToolHandler::OpStatus status);
|
||||||
|
void gotGdbserverSocket(int gdbFd);
|
||||||
|
void gotInferiorPid(pid_t pid);
|
||||||
|
void appOutput(const QString &output);
|
||||||
|
void errorMsg(const QString &msg);
|
||||||
|
void finished(bool cleanExit);
|
||||||
|
private slots:
|
||||||
|
void handleDidStartApp(Ios::IosToolHandler *handler, const QString &bundlePath,
|
||||||
|
const QString &deviceId, Ios::IosToolHandler::OpStatus status);
|
||||||
|
void handleGotGdbserverSocket(Ios::IosToolHandler *handler, const QString &bundlePath,
|
||||||
|
const QString &deviceId, int gdbFd);
|
||||||
|
void handleGotInferiorPid(Ios::IosToolHandler *handler, const QString &bundlePath,
|
||||||
|
const QString &deviceId, pid_t pid);
|
||||||
|
void handleAppOutput(Ios::IosToolHandler *handler, const QString &output);
|
||||||
|
void handleErrorMsg(Ios::IosToolHandler *handler, const QString &msg);
|
||||||
|
void handleToolExited(Ios::IosToolHandler *handler, int code);
|
||||||
|
void handleFinished(Ios::IosToolHandler *handler);
|
||||||
|
private:
|
||||||
|
IosToolHandler *m_toolHandler;
|
||||||
|
QString m_bundleDir;
|
||||||
|
QStringList m_arguments;
|
||||||
|
ProjectExplorer::IDevice::ConstPtr m_device;
|
||||||
|
bool m_debuggingMode;
|
||||||
|
bool m_cleanExit;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#endif // IOSRUNNER_H
|
75
src/plugins/ios/iossettingspage.cpp
Normal file
75
src/plugins/ios/iossettingspage.cpp
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "iossettingspage.h"
|
||||||
|
|
||||||
|
#include "iossettingswidget.h"
|
||||||
|
#include "iosconstants.h"
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
IosSettingsPage::IosSettingsPage(QObject *parent)
|
||||||
|
: Core::IOptionsPage(parent)
|
||||||
|
{
|
||||||
|
setId(Constants::IOS_SETTINGS_ID);
|
||||||
|
setDisplayName(tr("iOS Configurations"));
|
||||||
|
setCategory(Constants::IOS_SETTINGS_CATEGORY);
|
||||||
|
setDisplayCategory(QCoreApplication::translate("iOS",
|
||||||
|
Constants::IOS_SETTINGS_TR_CATEGORY));
|
||||||
|
setCategoryIcon(QLatin1String(Constants::IOS_SETTINGS_CATEGORY_ICON));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosSettingsPage::matches(const QString &searchKeyWord) const
|
||||||
|
{
|
||||||
|
return m_keywords.contains(searchKeyWord, Qt::CaseInsensitive);
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget *IosSettingsPage::createPage(QWidget *parent)
|
||||||
|
{
|
||||||
|
m_widget = new IosSettingsWidget(parent);
|
||||||
|
if (m_keywords.isEmpty())
|
||||||
|
m_keywords = m_widget->searchKeywords();
|
||||||
|
return m_widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosSettingsPage::apply()
|
||||||
|
{
|
||||||
|
m_widget->saveSettings();
|
||||||
|
IosConfigurations::instance().updateAutomaticKitList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosSettingsPage::finish()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
59
src/plugins/ios/iossettingspage.h
Normal file
59
src/plugins/ios/iossettingspage.h
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef IOSSETTINGSPAGE_H
|
||||||
|
#define IOSSETTINGSPAGE_H
|
||||||
|
|
||||||
|
#include <coreplugin/dialogs/ioptionspage.h>
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class IosSettingsWidget;
|
||||||
|
|
||||||
|
class IosSettingsPage : public Core::IOptionsPage
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit IosSettingsPage(QObject *parent = 0);
|
||||||
|
|
||||||
|
bool matches(const QString &searchKeyWord) const;
|
||||||
|
QWidget *createPage(QWidget *parent);
|
||||||
|
void apply();
|
||||||
|
void finish();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_keywords;
|
||||||
|
IosSettingsWidget *m_widget;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#endif // IOSSETTINGSPAGE_H
|
134
src/plugins/ios/iossettingswidget.cpp
Normal file
134
src/plugins/ios/iossettingswidget.cpp
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "iossettingswidget.h"
|
||||||
|
|
||||||
|
#include "ui_iossettingswidget.h"
|
||||||
|
|
||||||
|
#include "iosconfigurations.h"
|
||||||
|
#include "iosconstants.h"
|
||||||
|
|
||||||
|
#include <utils/hostosinfo.h>
|
||||||
|
#include <projectexplorer/toolchainmanager.h>
|
||||||
|
#include <projectexplorer/kitmanager.h>
|
||||||
|
#include <projectexplorer/kitinformation.h>
|
||||||
|
#include <qtsupport/qtkitinformation.h>
|
||||||
|
#include <qtsupport/qtversionmanager.h>
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#include <QTextStream>
|
||||||
|
#include <QProcess>
|
||||||
|
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QModelIndex>
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
IosSettingsWidget::IosSettingsWidget(QWidget *parent)
|
||||||
|
: QWidget(parent),
|
||||||
|
m_ui(new Ui_IosSettingsWidget),
|
||||||
|
m_iosConfig(IosConfigurations::instance().config()),
|
||||||
|
m_saveSettingsRequested(false)
|
||||||
|
{
|
||||||
|
initGui();
|
||||||
|
}
|
||||||
|
|
||||||
|
IosSettingsWidget::~IosSettingsWidget()
|
||||||
|
{
|
||||||
|
if (m_saveSettingsRequested)
|
||||||
|
IosConfigurations::instance().setConfig(m_iosConfig);
|
||||||
|
delete m_ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosSettingsWidget::searchKeywords() const
|
||||||
|
{
|
||||||
|
QString rc;
|
||||||
|
QTextStream(&rc) << m_ui->developerPathLabel->text();
|
||||||
|
rc.remove(QLatin1Char('&'));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosSettingsWidget::initGui()
|
||||||
|
{
|
||||||
|
m_ui->setupUi(this);
|
||||||
|
m_ui->developerPathLineEdit->setText(m_iosConfig.developerPath.toUserOutput());
|
||||||
|
m_ui->deviceAskCheckBox->setChecked(!m_iosConfig.ignoreAllDevices);
|
||||||
|
connect(m_ui->developerPathLineEdit, SIGNAL(editingFinished()),
|
||||||
|
SLOT(developerPathEditingFinished()));
|
||||||
|
connect(m_ui->developerPathPushButton, SIGNAL(clicked()),
|
||||||
|
SLOT(browseDeveloperPath()));
|
||||||
|
connect(m_ui->deviceAskCheckBox, SIGNAL(toggled(bool)),
|
||||||
|
SLOT(deviceAskToggled(bool)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosSettingsWidget::deviceAskToggled(bool checkboxValue)
|
||||||
|
{
|
||||||
|
m_iosConfig.ignoreAllDevices = !checkboxValue;
|
||||||
|
saveSettings(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosSettingsWidget::saveSettings(bool saveNow)
|
||||||
|
{
|
||||||
|
// We must defer this step because of a stupid bug on MacOS. See QTCREATORBUG-1675.
|
||||||
|
if (saveNow) {
|
||||||
|
IosConfigurations::instance().setConfig(m_iosConfig);
|
||||||
|
m_saveSettingsRequested = false;
|
||||||
|
} else {
|
||||||
|
m_saveSettingsRequested = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosSettingsWidget::developerPathEditingFinished()
|
||||||
|
{
|
||||||
|
Utils::FileName basePath = Utils::FileName::fromUserInput(m_ui->developerPathLineEdit->text());
|
||||||
|
// auto extend Contents/Developer if required
|
||||||
|
Utils::FileName devDir = basePath;
|
||||||
|
devDir.appendPath(QLatin1String("Contents/Developer"));
|
||||||
|
if (devDir.toFileInfo().isDir())
|
||||||
|
m_iosConfig.developerPath = devDir;
|
||||||
|
else
|
||||||
|
m_iosConfig.developerPath = basePath;
|
||||||
|
m_ui->developerPathLineEdit->setText(m_iosConfig.developerPath.toUserOutput());
|
||||||
|
saveSettings(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosSettingsWidget::browseDeveloperPath()
|
||||||
|
{
|
||||||
|
Utils::FileName dir = Utils::FileName::fromString(
|
||||||
|
QFileDialog::getOpenFileName(this,
|
||||||
|
tr("Select Xcode application"),
|
||||||
|
QLatin1String("/Applications"), QLatin1String("*.app")));
|
||||||
|
m_ui->developerPathLineEdit->setText(dir.toUserOutput());
|
||||||
|
developerPathEditingFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
73
src/plugins/ios/iossettingswidget.h
Normal file
73
src/plugins/ios/iossettingswidget.h
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef IOSSETTINGSWIDGET_H
|
||||||
|
#define IOSSETTINGSWIDGET_H
|
||||||
|
|
||||||
|
#include "iosconfigurations.h"
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
|
#include <QString>
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QAbstractTableModel>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class Ui_IosSettingsWidget;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class IosSettingsWidget : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
// Todo: This would be so much simpler if it just used Utils::PathChooser!!!
|
||||||
|
IosSettingsWidget(QWidget *parent);
|
||||||
|
~IosSettingsWidget();
|
||||||
|
|
||||||
|
void saveSettings(bool saveNow = false);
|
||||||
|
QString searchKeywords() const;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void deviceAskToggled(bool checkboxValue);
|
||||||
|
void developerPathEditingFinished();
|
||||||
|
void browseDeveloperPath();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initGui();
|
||||||
|
|
||||||
|
Ui_IosSettingsWidget *m_ui;
|
||||||
|
IosConfig m_iosConfig;
|
||||||
|
bool m_saveSettingsRequested;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#endif // IOSSETTINGSWIDGET_H
|
90
src/plugins/ios/iossettingswidget.ui
Normal file
90
src/plugins/ios/iossettingswidget.ui
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>IosSettingsWidget</class>
|
||||||
|
<widget class="QWidget" name="IosSettingsWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>679</width>
|
||||||
|
<height>104</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>iOS Configuration</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="developerPathLabel">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Xcode path:</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="developerPathLineEdit"/>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QPushButton" name="developerPathPushButton">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Browse</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QCheckBox" name="deviceAskCheckBox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Ask about devices not in developer mode</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
<slots>
|
||||||
|
<slot>sdkLocationEditingFinished()</slot>
|
||||||
|
<slot>ndkLocationEditingFinished()</slot>
|
||||||
|
<slot>browseSDKLocation()</slot>
|
||||||
|
<slot>browseNDKLocation()</slot>
|
||||||
|
<slot>antLocationEditingFinished()</slot>
|
||||||
|
<slot>browseAntLocation()</slot>
|
||||||
|
<slot>addAVD()</slot>
|
||||||
|
<slot>removeAVD()</slot>
|
||||||
|
<slot>startAVD()</slot>
|
||||||
|
<slot>avdActivated(QModelIndex)</slot>
|
||||||
|
<slot>dataPartitionSizeEditingFinished()</slot>
|
||||||
|
<slot>openJDKLocationEditingFinished()</slot>
|
||||||
|
<slot>browseOpenJDKLocation()</slot>
|
||||||
|
<slot>manageAVD()</slot>
|
||||||
|
<slot>createKitToggled()</slot>
|
||||||
|
</slots>
|
||||||
|
</ui>
|
142
src/plugins/ios/iossimulator.cpp
Normal file
142
src/plugins/ios/iossimulator.cpp
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "iossimulator.h"
|
||||||
|
#include "iosconstants.h"
|
||||||
|
|
||||||
|
#include <projectexplorer/kitinformation.h>
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
const char *SIMULATOR_PATH_KEY = "SIMULATOR_PATH";
|
||||||
|
|
||||||
|
IosSimulator::IosSimulator(Core::Id id, Utils::FileName simulatorPath)
|
||||||
|
: IDevice(Core::Id(Constants::IOS_SIMULATOR_TYPE),
|
||||||
|
IDevice::AutoDetected,
|
||||||
|
IDevice::Emulator,
|
||||||
|
id),
|
||||||
|
m_simulatorPath(simulatorPath)
|
||||||
|
{
|
||||||
|
setDisplayName(QCoreApplication::translate("Ios::Internal::IosSimulator", "Ios Simulator"));
|
||||||
|
}
|
||||||
|
|
||||||
|
IosSimulator::IosSimulator()
|
||||||
|
: IDevice(Core::Id(Constants::IOS_SIMULATOR_TYPE),
|
||||||
|
IDevice::AutoDetected,
|
||||||
|
IDevice::Emulator,
|
||||||
|
Core::Id(Constants::IOS_SIMULATOR_DEVICE_ID))
|
||||||
|
{
|
||||||
|
setDisplayName(QCoreApplication::translate("Ios::Internal::IosSimulator", "Ios Simulator"));
|
||||||
|
setDeviceState(DeviceReadyToUse);
|
||||||
|
}
|
||||||
|
|
||||||
|
IosSimulator::IosSimulator(const IosSimulator &other)
|
||||||
|
: IDevice(other)
|
||||||
|
{
|
||||||
|
setDisplayName(QCoreApplication::translate("Ios::Internal::IosSimulator", "Ios Simulator"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IDevice::DeviceInfo IosSimulator::deviceInformation() const
|
||||||
|
{
|
||||||
|
return IDevice::DeviceInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosSimulator::displayType() const
|
||||||
|
{
|
||||||
|
return QCoreApplication::translate("Ios::Internal::IosSimulator", "Ios Simulator");
|
||||||
|
}
|
||||||
|
|
||||||
|
IDeviceWidget *IosSimulator::createWidget()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<Core::Id> IosSimulator::actionIds() const
|
||||||
|
{
|
||||||
|
return QList<Core::Id>()<<Core::Id(Constants::IOS_DEVICE_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosSimulator::displayNameForActionId(Core::Id actionId) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(actionId)
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosSimulator::executeAction(Core::Id actionId, QWidget *parent)
|
||||||
|
{
|
||||||
|
Q_UNUSED(actionId)
|
||||||
|
Q_UNUSED(parent)
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceProcessSignalOperation::Ptr IosSimulator::signalOperation() const
|
||||||
|
{
|
||||||
|
return DeviceProcessSignalOperation::Ptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
Utils::FileName IosSimulator::simulatorPath() const
|
||||||
|
{
|
||||||
|
return m_simulatorPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
IDevice::Ptr IosSimulator::clone() const
|
||||||
|
{
|
||||||
|
return IDevice::Ptr(new IosSimulator(*this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosSimulator::fromMap(const QVariantMap &map)
|
||||||
|
{
|
||||||
|
IDevice::fromMap(map);
|
||||||
|
m_simulatorPath = Utils::FileName::fromString(map.value(QLatin1String(SIMULATOR_PATH_KEY))
|
||||||
|
.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap IosSimulator::toMap() const
|
||||||
|
{
|
||||||
|
QVariantMap res = IDevice::toMap();
|
||||||
|
res.insert(QLatin1String(SIMULATOR_PATH_KEY), simulatorPath().toString());
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
IosSimulator::ConstPtr IosKitInformation::simulator(Kit *kit)
|
||||||
|
{
|
||||||
|
if (!kit)
|
||||||
|
return IosSimulator::ConstPtr();
|
||||||
|
ProjectExplorer::IDevice::ConstPtr dev = ProjectExplorer::DeviceKitInformation::device(kit);
|
||||||
|
IosSimulator::ConstPtr res = dev.dynamicCast<const IosSimulator>();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
80
src/plugins/ios/iossimulator.h
Normal file
80
src/plugins/ios/iossimulator.h
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef IOSSIMULATOR_H
|
||||||
|
#define IOSSIMULATOR_H
|
||||||
|
|
||||||
|
#include <projectexplorer/devicesupport/idevice.h>
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
|
#include <QSharedPointer>
|
||||||
|
|
||||||
|
namespace ProjectExplorer {
|
||||||
|
class Kit;
|
||||||
|
}
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
class IosConfigurations;
|
||||||
|
class IosSimulatorFactory;
|
||||||
|
|
||||||
|
class IosSimulator : public ProjectExplorer::IDevice
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef QSharedPointer<const IosSimulator> ConstPtr;
|
||||||
|
typedef QSharedPointer<IosSimulator> Ptr;
|
||||||
|
ProjectExplorer::IDevice::DeviceInfo deviceInformation() const;
|
||||||
|
|
||||||
|
QString displayType() const;
|
||||||
|
ProjectExplorer::IDeviceWidget *createWidget();
|
||||||
|
QList<Core::Id> actionIds() const;
|
||||||
|
QString displayNameForActionId(Core::Id actionId) const;
|
||||||
|
void executeAction(Core::Id actionId, QWidget *parent = 0);
|
||||||
|
ProjectExplorer::DeviceProcessSignalOperation::Ptr signalOperation() const;
|
||||||
|
Utils::FileName simulatorPath() const;
|
||||||
|
void fromMap(const QVariantMap &map);
|
||||||
|
QVariantMap toMap() const;
|
||||||
|
|
||||||
|
ProjectExplorer::IDevice::Ptr clone() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
friend class IosSimulatorFactory;
|
||||||
|
friend class IosConfigurations;
|
||||||
|
IosSimulator();
|
||||||
|
IosSimulator(Core::Id id, Utils::FileName simulatorPath);
|
||||||
|
IosSimulator(const IosSimulator &other);
|
||||||
|
private:
|
||||||
|
Utils::FileName m_simulatorPath;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace IosKitInformation {
|
||||||
|
IosSimulator::ConstPtr simulator(ProjectExplorer::Kit *kit);
|
||||||
|
} // namespace IosKitInformation
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#endif // IOSSIMULATOR_H
|
81
src/plugins/ios/iossimulatorfactory.cpp
Normal file
81
src/plugins/ios/iossimulatorfactory.cpp
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "iossimulatorfactory.h"
|
||||||
|
#include <QLatin1String>
|
||||||
|
#include "iosconstants.h"
|
||||||
|
#include "iossimulator.h"
|
||||||
|
#include "utils/qtcassert.h"
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
IosSimulatorFactory::IosSimulatorFactory()
|
||||||
|
{
|
||||||
|
setObjectName(QLatin1String("IosSimulatorFactory"));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosSimulatorFactory::displayNameForId(Core::Id type) const
|
||||||
|
{
|
||||||
|
if (type == Constants::IOS_SIMULATOR_TYPE)
|
||||||
|
return tr("iOS Simulator");
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<Core::Id> IosSimulatorFactory::availableCreationIds() const
|
||||||
|
{
|
||||||
|
return QList<Core::Id>() << Core::Id(Constants::IOS_SIMULATOR_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosSimulatorFactory::canCreate() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectExplorer::IDevice::Ptr IosSimulatorFactory::create(Core::Id id) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(id)
|
||||||
|
return ProjectExplorer::IDevice::Ptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosSimulatorFactory::canRestore(const QVariantMap &map) const
|
||||||
|
{
|
||||||
|
return ProjectExplorer::IDevice::typeFromMap(map) == Constants::IOS_SIMULATOR_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectExplorer::IDevice::Ptr IosSimulatorFactory::restore(const QVariantMap &map) const
|
||||||
|
{
|
||||||
|
QTC_ASSERT(canRestore(map), return ProjectExplorer::IDevice::Ptr());
|
||||||
|
const ProjectExplorer::IDevice::Ptr device = ProjectExplorer::IDevice::Ptr(new IosSimulator());
|
||||||
|
device->fromMap(map);
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
55
src/plugins/ios/iossimulatorfactory.h
Normal file
55
src/plugins/ios/iossimulatorfactory.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef IOSSIMULATORFACTORY_H
|
||||||
|
#define IOSSIMULATORFACTORY_H
|
||||||
|
|
||||||
|
#include <projectexplorer/devicesupport/idevicefactory.h>
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class IosSimulatorFactory : public ProjectExplorer::IDeviceFactory
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
IosSimulatorFactory();
|
||||||
|
|
||||||
|
QString displayNameForId(Core::Id type) const;
|
||||||
|
QList<Core::Id> availableCreationIds() const;
|
||||||
|
|
||||||
|
bool canCreate() const;
|
||||||
|
ProjectExplorer::IDevice::Ptr create(Core::Id id) const;
|
||||||
|
bool canRestore(const QVariantMap &map) const;
|
||||||
|
ProjectExplorer::IDevice::Ptr restore(const QVariantMap &map) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#endif // IOSSIMULATORFACTORY_H
|
977
src/plugins/ios/iostoolhandler.cpp
Normal file
977
src/plugins/ios/iostoolhandler.cpp
Normal file
@@ -0,0 +1,977 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "iostoolhandler.h"
|
||||||
|
#include "iosconfigurations.h"
|
||||||
|
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QXmlStreamReader>
|
||||||
|
#include <QSocketNotifier>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
static const bool debugToolHandler = false;
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class MyProcess: public QProcess
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit MyProcess(QObject *parent = 0);
|
||||||
|
int processOutput();
|
||||||
|
QSocketNotifier *notifier();
|
||||||
|
protected:
|
||||||
|
virtual void setupChildProcess();
|
||||||
|
private:
|
||||||
|
int m_sockets[2];
|
||||||
|
QSocketNotifier *m_notifier;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ParserState {
|
||||||
|
enum Kind {
|
||||||
|
Msg,
|
||||||
|
DeviceId,
|
||||||
|
Key,
|
||||||
|
Value,
|
||||||
|
QueryResult,
|
||||||
|
AppOutput,
|
||||||
|
AppStarted,
|
||||||
|
InferiorPid,
|
||||||
|
Item,
|
||||||
|
Status,
|
||||||
|
AppTransfer,
|
||||||
|
DeviceInfo,
|
||||||
|
Exit
|
||||||
|
};
|
||||||
|
Kind kind;
|
||||||
|
QString elName;
|
||||||
|
QString chars;
|
||||||
|
QString key;
|
||||||
|
QString value;
|
||||||
|
QMap<QString,QString> info;
|
||||||
|
int progress, maxProgress;
|
||||||
|
bool collectChars() {
|
||||||
|
switch (kind) {
|
||||||
|
case Msg:
|
||||||
|
case DeviceId:
|
||||||
|
case Key:
|
||||||
|
case Value:
|
||||||
|
case Status:
|
||||||
|
case InferiorPid:
|
||||||
|
return true;
|
||||||
|
case QueryResult:
|
||||||
|
case AppOutput:
|
||||||
|
case AppStarted:
|
||||||
|
case AppTransfer:
|
||||||
|
case Item:
|
||||||
|
case DeviceInfo:
|
||||||
|
case Exit:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ParserState(Kind kind) :
|
||||||
|
kind(kind) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
class IosToolHandlerPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum State {
|
||||||
|
NonStarted,
|
||||||
|
Starting,
|
||||||
|
StartedInferior,
|
||||||
|
XmlEndSeenNotProcessed,
|
||||||
|
XmlEndProcessed,
|
||||||
|
Stopped
|
||||||
|
};
|
||||||
|
enum Op {
|
||||||
|
OpNone,
|
||||||
|
OpAppTransfer,
|
||||||
|
OpDeviceInfo,
|
||||||
|
OpAppRun
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit IosToolHandlerPrivate(IosToolHandler::DeviceType devType, IosToolHandler *q);
|
||||||
|
virtual void requestTransferApp(const QString &bundlePath, const QString &deviceId,
|
||||||
|
int timeout = 1000) = 0;
|
||||||
|
virtual void requestRunApp(const QString &bundlePath, const QStringList &extraArgs,
|
||||||
|
IosToolHandler::RunKind runKind,
|
||||||
|
const QString &deviceId, int timeout = 1000) = 0;
|
||||||
|
virtual void requestDeviceInfo(const QString &deviceId, int timeout = 1000) = 0;
|
||||||
|
bool isRunning();
|
||||||
|
void start(const QString &exe, const QStringList &args);
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
// signals
|
||||||
|
void isTransferringApp(const QString &bundlePath, const QString &deviceId, int progress,
|
||||||
|
int maxProgress, const QString &info);
|
||||||
|
void didTransferApp(const QString &bundlePath, const QString &deviceId,
|
||||||
|
IosToolHandler::OpStatus status);
|
||||||
|
void didStartApp(const QString &bundlePath, const QString &deviceId,
|
||||||
|
IosToolHandler::OpStatus status);
|
||||||
|
void gotGdbserverSocket(const QString &bundlePath, const QString &deviceId, int gdbFd);
|
||||||
|
void gotInferiorPid(const QString &bundlePath, const QString &deviceId, pid_t pid);
|
||||||
|
void deviceInfo(const QString &deviceId, const IosToolHandler::Dict &info);
|
||||||
|
void appOutput(const QString &output);
|
||||||
|
void errorMsg(const QString &msg);
|
||||||
|
void toolExited(int code);
|
||||||
|
// slots
|
||||||
|
void subprocessError(QProcess::ProcessError error);
|
||||||
|
void subprocessFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||||
|
void subprocessHasData(int socket);
|
||||||
|
virtual bool expectsFileDescriptor() = 0;
|
||||||
|
protected:
|
||||||
|
int checkForXmlEnd();
|
||||||
|
void processXml();
|
||||||
|
|
||||||
|
IosToolHandler *q;
|
||||||
|
MyProcess process;
|
||||||
|
QXmlStreamReader outputParser;
|
||||||
|
QString deviceId;
|
||||||
|
QString bundlePath;
|
||||||
|
IosToolHandler::RunKind runKind;
|
||||||
|
State state;
|
||||||
|
Op op;
|
||||||
|
IosToolHandler::DeviceType devType;
|
||||||
|
static const int lookaheadSize = 67;
|
||||||
|
QByteArray buffer;
|
||||||
|
QByteArray currentData;
|
||||||
|
int iBegin, iEnd, gdbSocket;
|
||||||
|
QList<ParserState> stack;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IosDeviceToolHandlerPrivate : public IosToolHandlerPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit IosDeviceToolHandlerPrivate(IosToolHandler::DeviceType devType, IosToolHandler *q);
|
||||||
|
virtual void requestTransferApp(const QString &bundlePath, const QString &deviceId,
|
||||||
|
int timeout = 1000);
|
||||||
|
virtual void requestRunApp(const QString &bundlePath, const QStringList &extraArgs,
|
||||||
|
IosToolHandler::RunKind runKind,
|
||||||
|
const QString &deviceId, int timeout = 1000);
|
||||||
|
virtual void requestDeviceInfo(const QString &deviceId, int timeout = 1000);
|
||||||
|
virtual bool expectsFileDescriptor();
|
||||||
|
};
|
||||||
|
|
||||||
|
class IosSimulatorToolHandlerPrivate : public IosToolHandlerPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit IosSimulatorToolHandlerPrivate(IosToolHandler::DeviceType devType, IosToolHandler *q);
|
||||||
|
virtual void requestTransferApp(const QString &bundlePath, const QString &deviceId,
|
||||||
|
int timeout = 1000);
|
||||||
|
virtual void requestRunApp(const QString &bundlePath, const QStringList &extraArgs,
|
||||||
|
IosToolHandler::RunKind runKind,
|
||||||
|
const QString &deviceId, int timeout = 1000);
|
||||||
|
virtual void requestDeviceInfo(const QString &deviceId, int timeout = 1000);
|
||||||
|
virtual bool expectsFileDescriptor();
|
||||||
|
private:
|
||||||
|
void addDeviceArguments(QStringList &args) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
MyProcess::MyProcess(QObject *parent) : QProcess(parent)
|
||||||
|
{
|
||||||
|
if (socketpair(PF_UNIX, SOCK_STREAM, 0, &m_sockets[0]) == -1) {
|
||||||
|
qDebug() << "IosToolHandler socketpair failed ";
|
||||||
|
}
|
||||||
|
shutdown(m_sockets[0], SHUT_WR);
|
||||||
|
m_notifier = new QSocketNotifier(m_sockets[0], QSocketNotifier::Read, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
int MyProcess::processOutput()
|
||||||
|
{
|
||||||
|
return m_sockets[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
QSocketNotifier *MyProcess::notifier()
|
||||||
|
{
|
||||||
|
return m_notifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyProcess::setupChildProcess()
|
||||||
|
{
|
||||||
|
if (dup2(m_sockets[1], 1) == -1) { // use the unix socket as stdout
|
||||||
|
qDebug() << "IosToolHandler dup2 call failed";
|
||||||
|
emit finished(-1, QProcess::CrashExit);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
shutdown(1, SHUT_RD); // leave open for handshake when transferring fd?
|
||||||
|
}
|
||||||
|
|
||||||
|
IosToolHandlerPrivate::IosToolHandlerPrivate(IosToolHandler::DeviceType devType,
|
||||||
|
Ios::IosToolHandler *q) :
|
||||||
|
q(q), state(NonStarted), devType(devType), buffer(4*lookaheadSize, 0), iBegin(0), iEnd(0),
|
||||||
|
gdbSocket(-1)
|
||||||
|
{
|
||||||
|
QObject::connect(process.notifier(), SIGNAL(activated(int)), q, SLOT(subprocessHasData(int)));
|
||||||
|
QObject::connect(&process, SIGNAL(finished(int,QProcess::ExitStatus)),
|
||||||
|
q, SLOT(subprocessFinished(int,QProcess::ExitStatus)));
|
||||||
|
QObject::connect(&process, SIGNAL(error(QProcess::ProcessError)),
|
||||||
|
q, SLOT(subprocessError(QProcess::ProcessError)));
|
||||||
|
int accessFlags = fcntl(process.processOutput(), F_GETFL);
|
||||||
|
if (fcntl(process.processOutput(), F_SETFL, accessFlags | O_NONBLOCK) == -1)
|
||||||
|
qDebug() << "IosToolHandler fcntl F_SETFL failed to set non blocking mode"
|
||||||
|
<< qt_error_string(errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosToolHandlerPrivate::isRunning()
|
||||||
|
{
|
||||||
|
return process.state() != QProcess::NotRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosToolHandlerPrivate::start(const QString &exe, const QStringList &args)
|
||||||
|
{
|
||||||
|
QTC_CHECK(state == NonStarted);
|
||||||
|
state = Starting;
|
||||||
|
if (debugToolHandler)
|
||||||
|
qDebug() << "running " << exe << args;
|
||||||
|
process.start(exe, args);
|
||||||
|
state = StartedInferior;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosToolHandlerPrivate::stop()
|
||||||
|
{
|
||||||
|
if (debugToolHandler)
|
||||||
|
qDebug() << "IosToolHandlerPrivate::stop";
|
||||||
|
if (process.state() != QProcess::NotRunning) {
|
||||||
|
close(process.processOutput());
|
||||||
|
process.close();
|
||||||
|
process.kill();
|
||||||
|
}
|
||||||
|
if (state != Stopped) {
|
||||||
|
state = Stopped;
|
||||||
|
emit q->finished(q);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// signals
|
||||||
|
void IosToolHandlerPrivate::isTransferringApp(const QString &bundlePath, const QString &deviceId,
|
||||||
|
int progress, int maxProgress, const QString &info)
|
||||||
|
{
|
||||||
|
emit q->isTransferringApp(q, bundlePath, deviceId, progress, maxProgress, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosToolHandlerPrivate::didTransferApp(const QString &bundlePath, const QString &deviceId,
|
||||||
|
Ios::IosToolHandler::OpStatus status)
|
||||||
|
{
|
||||||
|
emit q->didTransferApp(q, bundlePath, deviceId, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosToolHandlerPrivate::didStartApp(const QString &bundlePath, const QString &deviceId,
|
||||||
|
IosToolHandler::OpStatus status)
|
||||||
|
{
|
||||||
|
emit q->didStartApp(q, bundlePath, deviceId, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosToolHandlerPrivate::gotGdbserverSocket(const QString &bundlePath, const QString &deviceId,
|
||||||
|
int gdbFd)
|
||||||
|
{
|
||||||
|
emit q->gotGdbserverSocket(q, bundlePath, deviceId, gdbFd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosToolHandlerPrivate::gotInferiorPid(const QString &bundlePath, const QString &deviceId,
|
||||||
|
pid_t pid)
|
||||||
|
{
|
||||||
|
emit q->gotInferiorPid(q, bundlePath, deviceId, pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosToolHandlerPrivate::deviceInfo(const QString &deviceId,
|
||||||
|
const Ios::IosToolHandler::Dict &info)
|
||||||
|
{
|
||||||
|
emit q->deviceInfo(q, deviceId, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosToolHandlerPrivate::appOutput(const QString &output)
|
||||||
|
{
|
||||||
|
emit q->appOutput(q, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosToolHandlerPrivate::errorMsg(const QString &msg)
|
||||||
|
{
|
||||||
|
emit q->errorMsg(q, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosToolHandlerPrivate::toolExited(int code)
|
||||||
|
{
|
||||||
|
emit q->toolExited(q, code);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosToolHandlerPrivate::subprocessError(QProcess::ProcessError error)
|
||||||
|
{
|
||||||
|
switch (state) {
|
||||||
|
case NonStarted:
|
||||||
|
qDebug() << "subprocessError() when state was NonStarted";
|
||||||
|
// pass
|
||||||
|
case Starting:
|
||||||
|
switch (op){
|
||||||
|
case OpNone:
|
||||||
|
qDebug() << "subprocessError() when op is OpNone";
|
||||||
|
break;
|
||||||
|
case OpAppTransfer:
|
||||||
|
didTransferApp(bundlePath, deviceId, IosToolHandler::Failure);
|
||||||
|
break;
|
||||||
|
case OpAppRun:
|
||||||
|
didStartApp(bundlePath, deviceId, IosToolHandler::Failure);
|
||||||
|
break;
|
||||||
|
case OpDeviceInfo:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// pass
|
||||||
|
case StartedInferior:
|
||||||
|
case XmlEndSeenNotProcessed:
|
||||||
|
case XmlEndProcessed:
|
||||||
|
errorMsg(q->tr("Subprocess Error %1").arg(error));
|
||||||
|
toolExited(-1);
|
||||||
|
break;
|
||||||
|
case Stopped:
|
||||||
|
qDebug() << "IosToolHandler, subprocessError() in an already stopped process";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosToolHandlerPrivate::subprocessFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
||||||
|
{
|
||||||
|
// process potentially pending data
|
||||||
|
subprocessHasData(process.processOutput());
|
||||||
|
switch (state) {
|
||||||
|
case NonStarted:
|
||||||
|
qDebug() << "subprocessFinished() when state was NonStarted";
|
||||||
|
// pass
|
||||||
|
case Starting:
|
||||||
|
switch (op){
|
||||||
|
case OpNone:
|
||||||
|
qDebug() << "subprocessFinished() when op was OpNone";
|
||||||
|
break;
|
||||||
|
case OpAppTransfer:
|
||||||
|
didTransferApp(bundlePath, deviceId, IosToolHandler::Failure);
|
||||||
|
break;
|
||||||
|
case OpAppRun:
|
||||||
|
didStartApp(bundlePath, deviceId, IosToolHandler::Failure);
|
||||||
|
break;
|
||||||
|
case OpDeviceInfo:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// pass
|
||||||
|
case StartedInferior:
|
||||||
|
case XmlEndSeenNotProcessed:
|
||||||
|
case XmlEndProcessed:
|
||||||
|
toolExited((exitStatus == QProcess::CrashExit && exitCode == 0) ? -1 : exitCode);
|
||||||
|
break;
|
||||||
|
case Stopped:
|
||||||
|
if (debugToolHandler)
|
||||||
|
qDebug() << "IosToolHandler, subprocessFinished() in an already stopped process (normal)";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int recv_fd(int socket)
|
||||||
|
{
|
||||||
|
int sent_fd;
|
||||||
|
char message_buffer[1];
|
||||||
|
|
||||||
|
iovec io_vector[1];
|
||||||
|
memset(&io_vector[0], 0, sizeof(iovec));
|
||||||
|
/* setup a place to fill in message contents */
|
||||||
|
io_vector[0].iov_base = message_buffer;
|
||||||
|
io_vector[0].iov_len = 1;
|
||||||
|
|
||||||
|
msghdr socket_message;
|
||||||
|
memset(&socket_message, 0, sizeof(struct msghdr));
|
||||||
|
socket_message.msg_iov = io_vector;
|
||||||
|
socket_message.msg_iovlen = 1;
|
||||||
|
|
||||||
|
/* provide space for the ancillary data */
|
||||||
|
char ancillary_element_buffer[CMSG_SPACE(sizeof(int))];
|
||||||
|
memset(ancillary_element_buffer, 0, CMSG_SPACE(sizeof(int)));
|
||||||
|
socket_message.msg_control = ancillary_element_buffer;
|
||||||
|
socket_message.msg_controllen = CMSG_SPACE(sizeof(int));
|
||||||
|
|
||||||
|
int flags = 0;
|
||||||
|
#ifdef MSG_CMSG_CLOEXEC
|
||||||
|
flags = MSG_CMSG_CLOEXEC;
|
||||||
|
#endif
|
||||||
|
if (recvmsg(socket, &socket_message, flags) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (message_buffer[0] != '.') {
|
||||||
|
qDebug() << "IosToolHandler, unexpected inband data when receiving socket";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((socket_message.msg_flags & MSG_CTRUNC) == MSG_CTRUNC) {
|
||||||
|
qDebug() << "IosToolHandler, not provide enough space for the ancillary element array";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* iterate ancillary elements */
|
||||||
|
cmsghdr *control_message = NULL;
|
||||||
|
for (control_message = CMSG_FIRSTHDR(&socket_message);
|
||||||
|
control_message != NULL;
|
||||||
|
control_message = CMSG_NXTHDR(&socket_message, control_message)) {
|
||||||
|
if ( (control_message->cmsg_level == SOL_SOCKET) &&
|
||||||
|
(control_message->cmsg_type == SCM_RIGHTS) ) {
|
||||||
|
sent_fd = *((int *) CMSG_DATA(control_message));
|
||||||
|
return sent_fd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int IosToolHandlerPrivate::checkForXmlEnd()
|
||||||
|
{
|
||||||
|
const char *xmlEnd = "</query_result>";
|
||||||
|
int lenXmlEnd = 15;
|
||||||
|
int i = 0, j = 0;
|
||||||
|
while (i < lenXmlEnd && j < iEnd) {
|
||||||
|
if (buffer.at(j) != xmlEnd[i]) {
|
||||||
|
if (i == 0) {
|
||||||
|
++j;
|
||||||
|
if (j + lenXmlEnd > iEnd)
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
++i;
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == lenXmlEnd)
|
||||||
|
return j;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosToolHandlerPrivate::processXml()
|
||||||
|
{
|
||||||
|
while (!outputParser.atEnd()) {
|
||||||
|
QXmlStreamReader::TokenType tt = outputParser.readNext();
|
||||||
|
//qDebug() << "processXml, tt=" << tt;
|
||||||
|
switch (tt) {
|
||||||
|
case QXmlStreamReader::NoToken:
|
||||||
|
// The reader has not yet read anything.
|
||||||
|
continue;
|
||||||
|
case QXmlStreamReader::Invalid:
|
||||||
|
// An error has occurred, reported in error() and errorString().
|
||||||
|
break;
|
||||||
|
case QXmlStreamReader::StartDocument:
|
||||||
|
// The reader reports the XML version number in documentVersion(), and the encoding
|
||||||
|
// as specified in the XML document in documentEncoding(). If the document is declared
|
||||||
|
// standalone, isStandaloneDocument() returns true; otherwise it returns false.
|
||||||
|
break;
|
||||||
|
case QXmlStreamReader::EndDocument:
|
||||||
|
// The reader reports the end of the document.
|
||||||
|
// state = XmlEndProcessed;
|
||||||
|
break;
|
||||||
|
case QXmlStreamReader::StartElement:
|
||||||
|
// The reader reports the start of an element with namespaceUri() and name(). Empty
|
||||||
|
// elements are also reported as StartElement, followed directly by EndElement.
|
||||||
|
// The convenience function readElementText() can be called to concatenate all content
|
||||||
|
// until the corresponding EndElement. Attributes are reported in attributes(),
|
||||||
|
// namespace declarations in namespaceDeclarations().
|
||||||
|
{
|
||||||
|
QStringRef elName = outputParser.name();
|
||||||
|
if (elName == QLatin1String("msg")) {
|
||||||
|
stack.append(ParserState(ParserState::Msg));
|
||||||
|
} else if (elName == QLatin1String("exit")) {
|
||||||
|
stack.append(ParserState(ParserState::Exit));
|
||||||
|
toolExited(outputParser.attributes().value(QLatin1String("code"))
|
||||||
|
.toString().toInt());
|
||||||
|
} else if (elName == QLatin1String("device_id")) {
|
||||||
|
stack.append(ParserState(ParserState::DeviceId));
|
||||||
|
} else if (elName == QLatin1String("key")) {
|
||||||
|
stack.append(ParserState(ParserState::Key));
|
||||||
|
} else if (elName == QLatin1String("value")) {
|
||||||
|
stack.append(ParserState(ParserState::Value));
|
||||||
|
} else if (elName == QLatin1String("query_result")) {
|
||||||
|
stack.append(ParserState(ParserState::QueryResult));
|
||||||
|
} else if (elName == QLatin1String("app_output")) {
|
||||||
|
stack.append(ParserState(ParserState::AppOutput));
|
||||||
|
} else if (elName == QLatin1String("item")) {
|
||||||
|
stack.append(ParserState(ParserState::Item));
|
||||||
|
} else if (elName == QLatin1String("status")) {
|
||||||
|
ParserState pState(ParserState::Status);
|
||||||
|
QXmlStreamAttributes attributes = outputParser.attributes();
|
||||||
|
pState.progress = attributes.value(QLatin1String("progress")).toString().toInt();
|
||||||
|
pState.maxProgress = attributes.value(QLatin1String("max_progress")).toString().toInt();
|
||||||
|
stack.append(pState);
|
||||||
|
} else if (elName == QLatin1String("app_started")) {
|
||||||
|
stack.append(ParserState(ParserState::AppStarted));
|
||||||
|
QXmlStreamAttributes attributes = outputParser.attributes();
|
||||||
|
QStringRef statusStr = attributes.value(QLatin1String("status"));
|
||||||
|
Ios::IosToolHandler::OpStatus status = Ios::IosToolHandler::Unknown;
|
||||||
|
if (statusStr.compare(QLatin1String("success"), Qt::CaseInsensitive) == 0)
|
||||||
|
status = Ios::IosToolHandler::Success;
|
||||||
|
else if (statusStr.compare(QLatin1String("failure"), Qt::CaseInsensitive) == 0)
|
||||||
|
status = Ios::IosToolHandler::Failure;
|
||||||
|
didStartApp(bundlePath, deviceId, status);
|
||||||
|
} else if (elName == QLatin1String("app_transfer")) {
|
||||||
|
stack.append(ParserState(ParserState::AppTransfer));
|
||||||
|
QXmlStreamAttributes attributes = outputParser.attributes();
|
||||||
|
QStringRef statusStr = attributes.value(QLatin1String("status"));
|
||||||
|
Ios::IosToolHandler::OpStatus status = Ios::IosToolHandler::Unknown;
|
||||||
|
if (statusStr.compare(QLatin1String("success"), Qt::CaseInsensitive) == 0)
|
||||||
|
status = Ios::IosToolHandler::Success;
|
||||||
|
else if (statusStr.compare(QLatin1String("failure"), Qt::CaseInsensitive) == 0)
|
||||||
|
status = Ios::IosToolHandler::Failure;
|
||||||
|
emit didTransferApp(bundlePath, deviceId, status);
|
||||||
|
} else if (elName == QLatin1String("device_info")) {
|
||||||
|
stack.append(ParserState(ParserState::DeviceInfo));
|
||||||
|
} else if (elName == QLatin1String("inferior_pid")) {
|
||||||
|
stack.append(ParserState(ParserState::InferiorPid));
|
||||||
|
} else {
|
||||||
|
qDebug() << "unexpected element " << elName;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QXmlStreamReader::EndElement:
|
||||||
|
// The reader reports the end of an element with namespaceUri() and name().
|
||||||
|
{
|
||||||
|
ParserState p = stack.last();
|
||||||
|
stack.removeLast();
|
||||||
|
switch (p.kind) {
|
||||||
|
case ParserState::Msg:
|
||||||
|
errorMsg(p.chars);
|
||||||
|
break;
|
||||||
|
case ParserState::DeviceId:
|
||||||
|
if (deviceId.isEmpty())
|
||||||
|
deviceId = p.chars;
|
||||||
|
else
|
||||||
|
QTC_CHECK(deviceId.compare(p.chars, Qt::CaseInsensitive) == 0);
|
||||||
|
break;
|
||||||
|
case ParserState::Key:
|
||||||
|
stack.last().key = p.chars;
|
||||||
|
break;
|
||||||
|
case ParserState::Value:
|
||||||
|
stack.last().value = p.chars;
|
||||||
|
break;
|
||||||
|
case ParserState::Status:
|
||||||
|
isTransferringApp(bundlePath, deviceId, p.progress, p.maxProgress, p.chars);
|
||||||
|
break;
|
||||||
|
case ParserState::QueryResult:
|
||||||
|
state = XmlEndProcessed;
|
||||||
|
break;
|
||||||
|
case ParserState::AppOutput:
|
||||||
|
break;
|
||||||
|
case ParserState::AppStarted:
|
||||||
|
break;
|
||||||
|
case ParserState::AppTransfer:
|
||||||
|
break;
|
||||||
|
case ParserState::Item:
|
||||||
|
stack.last().info.insert(p.key, p.value);
|
||||||
|
break;
|
||||||
|
case ParserState::DeviceInfo:
|
||||||
|
deviceInfo(deviceId, p.info);
|
||||||
|
break;
|
||||||
|
case ParserState::Exit:
|
||||||
|
break;
|
||||||
|
case ParserState::InferiorPid:
|
||||||
|
gotInferiorPid(bundlePath, deviceId, pid_t(p.chars.toInt()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QXmlStreamReader::Characters:
|
||||||
|
// The reader reports characters in text(). If the characters are all white-space,
|
||||||
|
// isWhitespace() returns true. If the characters stem from a CDATA section,
|
||||||
|
// isCDATA() returns true.
|
||||||
|
if (stack.isEmpty())
|
||||||
|
break;
|
||||||
|
if (stack.last().kind == ParserState::AppOutput)
|
||||||
|
emit appOutput(outputParser.text().toString());
|
||||||
|
else if (stack.last().collectChars())
|
||||||
|
stack.last().chars.append(outputParser.text());
|
||||||
|
break;
|
||||||
|
case QXmlStreamReader::Comment:
|
||||||
|
// The reader reports a comment in text().
|
||||||
|
break;
|
||||||
|
case QXmlStreamReader::DTD:
|
||||||
|
// The reader reports a DTD in text(), notation declarations in notationDeclarations(),
|
||||||
|
// and entity declarations in entityDeclarations(). Details of the DTD declaration are
|
||||||
|
// reported in in dtdName(), dtdPublicId(), and dtdSystemId().
|
||||||
|
break;
|
||||||
|
case QXmlStreamReader::EntityReference:
|
||||||
|
// The reader reports an entity reference that could not be resolved. The name of
|
||||||
|
// the reference is reported in name(), the replacement text in text().
|
||||||
|
break;
|
||||||
|
case QXmlStreamReader::ProcessingInstruction:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (outputParser.hasError()
|
||||||
|
&& outputParser.error() != QXmlStreamReader::PrematureEndOfDocumentError) {
|
||||||
|
qDebug() << "error parsing iosTool output:" << outputParser.errorString();
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosToolHandlerPrivate::subprocessHasData(int socket)
|
||||||
|
{
|
||||||
|
if (debugToolHandler)
|
||||||
|
qDebug() << "subprocessHasData, state:" << state;
|
||||||
|
process.notifier()->setEnabled(false);
|
||||||
|
while (true) {
|
||||||
|
switch (state) {
|
||||||
|
case NonStarted:
|
||||||
|
qDebug() << "IosToolHandler unexpected state in subprocessHasData: NonStarted";
|
||||||
|
// pass
|
||||||
|
case Starting:
|
||||||
|
case StartedInferior:
|
||||||
|
// read some data
|
||||||
|
{
|
||||||
|
if (iEnd + lookaheadSize > buffer.size()) {
|
||||||
|
memmove(buffer.data(), buffer.data() + (iEnd - lookaheadSize), lookaheadSize);
|
||||||
|
iBegin = lookaheadSize;
|
||||||
|
iEnd = iBegin;
|
||||||
|
} else {
|
||||||
|
iBegin = iEnd;
|
||||||
|
}
|
||||||
|
currentData.clear();
|
||||||
|
ssize_t reallyRead = recv(socket, buffer.data() + iBegin, lookaheadSize, 0);
|
||||||
|
if (reallyRead == 0) { // eof
|
||||||
|
stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (reallyRead == -1) {
|
||||||
|
if (errno == EAGAIN) { // read all so far
|
||||||
|
if (debugToolHandler)
|
||||||
|
qDebug() << "read all for now";
|
||||||
|
process.notifier()->setEnabled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
qDebug() << "IosToolHandlerPrivate::subprocessHasData " << qt_error_string(errno);
|
||||||
|
stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
iEnd = iBegin + reallyRead;
|
||||||
|
int xmlEnd = checkForXmlEnd();
|
||||||
|
if (xmlEnd != -1) {
|
||||||
|
state = XmlEndSeenNotProcessed;
|
||||||
|
currentData = buffer.mid(iBegin, xmlEnd - iBegin);
|
||||||
|
} else {
|
||||||
|
currentData = buffer.mid(iBegin, reallyRead);
|
||||||
|
}
|
||||||
|
if (debugToolHandler)
|
||||||
|
qDebug() << "subprocessHasData read " << currentData;
|
||||||
|
outputParser.addData(currentData);
|
||||||
|
processXml();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XmlEndSeenNotProcessed:
|
||||||
|
qDebug() << "IosToolHandler unexpected state in subprocessHasData: XmlEndSeenNotProcessed";
|
||||||
|
// pass
|
||||||
|
case XmlEndProcessed:
|
||||||
|
{
|
||||||
|
// check for sent fd
|
||||||
|
if (!expectsFileDescriptor()) {
|
||||||
|
stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int lenToRead = lookaheadSize;
|
||||||
|
int spacerStart = iBegin + currentData.size();
|
||||||
|
while (spacerStart < iEnd && buffer.at(spacerStart) != 'n')
|
||||||
|
++spacerStart;
|
||||||
|
if (iEnd - (iBegin + currentData.size()) < lenToRead) {
|
||||||
|
int lastXmlSize = currentData.size();
|
||||||
|
if (iBegin > 0) {
|
||||||
|
memmove(buffer.data(), buffer.data() + iBegin, iEnd - iBegin);
|
||||||
|
iEnd -= iBegin;
|
||||||
|
iBegin = 0;
|
||||||
|
spacerStart -= iBegin;
|
||||||
|
currentData = buffer.mid(0, lastXmlSize); // remove this??
|
||||||
|
}
|
||||||
|
ssize_t toRead = lookaheadSize - (iEnd - spacerStart);
|
||||||
|
ssize_t reallyRead = recv(socket, buffer.data() + iBegin, toRead, 0);
|
||||||
|
if (reallyRead == 0) { // eof
|
||||||
|
stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (reallyRead == -1) {
|
||||||
|
if (errno == EAGAIN) { // read all so far
|
||||||
|
if (debugToolHandler)
|
||||||
|
qDebug() << "read all for now2";
|
||||||
|
process.notifier()->setEnabled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
if (debugToolHandler)
|
||||||
|
qDebug() << "IosToolHandlerPrivate::subprocessHasData " << qt_error_string(errno);
|
||||||
|
stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
iEnd += reallyRead;
|
||||||
|
if (reallyRead != toRead)
|
||||||
|
continue;
|
||||||
|
if (spacerStart < iEnd && buffer.at(spacerStart) != 'n') {
|
||||||
|
++spacerStart;
|
||||||
|
while (spacerStart < iEnd && buffer.at(spacerStart) != 'n')
|
||||||
|
++spacerStart;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gdbSocket = recv_fd(socket);
|
||||||
|
gotGdbserverSocket(bundlePath, deviceId, gdbSocket);
|
||||||
|
stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case Stopped:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
process.notifier()->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// IosDeviceToolHandlerPrivate
|
||||||
|
|
||||||
|
IosDeviceToolHandlerPrivate::IosDeviceToolHandlerPrivate(IosToolHandler::DeviceType devType,
|
||||||
|
IosToolHandler *q)
|
||||||
|
: IosToolHandlerPrivate(devType, q)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void IosDeviceToolHandlerPrivate::requestTransferApp(const QString &bundlePath,
|
||||||
|
const QString &deviceId, int timeout)
|
||||||
|
{
|
||||||
|
this->bundlePath = bundlePath;
|
||||||
|
this->deviceId = deviceId;
|
||||||
|
QStringList args;
|
||||||
|
args << QLatin1String("-device-id") << deviceId << QLatin1String("-bundle")
|
||||||
|
<< bundlePath << QLatin1String("-timeout") << QString::number(timeout)
|
||||||
|
<< QLatin1String("-deploy");
|
||||||
|
start(IosToolHandler::iosDeviceToolPath(), args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosDeviceToolHandlerPrivate::requestRunApp(const QString &bundlePath,
|
||||||
|
const QStringList &extraArgs,
|
||||||
|
IosToolHandler::RunKind runType,
|
||||||
|
const QString &deviceId, int timeout)
|
||||||
|
{
|
||||||
|
this->bundlePath = bundlePath;
|
||||||
|
this->deviceId = deviceId;
|
||||||
|
this->runKind = runType;
|
||||||
|
QStringList args;
|
||||||
|
args << QLatin1String("-device-id") << deviceId << QLatin1String("-bundle")
|
||||||
|
<< bundlePath << QLatin1String("-timeout") << QString::number(timeout);
|
||||||
|
//args << QLatin1String("--deploy"); // to remove when the separate deploy step is functional
|
||||||
|
switch (runType) {
|
||||||
|
case IosToolHandler::NormalRun:
|
||||||
|
args << QLatin1String("-run");
|
||||||
|
break;
|
||||||
|
case IosToolHandler::DebugRun:
|
||||||
|
args << QLatin1String("-debug");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
args << QLatin1String("-extra-args") << extraArgs;
|
||||||
|
op = OpAppRun;
|
||||||
|
start(IosToolHandler::iosDeviceToolPath(), args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosDeviceToolHandlerPrivate::requestDeviceInfo(const QString &deviceId, int timeout)
|
||||||
|
{
|
||||||
|
this->deviceId = deviceId;
|
||||||
|
QStringList args;
|
||||||
|
args << QLatin1String("-device-id") << deviceId << QLatin1String("-device-info")
|
||||||
|
<< QLatin1String("-timeout") << QString::number(timeout);
|
||||||
|
op = OpDeviceInfo;
|
||||||
|
start(IosToolHandler::iosDeviceToolPath(), args);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosDeviceToolHandlerPrivate::expectsFileDescriptor()
|
||||||
|
{
|
||||||
|
return op == OpAppRun && runKind == IosToolHandler::DebugRun;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IosSimulatorToolHandlerPrivate
|
||||||
|
|
||||||
|
IosSimulatorToolHandlerPrivate::IosSimulatorToolHandlerPrivate(IosToolHandler::DeviceType devType,
|
||||||
|
IosToolHandler *q)
|
||||||
|
: IosToolHandlerPrivate(devType, q)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void IosSimulatorToolHandlerPrivate::requestTransferApp(const QString &bundlePath,
|
||||||
|
const QString &deviceId, int timeout)
|
||||||
|
{
|
||||||
|
Q_UNUSED(timeout);
|
||||||
|
this->bundlePath = bundlePath;
|
||||||
|
this->deviceId = deviceId;
|
||||||
|
emit didTransferApp(bundlePath, deviceId, IosToolHandler::Success);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosSimulatorToolHandlerPrivate::requestRunApp(const QString &bundlePath,
|
||||||
|
const QStringList &extraArgs,
|
||||||
|
IosToolHandler::RunKind runType,
|
||||||
|
const QString &deviceId, int timeout)
|
||||||
|
{
|
||||||
|
Q_UNUSED(timeout);
|
||||||
|
this->bundlePath = bundlePath;
|
||||||
|
this->deviceId = deviceId;
|
||||||
|
this->runKind = runType;
|
||||||
|
QStringList args;
|
||||||
|
|
||||||
|
args << QLatin1String("launch") << bundlePath;
|
||||||
|
Utils::FileName devPath = IosConfigurations::instance().config().developerPath;
|
||||||
|
if (!devPath.isEmpty())
|
||||||
|
args << QLatin1String("--developer-path") << devPath.toString();
|
||||||
|
addDeviceArguments(args);
|
||||||
|
switch (runType) {
|
||||||
|
case IosToolHandler::NormalRun:
|
||||||
|
break;
|
||||||
|
case IosToolHandler::DebugRun:
|
||||||
|
args << QLatin1String("--wait-for-debugger");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
args << QLatin1String("--args") << extraArgs;
|
||||||
|
op = OpAppRun;
|
||||||
|
start(IosToolHandler::iosSimulatorToolPath(), args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosSimulatorToolHandlerPrivate::requestDeviceInfo(const QString &deviceId, int timeout)
|
||||||
|
{
|
||||||
|
Q_UNUSED(timeout);
|
||||||
|
this->deviceId = deviceId;
|
||||||
|
QStringList args;
|
||||||
|
args << QLatin1String("showsdks");
|
||||||
|
op = OpDeviceInfo;
|
||||||
|
start(IosToolHandler::iosSimulatorToolPath(), args);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosSimulatorToolHandlerPrivate::expectsFileDescriptor()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosSimulatorToolHandlerPrivate::addDeviceArguments(QStringList &args) const
|
||||||
|
{
|
||||||
|
switch (devType) {
|
||||||
|
case IosToolHandler::IosDeviceType:
|
||||||
|
qDebug() << "IosSimulatorToolHandlerPrivate has device type IosDeviceType";
|
||||||
|
break;
|
||||||
|
case IosToolHandler::IosSimulatedIphoneType:
|
||||||
|
args << QLatin1String("--family") << QLatin1String("iphone");
|
||||||
|
break;
|
||||||
|
case IosToolHandler::IosSimulatedIpadType:
|
||||||
|
args << QLatin1String("--family") << QLatin1String("ipad");
|
||||||
|
break;
|
||||||
|
case IosToolHandler::IosSimulatedIphoneRetina4InchType:
|
||||||
|
args << QLatin1String("--family") << QLatin1String("iphone")
|
||||||
|
<< QLatin1String("--retina") << QLatin1String("--tall");
|
||||||
|
break;
|
||||||
|
case IosToolHandler::IosSimulatedIphoneRetina3_5InchType:
|
||||||
|
args << QLatin1String("--family") << QLatin1String("iphone") << QLatin1String("--retina");
|
||||||
|
break;
|
||||||
|
case IosToolHandler::IosSimulatedIpadRetinaType:
|
||||||
|
args << QLatin1String("--family") << QLatin1String("ipad") << QLatin1String("--retina");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
|
||||||
|
QString IosToolHandler::iosDeviceToolPath()
|
||||||
|
{
|
||||||
|
QString res = QCoreApplication::applicationDirPath() + QLatin1String("/iosTool");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IosToolHandler::iosSimulatorToolPath()
|
||||||
|
{
|
||||||
|
QString res = QCoreApplication::applicationDirPath() + QLatin1String("/iossim");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
IosToolHandler::IosToolHandler(DeviceType devType, QObject *parent) :
|
||||||
|
QObject(parent)
|
||||||
|
{
|
||||||
|
if (devType == IosDeviceType)
|
||||||
|
d = new Internal::IosDeviceToolHandlerPrivate(devType, this);
|
||||||
|
else
|
||||||
|
d = new Internal::IosSimulatorToolHandlerPrivate(devType, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosToolHandler::stop()
|
||||||
|
{
|
||||||
|
d->stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosToolHandler::requestTransferApp(const QString &bundlePath, const QString &deviceId,
|
||||||
|
int timeout)
|
||||||
|
{
|
||||||
|
d->requestTransferApp(bundlePath, deviceId, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosToolHandler::requestRunApp(const QString &bundlePath, const QStringList &extraArgs,
|
||||||
|
RunKind runType, const QString &deviceId, int timeout)
|
||||||
|
{
|
||||||
|
d->requestRunApp(bundlePath, extraArgs, runType, deviceId, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosToolHandler::requestDeviceInfo(const QString &deviceId, int timeout)
|
||||||
|
{
|
||||||
|
d->requestDeviceInfo(deviceId, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IosToolHandler::isRunning()
|
||||||
|
{
|
||||||
|
return d->isRunning();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosToolHandler::subprocessError(QProcess::ProcessError error)
|
||||||
|
{
|
||||||
|
d->subprocessError(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosToolHandler::subprocessFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
||||||
|
{
|
||||||
|
d->subprocessFinished(exitCode, exitStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosToolHandler::subprocessHasData(int socket)
|
||||||
|
{
|
||||||
|
d->subprocessHasData(socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#include "iostoolhandler.moc"
|
107
src/plugins/ios/iostoolhandler.h
Normal file
107
src/plugins/ios/iostoolhandler.h
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef IOSTOOLHANDLER_H
|
||||||
|
#define IOSTOOLHANDLER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QProcess>
|
||||||
|
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
class IosToolHandlerPrivate;
|
||||||
|
}
|
||||||
|
|
||||||
|
class IosToolHandler : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
typedef QMap<QString,QString> Dict;
|
||||||
|
enum RunKind {
|
||||||
|
NormalRun,
|
||||||
|
DebugRun
|
||||||
|
};
|
||||||
|
enum OpStatus {
|
||||||
|
Success = 0,
|
||||||
|
Unknown = 1,
|
||||||
|
Failure = 2
|
||||||
|
};
|
||||||
|
enum DeviceType {
|
||||||
|
IosDeviceType,
|
||||||
|
IosSimulatedIphoneType,
|
||||||
|
IosSimulatedIpadType,
|
||||||
|
IosSimulatedIphoneRetina4InchType,
|
||||||
|
IosSimulatedIphoneRetina3_5InchType,
|
||||||
|
IosSimulatedIpadRetinaType
|
||||||
|
};
|
||||||
|
|
||||||
|
static QString iosDeviceToolPath();
|
||||||
|
static QString iosSimulatorToolPath();
|
||||||
|
explicit IosToolHandler(DeviceType = IosDeviceType, QObject *parent = 0);
|
||||||
|
void requestTransferApp(const QString &bundlePath, const QString &deviceId, int timeout = 1000);
|
||||||
|
void requestRunApp(const QString &bundlePath, const QStringList &extraArgs, RunKind runType,
|
||||||
|
const QString &deviceId, int timeout = 1000);
|
||||||
|
void requestDeviceInfo(const QString &deviceId, int timeout = 1000);
|
||||||
|
bool isRunning();
|
||||||
|
signals:
|
||||||
|
void isTransferringApp(Ios::IosToolHandler *handler, const QString &bundlePath,
|
||||||
|
const QString &deviceId, int progress, int maxProgress,
|
||||||
|
const QString &info);
|
||||||
|
void didTransferApp(Ios::IosToolHandler *handler, const QString &bundlePath,
|
||||||
|
const QString &deviceId, Ios::IosToolHandler::OpStatus status);
|
||||||
|
void didStartApp(Ios::IosToolHandler *handler, const QString &bundlePath,
|
||||||
|
const QString &deviceId, Ios::IosToolHandler::OpStatus status);
|
||||||
|
void gotGdbserverSocket(Ios::IosToolHandler *handler, const QString &bundlePath,
|
||||||
|
const QString &deviceId, int gdbFd);
|
||||||
|
void gotInferiorPid(Ios::IosToolHandler *handler, const QString &bundlePath,
|
||||||
|
const QString &deviceId, pid_t pid);
|
||||||
|
void deviceInfo(Ios::IosToolHandler *handler, const QString &deviceId,
|
||||||
|
const Ios::IosToolHandler::Dict &info);
|
||||||
|
void appOutput(Ios::IosToolHandler *handler, const QString &output);
|
||||||
|
void errorMsg(Ios::IosToolHandler *handler, const QString &msg);
|
||||||
|
void toolExited(Ios::IosToolHandler *handler, int code);
|
||||||
|
void finished(Ios::IosToolHandler *handler);
|
||||||
|
public slots:
|
||||||
|
void stop();
|
||||||
|
private slots:
|
||||||
|
void subprocessError(QProcess::ProcessError error);
|
||||||
|
void subprocessFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||||
|
void subprocessHasData(int socket);
|
||||||
|
private:
|
||||||
|
friend class Ios::Internal::IosToolHandlerPrivate;
|
||||||
|
Ios::Internal::IosToolHandlerPrivate *d;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#endif // IOSTOOLHANDLER_H
|
@@ -50,6 +50,10 @@ SUBDIRS = \
|
|||||||
clearcase \
|
clearcase \
|
||||||
baremetal
|
baremetal
|
||||||
|
|
||||||
|
macx {
|
||||||
|
SUBDIRS += ios
|
||||||
|
}
|
||||||
|
|
||||||
isEmpty(QBS_INSTALL_DIR): QBS_INSTALL_DIR = $$(QBS_INSTALL_DIR)
|
isEmpty(QBS_INSTALL_DIR): QBS_INSTALL_DIR = $$(QBS_INSTALL_DIR)
|
||||||
exists(../shared/qbs/qbs.pro)|!isEmpty(QBS_INSTALL_DIR): \
|
exists(../shared/qbs/qbs.pro)|!isEmpty(QBS_INSTALL_DIR): \
|
||||||
SUBDIRS += \
|
SUBDIRS += \
|
||||||
|
@@ -33,6 +33,7 @@ Project {
|
|||||||
"helloworld/helloworld.qbs",
|
"helloworld/helloworld.qbs",
|
||||||
"help/help.qbs",
|
"help/help.qbs",
|
||||||
"imageviewer/imageviewer.qbs",
|
"imageviewer/imageviewer.qbs",
|
||||||
|
"ios/ios.qbs",
|
||||||
"locator/locator.qbs",
|
"locator/locator.qbs",
|
||||||
"macros/macros.qbs",
|
"macros/macros.qbs",
|
||||||
"madde/madde.qbs",
|
"madde/madde.qbs",
|
||||||
|
@@ -148,6 +148,7 @@ private:
|
|||||||
class PROJECTEXPLORER_EXPORT ClangToolChain : public GccToolChain
|
class PROJECTEXPLORER_EXPORT ClangToolChain : public GccToolChain
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
explicit ClangToolChain(Detection d);
|
||||||
QString type() const;
|
QString type() const;
|
||||||
QString typeDisplayName() const;
|
QString typeDisplayName() const;
|
||||||
QString makeCommand(const Utils::Environment &environment) const;
|
QString makeCommand(const Utils::Environment &environment) const;
|
||||||
@@ -166,8 +167,6 @@ protected:
|
|||||||
virtual CompilerFlags defaultCompilerFlags() const;
|
virtual CompilerFlags defaultCompilerFlags() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit ClangToolChain(Detection d);
|
|
||||||
|
|
||||||
friend class Internal::ClangToolChainFactory;
|
friend class Internal::ClangToolChainFactory;
|
||||||
friend class ToolChainFactory;
|
friend class ToolChainFactory;
|
||||||
};
|
};
|
||||||
|
@@ -69,6 +69,7 @@ const char DESKTOP_PLATFORM[] = "Desktop";
|
|||||||
const char EMBEDDED_LINUX_PLATFORM[] = "Embedded Linux";
|
const char EMBEDDED_LINUX_PLATFORM[] = "Embedded Linux";
|
||||||
const char WINDOWS_CE_PLATFORM[] = "Windows CE";
|
const char WINDOWS_CE_PLATFORM[] = "Windows CE";
|
||||||
const char ANDROID_PLATFORM[] = "Android";
|
const char ANDROID_PLATFORM[] = "Android";
|
||||||
|
const char IOS_PLATFORM[] = "Ios";
|
||||||
|
|
||||||
const char MEEGO_HARMATTAN_PLATFORM_TR[] = QT_TRANSLATE_NOOP("QtSupport", "MeeGo/Harmattan");
|
const char MEEGO_HARMATTAN_PLATFORM_TR[] = QT_TRANSLATE_NOOP("QtSupport", "MeeGo/Harmattan");
|
||||||
const char MAEMO_FREMANTLE_PLATFORM_TR[] = QT_TRANSLATE_NOOP("QtSupport", "Maemo/Fremantle");
|
const char MAEMO_FREMANTLE_PLATFORM_TR[] = QT_TRANSLATE_NOOP("QtSupport", "Maemo/Fremantle");
|
||||||
@@ -76,6 +77,7 @@ const char DESKTOP_PLATFORM_TR[] = QT_TRANSLATE_NOOP("QtSupport", "Desktop");
|
|||||||
const char EMBEDDED_LINUX_PLATFORM_TR[] = QT_TRANSLATE_NOOP("QtSupport", "Embedded Linux");
|
const char EMBEDDED_LINUX_PLATFORM_TR[] = QT_TRANSLATE_NOOP("QtSupport", "Embedded Linux");
|
||||||
const char WINDOWS_CE_PLATFORM_TR[] = QT_TRANSLATE_NOOP("QtSupport", "Windows CE");
|
const char WINDOWS_CE_PLATFORM_TR[] = QT_TRANSLATE_NOOP("QtSupport", "Windows CE");
|
||||||
const char ANDROID_PLATFORM_TR[] = QT_TRANSLATE_NOOP("QtSupport", "Android");
|
const char ANDROID_PLATFORM_TR[] = QT_TRANSLATE_NOOP("QtSupport", "Android");
|
||||||
|
const char IOS_PLATFORM_TR[] = QT_TRANSLATE_NOOP("QtSupport", "Ios");
|
||||||
|
|
||||||
// QML wizard icon
|
// QML wizard icon
|
||||||
// both the qt4projectmanager and the qmlprojectmanager do have qt quick wizards
|
// both the qt4projectmanager and the qmlprojectmanager do have qt quick wizards
|
||||||
|
5
src/tools/3rdparty/3rdparty.pro
vendored
Normal file
5
src/tools/3rdparty/3rdparty.pro
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
TEMPLATE = subdirs
|
||||||
|
|
||||||
|
mac {
|
||||||
|
SUBDIRS += iossim
|
||||||
|
}
|
31
src/tools/3rdparty/iossim/IOSSIM_LICENSE
vendored
Normal file
31
src/tools/3rdparty/iossim/IOSSIM_LICENSE
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
Author: Landon Fuller <landonf@plausiblelabs.com>
|
||||||
|
Copyright (c) 2008-2011 Plausible Labs Cooperative, Inc.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person
|
||||||
|
obtaining a copy of this software and associated documentation
|
||||||
|
files (the "Software"), to deal in the Software without
|
||||||
|
restriction, including without limitation the rights to use,
|
||||||
|
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following
|
||||||
|
conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Modifications made by the following entities are licensed as above:
|
||||||
|
- Jeff Haynie, Appcelerator, Inc.
|
||||||
|
- https://github.com/hborders
|
||||||
|
- http://pivotallabs.com/users/scoward/blog
|
||||||
|
- Eloy Duran, Fingertips <eloy@fngtps.com>
|
||||||
|
- Fawzi Mohamed, digia <fawzi.mohamed@digia.com>
|
16
src/tools/3rdparty/iossim/Info.plist
vendored
Normal file
16
src/tools/3rdparty/iossim/Info.plist
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>@TYPEINFO@</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>@EXECUTABLE@</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>org.qt-project.qt-creator.iosTool</string>
|
||||||
|
<key>LSUIElement</key>
|
||||||
|
<string>1</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
53
src/tools/3rdparty/iossim/iossim.pro
vendored
Normal file
53
src/tools/3rdparty/iossim/iossim.pro
vendored
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
CONFIG += console
|
||||||
|
|
||||||
|
CONFIG -= app_bundle
|
||||||
|
|
||||||
|
include(../../../../qtcreator.pri)
|
||||||
|
|
||||||
|
# Prevent from popping up in the dock when launched.
|
||||||
|
# We embed the Info.plist file, so the application doesn't need to
|
||||||
|
# be a bundle.
|
||||||
|
QMAKE_LFLAGS += -sectcreate __TEXT __info_plist $$shell_quote($$PWD/Info.plist) \
|
||||||
|
-fobjc-link-runtime
|
||||||
|
|
||||||
|
LIBS += \
|
||||||
|
-framework Foundation \
|
||||||
|
-framework CoreServices \
|
||||||
|
-framework ApplicationServices \
|
||||||
|
-framework CoreFoundation \
|
||||||
|
-F/System/Library/PrivateFrameworks \
|
||||||
|
-framework IOKit
|
||||||
|
|
||||||
|
iPhoneSimulatorRemoteClientDirectLinking {
|
||||||
|
LIBS += \
|
||||||
|
-F/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks \
|
||||||
|
-F/Applications/Xcode.app/Contents/OtherFrameworks
|
||||||
|
|
||||||
|
QMAKE_LFLAGS += -Wl,-rpath,/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks \
|
||||||
|
-Wl,-rpath,/Applications/Xcode.app/Contents/OtherFrameworks \
|
||||||
|
LIBS += \
|
||||||
|
-framework iPhoneSimulatorRemoteClient
|
||||||
|
QMAKE_RPATHDIR += /Applications/Xcode5-DP5.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks \
|
||||||
|
/Applications/Xcode.app/Contents/OtherFrameworks
|
||||||
|
/System/Library/PrivateFrameworks \
|
||||||
|
}
|
||||||
|
|
||||||
|
TEMPLATE = app
|
||||||
|
|
||||||
|
DESTDIR = $$IDE_BIN_PATH
|
||||||
|
include(../../../rpath.pri)
|
||||||
|
|
||||||
|
OBJECTIVE_SOURCES += \
|
||||||
|
main.mm \
|
||||||
|
nsprintf.m \
|
||||||
|
nsstringexpandPath.m \
|
||||||
|
iphonesimulator.m
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
iphonesimulator.h \
|
||||||
|
nsprintf.h \
|
||||||
|
nsstringexpandpath.h \
|
||||||
|
version.h \
|
||||||
|
iphonesimulatorremoteclient/iphonesimulatorremoteclient.h
|
||||||
|
|
||||||
|
OTHER_FILES = LICENSE
|
27
src/tools/3rdparty/iossim/iossim.qbs
vendored
Normal file
27
src/tools/3rdparty/iossim/iossim.qbs
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import qbs.base 1.0
|
||||||
|
import "../../QtcTool.qbs" as QtcTool
|
||||||
|
|
||||||
|
|
||||||
|
QtcTool {
|
||||||
|
name: "iossim"
|
||||||
|
condition: qbs.targetOS.contains("osx")
|
||||||
|
|
||||||
|
Depends { name: "Qt"; submodules: ["widgets"] }
|
||||||
|
Depends { name: "app_version_header" }
|
||||||
|
|
||||||
|
files: [
|
||||||
|
"main.mm",
|
||||||
|
"nsprintf.m",
|
||||||
|
"nsstringexpandPath.m",
|
||||||
|
"iphonesimulator.m",
|
||||||
|
"iphonesimulator.h",
|
||||||
|
"nsprintf.h",
|
||||||
|
"nsstringexpandpath.h",
|
||||||
|
"version.h",
|
||||||
|
"iphonesimulatorremoteclient/iphonesimulatorremoteclient.h"
|
||||||
|
]
|
||||||
|
cpp.linkerFlags: base.concat(["-sectcreate", "__TEXT", "__info_plist", path + "/Info.plist",
|
||||||
|
"-fobjc-link-runtime"])
|
||||||
|
cpp.frameworks: base.concat(["Foundation", "CoreServices", "ApplicationServices", "IOKit"])
|
||||||
|
cpp.frameworkPaths: base.concat("/System/Library/PrivateFrameworks")
|
||||||
|
}
|
40
src/tools/3rdparty/iossim/iphonesimulator.h
vendored
Normal file
40
src/tools/3rdparty/iossim/iphonesimulator.h
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/* Author: Landon Fuller <landonf@plausiblelabs.com>
|
||||||
|
* Copyright (c) 2008-2011 Plausible Labs Cooperative, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the IOSSIM_LICENSE file in this directory for the license on the source code in this file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "iphonesimulatorremoteclient/iphonesimulatorremoteclient.h"
|
||||||
|
#import "version.h"
|
||||||
|
|
||||||
|
@interface iPhoneSimulator : NSObject <DTiPhoneSimulatorSessionDelegate> {
|
||||||
|
@private
|
||||||
|
DTiPhoneSimulatorSystemRoot *sdkRoot;
|
||||||
|
NSFileHandle *stdoutFileHandle;
|
||||||
|
NSFileHandle *stderrFileHandle;
|
||||||
|
DTiPhoneSimulatorSession *session;
|
||||||
|
NSTimer *pidCheckingTimer;
|
||||||
|
BOOL startOnly;
|
||||||
|
BOOL exitOnStartup;
|
||||||
|
BOOL shouldWaitDebugger;
|
||||||
|
BOOL shouldStartDebugger;
|
||||||
|
BOOL useGDB;
|
||||||
|
BOOL verbose;
|
||||||
|
BOOL alreadyPrintedData;
|
||||||
|
BOOL retinaDevice;
|
||||||
|
BOOL tallDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)init;
|
||||||
|
- (void)dealloc;
|
||||||
|
- (void)runWithArgc:(int)argc argv:(char **)argv;
|
||||||
|
|
||||||
|
- (void)createStdioFIFO:(NSFileHandle **)fileHandle ofType:(NSString *)type atPath:(NSString **)path;
|
||||||
|
- (void)removeStdioFIFO:(NSFileHandle *)fileHandle atPath:(NSString *)path;
|
||||||
|
- (void)stop;
|
||||||
|
- (void)checkPid:(NSTimer *)timer;
|
||||||
|
- (void)doExit:(int)errorCode;
|
||||||
|
|
||||||
|
@end
|
544
src/tools/3rdparty/iossim/iphonesimulator.m
vendored
Normal file
544
src/tools/3rdparty/iossim/iphonesimulator.m
vendored
Normal file
@@ -0,0 +1,544 @@
|
|||||||
|
/* Author: Landon Fuller <landonf@plausiblelabs.com>
|
||||||
|
* Copyright (c) 2008-2011 Plausible Labs Cooperative, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the IOSSIM_LICENSE file in this directory for the license on the source code in this file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "iphonesimulator.h"
|
||||||
|
#import "nsstringexpandpath.h"
|
||||||
|
#import "nsprintf.h"
|
||||||
|
#import <sys/types.h>
|
||||||
|
#import <sys/stat.h>
|
||||||
|
#import <objc/runtime.h>
|
||||||
|
|
||||||
|
NSString *simulatorPrefrencesName = @"com.apple.iphonesimulator";
|
||||||
|
NSString *deviceProperty = @"SimulateDevice";
|
||||||
|
NSString *deviceIphoneRetina3_5Inch = @"iPhone (Retina 3.5-inch)";
|
||||||
|
NSString *deviceIphoneRetina4_0Inch = @"iPhone (Retina 4-inch)";
|
||||||
|
NSString *deviceIphone = @"iPhone";
|
||||||
|
NSString *deviceIpad = @"iPad";
|
||||||
|
NSString *deviceIpadRetina = @"iPad (Retina)";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple iPhoneSimulatorRemoteClient framework.
|
||||||
|
*/
|
||||||
|
@implementation iPhoneSimulator
|
||||||
|
|
||||||
|
- (id)init {
|
||||||
|
self = [super init];
|
||||||
|
session = nil;
|
||||||
|
pidCheckingTimer = nil;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc {
|
||||||
|
[session release];
|
||||||
|
[pidCheckingTimer release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)doExit:(int)errorCode {
|
||||||
|
nsprintf(@"<exit code=\"%d\"/>", errorCode);
|
||||||
|
nsprintf(@"</query_result>");
|
||||||
|
fflush(stdout);
|
||||||
|
fflush(stderr);
|
||||||
|
exit(errorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) printUsage {
|
||||||
|
fprintf(stdout, "<msg>Usage: iossim <command> <options> [--args ...]\n");
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
fprintf(stdout, "Commands:\n");
|
||||||
|
fprintf(stdout, " showsdks List the available iOS SDK versions\n");
|
||||||
|
fprintf(stdout, " launch <application path> Launch the application at the specified path on the iOS Simulator\n");
|
||||||
|
fprintf(stdout, " start Launch iOS Simulator without an app\n");
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
fprintf(stdout, "Options:\n");
|
||||||
|
fprintf(stdout, " --version Print the version of ios-sim\n");
|
||||||
|
fprintf(stdout, " --developer-path <developerDir> path to the developer directory (in Xcode)");
|
||||||
|
fprintf(stdout, " --help Show this help text\n");
|
||||||
|
fprintf(stdout, " --verbose Set the output level to verbose\n");
|
||||||
|
fprintf(stdout, " --exit Exit after startup\n");
|
||||||
|
fprintf(stdout, " --wait-for-debugger Wait for debugger to attach\n");
|
||||||
|
fprintf(stdout, " --debug Attach LLDB to the application on startup\n");
|
||||||
|
fprintf(stdout, " --use-gdb Use GDB instead of LLDB. (Requires --debug)\n");
|
||||||
|
fprintf(stdout, " --sdk <sdkversion> The iOS SDK version to run the application on (defaults to the latest)\n");
|
||||||
|
fprintf(stdout, " --family <device family> The device type that should be simulated (defaults to `iphone')\n");
|
||||||
|
fprintf(stdout, " --retina Start a retina device\n");
|
||||||
|
fprintf(stdout, " --tall In combination with --retina flag, start the tall version of the retina device (e.g. iPhone 5 (4-inch))\n");
|
||||||
|
fprintf(stdout, " --uuid <uuid> A UUID identifying the session (is that correct?)\n");
|
||||||
|
fprintf(stdout, " --env <environment file path> A plist file containing environment key-value pairs that should be set\n");
|
||||||
|
fprintf(stdout, " --setenv NAME=VALUE Set an environment variable\n");
|
||||||
|
fprintf(stdout, " --stdout <stdout file path> The path where stdout of the simulator will be redirected to (defaults to stdout of ios-sim)\n");
|
||||||
|
fprintf(stdout, " --stderr <stderr file path> The path where stderr of the simulator will be redirected to (defaults to stderr of ios-sim)\n");
|
||||||
|
fprintf(stdout, " --timeout <seconds> The timeout time to wait for a response from the Simulator. Default value: 30 seconds\n");
|
||||||
|
fprintf(stdout, " --args <...> All following arguments will be passed on to the application</msg>\n");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (int) showSDKs {
|
||||||
|
id tClass = objc_getClass("DTiPhoneSimulatorSystemRoot");
|
||||||
|
if (tClass == nil) {
|
||||||
|
nsprintf(@"<msg>DTiPhoneSimulatorSystemRoot class is nil.</msg>");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
NSArray *roots = [tClass knownRoots];
|
||||||
|
|
||||||
|
nsprintf(@"<device_info>");
|
||||||
|
for (NSUInteger i = 0; i < [roots count]; ++i) {
|
||||||
|
DTiPhoneSimulatorSystemRoot *root = [roots objectAtIndex:i];
|
||||||
|
nsprintf(@"<item><key>sdk%d_name</key><value>%@</value></item>", i, [root sdkDisplayName]);
|
||||||
|
nsprintf(@"<item><key>sdk%d_version</key><value>%@</value></item>", i, [root sdkVersion]);
|
||||||
|
nsprintf(@"<item><key>sdk%d_sysroot</key><value>%@</value></item>", i, [root sdkRootPath]);
|
||||||
|
}
|
||||||
|
nsprintf(@"</device_info>");
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (void)session:(DTiPhoneSimulatorSession *)mySession didEndWithError:(NSError *)error {
|
||||||
|
if (verbose) {
|
||||||
|
nsprintf(@"<msg>Session did end with error %@</msg>", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stderrFileHandle != nil) {
|
||||||
|
NSString *stderrPath = [[mySession sessionConfig] simulatedApplicationStdErrPath];
|
||||||
|
[self removeStdioFIFO:stderrFileHandle atPath:stderrPath];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stdoutFileHandle != nil) {
|
||||||
|
NSString *stdoutPath = [[mySession sessionConfig] simulatedApplicationStdOutPath];
|
||||||
|
[self removeStdioFIFO:stdoutFileHandle atPath:stdoutPath];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error != nil)
|
||||||
|
[self doExit:EXIT_FAILURE];
|
||||||
|
else
|
||||||
|
[self doExit:EXIT_SUCCESS];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (void)session:(DTiPhoneSimulatorSession *)mySession didStart:(BOOL)started withError:(NSError *)error {
|
||||||
|
if (startOnly && mySession) {
|
||||||
|
nsprintf(@"<msg>Simulator started (no session)</msg>");
|
||||||
|
[self doExit:EXIT_SUCCESS];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (started) {
|
||||||
|
if (shouldStartDebugger) {
|
||||||
|
char*args[4] = { NULL, NULL, (char*)[[[mySession simulatedApplicationPID] description] UTF8String], NULL };
|
||||||
|
if (useGDB) {
|
||||||
|
args[0] = "gdb";
|
||||||
|
args[1] = "program";
|
||||||
|
} else {
|
||||||
|
args[0] = "lldb";
|
||||||
|
args[1] = "--attach-pid";
|
||||||
|
}
|
||||||
|
// The parent process must live on to process the stdout/stderr fifos,
|
||||||
|
// so start the debugger as a child process.
|
||||||
|
pid_t child_pid = fork();
|
||||||
|
if (child_pid == 0) {
|
||||||
|
execvp(args[0], args);
|
||||||
|
} else if (child_pid < 0) {
|
||||||
|
nsprintf(@"<msg>Could not start debugger process: %@</msg>", errno);
|
||||||
|
[self doExit:EXIT_FAILURE];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (verbose) {
|
||||||
|
nsprintf(@"<msg>Session started</msg>");
|
||||||
|
}
|
||||||
|
if (exitOnStartup) {
|
||||||
|
[self doExit:EXIT_SUCCESS];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
nsprintf(@"<inferior_pid>%@</inferior_pid>", [session simulatedApplicationPID]);
|
||||||
|
pidCheckingTimer = [[NSTimer scheduledTimerWithTimeInterval:5.0 target:self
|
||||||
|
selector:@selector(checkPid:) userInfo:nil repeats: TRUE] retain];
|
||||||
|
} else {
|
||||||
|
nsprintf(@"<msg>Session could not be started: %@</msg>", error);
|
||||||
|
[self doExit:EXIT_FAILURE];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)stop {
|
||||||
|
if (session)
|
||||||
|
[session requestEndWithTimeout: 0.1];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)checkPid:(NSTimer *)timer {
|
||||||
|
(void)timer;
|
||||||
|
if (session && [[session simulatedApplicationPID]intValue] > 0) {
|
||||||
|
if (kill((pid_t)[[session simulatedApplicationPID]intValue], 0) == -1) {
|
||||||
|
nsprintf(@"<msg>app stopped</msg>");
|
||||||
|
[self doExit:EXIT_SUCCESS];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- (void)stdioDataIsAvailable:(NSNotification *)notification {
|
||||||
|
[[notification object] readInBackgroundAndNotify];
|
||||||
|
NSData *data = [[notification userInfo] valueForKey:NSFileHandleNotificationDataItem];
|
||||||
|
NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; /* dangerous if partially encoded data is at the boundary */
|
||||||
|
if (!alreadyPrintedData) {
|
||||||
|
if ([str length] == 0) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
alreadyPrintedData = YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ([notification object] == stdoutFileHandle) {
|
||||||
|
printf("<app_output>%s</app_output>\n", [str UTF8String]);
|
||||||
|
} else {
|
||||||
|
nsprintf(@"<app_output>%@</app_output>", str); // handle stderr differently?
|
||||||
|
}
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (void)createStdioFIFO:(NSFileHandle **)fileHandle ofType:(NSString *)type atPath:(NSString **)path {
|
||||||
|
*path = [NSString stringWithFormat:@"%@/ios-sim-%@-pipe-%d", NSTemporaryDirectory(), type, (int)time(NULL)];
|
||||||
|
if (mkfifo([*path UTF8String], S_IRUSR | S_IWUSR) == -1) {
|
||||||
|
nsprintf(@"<msg>Unable to create %@ named pipe `%@'</msg>", type, *path);
|
||||||
|
[self doExit:EXIT_FAILURE];
|
||||||
|
} else {
|
||||||
|
if (verbose) {
|
||||||
|
nsprintf(@"<msg>Creating named pipe at `%@'</msg>", *path);
|
||||||
|
}
|
||||||
|
int fd = open([*path UTF8String], O_RDONLY | O_NDELAY);
|
||||||
|
*fileHandle = [[[NSFileHandle alloc] initWithFileDescriptor:fd] retain];
|
||||||
|
[*fileHandle readInBackgroundAndNotify];
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||||
|
selector:@selector(stdioDataIsAvailable:)
|
||||||
|
name:NSFileHandleReadCompletionNotification
|
||||||
|
object:*fileHandle];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (void)removeStdioFIFO:(NSFileHandle *)fileHandle atPath:(NSString *)path {
|
||||||
|
if (verbose) {
|
||||||
|
nsprintf(@"<msg>Removing named pipe at `%@'</msg>", path);
|
||||||
|
}
|
||||||
|
[fileHandle closeFile];
|
||||||
|
[fileHandle release];
|
||||||
|
if (![[NSFileManager defaultManager] removeItemAtPath:path error:NULL]) {
|
||||||
|
nsprintf(@"<msg>Unable to remove named pipe `%@'</msg>", path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (int)launchApp:(NSString *)path withFamily:(NSString *)family
|
||||||
|
uuid:(NSString *)uuid
|
||||||
|
environment:(NSDictionary *)environment
|
||||||
|
stdoutPath:(NSString *)stdoutPath
|
||||||
|
stderrPath:(NSString *)stderrPath
|
||||||
|
timeout:(NSTimeInterval)timeout
|
||||||
|
args:(NSArray *)args {
|
||||||
|
DTiPhoneSimulatorApplicationSpecifier *appSpec;
|
||||||
|
DTiPhoneSimulatorSessionConfig *config;
|
||||||
|
NSError *error = 0;
|
||||||
|
id tClass;
|
||||||
|
|
||||||
|
NSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease];
|
||||||
|
if (!startOnly && ![fileManager fileExistsAtPath:path]) {
|
||||||
|
nsprintf(@"<msg>Application path %@ doesn't exist!</msg>", path);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the app specifier */
|
||||||
|
tClass = objc_getClass("DTiPhoneSimulatorApplicationSpecifier");
|
||||||
|
if (tClass == nil) {
|
||||||
|
nsprintf(@"<msg>DTiPhoneSimulatorApplicationSpecifier class is nil.</msg>");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
appSpec = startOnly ? nil : [tClass specifierWithApplicationPath:path];
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
nsprintf(@"<msg>App Spec: %@</msg>", appSpec);
|
||||||
|
nsprintf(@"SDK Root: %@", sdkRoot);
|
||||||
|
|
||||||
|
for (id key in environment) {
|
||||||
|
nsprintf(@"<msg>Env: %@ = %@</msg>", key, [environment objectForKey:key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up the session configuration */
|
||||||
|
tClass = objc_getClass("DTiPhoneSimulatorSessionConfig");
|
||||||
|
if (tClass == nil) {
|
||||||
|
nsprintf(@"<msg>DTiPhoneSimulatorApplicationSpecifier class is nil.</msg>");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
config = [[[tClass alloc] init] autorelease];
|
||||||
|
[config setApplicationToSimulateOnStart:appSpec];
|
||||||
|
[config setSimulatedSystemRoot:sdkRoot];
|
||||||
|
[config setSimulatedApplicationShouldWaitForDebugger:shouldStartDebugger];
|
||||||
|
|
||||||
|
[config setSimulatedApplicationLaunchArgs:args];
|
||||||
|
[config setSimulatedApplicationLaunchEnvironment:environment];
|
||||||
|
|
||||||
|
if (stderrPath) {
|
||||||
|
stderrFileHandle = nil;
|
||||||
|
} else if (!exitOnStartup) {
|
||||||
|
[self createStdioFIFO:&stderrFileHandle ofType:@"stderr" atPath:&stderrPath];
|
||||||
|
}
|
||||||
|
[config setSimulatedApplicationStdErrPath:stderrPath];
|
||||||
|
|
||||||
|
if (stdoutPath) {
|
||||||
|
stdoutFileHandle = nil;
|
||||||
|
} else if (!exitOnStartup) {
|
||||||
|
[self createStdioFIFO:&stdoutFileHandle ofType:@"stdout" atPath:&stdoutPath];
|
||||||
|
}
|
||||||
|
[config setSimulatedApplicationStdOutPath:stdoutPath];
|
||||||
|
|
||||||
|
[config setLocalizedClientName: @"iossim"];
|
||||||
|
|
||||||
|
// this was introduced in 3.2 of SDK
|
||||||
|
if ([config respondsToSelector:@selector(setSimulatedDeviceFamily:)]) {
|
||||||
|
if (family == nil) {
|
||||||
|
family = @"iphone";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
nsprintf(@"using device family %@",family);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([family isEqualToString:@"ipad"]) {
|
||||||
|
[config setSimulatedDeviceFamily:[NSNumber numberWithInt:2]];
|
||||||
|
} else{
|
||||||
|
[config setSimulatedDeviceFamily:[NSNumber numberWithInt:1]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[self changeDeviceType:family retina:retinaDevice isTallDevice:tallDevice];
|
||||||
|
|
||||||
|
/* Start the session */
|
||||||
|
tClass = objc_getClass("DTiPhoneSimulatorSession");
|
||||||
|
if (tClass == nil) {
|
||||||
|
nsprintf(@"<msg>DTiPhoneSimulatorSession class is nil.</msg>");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
session = [[tClass alloc] init];
|
||||||
|
[session setDelegate:self];
|
||||||
|
if (uuid != nil){
|
||||||
|
[session setUuid:uuid];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (![session requestStartWithConfig:config timeout:timeout error:&error]) {
|
||||||
|
nsprintf(@"<msg>Could not start simulator session: %@</msg>", error);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) changeDeviceType:(NSString *)family retina:(BOOL)retina isTallDevice:(BOOL)isTallDevice {
|
||||||
|
NSString *devicePropertyValue;
|
||||||
|
if (retina) {
|
||||||
|
if (verbose) {
|
||||||
|
nsprintf(@"<msg>using retina</msg>");
|
||||||
|
}
|
||||||
|
if ([family isEqualToString:@"ipad"]) {
|
||||||
|
devicePropertyValue = deviceIpadRetina;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (isTallDevice) {
|
||||||
|
devicePropertyValue = deviceIphoneRetina4_0Inch;
|
||||||
|
} else {
|
||||||
|
devicePropertyValue = deviceIphoneRetina3_5Inch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ([family isEqualToString:@"ipad"]) {
|
||||||
|
devicePropertyValue = deviceIpad;
|
||||||
|
} else {
|
||||||
|
devicePropertyValue = deviceIphone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CFPreferencesSetAppValue((CFStringRef)deviceProperty, (CFPropertyListRef)devicePropertyValue, (CFStringRef)simulatorPrefrencesName);
|
||||||
|
CFPreferencesAppSynchronize((CFStringRef)simulatorPrefrencesName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute 'main'
|
||||||
|
*/
|
||||||
|
- (void)runWithArgc:(int)argc argv:(char **)argv {
|
||||||
|
if (argc < 2) {
|
||||||
|
[self printUsage];
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
retinaDevice = NO;
|
||||||
|
tallDevice = NO;
|
||||||
|
exitOnStartup = NO;
|
||||||
|
alreadyPrintedData = NO;
|
||||||
|
startOnly = strcmp(argv[1], "start") == 0;
|
||||||
|
nsprintf(@"<query_result>");
|
||||||
|
|
||||||
|
if (strcmp(argv[1], "showsdks") == 0) {
|
||||||
|
[self doExit:[self showSDKs]];
|
||||||
|
return;
|
||||||
|
} else if (strcmp(argv[1], "launch") == 0 || startOnly) {
|
||||||
|
if (strcmp(argv[1], "launch") == 0 && argc < 3) {
|
||||||
|
nsprintf(@"<msg>Missing application path argument</msg>");
|
||||||
|
[self printUsage];
|
||||||
|
[self doExit:EXIT_FAILURE];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *appPath = nil;
|
||||||
|
int argOffset;
|
||||||
|
if (startOnly) {
|
||||||
|
argOffset = 2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
argOffset = 3;
|
||||||
|
appPath = [[NSString stringWithUTF8String:argv[2]] expandPath];
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *family = nil;
|
||||||
|
NSString *uuid = nil;
|
||||||
|
NSString *stdoutPath = nil;
|
||||||
|
NSString *stderrPath = nil;
|
||||||
|
NSTimeInterval timeout = 30;
|
||||||
|
NSMutableDictionary *environment = [NSMutableDictionary dictionary];
|
||||||
|
|
||||||
|
int i = argOffset;
|
||||||
|
for (; i < argc; i++) {
|
||||||
|
if (strcmp(argv[i], "--version") == 0) {
|
||||||
|
printf("%s\n", IOS_SIM_VERSION);
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
} else if (strcmp(argv[i], "--help") == 0) {
|
||||||
|
[self printUsage];
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
} else if (strcmp(argv[i], "--verbose") == 0) {
|
||||||
|
verbose = YES;
|
||||||
|
} else if (strcmp(argv[i], "--exit") == 0) {
|
||||||
|
exitOnStartup = YES;
|
||||||
|
} else if (strcmp(argv[i], "--wait-for-debugger") == 0) {
|
||||||
|
shouldWaitDebugger = YES;
|
||||||
|
} else if (strcmp(argv[i], "--debug") == 0) {
|
||||||
|
shouldWaitDebugger = YES;
|
||||||
|
shouldStartDebugger = YES;
|
||||||
|
} else if (strcmp(argv[i], "--use-gdb") == 0) {
|
||||||
|
useGDB = YES;
|
||||||
|
} else if (strcmp(argv[i], "--developer-path") == 0) {
|
||||||
|
++i;
|
||||||
|
} else if (strcmp(argv[i], "--timeout") == 0) {
|
||||||
|
if (i + 1 < argc) {
|
||||||
|
timeout = [[NSString stringWithUTF8String:argv[++i]] doubleValue];
|
||||||
|
NSLog(@"<msg>Timeout: %f second(s)</msg>", timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[i], "--sdk") == 0) {
|
||||||
|
i++;
|
||||||
|
NSString* ver = [NSString stringWithCString:argv[i] encoding:NSUTF8StringEncoding];
|
||||||
|
id tClass = objc_getClass("DTiPhoneSimulatorSystemRoot");
|
||||||
|
NSArray *roots;
|
||||||
|
if (tClass == nil) {
|
||||||
|
nsprintf(@"<msg>DTiPhoneSimulatorSystemRoot class is nil.</msg>");
|
||||||
|
[self doExit:EXIT_FAILURE];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
roots = [tClass knownRoots];
|
||||||
|
for (DTiPhoneSimulatorSystemRoot *root in roots) {
|
||||||
|
NSString *v = [root sdkVersion];
|
||||||
|
if ([v isEqualToString:ver]) {
|
||||||
|
sdkRoot = root;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sdkRoot == nil) {
|
||||||
|
fprintf(stdout,"<msg>Unknown or unsupported SDK version: %s</msg>\n",argv[i]);
|
||||||
|
[self showSDKs];
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
} else if (strcmp(argv[i], "--family") == 0) {
|
||||||
|
i++;
|
||||||
|
family = [NSString stringWithUTF8String:argv[i]];
|
||||||
|
} else if (strcmp(argv[i], "--uuid") == 0) {
|
||||||
|
i++;
|
||||||
|
uuid = [NSString stringWithUTF8String:argv[i]];
|
||||||
|
} else if (strcmp(argv[i], "--setenv") == 0) {
|
||||||
|
i++;
|
||||||
|
NSArray *parts = [[NSString stringWithUTF8String:argv[i]] componentsSeparatedByString:@"="];
|
||||||
|
[environment setObject:[parts objectAtIndex:1] forKey:[parts objectAtIndex:0]];
|
||||||
|
} else if (strcmp(argv[i], "--env") == 0) {
|
||||||
|
i++;
|
||||||
|
NSString *envFilePath = [[NSString stringWithUTF8String:argv[i]] expandPath];
|
||||||
|
environment = [NSDictionary dictionaryWithContentsOfFile:envFilePath];
|
||||||
|
if (!environment) {
|
||||||
|
fprintf(stdout, "<msg>Could not read environment from file: %s</msg>\n", argv[i]);
|
||||||
|
[self printUsage];
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
} else if (strcmp(argv[i], "--stdout") == 0) {
|
||||||
|
i++;
|
||||||
|
stdoutPath = [[NSString stringWithUTF8String:argv[i]] expandPath];
|
||||||
|
NSLog(@"stdoutPath: %@", stdoutPath);
|
||||||
|
} else if (strcmp(argv[i], "--stderr") == 0) {
|
||||||
|
i++;
|
||||||
|
stderrPath = [[NSString stringWithUTF8String:argv[i]] expandPath];
|
||||||
|
NSLog(@"stderrPath: %@", stderrPath);
|
||||||
|
} else if (strcmp(argv[i], "--retina") == 0) {
|
||||||
|
retinaDevice = YES;
|
||||||
|
} else if (strcmp(argv[i], "--tall") == 0) {
|
||||||
|
tallDevice = YES;
|
||||||
|
} else if (strcmp(argv[i], "--args") == 0) {
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
printf("<msg>unrecognized argument:%s</msg>\n", argv[i]);
|
||||||
|
[self printUsage];
|
||||||
|
[self doExit:EXIT_FAILURE];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NSMutableArray *args = [NSMutableArray arrayWithCapacity:MAX(argc - i,0)];
|
||||||
|
for (; i < argc; i++) {
|
||||||
|
[args addObject:[NSString stringWithUTF8String:argv[i]]];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sdkRoot == nil) {
|
||||||
|
id tClass = objc_getClass("DTiPhoneSimulatorSystemRoot");
|
||||||
|
if (tClass == nil) {
|
||||||
|
nsprintf(@"<msg>DTiPhoneSimulatorSystemRoot class is nil.</msg>");
|
||||||
|
[self doExit:EXIT_FAILURE];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sdkRoot = [tClass defaultRoot];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Don't exit, adds to runloop */
|
||||||
|
int res = [self launchApp:appPath
|
||||||
|
withFamily:family
|
||||||
|
uuid:uuid
|
||||||
|
environment:environment
|
||||||
|
stdoutPath:stdoutPath
|
||||||
|
stderrPath:stderrPath
|
||||||
|
timeout:timeout
|
||||||
|
args:args];
|
||||||
|
nsprintf(@"<app_started status=\"%@\" />", ((res == 0) ? @"SUCCESS" : @"FAILURE"));
|
||||||
|
fflush(stdout);
|
||||||
|
fflush(stderr);
|
||||||
|
if (res != 0)
|
||||||
|
[self doExit:EXIT_FAILURE];
|
||||||
|
} else {
|
||||||
|
if (argc == 2 && strcmp(argv[1], "--help") == 0) {
|
||||||
|
[self printUsage];
|
||||||
|
[self doExit:EXIT_SUCCESS];
|
||||||
|
} else if (argc == 2 && strcmp(argv[1], "--version") == 0) {
|
||||||
|
printf("%s\n", IOS_SIM_VERSION);
|
||||||
|
[self doExit:EXIT_SUCCESS];
|
||||||
|
} else {
|
||||||
|
fprintf(stdout, "<msg>Unknown command</msg>\n");
|
||||||
|
[self printUsage];
|
||||||
|
[self doExit:EXIT_FAILURE];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
126
src/tools/3rdparty/iossim/iphonesimulatorremoteclient/iphonesimulatorremoteclient.h
vendored
Normal file
126
src/tools/3rdparty/iossim/iphonesimulatorremoteclient/iphonesimulatorremoteclient.h
vendored
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* File: /Developer/Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks/iPhoneSimulatorRemoteClient.framework/Versions/A/iPhoneSimulatorRemoteClient
|
||||||
|
* Arch: Intel 80x86 (i386)
|
||||||
|
* Current version: 12.0.0, Compatibility version: 1.0.0
|
||||||
|
*
|
||||||
|
* See the IOSSIM_LICENSE file in the parent directory for the license on the source code in this file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@class DTiPhoneSimulatorSession;
|
||||||
|
|
||||||
|
@protocol DTiPhoneSimulatorSessionDelegate
|
||||||
|
|
||||||
|
- (void) session: (DTiPhoneSimulatorSession *) session didEndWithError: (NSError *) error;
|
||||||
|
- (void) session: (DTiPhoneSimulatorSession *) session didStart: (BOOL) started withError: (NSError *) error;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface DTiPhoneSimulatorApplicationSpecifier : NSObject <NSCopying>
|
||||||
|
{
|
||||||
|
NSString *_appPath;
|
||||||
|
NSString *_bundleID;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (id) specifierWithApplicationPath: (NSString *) appPath;
|
||||||
|
+ (id) specifierWithApplicationBundleIdentifier: (NSString *) bundleID;
|
||||||
|
- (NSString *) bundleID;
|
||||||
|
- (void) setBundleID: (NSString *) bundleId;
|
||||||
|
- (NSString *) appPath;
|
||||||
|
- (void) setAppPath: (NSString *) appPath;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface DTiPhoneSimulatorSystemRoot : NSObject <NSCopying>
|
||||||
|
{
|
||||||
|
NSString *sdkRootPath;
|
||||||
|
NSString *sdkVersion;
|
||||||
|
NSString *sdkDisplayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (id) defaultRoot;
|
||||||
|
|
||||||
|
+ (id)rootWithSDKPath:(id)fp8;
|
||||||
|
+ (id)rootWithSDKVersion:(id)fp8;
|
||||||
|
+ (NSArray *) knownRoots;
|
||||||
|
- (id)initWithSDKPath:(id)fp8;
|
||||||
|
- (id)sdkDisplayName;
|
||||||
|
- (void)setSdkDisplayName:(id)fp8;
|
||||||
|
- (id)sdkVersion;
|
||||||
|
- (void)setSdkVersion:(id)fp8;
|
||||||
|
- (id)sdkRootPath;
|
||||||
|
- (void)setSdkRootPath:(id)fp8;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@interface DTiPhoneSimulatorSessionConfig : NSObject <NSCopying>
|
||||||
|
{
|
||||||
|
NSString *_localizedClientName;
|
||||||
|
DTiPhoneSimulatorSystemRoot *_simulatedSystemRoot;
|
||||||
|
DTiPhoneSimulatorApplicationSpecifier *_applicationToSimulateOnStart;
|
||||||
|
NSArray *_simulatedApplicationLaunchArgs;
|
||||||
|
NSDictionary *_simulatedApplicationLaunchEnvironment;
|
||||||
|
BOOL _simulatedApplicationShouldWaitForDebugger;
|
||||||
|
NSString *_simulatedApplicationStdOutPath;
|
||||||
|
NSString *_simulatedApplicationStdErrPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)simulatedApplicationStdErrPath;
|
||||||
|
- (void)setSimulatedApplicationStdErrPath:(id)fp8;
|
||||||
|
- (id)simulatedApplicationStdOutPath;
|
||||||
|
- (void)setSimulatedApplicationStdOutPath:(id)fp8;
|
||||||
|
- (id)simulatedApplicationLaunchEnvironment;
|
||||||
|
- (void)setSimulatedApplicationLaunchEnvironment:(id)fp8;
|
||||||
|
- (id)simulatedApplicationLaunchArgs;
|
||||||
|
- (void)setSimulatedApplicationLaunchArgs:(id)fp8;
|
||||||
|
|
||||||
|
- (DTiPhoneSimulatorApplicationSpecifier *) applicationToSimulateOnStart;
|
||||||
|
- (void) setApplicationToSimulateOnStart: (DTiPhoneSimulatorApplicationSpecifier *) appSpec;
|
||||||
|
- (DTiPhoneSimulatorSystemRoot *) simulatedSystemRoot;
|
||||||
|
- (void) setSimulatedSystemRoot: (DTiPhoneSimulatorSystemRoot *) simulatedSystemRoot;
|
||||||
|
|
||||||
|
|
||||||
|
- (BOOL) simulatedApplicationShouldWaitForDebugger;
|
||||||
|
- (void) setSimulatedApplicationShouldWaitForDebugger: (BOOL) waitForDebugger;
|
||||||
|
|
||||||
|
- (id)localizedClientName;
|
||||||
|
- (void)setLocalizedClientName:(id)fp8;
|
||||||
|
|
||||||
|
// Added in 3.2 to support iPad/iPhone device families
|
||||||
|
- (void)setSimulatedDeviceFamily:(NSNumber*)family;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@interface DTiPhoneSimulatorSession : NSObject {
|
||||||
|
NSString *_uuid;
|
||||||
|
id <DTiPhoneSimulatorSessionDelegate> _delegate;
|
||||||
|
NSNumber *_simulatedApplicationPID;
|
||||||
|
int _sessionLifecycleProgress;
|
||||||
|
NSTimer *_timeoutTimer;
|
||||||
|
DTiPhoneSimulatorSessionConfig *_sessionConfig;
|
||||||
|
struct ProcessSerialNumber _simulatorPSN;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) requestStartWithConfig: (DTiPhoneSimulatorSessionConfig *) config timeout: (NSTimeInterval) timeout error: (NSError **) outError;
|
||||||
|
- (void) requestEndWithTimeout: (NSTimeInterval) timeout;
|
||||||
|
|
||||||
|
- (id)sessionConfig;
|
||||||
|
- (void)setSessionConfig:(id)fp8;
|
||||||
|
- (id)timeoutTimer;
|
||||||
|
- (void)setTimeoutTimer:(id)fp8;
|
||||||
|
- (int)sessionLifecycleProgress;
|
||||||
|
- (void)setSessionLifecycleProgress:(int)fp8;
|
||||||
|
- (id)simulatedApplicationPID;
|
||||||
|
- (void)setSimulatedApplicationPID:(id)fp8;
|
||||||
|
|
||||||
|
- (id<DTiPhoneSimulatorSessionDelegate>) delegate;
|
||||||
|
- (void) setDelegate: (id<DTiPhoneSimulatorSessionDelegate>) delegate;
|
||||||
|
|
||||||
|
- (id)uuid;
|
||||||
|
- (void)setUuid:(id)fp8;
|
||||||
|
|
||||||
|
@end
|
64
src/tools/3rdparty/iossim/main.mm
vendored
Normal file
64
src/tools/3rdparty/iossim/main.mm
vendored
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
/* Author: Landon Fuller <landonf@plausiblelabs.com>
|
||||||
|
* Copyright (c) 2008-2011 Plausible Labs Cooperative, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* See the IOSSIM_LICENSE file in this directory for the license on the source code in this file.
|
||||||
|
*/
|
||||||
|
/* derived from https://github.com/phonegap/ios-sim */
|
||||||
|
#import <AppKit/AppKit.h>
|
||||||
|
#import "iphonesimulator.h"
|
||||||
|
#include <QLibrary>
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
/* to do:
|
||||||
|
* - try to stop inferior when killed (or communicate with creator to allow killing the inferior)
|
||||||
|
* - remove unneeded functionality and streamline a bit
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Runs the iPhoneSimulator backed by a main runloop.
|
||||||
|
*/
|
||||||
|
int main (int argc, char *argv[]) {
|
||||||
|
QGuiApplication a(argc, argv);
|
||||||
|
|
||||||
|
//NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||||
|
|
||||||
|
QString xcodePath = QLatin1String("/Applications/Xcode.app/Contents/Developer/");
|
||||||
|
for (int i = 0; i + 1 < argc; ++i) {
|
||||||
|
if (strcmp(argv[i], "--developer-path") == 0)
|
||||||
|
xcodePath = QCoreApplication::arguments().at(i+1);
|
||||||
|
}
|
||||||
|
if (!xcodePath.endsWith(QLatin1Char('/')))
|
||||||
|
xcodePath.append(QLatin1Char('/'));
|
||||||
|
|
||||||
|
/* manual loading of the private deps */
|
||||||
|
QStringList deps = QStringList()
|
||||||
|
<< QLatin1String("/System/Library/PrivateFrameworks/DebugSymbols.framework/Versions/A/DebugSymbols")
|
||||||
|
<< QLatin1String("/System/Library/PrivateFrameworks/CoreSymbolication.framework/CoreSymbolication")
|
||||||
|
<< (xcodePath + QLatin1String("../OtherFrameworks/DevToolsFoundation.framework/DevToolsFoundation"));
|
||||||
|
foreach (const QString &libPath, deps) {
|
||||||
|
QLibrary *lib = new QLibrary(libPath);
|
||||||
|
//lib->setLoadHints(QLibrary::ExportExternalSymbolsHint);
|
||||||
|
if (!lib->load())
|
||||||
|
printf("<msg>error loading %s</msg>", libPath.toUtf8().constData());
|
||||||
|
}
|
||||||
|
QLibrary *libIPhoneSimulatorRemoteClient = new QLibrary(xcodePath
|
||||||
|
+ QLatin1String("Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks/iPhoneSimulatorRemoteClient.framework/iPhoneSimulatorRemoteClient"));
|
||||||
|
//libIPhoneSimulatorRemoteClient->setLoadHints(QLibrary::ResolveAllSymbolsHint|QLibrary::ExportExternalSymbolsHint);
|
||||||
|
if (!libIPhoneSimulatorRemoteClient->load())
|
||||||
|
printf("<msg>error loading iPhoneSimulatorRemoteClient</msg>");
|
||||||
|
|
||||||
|
iPhoneSimulator *sim = [[iPhoneSimulator alloc] init];
|
||||||
|
|
||||||
|
/* Execute command line handler */
|
||||||
|
[sim runWithArgc: argc argv: argv];
|
||||||
|
|
||||||
|
/* Run the loop to handle added input sources, if any */
|
||||||
|
|
||||||
|
int res = a.exec();
|
||||||
|
exit(res);
|
||||||
|
// [pool release];
|
||||||
|
return 0;
|
||||||
|
}
|
6
src/tools/3rdparty/iossim/nsprintf.h
vendored
Normal file
6
src/tools/3rdparty/iossim/nsprintf.h
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
/*
|
||||||
|
* See the IOSSIM_LICENSE file in this directory for the license on the source code in this file.
|
||||||
|
*/
|
||||||
|
int nsvfprintf (FILE *stream, NSString *format, va_list args);
|
||||||
|
int nsfprintf (FILE *stream, NSString *format, ...);
|
||||||
|
int nsprintf (NSString *format, ...);
|
44
src/tools/3rdparty/iossim/nsprintf.m
vendored
Normal file
44
src/tools/3rdparty/iossim/nsprintf.m
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* NSLog() clone, but writes to arbitrary output stream
|
||||||
|
*
|
||||||
|
* See the IOSSIM_LICENSE file in this directory for the license on the source code in this file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <stdio.h>
|
||||||
|
|
||||||
|
int nsvfprintf (FILE *stream, NSString *format, va_list args) {
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
NSString *str = (NSString *) CFStringCreateWithFormatAndArguments(NULL, NULL, (CFStringRef) format, args);
|
||||||
|
retval = fprintf(stream, "%s\n", [str UTF8String]);
|
||||||
|
[str release];
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nsfprintf (FILE *stream, NSString *format, ...) {
|
||||||
|
va_list ap;
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
{
|
||||||
|
retval = nsvfprintf(stream, format, ap);
|
||||||
|
}
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nsprintf (NSString *format, ...) {
|
||||||
|
va_list ap;
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
{
|
||||||
|
retval = nsvfprintf(stdout, format, ap);
|
||||||
|
}
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
11
src/tools/3rdparty/iossim/nsstringexpandpath.h
vendored
Normal file
11
src/tools/3rdparty/iossim/nsstringexpandpath.h
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/*
|
||||||
|
* See the IOSSIM_LICENSE file in this directory for the license on the source code in this file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@interface NSString (ExpandPath)
|
||||||
|
|
||||||
|
- (NSString *)expandPath;
|
||||||
|
|
||||||
|
@end
|
18
src/tools/3rdparty/iossim/nsstringexpandpath.m
vendored
Normal file
18
src/tools/3rdparty/iossim/nsstringexpandpath.m
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* See the IOSSIM_LICENSE file in this directory for the license on the source code in this file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "nsstringexpandpath.h"
|
||||||
|
|
||||||
|
@implementation NSString (ExpandPath)
|
||||||
|
|
||||||
|
- (NSString *)expandPath {
|
||||||
|
if ([self isAbsolutePath]) {
|
||||||
|
return [self stringByStandardizingPath];
|
||||||
|
} else {
|
||||||
|
NSString *cwd = [[NSFileManager defaultManager] currentDirectoryPath];
|
||||||
|
return [[cwd stringByAppendingPathComponent:self] stringByStandardizingPath];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
1
src/tools/3rdparty/iossim/version.h
vendored
Normal file
1
src/tools/3rdparty/iossim/version.h
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#define IOS_SIM_VERSION "1.8.2m"
|
16
src/tools/iostool/Info.plist
Normal file
16
src/tools/iostool/Info.plist
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>@TYPEINFO@</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>@EXECUTABLE@</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>org.qt-project.qt-creator.iosTool</string>
|
||||||
|
<key>LSUIElement</key>
|
||||||
|
<string>1</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
1584
src/tools/iostool/iosdevicemanager.cpp
Normal file
1584
src/tools/iostool/iosdevicemanager.cpp
Normal file
File diff suppressed because it is too large
Load Diff
93
src/tools/iostool/iosdevicemanager.h
Normal file
93
src/tools/iostool/iosdevicemanager.h
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef IOSMANAGER_H
|
||||||
|
#define IOSMANAGER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QMap>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
namespace Ios {
|
||||||
|
namespace Internal {
|
||||||
|
class IosDeviceManagerPrivate;
|
||||||
|
} // namespace Internal
|
||||||
|
|
||||||
|
class IosDeviceManager : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
typedef QMap<QString,QString> Dict;
|
||||||
|
enum OpStatus {
|
||||||
|
Success = 0,
|
||||||
|
Warning = 1,
|
||||||
|
Failure = 2
|
||||||
|
};
|
||||||
|
enum AppOp {
|
||||||
|
None = 0,
|
||||||
|
Install = 1,
|
||||||
|
Run = 2,
|
||||||
|
InstallAndRun = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
static IosDeviceManager *instance();
|
||||||
|
bool watchDevices();
|
||||||
|
void requestAppOp(const QString &bundlePath, const QStringList &extraArgs, AppOp appOp,
|
||||||
|
const QString &deviceId, int timeout = 1000);
|
||||||
|
void requestDeviceInfo(const QString &deviceId, int timeout = 1000);
|
||||||
|
int processGdbServer(int fd);
|
||||||
|
QStringList errors();
|
||||||
|
signals:
|
||||||
|
void deviceAdded(const QString &deviceId);
|
||||||
|
void deviceRemoved(const QString &deviceId);
|
||||||
|
void isTransferringApp(const QString &bundlePath, const QString &deviceId, int progress,
|
||||||
|
const QString &info);
|
||||||
|
void didTransferApp(const QString &bundlePath, const QString &deviceId,
|
||||||
|
Ios::IosDeviceManager::OpStatus status);
|
||||||
|
void didStartApp(const QString &bundlePath, const QString &deviceId,
|
||||||
|
Ios::IosDeviceManager::OpStatus status, int gdbFd);
|
||||||
|
void deviceInfo(const QString &deviceId, const Ios::IosDeviceManager::Dict &info);
|
||||||
|
void appOutput(const QString &output);
|
||||||
|
void errorMsg(const QString &msg);
|
||||||
|
private slots:
|
||||||
|
void checkPendingLookups();
|
||||||
|
private:
|
||||||
|
friend class Internal::IosDeviceManagerPrivate;
|
||||||
|
IosDeviceManager(QObject *parent = 0);
|
||||||
|
Internal::IosDeviceManagerPrivate *d;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Ios
|
||||||
|
|
||||||
|
#endif // IOSMANAGER_H
|
27
src/tools/iostool/iostool.pro
Normal file
27
src/tools/iostool/iostool.pro
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
TARGET = iosTool
|
||||||
|
|
||||||
|
QT += core
|
||||||
|
QT += gui xml
|
||||||
|
|
||||||
|
CONFIG += console
|
||||||
|
|
||||||
|
# Prevent from popping up in the dock when launched.
|
||||||
|
# We embed the Info.plist file, so the application doesn't need to
|
||||||
|
# be a bundle.
|
||||||
|
QMAKE_LFLAGS += -sectcreate __TEXT __info_plist $$shell_quote($$PWD/Info.plist)
|
||||||
|
CONFIG -= app_bundle
|
||||||
|
|
||||||
|
LIBS += -framework CoreFoundation -framework CoreServices -framework IOKit -lssl -lbz2 -framework Security -framework SystemConfiguration
|
||||||
|
|
||||||
|
TEMPLATE = app
|
||||||
|
|
||||||
|
include(../../../qtcreator.pri)
|
||||||
|
|
||||||
|
DESTDIR = $$IDE_BIN_PATH
|
||||||
|
include(../../rpath.pri)
|
||||||
|
|
||||||
|
SOURCES += main.cpp \
|
||||||
|
iosdevicemanager.cpp
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
iosdevicemanager.h
|
21
src/tools/iostool/iostool.qbs
Normal file
21
src/tools/iostool/iostool.qbs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import qbs.base 1.0
|
||||||
|
import "../QtcTool.qbs" as QtcTool
|
||||||
|
|
||||||
|
QtcTool {
|
||||||
|
name: "iostool"
|
||||||
|
condition: qbs.targetOS.contains("osx")
|
||||||
|
|
||||||
|
Depends { name: "Qt.widgets" }
|
||||||
|
Depends { name: "Qt.xml" }
|
||||||
|
Depends { name: "app_version_header" }
|
||||||
|
|
||||||
|
files: [
|
||||||
|
"main.cpp",
|
||||||
|
"iosdevicemanager.cpp",
|
||||||
|
"iosdevicemanager.h"
|
||||||
|
]
|
||||||
|
cpp.linkerFlags: base.concat(["-sectcreate", "__TEXT", "__info_plist", path + "/Info.plist"])
|
||||||
|
cpp.frameworks: base.concat(["CoreFoundation", "CoreServices", "IOKit", "Security",
|
||||||
|
"SystemConfiguration"])
|
||||||
|
cpp.libraries: base.concat(["ssl", "bz2"])
|
||||||
|
}
|
386
src/tools/iostool/main.cpp
Normal file
386
src/tools/iostool/main.cpp
Normal file
@@ -0,0 +1,386 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#include <QTextStream>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QXmlStreamWriter>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QMapIterator>
|
||||||
|
#include "iosdevicemanager.h"
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
class IosTool: public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
IosTool(QObject *parent = 0);
|
||||||
|
void run(const QStringList &args);
|
||||||
|
void doExit(int errorCode = 0);
|
||||||
|
void writeMsg(const char *msg);
|
||||||
|
void writeMsg(const QString &msg);
|
||||||
|
void stopXml(int errorCode);
|
||||||
|
public slots:
|
||||||
|
void isTransferringApp(const QString &bundlePath, const QString &deviceId, int progress,
|
||||||
|
const QString &info);
|
||||||
|
void didTransferApp(const QString &bundlePath, const QString &deviceId,
|
||||||
|
Ios::IosDeviceManager::OpStatus status);
|
||||||
|
void didStartApp(const QString &bundlePath, const QString &deviceId,
|
||||||
|
Ios::IosDeviceManager::OpStatus status, int gdbFd);
|
||||||
|
void deviceInfo(const QString &deviceId, const Ios::IosDeviceManager::Dict &info);
|
||||||
|
void appOutput(const QString &output);
|
||||||
|
void errorMsg(const QString &msg);
|
||||||
|
private:
|
||||||
|
int maxProgress;
|
||||||
|
int opLeft;
|
||||||
|
bool debug;
|
||||||
|
bool inAppOutput;
|
||||||
|
bool splitAppOutput; // as QXmlStreamReader reports the text attributes atomically it is better to split
|
||||||
|
Ios::IosDeviceManager::AppOp appOp;
|
||||||
|
QFile outFile;
|
||||||
|
QXmlStreamWriter out;
|
||||||
|
};
|
||||||
|
|
||||||
|
IosTool::IosTool(QObject *parent):
|
||||||
|
QObject(parent),
|
||||||
|
maxProgress(0),
|
||||||
|
opLeft(0),
|
||||||
|
debug(false),
|
||||||
|
inAppOutput(false),
|
||||||
|
splitAppOutput(true),
|
||||||
|
appOp(Ios::IosDeviceManager::Install),
|
||||||
|
outFile(),
|
||||||
|
out(&outFile)
|
||||||
|
{
|
||||||
|
outFile.open(stdout, QIODevice::WriteOnly, QFileDevice::DontCloseHandle);
|
||||||
|
out.setAutoFormatting(true);
|
||||||
|
out.setCodec("UTF-8");
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosTool::run(const QStringList &args)
|
||||||
|
{
|
||||||
|
Ios::IosDeviceManager *manager = Ios::IosDeviceManager::instance();
|
||||||
|
QString deviceId;
|
||||||
|
QString bundlePath;
|
||||||
|
bool deviceInfo = false;
|
||||||
|
bool printHelp = false;
|
||||||
|
int timeout = 1000;
|
||||||
|
QStringList extraArgs;
|
||||||
|
|
||||||
|
out.writeStartDocument();
|
||||||
|
out.writeStartElement(QLatin1String("query_result"));
|
||||||
|
for (int iarg = 1; iarg < args.size(); ++iarg) {
|
||||||
|
const QString &arg = args[iarg];
|
||||||
|
if (arg == QLatin1String("-device-id")) {
|
||||||
|
if (++iarg == args.size()) {
|
||||||
|
writeMsg("missing device id value after -device-id");
|
||||||
|
printHelp = true;
|
||||||
|
}
|
||||||
|
deviceId = args.value(iarg);
|
||||||
|
} else if (arg == QLatin1String("-bundle")) {
|
||||||
|
if (++iarg == args.size()) {
|
||||||
|
writeMsg("missing bundle path after -bundle");
|
||||||
|
printHelp = true;
|
||||||
|
}
|
||||||
|
bundlePath = args.value(iarg);
|
||||||
|
} else if (arg == QLatin1String("-deploy")) {
|
||||||
|
appOp = Ios::IosDeviceManager::AppOp(appOp | Ios::IosDeviceManager::Install);
|
||||||
|
} else if (arg == QLatin1String("-run")) {
|
||||||
|
appOp = Ios::IosDeviceManager::AppOp(appOp | Ios::IosDeviceManager::Run);
|
||||||
|
} else if (arg == QLatin1String("-debug")) {
|
||||||
|
appOp = Ios::IosDeviceManager::AppOp(appOp | Ios::IosDeviceManager::Run);
|
||||||
|
debug = true;
|
||||||
|
} else if (arg == QLatin1String("-device-info")) {
|
||||||
|
deviceInfo = true;
|
||||||
|
} else if (arg == QLatin1String("-timeout")) {
|
||||||
|
if (++iarg == args.size()) {
|
||||||
|
writeMsg("missing timeout value after -timeout");
|
||||||
|
printHelp = true;
|
||||||
|
}
|
||||||
|
bool ok = false;
|
||||||
|
int tOut = args.value(iarg).toInt(&ok);
|
||||||
|
if (ok && tOut > 0) {
|
||||||
|
timeout = tOut;
|
||||||
|
} else {
|
||||||
|
writeMsg("timeout value should be an integer");
|
||||||
|
printHelp = true;
|
||||||
|
}
|
||||||
|
} else if (arg == QLatin1String("-extra-args")) {
|
||||||
|
++iarg;
|
||||||
|
extraArgs = args.mid(iarg, args.size() - iarg);
|
||||||
|
} else if (arg == QLatin1String("-help") || arg == QLatin1String("--help")) {
|
||||||
|
printHelp = true;
|
||||||
|
} else {
|
||||||
|
writeMsg(QString::fromLatin1("unexpected argument '%1'").arg(arg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (printHelp) {
|
||||||
|
out.writeStartElement(QLatin1String("msg"));
|
||||||
|
out.writeCharacters(QLatin1String("iosTool [-device-id <deviceId>] [-bundle <pathToBundle>] [-deploy] [-run] [-debug]\n"));
|
||||||
|
out.writeCharacters(QLatin1String(" [-device-info] [-timeout <timeoutIn_ms>]\n")); // to do pass in env as stub does
|
||||||
|
out.writeCharacters(QLatin1String(" [-extra-args <arguments for the target app>]"));
|
||||||
|
out.writeEndElement();
|
||||||
|
doExit(-1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
outFile.flush();
|
||||||
|
connect(manager,SIGNAL(isTransferringApp(QString,QString,int,QString)),
|
||||||
|
SLOT(isTransferringApp(QString,QString,int,QString)));
|
||||||
|
connect(manager,SIGNAL(didTransferApp(QString,QString,Ios::IosDeviceManager::OpStatus)),
|
||||||
|
SLOT(didTransferApp(QString,QString,Ios::IosDeviceManager::OpStatus)));
|
||||||
|
connect(manager,SIGNAL(didStartApp(QString,QString,Ios::IosDeviceManager::OpStatus,int)),
|
||||||
|
SLOT(didStartApp(QString,QString,Ios::IosDeviceManager::OpStatus,int)));
|
||||||
|
connect(manager,SIGNAL(deviceInfo(QString,Ios::IosDeviceManager::Dict)),
|
||||||
|
SLOT(deviceInfo(QString,Ios::IosDeviceManager::Dict)));
|
||||||
|
connect(manager,SIGNAL(appOutput(QString)), SLOT(appOutput(QString)));
|
||||||
|
connect(manager,SIGNAL(errorMsg(QString)), SLOT(errorMsg(QString)));
|
||||||
|
manager->watchDevices();
|
||||||
|
if (deviceInfo) {
|
||||||
|
if (!bundlePath.isEmpty())
|
||||||
|
writeMsg("-device-info overrides bundlePath");
|
||||||
|
++opLeft;
|
||||||
|
manager->requestDeviceInfo(deviceId, timeout);
|
||||||
|
} else if (!bundlePath.isEmpty()) {
|
||||||
|
switch (appOp) {
|
||||||
|
case Ios::IosDeviceManager::None:
|
||||||
|
break;
|
||||||
|
case Ios::IosDeviceManager::Install:
|
||||||
|
case Ios::IosDeviceManager::Run:
|
||||||
|
++opLeft;
|
||||||
|
break;
|
||||||
|
case Ios::IosDeviceManager::InstallAndRun:
|
||||||
|
opLeft += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
maxProgress = 200;
|
||||||
|
manager->requestAppOp(bundlePath, extraArgs, appOp, deviceId, timeout);
|
||||||
|
}
|
||||||
|
if (opLeft == 0)
|
||||||
|
doExit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosTool::stopXml(int errorCode)
|
||||||
|
{
|
||||||
|
out.writeEmptyElement(QLatin1String("exit"));
|
||||||
|
out.writeAttribute(QLatin1String("code"), QString::number(errorCode));
|
||||||
|
out.writeEndElement(); // result element (hopefully)
|
||||||
|
out.writeEndDocument();
|
||||||
|
outFile.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosTool::doExit(int errorCode)
|
||||||
|
{
|
||||||
|
stopXml(errorCode);
|
||||||
|
QCoreApplication::exit(errorCode); // sometime does not really exit
|
||||||
|
exit(errorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosTool::isTransferringApp(const QString &bundlePath, const QString &deviceId, int progress,
|
||||||
|
const QString &info)
|
||||||
|
{
|
||||||
|
Q_UNUSED(bundlePath);
|
||||||
|
Q_UNUSED(deviceId);
|
||||||
|
out.writeStartElement(QLatin1String("status"));
|
||||||
|
out.writeAttribute(QLatin1String("progress"), QString::number(progress));
|
||||||
|
out.writeAttribute(QLatin1String("max_progress"), QString::number(maxProgress));
|
||||||
|
out.writeCharacters(info);
|
||||||
|
out.writeEndElement();
|
||||||
|
outFile.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
int send_fd(int socket, int fd_to_send)
|
||||||
|
{
|
||||||
|
/* storage space needed for an ancillary element with a paylod of length is CMSG_SPACE(sizeof(length)) */
|
||||||
|
char ancillary_element_buffer[CMSG_SPACE(sizeof(int))];
|
||||||
|
int available_ancillary_element_buffer_space;
|
||||||
|
|
||||||
|
/* at least one vector of one byte must be sent */
|
||||||
|
char message_buffer[1];
|
||||||
|
message_buffer[0] = '.';
|
||||||
|
iovec io_vector[1];
|
||||||
|
|
||||||
|
io_vector[0].iov_base = message_buffer;
|
||||||
|
io_vector[0].iov_len = 1;
|
||||||
|
|
||||||
|
/* initialize socket message */
|
||||||
|
msghdr socket_message;
|
||||||
|
memset(&socket_message, 0, sizeof(msghdr));
|
||||||
|
socket_message.msg_iov = io_vector;
|
||||||
|
socket_message.msg_iovlen = 1;
|
||||||
|
|
||||||
|
/* provide space for the ancillary data */
|
||||||
|
available_ancillary_element_buffer_space = CMSG_SPACE(sizeof(int));
|
||||||
|
memset(ancillary_element_buffer, 0, available_ancillary_element_buffer_space);
|
||||||
|
socket_message.msg_control = ancillary_element_buffer;
|
||||||
|
socket_message.msg_controllen = available_ancillary_element_buffer_space;
|
||||||
|
|
||||||
|
/* initialize a single ancillary data element for fd passing */
|
||||||
|
cmsghdr *control_message = NULL;
|
||||||
|
control_message = CMSG_FIRSTHDR(&socket_message);
|
||||||
|
control_message->cmsg_level = SOL_SOCKET;
|
||||||
|
control_message->cmsg_type = SCM_RIGHTS;
|
||||||
|
control_message->cmsg_len = CMSG_LEN(sizeof(int));
|
||||||
|
*((int *) CMSG_DATA(control_message)) = fd_to_send;
|
||||||
|
|
||||||
|
return sendmsg(socket, &socket_message, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosTool::didTransferApp(const QString &bundlePath, const QString &deviceId,
|
||||||
|
Ios::IosDeviceManager::OpStatus status)
|
||||||
|
{
|
||||||
|
Q_UNUSED(bundlePath);
|
||||||
|
Q_UNUSED(deviceId);
|
||||||
|
if (status == Ios::IosDeviceManager::Success) {
|
||||||
|
out.writeStartElement(QLatin1String("status"));
|
||||||
|
out.writeAttribute(QLatin1String("progress"), QString::number(maxProgress));
|
||||||
|
out.writeAttribute(QLatin1String("max_progress"), QString::number(maxProgress));
|
||||||
|
out.writeCharacters(QLatin1String("App Transferred"));
|
||||||
|
out.writeEndElement();
|
||||||
|
}
|
||||||
|
out.writeEmptyElement(QLatin1String("app_transfer"));
|
||||||
|
out.writeAttribute(QLatin1String("status"),
|
||||||
|
(status == Ios::IosDeviceManager::Success) ?
|
||||||
|
QLatin1String("SUCCESS") :
|
||||||
|
QLatin1String("FAILURE"));
|
||||||
|
//out.writeCharacters(QString()); // trigger a complete closing of the empty element
|
||||||
|
outFile.flush();
|
||||||
|
if (status != Ios::IosDeviceManager::Success || --opLeft == 0)
|
||||||
|
doExit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosTool::didStartApp(const QString &bundlePath, const QString &deviceId,
|
||||||
|
Ios::IosDeviceManager::OpStatus status, int gdbFd)
|
||||||
|
{
|
||||||
|
Q_UNUSED(bundlePath);
|
||||||
|
Q_UNUSED(deviceId);
|
||||||
|
out.writeEmptyElement(QLatin1String("app_started"));
|
||||||
|
out.writeAttribute(QLatin1String("status"),
|
||||||
|
(status == Ios::IosDeviceManager::Success) ?
|
||||||
|
QLatin1String("SUCCESS") :
|
||||||
|
QLatin1String("FAILURE"));
|
||||||
|
//out.writeCharacters(QString()); // trigger a complete closing of the empty element
|
||||||
|
outFile.flush();
|
||||||
|
if (appOp == Ios::IosDeviceManager::Install) {
|
||||||
|
doExit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (gdbFd <= 0) {
|
||||||
|
writeMsg("no gdb connection");
|
||||||
|
doExit(-2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (appOp != Ios::IosDeviceManager::InstallAndRun && appOp != Ios::IosDeviceManager::Run) {
|
||||||
|
writeMsg(QString::fromLatin1("unexpected appOp value %1").arg(appOp));
|
||||||
|
doExit(-3);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (debug) {
|
||||||
|
stopXml(0);
|
||||||
|
// these are 67 characters, this is used as read size on the other side...
|
||||||
|
const char *msg = "now sending the gdbserver socket, will need a unix socket to succeed";
|
||||||
|
outFile.write(msg, strlen(msg));
|
||||||
|
outFile.flush();
|
||||||
|
int sent = send_fd(1, gdbFd);
|
||||||
|
sleep(1);
|
||||||
|
QCoreApplication::exit(sent == -1);
|
||||||
|
} else {
|
||||||
|
if (!splitAppOutput) {
|
||||||
|
out.writeStartElement(QLatin1String("app_output"));
|
||||||
|
inAppOutput = true;
|
||||||
|
}
|
||||||
|
outFile.flush();
|
||||||
|
Ios::IosDeviceManager::instance()->processGdbServer(gdbFd);
|
||||||
|
if (!splitAppOutput) {
|
||||||
|
inAppOutput = false;
|
||||||
|
out.writeEndElement();
|
||||||
|
}
|
||||||
|
outFile.flush();
|
||||||
|
close(gdbFd);
|
||||||
|
doExit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosTool::writeMsg(const char *msg)
|
||||||
|
{
|
||||||
|
out.writeTextElement(QLatin1String("msg"), QLatin1String(msg));
|
||||||
|
outFile.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosTool::writeMsg(const QString &msg)
|
||||||
|
{
|
||||||
|
out.writeTextElement(QLatin1String("msg"), msg);
|
||||||
|
outFile.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosTool::deviceInfo(const QString &deviceId, const Ios::IosDeviceManager::Dict &devInfo)
|
||||||
|
{
|
||||||
|
Q_UNUSED(deviceId);
|
||||||
|
out.writeTextElement(QLatin1String("device_id"), deviceId);
|
||||||
|
out.writeStartElement(QLatin1String("device_info"));
|
||||||
|
QMapIterator<QString,QString> i(devInfo);
|
||||||
|
while (i.hasNext()) {
|
||||||
|
i.next();
|
||||||
|
out.writeStartElement(QLatin1String("item"));
|
||||||
|
out.writeTextElement(QLatin1String("key"), i.key());
|
||||||
|
out.writeTextElement(QLatin1String("value"), i.value());
|
||||||
|
out.writeEndElement();
|
||||||
|
}
|
||||||
|
out.writeEndElement();
|
||||||
|
outFile.flush();
|
||||||
|
doExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosTool::appOutput(const QString &output)
|
||||||
|
{
|
||||||
|
if (inAppOutput)
|
||||||
|
out.writeCharacters(output);
|
||||||
|
else
|
||||||
|
out.writeTextElement(QLatin1String("app_output"), output);
|
||||||
|
outFile.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IosTool::errorMsg(const QString &msg)
|
||||||
|
{
|
||||||
|
writeMsg(msg + QLatin1Char('\n'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QGuiApplication a(argc, argv);
|
||||||
|
IosTool tool;
|
||||||
|
tool.run(QCoreApplication::arguments());
|
||||||
|
int res = a.exec();
|
||||||
|
exit(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "main.moc"
|
@@ -4,13 +4,18 @@ SUBDIRS = qtpromaker \
|
|||||||
qmlpuppet \
|
qmlpuppet \
|
||||||
../plugins/cpaster/frontend \
|
../plugins/cpaster/frontend \
|
||||||
sdktool \
|
sdktool \
|
||||||
valgrindfake
|
valgrindfake \
|
||||||
|
3rdparty
|
||||||
|
|
||||||
win32 {
|
win32 {
|
||||||
SUBDIRS += qtcdebugger
|
SUBDIRS += qtcdebugger
|
||||||
SUBDIRS += wininterrupt
|
SUBDIRS += wininterrupt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mac {
|
||||||
|
SUBDIRS += iostool
|
||||||
|
}
|
||||||
|
|
||||||
QT_BREAKPAD_ROOT_PATH = $$(QT_BREAKPAD_ROOT_PATH)
|
QT_BREAKPAD_ROOT_PATH = $$(QT_BREAKPAD_ROOT_PATH)
|
||||||
!isEmpty(QT_BREAKPAD_ROOT_PATH) {
|
!isEmpty(QT_BREAKPAD_ROOT_PATH) {
|
||||||
SUBDIRS += qtcrashhandler
|
SUBDIRS += qtcrashhandler
|
||||||
|
@@ -7,6 +7,8 @@ Project {
|
|||||||
"qtcreatorcrashhandler/qtcreatorcrashhandler.qbs",
|
"qtcreatorcrashhandler/qtcreatorcrashhandler.qbs",
|
||||||
"qtpromaker/qtpromaker.qbs",
|
"qtpromaker/qtpromaker.qbs",
|
||||||
"sdktool/sdktool.qbs",
|
"sdktool/sdktool.qbs",
|
||||||
"valgrindfake/valgrindfake.qbs"
|
"valgrindfake/valgrindfake.qbs",
|
||||||
|
"3rdparty/iossim/iossim.qbs",
|
||||||
|
"iostool/iostool.qbs"
|
||||||
].concat(project.additionalTools)
|
].concat(project.additionalTools)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user