summaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
authorFawzi Mohamed <fawzi.mohamed@digia.com>2013-04-25 16:02:17 +0200
committerEike Ziller <eike.ziller@digia.com>2013-10-02 13:15:49 +0200
commit8d96ce557ef5b49d0cfea2b1633e09354948088c (patch)
tree8810583d9685f954b0d7ea6689b314fb2f2eb4bb /src/plugins
parent3a7d91ca4404937889986c54b730d7b01208cc27 (diff)
downloadqt-creator-8d96ce557ef5b49d0cfea2b1633e09354948088c.tar.gz
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>
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/ios/Ios.pluginspec.in17
-rwxr-xr-xsrc/plugins/ios/images/QtIos.pngbin0 -> 16512 bytes
-rw-r--r--src/plugins/ios/ios.pro69
-rw-r--r--src/plugins/ios/ios.qbs73
-rw-r--r--src/plugins/ios/ios.qrc5
-rw-r--r--src/plugins/ios/ios_dependencies.pri8
-rw-r--r--src/plugins/ios/iosbuildstep.cpp433
-rw-r--r--src/plugins/ios/iosbuildstep.h134
-rw-r--r--src/plugins/ios/iosbuildstep.ui65
-rw-r--r--src/plugins/ios/iosconfigurations.cpp448
-rw-r--r--src/plugins/ios/iosconfigurations.h90
-rw-r--r--src/plugins/ios/iosconstants.h67
-rw-r--r--src/plugins/ios/iosdebugsupport.cpp136
-rw-r--r--src/plugins/ios/iosdebugsupport.h73
-rw-r--r--src/plugins/ios/iosdeployconfiguration.cpp138
-rw-r--r--src/plugins/ios/iosdeployconfiguration.h82
-rw-r--r--src/plugins/ios/iosdeploystep.cpp231
-rw-r--r--src/plugins/ios/iosdeploystep.h135
-rw-r--r--src/plugins/ios/iosdeploystepfactory.cpp111
-rw-r--r--src/plugins/ios/iosdeploystepfactory.h62
-rw-r--r--src/plugins/ios/iosdeploystepwidget.cpp70
-rw-r--r--src/plugins/ios/iosdeploystepwidget.h61
-rw-r--r--src/plugins/ios/iosdeploystepwidget.ui26
-rw-r--r--src/plugins/ios/iosdevice.cpp519
-rw-r--r--src/plugins/ios/iosdevice.h111
-rw-r--r--src/plugins/ios/iosdevicefactory.cpp81
-rw-r--r--src/plugins/ios/iosdevicefactory.h58
-rw-r--r--src/plugins/ios/iosmanager.cpp76
-rw-r--r--src/plugins/ios/iosmanager.h55
-rw-r--r--src/plugins/ios/iosplugin.cpp96
-rw-r--r--src/plugins/ios/iosplugin.h52
-rw-r--r--src/plugins/ios/iosprobe.cpp355
-rw-r--r--src/plugins/ios/iosprobe.h84
-rw-r--r--src/plugins/ios/iosqtversion.cpp131
-rw-r--r--src/plugins/ios/iosqtversion.h67
-rw-r--r--src/plugins/ios/iosqtversionfactory.cpp78
-rw-r--r--src/plugins/ios/iosqtversionfactory.h54
-rw-r--r--src/plugins/ios/iosrunconfiguration.cpp275
-rw-r--r--src/plugins/ios/iosrunconfiguration.h78
-rw-r--r--src/plugins/ios/iosrunconfiguration.ui51
-rw-r--r--src/plugins/ios/iosruncontrol.cpp112
-rw-r--r--src/plugins/ios/iosruncontrol.h69
-rw-r--r--src/plugins/ios/iosrunfactories.cpp202
-rw-r--r--src/plugins/ios/iosrunfactories.h97
-rw-r--r--src/plugins/ios/iosrunner.cpp195
-rw-r--r--src/plugins/ios/iosrunner.h95
-rw-r--r--src/plugins/ios/iossettingspage.cpp75
-rw-r--r--src/plugins/ios/iossettingspage.h59
-rw-r--r--src/plugins/ios/iossettingswidget.cpp134
-rw-r--r--src/plugins/ios/iossettingswidget.h73
-rw-r--r--src/plugins/ios/iossettingswidget.ui90
-rw-r--r--src/plugins/ios/iossimulator.cpp142
-rw-r--r--src/plugins/ios/iossimulator.h80
-rw-r--r--src/plugins/ios/iossimulatorfactory.cpp81
-rw-r--r--src/plugins/ios/iossimulatorfactory.h55
-rw-r--r--src/plugins/ios/iostoolhandler.cpp977
-rw-r--r--src/plugins/ios/iostoolhandler.h107
-rw-r--r--src/plugins/plugins.pro4
-rw-r--r--src/plugins/plugins.qbs1
-rw-r--r--src/plugins/projectexplorer/gcctoolchain.h3
-rw-r--r--src/plugins/qtsupport/qtsupportconstants.h2
61 files changed, 7406 insertions, 2 deletions
diff --git a/src/plugins/ios/Ios.pluginspec.in b/src/plugins/ios/Ios.pluginspec.in
new file mode 100644
index 0000000000..dc4c0656d2
--- /dev/null
+++ b/src/plugins/ios/Ios.pluginspec.in
@@ -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>
diff --git a/src/plugins/ios/images/QtIos.png b/src/plugins/ios/images/QtIos.png
new file mode 100755
index 0000000000..b68467437a
--- /dev/null
+++ b/src/plugins/ios/images/QtIos.png
Binary files differ
diff --git a/src/plugins/ios/ios.pro b/src/plugins/ios/ios.pro
new file mode 100644
index 0000000000..476df08e52
--- /dev/null
+++ b/src/plugins/ios/ios.pro
@@ -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
+
diff --git a/src/plugins/ios/ios.qbs b/src/plugins/ios/ios.qbs
new file mode 100644
index 0000000000..5c1ad996c2
--- /dev/null
+++ b/src/plugins/ios/ios.qbs
@@ -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"
+ ]
+}
diff --git a/src/plugins/ios/ios.qrc b/src/plugins/ios/ios.qrc
new file mode 100644
index 0000000000..81314b84cd
--- /dev/null
+++ b/src/plugins/ios/ios.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/ios">
+ <file>images/QtIos.png</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/ios/ios_dependencies.pri b/src/plugins/ios/ios_dependencies.pri
new file mode 100644
index 0000000000..020498834b
--- /dev/null
+++ b/src/plugins/ios/ios_dependencies.pri
@@ -0,0 +1,8 @@
+QTC_PLUGIN_NAME = Ios
+QTC_LIB_DEPENDS += \
+ utils
+QTC_PLUGIN_DEPENDS += \
+ coreplugin \
+ debugger \
+ projectexplorer \
+ qt4projectmanager
diff --git a/src/plugins/ios/iosbuildstep.cpp b/src/plugins/ios/iosbuildstep.cpp
new file mode 100644
index 0000000000..df63f0ef8c
--- /dev/null
+++ b/src/plugins/ios/iosbuildstep.cpp
@@ -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
diff --git a/src/plugins/ios/iosbuildstep.h b/src/plugins/ios/iosbuildstep.h
new file mode 100644
index 0000000000..43d99ce8a4
--- /dev/null
+++ b/src/plugins/ios/iosbuildstep.h
@@ -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
diff --git a/src/plugins/ios/iosbuildstep.ui b/src/plugins/ios/iosbuildstep.ui
new file mode 100644
index 0000000000..70f1599101
--- /dev/null
+++ b/src/plugins/ios/iosbuildstep.ui
@@ -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>
diff --git a/src/plugins/ios/iosconfigurations.cpp b/src/plugins/ios/iosconfigurations.cpp
new file mode 100644
index 0000000000..19f0a4d8a8
--- /dev/null
+++ b/src/plugins/ios/iosconfigurations.cpp
@@ -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
diff --git a/src/plugins/ios/iosconfigurations.h b/src/plugins/ios/iosconfigurations.h
new file mode 100644
index 0000000000..0bb0f1abf3
--- /dev/null
+++ b/src/plugins/ios/iosconfigurations.h
@@ -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
diff --git a/src/plugins/ios/iosconstants.h b/src/plugins/ios/iosconstants.h
new file mode 100644
index 0000000000..915b91f119
--- /dev/null
+++ b/src/plugins/ios/iosconstants.h
@@ -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
diff --git a/src/plugins/ios/iosdebugsupport.cpp b/src/plugins/ios/iosdebugsupport.cpp
new file mode 100644
index 0000000000..2a9bf59445
--- /dev/null
+++ b/src/plugins/ios/iosdebugsupport.cpp
@@ -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
diff --git a/src/plugins/ios/iosdebugsupport.h b/src/plugins/ios/iosdebugsupport.h
new file mode 100644
index 0000000000..7d2047bfc5
--- /dev/null
+++ b/src/plugins/ios/iosdebugsupport.h
@@ -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
diff --git a/src/plugins/ios/iosdeployconfiguration.cpp b/src/plugins/ios/iosdeployconfiguration.cpp
new file mode 100644
index 0000000000..975a62647a
--- /dev/null
+++ b/src/plugins/ios/iosdeployconfiguration.cpp
@@ -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
diff --git a/src/plugins/ios/iosdeployconfiguration.h b/src/plugins/ios/iosdeployconfiguration.h
new file mode 100644
index 0000000000..632b2b5aa4
--- /dev/null
+++ b/src/plugins/ios/iosdeployconfiguration.h
@@ -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
diff --git a/src/plugins/ios/iosdeploystep.cpp b/src/plugins/ios/iosdeploystep.cpp
new file mode 100644
index 0000000000..f6bce58dbc
--- /dev/null
+++ b/src/plugins/ios/iosdeploystep.cpp
@@ -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
diff --git a/src/plugins/ios/iosdeploystep.h b/src/plugins/ios/iosdeploystep.h
new file mode 100644
index 0000000000..23988cf68f
--- /dev/null
+++ b/src/plugins/ios/iosdeploystep.h
@@ -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
diff --git a/src/plugins/ios/iosdeploystepfactory.cpp b/src/plugins/ios/iosdeploystepfactory.cpp
new file mode 100644
index 0000000000..8b8430fbe6
--- /dev/null
+++ b/src/plugins/ios/iosdeploystepfactory.cpp
@@ -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
diff --git a/src/plugins/ios/iosdeploystepfactory.h b/src/plugins/ios/iosdeploystepfactory.h
new file mode 100644
index 0000000000..9249488392
--- /dev/null
+++ b/src/plugins/ios/iosdeploystepfactory.h
@@ -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
diff --git a/src/plugins/ios/iosdeploystepwidget.cpp b/src/plugins/ios/iosdeploystepwidget.cpp
new file mode 100644
index 0000000000..d1e09b7adb
--- /dev/null
+++ b/src/plugins/ios/iosdeploystepwidget.cpp
@@ -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
diff --git a/src/plugins/ios/iosdeploystepwidget.h b/src/plugins/ios/iosdeploystepwidget.h
new file mode 100644
index 0000000000..1c3be04e40
--- /dev/null
+++ b/src/plugins/ios/iosdeploystepwidget.h
@@ -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
diff --git a/src/plugins/ios/iosdeploystepwidget.ui b/src/plugins/ios/iosdeploystepwidget.ui
new file mode 100644
index 0000000000..7b97b387b2
--- /dev/null
+++ b/src/plugins/ios/iosdeploystepwidget.ui
@@ -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>
diff --git a/src/plugins/ios/iosdevice.cpp b/src/plugins/ios/iosdevice.cpp
new file mode 100644
index 0000000000..853328a0ff
--- /dev/null
+++ b/src/plugins/ios/iosdevice.cpp
@@ -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
diff --git a/src/plugins/ios/iosdevice.h b/src/plugins/ios/iosdevice.h
new file mode 100644
index 0000000000..f8801ffbf5
--- /dev/null
+++ b/src/plugins/ios/iosdevice.h
@@ -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
diff --git a/src/plugins/ios/iosdevicefactory.cpp b/src/plugins/ios/iosdevicefactory.cpp
new file mode 100644
index 0000000000..980e8ea412
--- /dev/null
+++ b/src/plugins/ios/iosdevicefactory.cpp
@@ -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
diff --git a/src/plugins/ios/iosdevicefactory.h b/src/plugins/ios/iosdevicefactory.h
new file mode 100644
index 0000000000..c77ecc7483
--- /dev/null
+++ b/src/plugins/ios/iosdevicefactory.h
@@ -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
diff --git a/src/plugins/ios/iosmanager.cpp b/src/plugins/ios/iosmanager.cpp
new file mode 100644
index 0000000000..4f25cba3b9
--- /dev/null
+++ b/src/plugins/ios/iosmanager.cpp
@@ -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
diff --git a/src/plugins/ios/iosmanager.h b/src/plugins/ios/iosmanager.h
new file mode 100644
index 0000000000..83f1c58a02
--- /dev/null
+++ b/src/plugins/ios/iosmanager.h
@@ -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
diff --git a/src/plugins/ios/iosplugin.cpp b/src/plugins/ios/iosplugin.cpp
new file mode 100644
index 0000000000..c4eb232575
--- /dev/null
+++ b/src/plugins/ios/iosplugin.cpp
@@ -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)
diff --git a/src/plugins/ios/iosplugin.h b/src/plugins/ios/iosplugin.h
new file mode 100644
index 0000000000..832343919e
--- /dev/null
+++ b/src/plugins/ios/iosplugin.h
@@ -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
diff --git a/src/plugins/ios/iosprobe.cpp b/src/plugins/ios/iosprobe.cpp
new file mode 100644
index 0000000000..318220cb8d
--- /dev/null
+++ b/src/plugins/ios/iosprobe.cpp
@@ -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;
+}
+
+}
diff --git a/src/plugins/ios/iosprobe.h b/src/plugins/ios/iosprobe.h
new file mode 100644
index 0000000000..cc481881b5
--- /dev/null
+++ b/src/plugins/ios/iosprobe.h
@@ -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
diff --git a/src/plugins/ios/iosqtversion.cpp b/src/plugins/ios/iosqtversion.cpp
new file mode 100644
index 0000000000..881cc41567
--- /dev/null
+++ b/src/plugins/ios/iosqtversion.cpp
@@ -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);
+}
diff --git a/src/plugins/ios/iosqtversion.h b/src/plugins/ios/iosqtversion.h
new file mode 100644
index 0000000000..7c720a0590
--- /dev/null
+++ b/src/plugins/ios/iosqtversion.h
@@ -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
diff --git a/src/plugins/ios/iosqtversionfactory.cpp b/src/plugins/ios/iosqtversionfactory.cpp
new file mode 100644
index 0000000000..c842c5a9c2
--- /dev/null
+++ b/src/plugins/ios/iosqtversionfactory.cpp
@@ -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
diff --git a/src/plugins/ios/iosqtversionfactory.h b/src/plugins/ios/iosqtversionfactory.h
new file mode 100644
index 0000000000..d63b578086
--- /dev/null
+++ b/src/plugins/ios/iosqtversionfactory.h
@@ -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
diff --git a/src/plugins/ios/iosrunconfiguration.cpp b/src/plugins/ios/iosrunconfiguration.cpp
new file mode 100644
index 0000000000..851d6574be
--- /dev/null
+++ b/src/plugins/ios/iosrunconfiguration.cpp
@@ -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"
diff --git a/src/plugins/ios/iosrunconfiguration.h b/src/plugins/ios/iosrunconfiguration.h
new file mode 100644
index 0000000000..bb8dc31765
--- /dev/null
+++ b/src/plugins/ios/iosrunconfiguration.h
@@ -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
diff --git a/src/plugins/ios/iosrunconfiguration.ui b/src/plugins/ios/iosrunconfiguration.ui
new file mode 100644
index 0000000000..0b6e5f75b9
--- /dev/null
+++ b/src/plugins/ios/iosrunconfiguration.ui
@@ -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>
diff --git a/src/plugins/ios/iosruncontrol.cpp b/src/plugins/ios/iosruncontrol.cpp
new file mode 100644
index 0000000000..cbba7f0245
--- /dev/null
+++ b/src/plugins/ios/iosruncontrol.cpp
@@ -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
diff --git a/src/plugins/ios/iosruncontrol.h b/src/plugins/ios/iosruncontrol.h
new file mode 100644
index 0000000000..922a5bdd0c
--- /dev/null
+++ b/src/plugins/ios/iosruncontrol.h
@@ -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
diff --git a/src/plugins/ios/iosrunfactories.cpp b/src/plugins/ios/iosrunfactories.cpp
new file mode 100644
index 0000000000..2ddaf5e1b1
--- /dev/null
+++ b/src/plugins/ios/iosrunfactories.cpp
@@ -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
diff --git a/src/plugins/ios/iosrunfactories.h b/src/plugins/ios/iosrunfactories.h
new file mode 100644
index 0000000000..d45bd47069
--- /dev/null
+++ b/src/plugins/ios/iosrunfactories.h
@@ -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
diff --git a/src/plugins/ios/iosrunner.cpp b/src/plugins/ios/iosrunner.cpp
new file mode 100644
index 0000000000..e2cb6b6f8f
--- /dev/null
+++ b/src/plugins/ios/iosrunner.cpp
@@ -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
diff --git a/src/plugins/ios/iosrunner.h b/src/plugins/ios/iosrunner.h
new file mode 100644
index 0000000000..f7a82552e9
--- /dev/null
+++ b/src/plugins/ios/iosrunner.h
@@ -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
diff --git a/src/plugins/ios/iossettingspage.cpp b/src/plugins/ios/iossettingspage.cpp
new file mode 100644
index 0000000000..75270a86d2
--- /dev/null
+++ b/src/plugins/ios/iossettingspage.cpp
@@ -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
diff --git a/src/plugins/ios/iossettingspage.h b/src/plugins/ios/iossettingspage.h
new file mode 100644
index 0000000000..96ee190905
--- /dev/null
+++ b/src/plugins/ios/iossettingspage.h
@@ -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
diff --git a/src/plugins/ios/iossettingswidget.cpp b/src/plugins/ios/iossettingswidget.cpp
new file mode 100644
index 0000000000..74d1aa9e68
--- /dev/null
+++ b/src/plugins/ios/iossettingswidget.cpp
@@ -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
diff --git a/src/plugins/ios/iossettingswidget.h b/src/plugins/ios/iossettingswidget.h
new file mode 100644
index 0000000000..6f9b946352
--- /dev/null
+++ b/src/plugins/ios/iossettingswidget.h
@@ -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
diff --git a/src/plugins/ios/iossettingswidget.ui b/src/plugins/ios/iossettingswidget.ui
new file mode 100644
index 0000000000..c2293246fc
--- /dev/null
+++ b/src/plugins/ios/iossettingswidget.ui
@@ -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>
diff --git a/src/plugins/ios/iossimulator.cpp b/src/plugins/ios/iossimulator.cpp
new file mode 100644
index 0000000000..aa7ac3341b
--- /dev/null
+++ b/src/plugins/ios/iossimulator.cpp
@@ -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
diff --git a/src/plugins/ios/iossimulator.h b/src/plugins/ios/iossimulator.h
new file mode 100644
index 0000000000..2a6e85f123
--- /dev/null
+++ b/src/plugins/ios/iossimulator.h
@@ -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
diff --git a/src/plugins/ios/iossimulatorfactory.cpp b/src/plugins/ios/iossimulatorfactory.cpp
new file mode 100644
index 0000000000..7ee5d8e211
--- /dev/null
+++ b/src/plugins/ios/iossimulatorfactory.cpp
@@ -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
diff --git a/src/plugins/ios/iossimulatorfactory.h b/src/plugins/ios/iossimulatorfactory.h
new file mode 100644
index 0000000000..763912ce8e
--- /dev/null
+++ b/src/plugins/ios/iossimulatorfactory.h
@@ -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
diff --git a/src/plugins/ios/iostoolhandler.cpp b/src/plugins/ios/iostoolhandler.cpp
new file mode 100644
index 0000000000..e91276b6c0
--- /dev/null
+++ b/src/plugins/ios/iostoolhandler.cpp
@@ -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"
diff --git a/src/plugins/ios/iostoolhandler.h b/src/plugins/ios/iostoolhandler.h
new file mode 100644
index 0000000000..e817acc102
--- /dev/null
+++ b/src/plugins/ios/iostoolhandler.h
@@ -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
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index 430e135b40..6460e1d5fd 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -50,6 +50,10 @@ SUBDIRS = \
clearcase \
baremetal
+macx {
+ SUBDIRS += ios
+}
+
isEmpty(QBS_INSTALL_DIR): QBS_INSTALL_DIR = $$(QBS_INSTALL_DIR)
exists(../shared/qbs/qbs.pro)|!isEmpty(QBS_INSTALL_DIR): \
SUBDIRS += \
diff --git a/src/plugins/plugins.qbs b/src/plugins/plugins.qbs
index 0d276cf5b4..a91139a8ac 100644
--- a/src/plugins/plugins.qbs
+++ b/src/plugins/plugins.qbs
@@ -33,6 +33,7 @@ Project {
"helloworld/helloworld.qbs",
"help/help.qbs",
"imageviewer/imageviewer.qbs",
+ "ios/ios.qbs",
"locator/locator.qbs",
"macros/macros.qbs",
"madde/madde.qbs",
diff --git a/src/plugins/projectexplorer/gcctoolchain.h b/src/plugins/projectexplorer/gcctoolchain.h
index 64dda77a30..1361f4b433 100644
--- a/src/plugins/projectexplorer/gcctoolchain.h
+++ b/src/plugins/projectexplorer/gcctoolchain.h
@@ -148,6 +148,7 @@ private:
class PROJECTEXPLORER_EXPORT ClangToolChain : public GccToolChain
{
public:
+ explicit ClangToolChain(Detection d);
QString type() const;
QString typeDisplayName() const;
QString makeCommand(const Utils::Environment &environment) const;
@@ -166,8 +167,6 @@ protected:
virtual CompilerFlags defaultCompilerFlags() const;
private:
- explicit ClangToolChain(Detection d);
-
friend class Internal::ClangToolChainFactory;
friend class ToolChainFactory;
};
diff --git a/src/plugins/qtsupport/qtsupportconstants.h b/src/plugins/qtsupport/qtsupportconstants.h
index 386709e1fa..8d6860b3f3 100644
--- a/src/plugins/qtsupport/qtsupportconstants.h
+++ b/src/plugins/qtsupport/qtsupportconstants.h
@@ -69,6 +69,7 @@ const char DESKTOP_PLATFORM[] = "Desktop";
const char EMBEDDED_LINUX_PLATFORM[] = "Embedded Linux";
const char WINDOWS_CE_PLATFORM[] = "Windows CE";
const char ANDROID_PLATFORM[] = "Android";
+const char IOS_PLATFORM[] = "Ios";
const char MEEGO_HARMATTAN_PLATFORM_TR[] = QT_TRANSLATE_NOOP("QtSupport", "MeeGo/Harmattan");
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 WINDOWS_CE_PLATFORM_TR[] = QT_TRANSLATE_NOOP("QtSupport", "Windows CE");
const char ANDROID_PLATFORM_TR[] = QT_TRANSLATE_NOOP("QtSupport", "Android");
+const char IOS_PLATFORM_TR[] = QT_TRANSLATE_NOOP("QtSupport", "Ios");
// QML wizard icon
// both the qt4projectmanager and the qmlprojectmanager do have qt quick wizards