summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Hunger <tobias.hunger@digia.com>2012-10-05 16:54:49 +0200
committerTobias Hunger <tobias.hunger@digia.com>2013-01-24 15:11:20 +0100
commit90b19acccb27b082104ca80d3ec223b76117db4b (patch)
tree2054bc3ea447a1dcd2cfdbf0529821146aeed063
parentdf4530faadfae946fdc97752d4c174f272a72e22 (diff)
downloadqt-creator-90b19acccb27b082104ca80d3ec223b76117db4b.tar.gz
Initial version of qbs plugin
Change-Id: I9c995247d35f291496ffde5bf42522ac6a6f3609
-rw-r--r--qtcreator.qbs1
-rw-r--r--src/plugins/autotoolsprojectmanager/autotoolsbuildconfiguration.cpp2
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp2
-rw-r--r--src/plugins/genericprojectmanager/genericbuildconfiguration.cpp2
-rw-r--r--src/plugins/plugins.pro9
-rw-r--r--src/plugins/projectexplorer/buildsettingspropertiespage.cpp3
-rw-r--r--src/plugins/projectexplorer/projectnodes.cpp5
-rw-r--r--src/plugins/projectexplorer/projectnodes.h2
-rw-r--r--src/plugins/projectexplorer/projecttreewidget.cpp8
-rw-r--r--src/plugins/projectexplorer/taskhub.cpp2
-rw-r--r--src/plugins/qbsprojectmanager/QbsProjectManager.mimetypes.xml10
-rw-r--r--src/plugins/qbsprojectmanager/QbsProjectManager.pluginspec.in23
-rw-r--r--src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp339
-rw-r--r--src/plugins/qbsprojectmanager/qbsbuildconfiguration.h125
-rw-r--r--src/plugins/qbsprojectmanager/qbsbuildconfigurationwidget.cpp87
-rw-r--r--src/plugins/qbsprojectmanager/qbsbuildconfigurationwidget.h66
-rw-r--r--src/plugins/qbsprojectmanager/qbsbuildstep.cpp509
-rw-r--r--src/plugins/qbsprojectmanager/qbsbuildstep.h172
-rw-r--r--src/plugins/qbsprojectmanager/qbsbuildstepconfigwidget.ui88
-rw-r--r--src/plugins/qbsprojectmanager/qbscleanstep.cpp396
-rw-r--r--src/plugins/qbsprojectmanager/qbscleanstep.h155
-rw-r--r--src/plugins/qbsprojectmanager/qbscleanstepconfigwidget.ui65
-rw-r--r--src/plugins/qbsprojectmanager/qbslogsink.cpp131
-rw-r--r--src/plugins/qbsprojectmanager/qbslogsink.h61
-rw-r--r--src/plugins/qbsprojectmanager/qbsnodes.cpp294
-rw-r--r--src/plugins/qbsprojectmanager/qbsnodes.h149
-rw-r--r--src/plugins/qbsprojectmanager/qbsparser.cpp66
-rw-r--r--src/plugins/qbsprojectmanager/qbsparser.h59
-rw-r--r--src/plugins/qbsprojectmanager/qbsproject.cpp660
-rw-r--r--src/plugins/qbsprojectmanager/qbsproject.h146
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectfile.cpp112
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectfile.h71
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectmanager.cpp238
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectmanager.h90
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectmanager.pro53
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectmanager.qbs31
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectmanager.qrc5
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectmanager_dependencies.pri4
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectmanager_global.h41
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectmanagerconstants.h66
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.cpp194
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.h91
-rw-r--r--src/plugins/qmljseditor/QmlJSEditor.mimetypes.xml2
-rw-r--r--src/plugins/qt4projectmanager/qt4buildconfiguration.cpp10
-rw-r--r--src/plugins/qtsupport/baseqtversion.cpp35
-rw-r--r--src/plugins/qtsupport/baseqtversion.h9
46 files changed, 4672 insertions, 17 deletions
diff --git a/qtcreator.qbs b/qtcreator.qbs
index 4413f66cae..07e40f2157 100644
--- a/qtcreator.qbs
+++ b/qtcreator.qbs
@@ -59,6 +59,7 @@ Project {
"src/plugins/mercurial/mercurial.qbs",
"src/plugins/perforce/perforce.qbs",
"src/plugins/projectexplorer/projectexplorer.qbs",
+ "src/plugins/qbsprojectmanager/qbsprojectmanager.qbs",
// "src/plugins/qmldesigner/qmldesigner.qbs",
"src/plugins/qmljseditor/qmljseditor.qbs",
"src/plugins/qmljstools/qmljstools.qbs",
diff --git a/src/plugins/autotoolsprojectmanager/autotoolsbuildconfiguration.cpp b/src/plugins/autotoolsprojectmanager/autotoolsbuildconfiguration.cpp
index e7194452e4..53b519a043 100644
--- a/src/plugins/autotoolsprojectmanager/autotoolsbuildconfiguration.cpp
+++ b/src/plugins/autotoolsprojectmanager/autotoolsbuildconfiguration.cpp
@@ -150,7 +150,7 @@ AutotoolsBuildConfiguration *AutotoolsBuildConfigurationFactory::create(Target *
bool ok = true;
QString buildConfigurationName = name;
- if (buildConfigurationName.isEmpty())
+ if (buildConfigurationName.isNull())
buildConfigurationName = QInputDialog::getText(0,
tr("New Configuration"),
tr("New configuration name:"),
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp
index b9469c932e..ed52a42b54 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp
@@ -173,7 +173,7 @@ CMakeBuildConfiguration *CMakeBuildConfigurationFactory::create(ProjectExplorer:
bool ok = true;
QString buildConfigurationName = name;
- if (buildConfigurationName.isEmpty())
+ if (buildConfigurationName.isNull())
buildConfigurationName = QInputDialog::getText(0,
tr("New Configuration"),
tr("New configuration name:"),
diff --git a/src/plugins/genericprojectmanager/genericbuildconfiguration.cpp b/src/plugins/genericprojectmanager/genericbuildconfiguration.cpp
index d065040231..c422e62b37 100644
--- a/src/plugins/genericprojectmanager/genericbuildconfiguration.cpp
+++ b/src/plugins/genericprojectmanager/genericbuildconfiguration.cpp
@@ -155,7 +155,7 @@ BuildConfiguration *GenericBuildConfigurationFactory::create(Target *parent, con
// wizards will show up, that incorporate choosing the nam
bool ok = true;
QString buildConfigurationName = name;
- if (buildConfigurationName.isEmpty())
+ if (buildConfigurationName.isNull())
buildConfigurationName = QInputDialog::getText(0,
tr("New Configuration"),
tr("New configuration name:"),
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index e82b02806f..6432a23dfe 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -45,7 +45,8 @@ SUBDIRS = plugin_coreplugin \
plugin_madde \
plugin_valgrind \
plugin_todo \
- plugin_qnx
+ plugin_qnx \
+ plugin_qbsprojectmanager \
isEmpty(IDE_PACKAGE_MODE) {
SUBDIRS += plugin_helloworld \
@@ -332,6 +333,12 @@ plugin_qnx.depends += plugin_qt4projectmanager
plugin_qnx.depends += plugin_coreplugin
plugin_qnx.depends += plugin_texteditor
+plugin_qbsprojectmanager.subdir = qbsprojectmanager
+plugin_qbsprojectmanager.depends = plugin_texteditor
+plugin_qbsprojectmanager.depends += plugin_projectexplorer
+plugin_qbsprojectmanager.depends += plugin_cpptools
+plugin_qbsprojectmanager.depends += plugin_qtsupport
+
plugin_clearcase.subdir = clearcase
plugin_clearcase.depends = plugin_vcsbase
plugin_clearcase.depends += plugin_projectexplorer
diff --git a/src/plugins/projectexplorer/buildsettingspropertiespage.cpp b/src/plugins/projectexplorer/buildsettingspropertiespage.cpp
index c3e3548b5e..adfcc54c28 100644
--- a/src/plugins/projectexplorer/buildsettingspropertiespage.cpp
+++ b/src/plugins/projectexplorer/buildsettingspropertiespage.cpp
@@ -240,7 +240,8 @@ void BuildSettingsWidget::updateBuildSettings()
// Add pages
NamedWidget *generalConfigWidget = m_buildConfiguration->createConfigWidget();
- addSubWidget(generalConfigWidget);
+ if (generalConfigWidget)
+ addSubWidget(generalConfigWidget);
addSubWidget(new BuildStepsPage(m_buildConfiguration, Core::Id(Constants::BUILDSTEPS_BUILD)));
addSubWidget(new BuildStepsPage(m_buildConfiguration, Core::Id(Constants::BUILDSTEPS_CLEAN)));
diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp
index 696ca553e8..f493856ce9 100644
--- a/src/plugins/projectexplorer/projectnodes.cpp
+++ b/src/plugins/projectexplorer/projectnodes.cpp
@@ -102,6 +102,11 @@ QString Node::path() const
return m_path;
}
+int Node::line() const
+{
+ return -1;
+}
+
QString Node::displayName() const
{
return QFileInfo(path()).fileName();
diff --git a/src/plugins/projectexplorer/projectnodes.h b/src/plugins/projectexplorer/projectnodes.h
index 0b2f2e0945..bc1e13774c 100644
--- a/src/plugins/projectexplorer/projectnodes.h
+++ b/src/plugins/projectexplorer/projectnodes.h
@@ -85,6 +85,7 @@ public:
ProjectNode *projectNode() const; // managing project
FolderNode *parentFolderNode() const; // parent folder or project
QString path() const; // file system path
+ virtual int line() const;
virtual QString displayName() const;
virtual QString vcsTopic() const;
virtual QString tooltip() const;
@@ -331,7 +332,6 @@ private:
friend class Node;
};
-
} // namespace ProjectExplorer
// HACK: THERE SHOULD BE ONE PLACE TO MAKE THE FILE ENDING->FILE TYPE ASSOCIATION
diff --git a/src/plugins/projectexplorer/projecttreewidget.cpp b/src/plugins/projectexplorer/projecttreewidget.cpp
index 8e72e423cb..0da156558e 100644
--- a/src/plugins/projectexplorer/projecttreewidget.cpp
+++ b/src/plugins/projectexplorer/projecttreewidget.cpp
@@ -40,6 +40,7 @@
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/icontext.h>
#include <utils/qtcassert.h>
@@ -374,8 +375,11 @@ void ProjectTreeWidget::initView()
void ProjectTreeWidget::openItem(const QModelIndex &mainIndex)
{
Node *node = m_model->nodeForIndex(mainIndex);
- if (node->nodeType() == FileNodeType)
- EditorManager::openEditor(node->path(), Id(), EditorManager::ModeSwitch);
+ if (node->nodeType() != FileNodeType)
+ return;
+ Core::IEditor *editor = Core::EditorManager::openEditor(node->path(), Core::Id(), Core::EditorManager::ModeSwitch);
+ if (node->line() >= 0)
+ editor->gotoLine(node->line());
}
void ProjectTreeWidget::setProjectFilter(bool filter)
diff --git a/src/plugins/projectexplorer/taskhub.cpp b/src/plugins/projectexplorer/taskhub.cpp
index 99200097f1..0f505a7f51 100644
--- a/src/plugins/projectexplorer/taskhub.cpp
+++ b/src/plugins/projectexplorer/taskhub.cpp
@@ -102,7 +102,7 @@ void TaskHub::addCategory(const Core::Id &categoryId, const QString &displayName
void TaskHub::addTask(Task task)
{
- if (task.line != -1 && !task.file.isEmpty()) {
+ if (task.line >= 0 && !task.file.isEmpty()) {
bool visible = (task.type == Task::Warning || task.type == Task::Error);
TaskMark *mark = new TaskMark(task.taskId, task.file.toString(), task.line, visible);
mark->setIcon(taskTypeIcon(task.type));
diff --git a/src/plugins/qbsprojectmanager/QbsProjectManager.mimetypes.xml b/src/plugins/qbsprojectmanager/QbsProjectManager.mimetypes.xml
new file mode 100644
index 0000000000..5694b619ed
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/QbsProjectManager.mimetypes.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
+ <mime-type type="application/vnd.qtproject.qbsproject">
+ <alias type="text/x-qbs"/>
+ <sub-class-of type="text/x-qml"/>
+ <comment>QBS Project file</comment>
+ <glob pattern="*.qbp"/>
+ <glob pattern="*.qbs"/>
+ </mime-type>
+</mime-info>
diff --git a/src/plugins/qbsprojectmanager/QbsProjectManager.pluginspec.in b/src/plugins/qbsprojectmanager/QbsProjectManager.pluginspec.in
new file mode 100644
index 0000000000..a3490f3385
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/QbsProjectManager.pluginspec.in
@@ -0,0 +1,23 @@
+<plugin name=\"QbsProjectManager\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>Digia Plc</vendor>
+ <copyright>(C) 2012 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>
+ <category>Build Systems</category>
+ <description>QBS support</description>
+ <url>http://www.qt-project.org</url>
+ <dependencyList>
+ <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"CppTools\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"QtSupport\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"Designer\" version=\"$$QTCREATOR_VERSION\" type=\"optional\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp
new file mode 100644
index 0000000000..11cbe32af7
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp
@@ -0,0 +1,339 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 "qbsbuildconfiguration.h"
+
+#include "qbsbuildconfigurationwidget.h"
+#include "qbsbuildstep.h"
+#include "qbscleanstep.h"
+#include "qbsproject.h"
+#include "qbsprojectmanagerconstants.h"
+
+#include <utils/qtcassert.h>
+#include <projectexplorer/buildsteplist.h>
+#include <projectexplorer/kit.h>
+#include <projectexplorer/kitinformation.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/target.h>
+#include <projectexplorer/toolchain.h>
+
+#include <QInputDialog>
+
+// <debug>
+#include <QDebug>
+// </debug>
+
+static const char QBS_BC_ID[] = "Qbs.QbsBuildConfiguration";
+static const char QBS_BUILD_DIRECTORY_KEY[] = "Qbs.BuildDirectory";
+
+namespace QbsProjectManager {
+namespace Internal {
+
+// ---------------------------------------------------------------------------
+// QbsBuildConfiguration:
+// ---------------------------------------------------------------------------
+
+QbsBuildConfiguration::QbsBuildConfiguration(ProjectExplorer::Target *target) :
+ BuildConfiguration(target, Core::Id(QBS_BC_ID)),
+ m_isParsing(true),
+ m_parsingError(false)
+{
+ connect(project(), SIGNAL(projectParsingStarted()), this, SIGNAL(enabledChanged()));
+ connect(project(), SIGNAL(projectParsingDone(bool)), this, SIGNAL(enabledChanged()));
+
+ connect(this, SIGNAL(buildDirectoryChanged()), target, SLOT(onBuildDirectoryChanged()));
+ ProjectExplorer::BuildStepList *bsl
+ = stepList(Core::Id(ProjectExplorer::Constants::BUILDSTEPS_BUILD));
+ connect(bsl, SIGNAL(stepInserted(int)), this, SLOT(buildStepInserted(int)));
+}
+
+QbsBuildConfiguration::QbsBuildConfiguration(ProjectExplorer::Target *target, const Core::Id id) :
+ BuildConfiguration(target, id)
+{ }
+
+QbsBuildConfiguration::QbsBuildConfiguration(ProjectExplorer::Target *target, QbsBuildConfiguration *source) :
+ BuildConfiguration(target, source),
+ m_buildDirectory(source->m_buildDirectory)
+{
+ cloneSteps(source);
+}
+
+QVariantMap QbsBuildConfiguration::toMap() const
+{
+ QVariantMap map(BuildConfiguration::toMap());
+ map.insert(QLatin1String(QBS_BUILD_DIRECTORY_KEY), m_buildDirectory.toUserOutput());
+ return map;
+}
+
+bool QbsBuildConfiguration::fromMap(const QVariantMap &map)
+{
+ if (!BuildConfiguration::fromMap(map))
+ return false;
+
+ ProjectExplorer::BuildStepList *bsl
+ = stepList(Core::Id(ProjectExplorer::Constants::BUILDSTEPS_BUILD));
+ // Fix up the existing build steps:
+ for (int i = 0; i < bsl->count(); ++i) {
+ QbsBuildStep *bs = qobject_cast<QbsBuildStep *>(bsl->at(i));
+ if (bs)
+ connect(bs, SIGNAL(qbsConfigurationChanged()), this, SIGNAL(qbsConfigurationChanged()));
+ }
+
+ m_buildDirectory = Utils::FileName::fromUserInput(map.value(QLatin1String(QBS_BUILD_DIRECTORY_KEY)).toString());
+
+ return true;
+}
+
+void QbsBuildConfiguration::buildStepInserted(int pos)
+{
+ QbsBuildStep *step = qobject_cast<QbsBuildStep *>(stepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD)->at(pos));
+ if (step) {
+ connect(step, SIGNAL(qbsConfigurationChanged()), this, SIGNAL(qbsConfigurationChanged()));
+ emit qbsConfigurationChanged();
+ }
+}
+
+ProjectExplorer::NamedWidget *QbsBuildConfiguration::createConfigWidget()
+{
+ return new QbsBuildConfigurationWidget(this);
+}
+
+QbsBuildStep *QbsBuildConfiguration::qbsStep() const
+{
+ foreach (ProjectExplorer::BuildStep *bs,
+ stepList(Core::Id(ProjectExplorer::Constants::BUILDSTEPS_BUILD))->steps()) {
+ if (QbsBuildStep *qbsBs = qobject_cast<QbsBuildStep *>(bs))
+ return qbsBs;
+ }
+ return 0;
+}
+
+QVariantMap QbsBuildConfiguration::qbsConfiguration() const
+{
+ QVariantMap config;
+ QbsBuildStep *qbsBs = qbsStep();
+ if (qbsBs)
+ config = qbsBs->qbsConfiguration();
+ return config;
+}
+
+QString QbsBuildConfiguration::buildDirectory() const
+{
+ QString path = QDir::cleanPath(environment().expandVariables(m_buildDirectory.toString()));
+ return QDir::cleanPath(QDir(target()->project()->projectDirectory()).absoluteFilePath(path));
+}
+
+Internal::QbsProject *QbsBuildConfiguration::project() const
+{
+ return qobject_cast<Internal::QbsProject *>(target()->project());
+}
+
+ProjectExplorer::IOutputParser *QbsBuildConfiguration::createOutputParser() const
+{
+ ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainKitInformation::toolChain(target()->kit());
+ return tc ? tc->outputParser() : 0;
+}
+
+bool QbsBuildConfiguration::isEnabled() const
+{
+ return !project()->isParsing() && project()->hasParseResult();
+}
+
+QString QbsBuildConfiguration::disabledReason() const
+{
+ if (project()->isParsing())
+ return tr("Parsing the Qbs project.");
+ if (!project()->hasParseResult())
+ return tr("Parsing of Qbs project has failed.");
+ return QString();
+}
+
+ProjectExplorer::BuildConfiguration::BuildType QbsBuildConfiguration::buildType() const
+{
+ QString variant;
+ if (qbsStep())
+ variant = qbsStep()->buildVariant();
+
+ if (variant == QLatin1String(Constants::QBS_VARIANT_DEBUG))
+ return Debug;
+ if (variant == QLatin1String(Constants::QBS_VARIANT_RELEASE))
+ return Release;
+ return Unknown;
+}
+
+QbsBuildConfiguration *QbsBuildConfiguration::setup(ProjectExplorer::Target *t,
+ const QString &defaultDisplayName,
+ const QString &displayName,
+ const QVariantMap &buildData,
+ const Utils::FileName &directory)
+{
+ // Add the build configuration.
+ QbsBuildConfiguration *bc = new QbsBuildConfiguration(t);
+ bc->setDefaultDisplayName(defaultDisplayName);
+ bc->setDisplayName(displayName);
+ bc->setBuildDirectory(directory);
+
+ ProjectExplorer::BuildStepList *buildSteps
+ = bc->stepList(Core::Id(ProjectExplorer::Constants::BUILDSTEPS_BUILD));
+ QbsBuildStep *bs = new QbsBuildStep(buildSteps);
+ bs->setQbsConfiguration(buildData);
+ buildSteps->insertStep(0, bs);
+
+ ProjectExplorer::BuildStepList *cleanSteps
+ = bc->stepList(Core::Id(ProjectExplorer::Constants::BUILDSTEPS_CLEAN));
+ QbsCleanStep *cs = new QbsCleanStep(cleanSteps);
+ cleanSteps->insertStep(0, cs);
+
+ return bc;
+}
+
+void QbsBuildConfiguration::setBuildDirectory(const Utils::FileName &dir)
+{
+ if (m_buildDirectory == dir)
+ return;
+ m_buildDirectory = dir;
+ emit buildDirectoryChanged();
+}
+
+// ---------------------------------------------------------------------------
+// QbsBuildConfigurationFactory:
+// ---------------------------------------------------------------------------
+
+QbsBuildConfigurationFactory::QbsBuildConfigurationFactory(QObject *parent) :
+ IBuildConfigurationFactory(parent)
+{ }
+
+QbsBuildConfigurationFactory::~QbsBuildConfigurationFactory()
+{ }
+
+bool QbsBuildConfigurationFactory::canHandle(const ProjectExplorer::Target *t) const
+{
+ return qobject_cast<Internal::QbsProject *>(t->project());
+}
+
+QList<Core::Id> QbsBuildConfigurationFactory::availableCreationIds(const ProjectExplorer::Target *parent) const
+{
+ if (!canHandle(parent))
+ return QList<Core::Id>();
+ return QList<Core::Id>() << Core::Id(QBS_BC_ID);
+}
+
+QString QbsBuildConfigurationFactory::displayNameForId(const Core::Id id) const
+{
+ if (id == QBS_BC_ID)
+ return tr("Qbs based build");
+ return QString();
+}
+
+bool QbsBuildConfigurationFactory::canCreate(const ProjectExplorer::Target *parent, const Core::Id id) const
+{
+ if (!canHandle(parent))
+ return false;
+ return id == QBS_BC_ID;
+}
+
+ProjectExplorer::BuildConfiguration *QbsBuildConfigurationFactory::create(ProjectExplorer::Target *parent,
+ const Core::Id id,
+ const QString &name)
+{
+ if (!canCreate(parent, id))
+ return 0;
+
+ Internal::QbsProject *project = static_cast<Internal::QbsProject *>(parent->project());
+
+ bool ok = true;
+ QString buildConfigurationName = name;
+ if (buildConfigurationName.isNull())
+ buildConfigurationName = QInputDialog::getText(0,
+ tr("New Configuration"),
+ tr("New configuration name:"),
+ QLineEdit::Normal,
+ QString(), &ok);
+ buildConfigurationName = buildConfigurationName.trimmed();
+ if (!ok || buildConfigurationName.isEmpty())
+ return 0;
+
+ //: Debug build configuration. We recommend not translating it.
+ QString firstName = tr("%1 Debug").arg(buildConfigurationName).trimmed();
+
+ //: Release build configuration. We recommend not translating it.
+ QString secondName = tr("%1 Release").arg(buildConfigurationName).trimmed();
+
+ QVariantMap configData;
+ configData.insert(QLatin1String(Constants::QBS_CONFIG_VARIANT_KEY),
+ QLatin1String(Constants::QBS_VARIANT_DEBUG));
+
+ ProjectExplorer::BuildConfiguration *bc
+ = QbsBuildConfiguration::setup(parent, firstName, firstName,
+ configData, project->defaultBuildDirectory());
+ configData.insert(QLatin1String(Constants::QBS_CONFIG_VARIANT_KEY),
+ QLatin1String(Constants::QBS_VARIANT_RELEASE));
+ parent->addBuildConfiguration(
+ QbsBuildConfiguration::setup(parent, secondName, secondName,
+ configData, project->defaultBuildDirectory()));
+ return bc;
+}
+
+bool QbsBuildConfigurationFactory::canClone(const ProjectExplorer::Target *parent,
+ ProjectExplorer::BuildConfiguration *source) const
+{
+ return canHandle(parent) && qobject_cast<QbsBuildConfiguration *>(source);
+}
+
+ProjectExplorer::BuildConfiguration *QbsBuildConfigurationFactory::clone(ProjectExplorer::Target *parent,
+ ProjectExplorer::BuildConfiguration *source)
+{
+ if (!canClone(parent, source))
+ return 0;
+ QbsBuildConfiguration *oldbc(static_cast<QbsBuildConfiguration *>(source));
+ return new QbsBuildConfiguration(parent, oldbc);
+}
+
+bool QbsBuildConfigurationFactory::canRestore(const ProjectExplorer::Target *parent,
+ const QVariantMap &map) const
+{
+ if (!canHandle(parent))
+ return false;
+ return ProjectExplorer::idFromMap(map) == Core::Id(QBS_BC_ID);
+}
+
+ProjectExplorer::BuildConfiguration *QbsBuildConfigurationFactory::restore(ProjectExplorer::Target *parent,
+ const QVariantMap &map)
+{
+ if (!canRestore(parent, map))
+ return 0;
+ QbsBuildConfiguration *bc = new QbsBuildConfiguration(parent);
+ if (bc->fromMap(map))
+ return bc;
+ delete bc;
+ return 0;
+}
+
+} // namespace Internal
+} // namespace QbsProjectManager
diff --git a/src/plugins/qbsprojectmanager/qbsbuildconfiguration.h b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.h
new file mode 100644
index 0000000000..bc25e72be1
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 QBSBUILDCONFIGURATION_H
+#define QBSBUILDCONFIGURATION_H
+
+#include "qbsprojectmanager_global.h"
+
+#include <projectexplorer/buildconfiguration.h>
+#include <qtsupport/baseqtversion.h>
+
+namespace ProjectExplorer { class FileNode; }
+
+namespace QbsProjectManager {
+
+namespace Internal {
+
+class QbsBuildConfigurationFactory;
+class QbsBuildConfigurationWidget;
+class QbsBuildStep;
+class QbsProject;
+
+class QbsBuildConfiguration : public ProjectExplorer::BuildConfiguration
+{
+ Q_OBJECT
+
+public:
+ explicit QbsBuildConfiguration(ProjectExplorer::Target *target);
+
+ ProjectExplorer::NamedWidget *createConfigWidget();
+
+ QbsBuildStep *qbsStep() const;
+ QVariantMap qbsConfiguration() const;
+ QString buildDirectory() const;
+
+ Internal::QbsProject *project() const;
+
+ QVariantMap toMap() const;
+
+ ProjectExplorer::IOutputParser *createOutputParser() const;
+
+ bool isEnabled() const;
+ QString disabledReason() const;
+
+ BuildType buildType() const;
+
+signals:
+ void qbsConfigurationChanged();
+
+protected:
+ QbsBuildConfiguration(ProjectExplorer::Target *target, QbsBuildConfiguration *source);
+ QbsBuildConfiguration(ProjectExplorer::Target *target, const Core::Id id);
+ bool fromMap(const QVariantMap &map);
+
+private slots:
+ void buildStepInserted(int pos);
+
+private:
+ static QbsBuildConfiguration *setup(ProjectExplorer::Target *t,
+ const QString &defaultDisplayName,
+ const QString &displayName,
+ const QVariantMap &buildData,
+ const Utils::FileName &directory);
+ void setBuildDirectory(const Utils::FileName &dir);
+
+ bool m_isParsing;
+ bool m_parsingError;
+ Utils::FileName m_buildDirectory;
+
+ friend class QbsBuildConfigurationFactory;
+ friend class QbsBuildConfigurationWidget;
+};
+
+class QbsBuildConfigurationFactory : public ProjectExplorer::IBuildConfigurationFactory
+{
+ Q_OBJECT
+
+public:
+ explicit QbsBuildConfigurationFactory(QObject *parent = 0);
+ ~QbsBuildConfigurationFactory();
+
+ QList<Core::Id> availableCreationIds(const ProjectExplorer::Target *parent) const;
+ QString displayNameForId(const Core::Id id) const;
+
+ bool canCreate(const ProjectExplorer::Target *parent, const Core::Id id) const;
+ ProjectExplorer::BuildConfiguration *create(ProjectExplorer::Target *parent, const Core::Id id, const QString &name = QString());
+ bool canClone(const ProjectExplorer::Target *parent, ProjectExplorer::BuildConfiguration *source) const;
+ ProjectExplorer::BuildConfiguration *clone(ProjectExplorer::Target *parent, ProjectExplorer::BuildConfiguration *source);
+ bool canRestore(const ProjectExplorer::Target *parent, const QVariantMap &map) const;
+ ProjectExplorer::BuildConfiguration *restore(ProjectExplorer::Target *parent, const QVariantMap &map);
+
+private:
+ bool canHandle(const ProjectExplorer::Target *t) const;
+};
+
+} // namespace Internal
+} // namespace QbsProjectManager
+
+#endif // QBSBUILDCONFIGURATION_H
diff --git a/src/plugins/qbsprojectmanager/qbsbuildconfigurationwidget.cpp b/src/plugins/qbsprojectmanager/qbsbuildconfigurationwidget.cpp
new file mode 100644
index 0000000000..626c06045e
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsbuildconfigurationwidget.cpp
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 "qbsbuildconfigurationwidget.h"
+
+#include "qbsbuildconfiguration.h"
+
+#include <utils/detailswidget.h>
+#include <utils/pathchooser.h>
+
+#include <QGridLayout>
+#include <QLabel>
+#include <QWidget>
+
+namespace QbsProjectManager {
+namespace Internal {
+
+QbsBuildConfigurationWidget::QbsBuildConfigurationWidget(QbsProjectManager::Internal::QbsBuildConfiguration *bc) :
+ m_buildConfiguration(bc),
+ m_ignoreChange(false)
+{
+ connect(m_buildConfiguration, SIGNAL(buildDirectoryChanged()),
+ this, SLOT(buildDirectoryChanged()));
+
+ QVBoxLayout *vbox = new QVBoxLayout(this);
+ vbox->setMargin(0);
+ Utils::DetailsWidget *container = new Utils::DetailsWidget(this);
+ container->setState(Utils::DetailsWidget::NoSummary);
+ vbox->addWidget(container);
+
+ QWidget *details = new QWidget(container);
+ container->setWidget(details);
+
+ QGridLayout *layout = new QGridLayout(details);
+ layout->addWidget(new QLabel(tr("Build directory:"), 0, 0));
+
+ m_buildDirChooser = new Utils::PathChooser;
+ m_buildDirChooser->setExpectedKind(Utils::PathChooser::Directory);
+ layout->addWidget(m_buildDirChooser, 0, 1);
+
+ connect(m_buildDirChooser, SIGNAL(changed(QString)), this, SLOT(buildDirEdited()));
+
+ buildDirectoryChanged();
+}
+
+void QbsBuildConfigurationWidget::buildDirEdited()
+{
+ m_ignoreChange = true;
+ m_buildConfiguration->setBuildDirectory(m_buildDirChooser->fileName());
+}
+
+void QbsBuildConfigurationWidget::buildDirectoryChanged()
+{
+ if (m_ignoreChange)
+ return;
+
+ m_buildDirChooser->setPath(m_buildConfiguration->buildDirectory());
+}
+
+} // namespace Internal
+} // namespace QbsProjectManager
diff --git a/src/plugins/qbsprojectmanager/qbsbuildconfigurationwidget.h b/src/plugins/qbsprojectmanager/qbsbuildconfigurationwidget.h
new file mode 100644
index 0000000000..825f98588d
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsbuildconfigurationwidget.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 QBSBUILDCONFIGURATIONWIDGET_H
+#define QBSBUILDCONFIGURATIONWIDGET_H
+
+#include <projectexplorer/namedwidget.h>
+
+namespace Utils {
+class DetailsWidget;
+class PathChooser;
+} // namespace Utils
+
+namespace QbsProjectManager {
+namespace Internal {
+class QbsBuildConfiguration;
+
+class QbsBuildConfigurationWidget : public ProjectExplorer::NamedWidget
+{
+ Q_OBJECT
+
+public:
+ QbsBuildConfigurationWidget(Internal::QbsBuildConfiguration *bc);
+
+private slots:
+ void buildDirEdited();
+
+ // Changes triggered from creator
+ void buildDirectoryChanged();
+
+private:
+ Internal::QbsBuildConfiguration *m_buildConfiguration;
+ Utils::PathChooser *m_buildDirChooser;
+ bool m_ignoreChange;
+};
+
+} // namespace Internal
+} // namespace QbsProjectManager
+
+#endif // QBSBUILDCONFIGURATIONWIDGET_H
diff --git a/src/plugins/qbsprojectmanager/qbsbuildstep.cpp b/src/plugins/qbsprojectmanager/qbsbuildstep.cpp
new file mode 100644
index 0000000000..d274212c5a
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsbuildstep.cpp
@@ -0,0 +1,509 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 "qbsbuildstep.h"
+
+#include "qbsbuildconfiguration.h"
+#include "qbsparser.h"
+#include "qbsproject.h"
+#include "qbsprojectmanagerconstants.h"
+
+#include "ui_qbsbuildstepconfigwidget.h"
+
+#include <projectexplorer/buildsteplist.h>
+#include <projectexplorer/kit.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/target.h>
+#include <utils/qtcassert.h>
+
+// <debug>
+#include <QDebug>
+// </debug>
+
+static const char QBS_CONFIG[] = "Qbs.Configuration";
+static const char QBS_DRY_RUN[] = "Qbs.DryRun";
+static const char QBS_KEEP_GOING[] = "Qbs.DryKeepGoing";
+static const char QBS_MAXJOBCOUNT[] = "Qbs.MaxJobs";
+
+// --------------------------------------------------------------------
+// Constants:
+// --------------------------------------------------------------------
+
+namespace QbsProjectManager {
+namespace Internal {
+
+// --------------------------------------------------------------------
+// QbsBuildStep:
+// --------------------------------------------------------------------
+
+QbsBuildStep::QbsBuildStep(ProjectExplorer::BuildStepList *bsl) :
+ ProjectExplorer::BuildStep(bsl, Core::Id(Constants::QBS_BUILDSTEP_ID)),
+ m_job(0), m_showCompilerOutput(true), m_parser(0)
+{ }
+
+QbsBuildStep::QbsBuildStep(ProjectExplorer::BuildStepList *bsl, const QbsBuildStep *other) :
+ ProjectExplorer::BuildStep(bsl, Core::Id(Constants::QBS_BUILDSTEP_ID)),
+ m_qbsBuildOptions(other->m_qbsBuildOptions), m_job(0),
+ m_showCompilerOutput(other->m_showCompilerOutput), m_parser(0)
+{ }
+
+QbsBuildStep::~QbsBuildStep()
+{
+ cancel();
+ delete m_parser;
+}
+
+bool QbsBuildStep::init()
+{
+ if (static_cast<QbsProject *>(project())->isParsing() || m_job)
+ return false;
+
+ QbsBuildConfiguration *bc = static_cast<QbsBuildConfiguration *>(buildConfiguration());
+ if (!bc)
+ bc = static_cast<QbsBuildConfiguration *>(target()->activeBuildConfiguration());
+
+ if (!bc)
+ return false;
+
+ delete m_parser;
+ m_parser = new Internal::QbsParser;
+ ProjectExplorer::IOutputParser *parser = target()->kit()->createOutputParser();
+ if (parser)
+ m_parser->appendOutputParser(parser);
+
+ connect(m_parser, SIGNAL(addOutput(QString,ProjectExplorer::BuildStep::OutputFormat)),
+ this, SIGNAL(addOutput(QString,ProjectExplorer::BuildStep::OutputFormat)));
+ connect(m_parser, SIGNAL(addTask(ProjectExplorer::Task)),
+ this, SIGNAL(addTask(ProjectExplorer::Task)));
+
+ return true;
+}
+
+void QbsBuildStep::run(QFutureInterface<bool> &fi)
+{
+ m_fi = &fi;
+
+ // <// <debug>
+ m_progressCount = 0;
+ m_describeCount = 0;
+ m_warningCount = 0;
+ m_resultCount = 0;
+ // </debug>
+
+ QbsProject *pro = static_cast<QbsProject *>(project());
+ qbs::BuildOptions options(m_qbsBuildOptions);
+
+ m_job = pro->build(options);
+
+ if (!m_job) {
+ m_fi->reportResult(false);
+ return;
+ }
+
+ m_progressBase = 0;
+
+ m_timer.start();
+
+ connect(m_job, SIGNAL(finished(bool,qbs::AbstractJob*)), this, SLOT(buildingDone(bool)));
+ connect(m_job, SIGNAL(taskStarted(QString,int,qbs::AbstractJob*)),
+ this, SLOT(handleTaskStarted(QString,int)));
+ connect(m_job, SIGNAL(taskProgress(int,qbs::AbstractJob*)),
+ this, SLOT(handleProgress(int)));
+ connect(m_job, SIGNAL(reportCommandDescription(QString,QString)),
+ this, SLOT(handleCommandDescriptionReport(QString,QString)));
+ connect(m_job, SIGNAL(reportWarning(qbs::CodeLocation,QString)),
+ this, SLOT(handleWarningReport(qbs::CodeLocation,QString)));
+ connect(m_job, SIGNAL(reportProcessResult(qbs::ProcessResult)),
+ this, SLOT(handleProcessResultReport(qbs::ProcessResult)));
+}
+
+ProjectExplorer::BuildStepConfigWidget *QbsBuildStep::createConfigWidget()
+{
+ return new QbsBuildStepConfigWidget(this);
+}
+
+bool QbsBuildStep::runInGuiThread() const
+{
+ return true;
+}
+
+void QbsBuildStep::cancel()
+{
+ m_job->deleteLater();
+ m_job = 0;
+}
+
+QVariantMap QbsBuildStep::qbsConfiguration() const
+{
+ return m_qbsConfiguration;
+}
+
+void QbsBuildStep::setQbsConfiguration(const QVariantMap &config)
+{
+ QbsProject *pro = static_cast<QbsProject *>(project());
+
+ QVariantMap tmp = config;
+ tmp.insert(QLatin1String(Constants::QBS_CONFIG_PROFILE_KEY), pro->projectManager()->profileForKit(target()->kit()));
+ if (!tmp.contains(QLatin1String(Constants::QBS_CONFIG_VARIANT_KEY)))
+ tmp.insert(QLatin1String(Constants::QBS_CONFIG_VARIANT_KEY),
+ QString::fromLatin1(Constants::QBS_VARIANT_DEBUG));
+
+ if (tmp == m_qbsConfiguration)
+ return;
+ m_qbsConfiguration = tmp;
+ emit qbsConfigurationChanged();
+}
+
+bool QbsBuildStep::dryRun() const
+{
+ return m_qbsBuildOptions.dryRun;
+}
+
+bool QbsBuildStep::keepGoing() const
+{
+ return m_qbsBuildOptions.keepGoing;
+}
+
+int QbsBuildStep::maxJobs() const
+{
+ return m_qbsBuildOptions.maxJobCount;
+}
+
+bool QbsBuildStep::fromMap(const QVariantMap &map)
+{
+ if (!ProjectExplorer::BuildStep::fromMap(map))
+ return false;
+
+ setQbsConfiguration(map.value(QLatin1String(QBS_CONFIG)).toMap());
+ m_qbsBuildOptions.dryRun = map.value(QLatin1String(QBS_DRY_RUN)).toBool();
+ m_qbsBuildOptions.keepGoing = map.value(QLatin1String(QBS_KEEP_GOING)).toBool();
+ m_qbsBuildOptions.maxJobCount = map.value(QLatin1String(QBS_MAXJOBCOUNT)).toInt();
+ return true;
+}
+
+QVariantMap QbsBuildStep::toMap() const
+{
+ QVariantMap map = ProjectExplorer::BuildStep::toMap();
+ map.insert(QLatin1String(QBS_CONFIG), m_qbsConfiguration);
+ map.insert(QLatin1String(QBS_DRY_RUN), m_qbsBuildOptions.dryRun);
+ map.insert(QLatin1String(QBS_KEEP_GOING), m_qbsBuildOptions.keepGoing);
+ map.insert(QLatin1String(QBS_MAXJOBCOUNT), m_qbsBuildOptions.maxJobCount);
+ return map;
+}
+
+void QbsBuildStep::buildingDone(bool success)
+{
+ // Report errors:
+ foreach (const qbs::ErrorData &data, m_job->error().entries())
+ createTaskAndOutput(ProjectExplorer::Task::Error, data.description(), data.file(), data.line());
+
+ QTC_ASSERT(m_fi, return);
+ m_fi->reportResult(success);
+ m_fi = 0; // do not delete, it is not ours
+ m_job->deleteLater();
+ m_job = 0;
+
+ // <debug>
+// double elapsed = m_timer.elapsed() / 1000;
+// if (elapsed == 0)
+// elapsed = 0.001;
+
+// qDebug() << "QbsCounts:" << success << "in" << elapsed << "s\n"
+// << " Progress:" << m_progressCount << "(" << (m_progressCount / elapsed) << "/s)\n"
+// << " Warnings:" << m_warningCount << "(" << (m_warningCount / elapsed) << "/s)\n"
+// << " Describe:" << m_describeCount << "(" << (m_describeCount / elapsed) << "/s)\n"
+// << " Results :" << m_resultCount << "(" << (m_resultCount / elapsed) << "/s)\n";
+ // </debug>
+ emit finished();
+}
+
+void QbsBuildStep::handleTaskStarted(const QString &desciption, int max)
+{
+ Q_UNUSED(desciption);
+ QTC_ASSERT(m_fi, return);
+
+ m_progressBase = m_fi->progressValue();
+ m_fi->setProgressRange(0, m_progressBase + max);
+}
+
+void QbsBuildStep::handleProgress(int value)
+{
+ QTC_ASSERT(m_fi, return);
+ // <debug>
+ ++m_progressCount;
+ // </debug>
+ m_fi->setProgressValue(m_progressBase + value);
+}
+
+void QbsBuildStep::handleWarningReport(const qbs::CodeLocation &location, const QString &message)
+{
+ // <debug>
+ ++m_warningCount;
+ // </debug>
+ createTaskAndOutput(ProjectExplorer::Task::Warning, message, location.fileName, location.line);
+}
+
+void QbsBuildStep::handleCommandDescriptionReport(const QString &highlight, const QString &message)
+{
+ // <debug>
+ ++m_describeCount;
+ // </debug>
+ Q_UNUSED(highlight);
+ emit addOutput(message, NormalOutput);
+}
+
+void QbsBuildStep::handleProcessResultReport(const qbs::ProcessResult &result)
+{
+ // <debug>
+ ++m_resultCount;
+ // </debug>
+ bool hasOutput = !result.stdOut.isEmpty() || !result.stdErr.isEmpty();
+
+ if (result.success && !hasOutput && !m_showCompilerOutput)
+ return;
+
+ m_parser->setWorkingDirectory(result.workingDirectory);
+ foreach (const QString &line, result.stdErr) {
+ m_parser->stdError(line);
+ addOutput(line, ErrorOutput);
+ }
+ foreach (const QString &line, result.stdOut) {
+ m_parser->stdOutput(line);
+ addOutput(line, NormalOutput);
+ }
+}
+
+void QbsBuildStep::createTaskAndOutput(ProjectExplorer::Task::TaskType type, const QString &message,
+ const QString &file, int line)
+{
+ emit addTask(ProjectExplorer::Task(type, message,
+ Utils::FileName::fromString(file), line,
+ ProjectExplorer::Constants::TASK_CATEGORY_COMPILE));
+ emit addOutput(message, NormalOutput);
+}
+
+QString QbsBuildStep::buildVariant() const
+{
+ return qbsConfiguration().value(QLatin1String(Constants::QBS_CONFIG_VARIANT_KEY)).toString();
+}
+
+void QbsBuildStep::setBuildVariant(const QString &variant)
+{
+ if (m_qbsConfiguration.value(QLatin1String(Constants::QBS_CONFIG_VARIANT_KEY)).toString() == variant)
+ return;
+ m_qbsConfiguration.insert(QLatin1String(Constants::QBS_CONFIG_VARIANT_KEY), variant);
+ emit qbsConfigurationChanged();
+}
+
+QString QbsBuildStep::profile() const
+{
+ return qbsConfiguration().value(QLatin1String(Constants::QBS_CONFIG_PROFILE_KEY)).toString();
+}
+
+void QbsBuildStep::setDryRun(bool dr)
+{
+ if (m_qbsBuildOptions.dryRun == dr)
+ return;
+ m_qbsBuildOptions.dryRun = dr;
+ emit qbsBuildOptionsChanged();
+}
+
+void QbsBuildStep::setKeepGoing(bool kg)
+{
+ if (m_qbsBuildOptions.keepGoing == kg)
+ return;
+ m_qbsBuildOptions.keepGoing = kg;
+ emit qbsBuildOptionsChanged();
+}
+
+void QbsBuildStep::setMaxJobs(int jobcount)
+{
+ if (m_qbsBuildOptions.maxJobCount == jobcount)
+ return;
+ m_qbsBuildOptions.maxJobCount = jobcount;
+ emit qbsBuildOptionsChanged();
+}
+
+// --------------------------------------------------------------------
+// QbsBuildStepConfigWidget:
+// --------------------------------------------------------------------
+
+QbsBuildStepConfigWidget::QbsBuildStepConfigWidget(QbsBuildStep *step) :
+ m_step(step)
+{
+ connect(m_step, SIGNAL(displayNameChanged()), this, SLOT(updateState()));
+ connect(m_step, SIGNAL(qbsConfigurationChanged()), this, SLOT(updateState()));
+ connect(m_step, SIGNAL(qbsBuildOptionsChanged()), this, SLOT(updateState()));
+
+ setContentsMargins(0, 0, 0, 0);
+
+ m_ui = new Ui::QbsBuildStepConfigWidget;
+ m_ui->setupUi(this);
+
+ connect(m_ui->buildVariantComboBox, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(changeBuildVariant(int)));
+ connect(m_ui->dryRunCheckBox, SIGNAL(toggled(bool)), this, SLOT(changeDryRun(bool)));
+ connect(m_ui->keepGoingCheckBox, SIGNAL(toggled(bool)), this, SLOT(changeKeepGoing(bool)));
+ connect(m_ui->jobSpinBox, SIGNAL(valueChanged(int)), this, SLOT(changeJobCount(int)));
+
+ updateState();
+}
+
+QString QbsBuildStepConfigWidget::summaryText() const
+{
+ return m_summary;
+}
+
+QString QbsBuildStepConfigWidget::displayName() const
+{
+ return m_step->displayName();
+}
+
+void QbsBuildStepConfigWidget::updateState()
+{
+ m_ui->dryRunCheckBox->setChecked(m_step->dryRun());
+ m_ui->keepGoingCheckBox->setChecked(m_step->keepGoing());
+ m_ui->jobSpinBox->setValue(m_step->maxJobs());
+
+ const QString buildVariant = m_step->buildVariant();
+ const int idx = (buildVariant == QLatin1String(Constants::QBS_VARIANT_DEBUG)) ? 0 : 1;
+ m_ui->buildVariantComboBox->setCurrentIndex(idx);
+
+ qbs::BuildOptions defaultOptions;
+
+ QString command = QLatin1String("qbs ");
+ if (m_step->dryRun())
+ command += QLatin1String("--dryRun ");
+ if (m_step->keepGoing())
+ command += QLatin1String("--keepGoing ");
+ if (m_step->maxJobs() != defaultOptions.maxJobCount)
+ command += QString::fromLatin1("--jobs %1 ").arg(m_step->maxJobs());
+ command += QString::fromLatin1("build profile:%1 %2").arg(m_step->profile(), buildVariant);
+
+ QString summary = tr("<b>Qbs:</b> %1").arg(command);
+ if (m_summary != summary) {
+ m_summary = summary;
+ emit updateSummary();
+ }
+}
+
+void QbsBuildStepConfigWidget::changeBuildVariant(int idx)
+{
+ QString variant;
+ if (idx == 1)
+ variant = QLatin1String(Constants::QBS_VARIANT_RELEASE);
+ else
+ variant = QLatin1String(Constants::QBS_VARIANT_DEBUG);
+ m_step->setBuildVariant(variant);
+}
+
+void QbsBuildStepConfigWidget::changeDryRun(bool dr)
+{
+ m_step->setDryRun(dr);
+}
+
+void QbsBuildStepConfigWidget::changeKeepGoing(bool kg)
+{
+ m_step->setKeepGoing(kg);
+}
+
+void QbsBuildStepConfigWidget::changeJobCount(int count)
+{
+ m_step->setMaxJobs(count);
+}
+
+// --------------------------------------------------------------------
+// QbsBuildStepFactory:
+// --------------------------------------------------------------------
+
+QbsBuildStepFactory::QbsBuildStepFactory(QObject *parent) :
+ ProjectExplorer::IBuildStepFactory(parent)
+{ }
+
+QList<Core::Id> QbsBuildStepFactory::availableCreationIds(ProjectExplorer::BuildStepList *parent) const
+{
+ if (parent->id() == ProjectExplorer::Constants::BUILDSTEPS_BUILD
+ && qobject_cast<QbsBuildConfiguration *>(parent->parent()))
+ return QList<Core::Id>() << Core::Id(Constants::QBS_BUILDSTEP_ID);
+ return QList<Core::Id>();
+}
+
+QString QbsBuildStepFactory::displayNameForId(const Core::Id id) const
+{
+ if (id == Core::Id(Constants::QBS_BUILDSTEP_ID))
+ return tr("Qbs");
+ return QString();
+}
+
+bool QbsBuildStepFactory::canCreate(ProjectExplorer::BuildStepList *parent, const Core::Id id) const
+{
+ if (parent->id() != Core::Id(ProjectExplorer::Constants::BUILDSTEPS_BUILD)
+ || !qobject_cast<QbsBuildConfiguration *>(parent->parent()))
+ return false;
+ return id == Core::Id(Constants::QBS_BUILDSTEP_ID);
+}
+
+ProjectExplorer::BuildStep *QbsBuildStepFactory::create(ProjectExplorer::BuildStepList *parent, const Core::Id id)
+{
+ if (!canCreate(parent, id))
+ return 0;
+ return new QbsBuildStep(parent);
+}
+
+bool QbsBuildStepFactory::canRestore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) const
+{
+ return canCreate(parent, ProjectExplorer::idFromMap(map));
+}
+
+ProjectExplorer::BuildStep *QbsBuildStepFactory::restore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map)
+{
+ if (!canRestore(parent, map))
+ return 0;
+ QbsBuildStep *bs = new QbsBuildStep(parent);
+ if (!bs->fromMap(map)) {
+ delete bs;
+ return 0;
+ }
+ return bs;
+}
+
+bool QbsBuildStepFactory::canClone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product) const
+{
+ return canCreate(parent, product->id());
+}
+
+ProjectExplorer::BuildStep *QbsBuildStepFactory::clone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product)
+{
+ if (!canClone(parent, product))
+ return 0;
+ return new QbsBuildStep(parent, static_cast<QbsBuildStep *>(product));
+}
+
+} // namespace Internal
+} // namespace QbsProjectManager
diff --git a/src/plugins/qbsprojectmanager/qbsbuildstep.h b/src/plugins/qbsprojectmanager/qbsbuildstep.h
new file mode 100644
index 0000000000..59326d5cac
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsbuildstep.h
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 QBSBUILDSTEP_H
+#define QBSBUILDSTEP_H
+
+#include "qbsbuildconfiguration.h"
+
+#include <projectexplorer/buildstep.h>
+
+#include <api/jobs.h> // qbs
+#include <tools/buildoptions.h> // qbs
+
+// <debug>
+#include <QElapsedTimer>
+// </debug>
+
+namespace QbsProjectManager {
+namespace Internal {
+
+class QbsBuildStepConfigWidget;
+
+class QbsBuildStep : public ProjectExplorer::BuildStep
+{
+ Q_OBJECT
+
+public:
+ QbsBuildStep(ProjectExplorer::BuildStepList *bsl);
+ QbsBuildStep(ProjectExplorer::BuildStepList *bsl, const QbsBuildStep *other);
+ ~QbsBuildStep();
+
+ bool init();
+
+ void run(QFutureInterface<bool> &fi);
+
+ ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
+
+ bool runInGuiThread() const;
+ void cancel();
+
+ QVariantMap qbsConfiguration() const;
+ void setQbsConfiguration(const QVariantMap &config);
+
+ bool dryRun() const;
+ bool keepGoing() const;
+ int maxJobs() const;
+ QString buildVariant() const;
+
+ bool fromMap(const QVariantMap &map);
+ QVariantMap toMap() const;
+
+signals:
+ void qbsConfigurationChanged();
+ void qbsBuildOptionsChanged();
+
+private slots:
+ void buildingDone(bool success);
+ void handleTaskStarted(const QString &desciption, int max);
+ void handleProgress(int value);
+ void handleWarningReport(const qbs::CodeLocation &location, const QString &message);
+ void handleCommandDescriptionReport(const QString &highlight, const QString &message);
+ void handleProcessResultReport(const qbs::ProcessResult &result);
+
+private:
+ void createTaskAndOutput(ProjectExplorer::Task::TaskType type,
+ const QString &message, const QString &file, int line);
+
+ void setBuildVariant(const QString &variant);
+ QString profile() const;
+
+ void setDryRun(bool dr);
+ void setKeepGoing(bool kg);
+ void setMaxJobs(int jobcount);
+
+ QVariantMap m_qbsConfiguration;
+ qbs::BuildOptions m_qbsBuildOptions;
+
+ QFutureInterface<bool> *m_fi;
+ qbs::BuildJob *m_job;
+ int m_progressBase;
+ bool m_showCompilerOutput;
+ ProjectExplorer::IOutputParser *m_parser;
+
+ // <debug>
+ QElapsedTimer m_timer;
+ quint64 m_progressCount;
+ quint64 m_warningCount;
+ quint64 m_describeCount;
+ quint64 m_resultCount;
+ // </debug>
+
+ friend class QbsBuildStepConfigWidget;
+};
+
+namespace Ui { class QbsBuildStepConfigWidget; }
+
+class QbsBuildStepConfigWidget : public ProjectExplorer::BuildStepConfigWidget
+{
+ Q_OBJECT
+public:
+ QbsBuildStepConfigWidget(QbsBuildStep *step);
+ QString summaryText() const;
+ QString displayName() const;
+
+private slots:
+ void updateState();
+
+ void changeBuildVariant(int);
+ void changeDryRun(bool dr);
+ void changeKeepGoing(bool kg);
+ void changeJobCount(int count);
+
+private:
+ Ui::QbsBuildStepConfigWidget *m_ui;
+
+ QbsBuildStep *m_step;
+ QString m_summary;
+};
+
+
+class QbsBuildStepFactory : public ProjectExplorer::IBuildStepFactory
+{
+ Q_OBJECT
+
+public:
+ explicit QbsBuildStepFactory(QObject *parent = 0);
+
+ // used to show the list of possible additons to a target, returns a list of types
+ QList<Core::Id> availableCreationIds(ProjectExplorer::BuildStepList *parent) const;
+ // used to translate the types to names to display to the user
+ 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);
+ // used to recreate the runConfigurations when restoring settings
+ 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 QbsProjectManager
+
+#endif // QBSBUILDSTEP_H
diff --git a/src/plugins/qbsprojectmanager/qbsbuildstepconfigwidget.ui b/src/plugins/qbsprojectmanager/qbsbuildstepconfigwidget.ui
new file mode 100644
index 0000000000..cf0f48058c
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsbuildstepconfigwidget.ui
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>QbsProjectManager::Internal::QbsBuildStepConfigWidget</class>
+ <widget class="QWidget" name="QbsProjectManager::Internal::QbsBuildStepConfigWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>440</width>
+ <height>97</height>
+ </rect>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="verticalSpacing">
+ <number>16</number>
+ </property>
+ <item row="1" column="0" colspan="2">
+ <widget class="QFrame" name="frame">
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QCheckBox" name="dryRunCheckBox">
+ <property name="text">
+ <string>Dry run</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="keepGoingCheckBox">
+ <property name="text">
+ <string>Keep Going</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QSpinBox" name="jobSpinBox"/>
+ </item>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>jobs</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="buildVariantComboBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <item>
+ <property name="text">
+ <string>Debug</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Release</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="buildVariantLabel">
+ <property name="text">
+ <string>Build variant:</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/qbsprojectmanager/qbscleanstep.cpp b/src/plugins/qbsprojectmanager/qbscleanstep.cpp
new file mode 100644
index 0000000000..9209d33c85
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbscleanstep.cpp
@@ -0,0 +1,396 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 "qbscleanstep.h"
+
+#include "qbsbuildconfiguration.h"
+#include "qbsproject.h"
+#include "qbsprojectmanagerconstants.h"
+
+#include "ui_qbscleanstepconfigwidget.h"
+
+#include <projectexplorer/buildsteplist.h>
+#include <projectexplorer/kit.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/target.h>
+#include <utils/qtcassert.h>
+
+// <debug>
+#include <QDebug>
+// </debug>
+
+static const char QBS_CLEAN_ALL[] = "Qbs.CleanAll";
+static const char QBS_DRY_RUN[] = "Qbs.DryRun";
+static const char QBS_KEEP_GOING[] = "Qbs.DryKeepGoing";
+static const char QBS_MAXJOBCOUNT[] = "Qbs.MaxJobs";
+
+// --------------------------------------------------------------------
+// Constants:
+// --------------------------------------------------------------------
+
+namespace QbsProjectManager {
+namespace Internal {
+
+// --------------------------------------------------------------------
+// QbsCleanStep:
+// --------------------------------------------------------------------
+
+QbsCleanStep::QbsCleanStep(ProjectExplorer::BuildStepList *bsl) :
+ ProjectExplorer::BuildStep(bsl, Core::Id(Constants::QBS_CLEANSTEP_ID)),
+ m_cleanAll(false), m_job(0), m_showCompilerOutput(true), m_parser(0)
+{ }
+
+QbsCleanStep::QbsCleanStep(ProjectExplorer::BuildStepList *bsl, const QbsCleanStep *other) :
+ ProjectExplorer::BuildStep(bsl, Core::Id(Constants::QBS_CLEANSTEP_ID)),
+ m_qbsBuildOptions(other->m_qbsBuildOptions), m_cleanAll(other->m_cleanAll), m_job(0),
+ m_showCompilerOutput(other->m_showCompilerOutput), m_parser(0)
+{ }
+
+QbsCleanStep::~QbsCleanStep()
+{
+ cancel();
+}
+
+bool QbsCleanStep::init()
+{
+ if (static_cast<QbsProject *>(project())->isParsing() || m_job)
+ return false;
+
+ QbsBuildConfiguration *bc = static_cast<QbsBuildConfiguration *>(buildConfiguration());
+ if (!bc)
+ bc = static_cast<QbsBuildConfiguration *>(target()->activeBuildConfiguration());
+
+ if (!bc)
+ return false;
+
+ return true;
+}
+
+void QbsCleanStep::run(QFutureInterface<bool> &fi)
+{
+ m_fi = &fi;
+
+ QbsProject *pro = static_cast<QbsProject *>(project());
+ qbs::BuildOptions options(m_qbsBuildOptions);
+
+ m_job = pro->clean(options, m_cleanAll);
+
+ if (!m_job) {
+ m_fi->reportResult(false);
+ return;
+ }
+
+ m_progressBase = 0;
+
+ connect(m_job, SIGNAL(finished(bool,qbs::AbstractJob*)), this, SLOT(cleaningDone(bool)));
+ connect(m_job, SIGNAL(taskStarted(QString,int,qbs::AbstractJob*)),
+ this, SLOT(handleTaskStarted(QString,int)));
+ connect(m_job, SIGNAL(taskProgress(int,qbs::AbstractJob*)),
+ this, SLOT(handleProgress(int)));
+}
+
+ProjectExplorer::BuildStepConfigWidget *QbsCleanStep::createConfigWidget()
+{
+ return new QbsCleanStepConfigWidget(this);
+}
+
+bool QbsCleanStep::runInGuiThread() const
+{
+ return true;
+}
+
+void QbsCleanStep::cancel()
+{
+ // FIXME: Will this work? I somehow doubt it...
+ delete m_job;
+ m_job = 0;
+}
+
+bool QbsCleanStep::dryRun() const
+{
+ return m_qbsBuildOptions.dryRun;
+}
+
+bool QbsCleanStep::keepGoing() const
+{
+ return m_qbsBuildOptions.keepGoing;
+}
+
+int QbsCleanStep::maxJobs() const
+{
+ return m_qbsBuildOptions.maxJobCount;
+}
+
+bool QbsCleanStep::cleanAll() const
+{
+ return m_cleanAll;
+}
+
+bool QbsCleanStep::fromMap(const QVariantMap &map)
+{
+ if (!ProjectExplorer::BuildStep::fromMap(map))
+ return false;
+
+ m_qbsBuildOptions.dryRun = map.value(QLatin1String(QBS_DRY_RUN)).toBool();
+ m_qbsBuildOptions.keepGoing = map.value(QLatin1String(QBS_KEEP_GOING)).toBool();
+ m_qbsBuildOptions.maxJobCount = map.value(QLatin1String(QBS_MAXJOBCOUNT)).toInt();
+ m_cleanAll = map.value(QLatin1String(QBS_CLEAN_ALL)).toBool();
+
+ return true;
+}
+
+QVariantMap QbsCleanStep::toMap() const
+{
+ QVariantMap map = ProjectExplorer::BuildStep::toMap();
+ map.insert(QLatin1String(QBS_DRY_RUN), m_qbsBuildOptions.dryRun);
+ map.insert(QLatin1String(QBS_KEEP_GOING), m_qbsBuildOptions.keepGoing);
+ map.insert(QLatin1String(QBS_MAXJOBCOUNT), m_qbsBuildOptions.maxJobCount);
+ map.insert(QLatin1String(QBS_CLEAN_ALL), m_cleanAll);
+
+ return map;
+}
+
+void QbsCleanStep::cleaningDone(bool success)
+{
+ // Report errors:
+ foreach (const qbs::ErrorData &data, m_job->error().entries())
+ createTaskAndOutput(ProjectExplorer::Task::Error, data.description(), data.file(), data.line());
+
+ QTC_ASSERT(m_fi, return);
+ m_fi->reportResult(success);
+ m_fi = 0; // do not delete, it is not ours
+ m_job->deleteLater();
+ m_job = 0;
+
+ emit finished();
+}
+
+void QbsCleanStep::handleTaskStarted(const QString &desciption, int max)
+{
+ Q_UNUSED(desciption);
+ QTC_ASSERT(m_fi, return);
+ m_progressBase = m_fi->progressValue();
+ m_fi->setProgressRange(0, m_progressBase + max);
+}
+
+void QbsCleanStep::handleProgress(int value)
+{
+ QTC_ASSERT(m_fi, return);
+ m_fi->setProgressValue(m_progressBase + value);
+}
+
+void QbsCleanStep::createTaskAndOutput(ProjectExplorer::Task::TaskType type, const QString &message, const QString &file, int line)
+{
+ emit addTask(ProjectExplorer::Task(type, message,
+ Utils::FileName::fromString(file), line,
+ ProjectExplorer::Constants::TASK_CATEGORY_COMPILE));
+ emit addOutput(message, NormalOutput);
+}
+
+void QbsCleanStep::setDryRun(bool dr)
+{
+ if (m_qbsBuildOptions.dryRun == dr)
+ return;
+ m_qbsBuildOptions.dryRun = dr;
+ emit changed();
+}
+
+void QbsCleanStep::setKeepGoing(bool kg)
+{
+ if (m_qbsBuildOptions.keepGoing == kg)
+ return;
+ m_qbsBuildOptions.keepGoing = kg;
+ emit changed();
+}
+
+void QbsCleanStep::setMaxJobs(int jobcount)
+{
+ if (m_qbsBuildOptions.maxJobCount == jobcount)
+ return;
+ m_qbsBuildOptions.maxJobCount = jobcount;
+ emit changed();
+}
+
+void QbsCleanStep::setCleanAll(bool ca)
+{
+ if (m_cleanAll == ca)
+ return;
+ m_cleanAll = ca;
+ emit changed();
+}
+
+// --------------------------------------------------------------------
+// QbsCleanStepConfigWidget:
+// --------------------------------------------------------------------
+
+QbsCleanStepConfigWidget::QbsCleanStepConfigWidget(QbsCleanStep *step) :
+ m_step(step)
+{
+ connect(m_step, SIGNAL(displayNameChanged()), this, SLOT(updateState()));
+ connect(m_step, SIGNAL(changed()), this, SLOT(updateState()));
+
+ setContentsMargins(0, 0, 0, 0);
+
+ m_ui = new Ui::QbsCleanStepConfigWidget;
+ m_ui->setupUi(this);
+
+ connect(m_ui->cleanAllCheckBox, SIGNAL(toggled(bool)),
+ this, SLOT(changeCleanAll(bool)));
+ connect(m_ui->dryRunCheckBox, SIGNAL(toggled(bool)), this, SLOT(changeDryRun(bool)));
+ connect(m_ui->keepGoingCheckBox, SIGNAL(toggled(bool)), this, SLOT(changeKeepGoing(bool)));
+ connect(m_ui->jobSpinBox, SIGNAL(valueChanged(int)), this, SLOT(changeJobCount(int)));
+
+ updateState();
+}
+
+QString QbsCleanStepConfigWidget::summaryText() const
+{
+ return m_summary;
+}
+
+QString QbsCleanStepConfigWidget::displayName() const
+{
+ return m_step->displayName();
+}
+
+void QbsCleanStepConfigWidget::updateState()
+{
+ m_ui->cleanAllCheckBox->setChecked(m_step->cleanAll());
+ m_ui->dryRunCheckBox->setChecked(m_step->dryRun());
+ m_ui->keepGoingCheckBox->setChecked(m_step->keepGoing());
+ m_ui->jobSpinBox->setValue(m_step->maxJobs());
+
+ qbs::BuildOptions defaultOptions;
+
+ QString command = QLatin1String("qbs clean ");
+ if (m_step->dryRun())
+ command += QLatin1String("--dryRun ");
+ if (m_step->keepGoing())
+ command += QLatin1String("--keepGoing ");
+ if (m_step->maxJobs() != defaultOptions.maxJobCount)
+ command += QString::fromLatin1("--jobs %1 ").arg(m_step->maxJobs());
+ if (m_step->cleanAll())
+ command += QLatin1String(" --all-artifacts");
+
+ QString summary = tr("<b>Qbs:</b> %1").arg(command);
+ if (m_summary != summary) {
+ m_summary = summary;
+ emit updateSummary();
+ }
+}
+
+void QbsCleanStepConfigWidget::changeCleanAll(bool ca)
+{
+ m_step->setCleanAll(ca);
+}
+
+void QbsCleanStepConfigWidget::changeDryRun(bool dr)
+{
+ m_step->setDryRun(dr);
+}
+
+void QbsCleanStepConfigWidget::changeKeepGoing(bool kg)
+{
+ m_step->setKeepGoing(kg);
+}
+
+void QbsCleanStepConfigWidget::changeJobCount(int count)
+{
+ m_step->setMaxJobs(count);
+}
+
+// --------------------------------------------------------------------
+// QbsCleanStepFactory:
+// --------------------------------------------------------------------
+
+QbsCleanStepFactory::QbsCleanStepFactory(QObject *parent) :
+ ProjectExplorer::IBuildStepFactory(parent)
+{ }
+
+QList<Core::Id> QbsCleanStepFactory::availableCreationIds(ProjectExplorer::BuildStepList *parent) const
+{
+ if (parent->id() == ProjectExplorer::Constants::BUILDSTEPS_CLEAN
+ && qobject_cast<QbsBuildConfiguration *>(parent->parent()))
+ return QList<Core::Id>() << Core::Id(Constants::QBS_CLEANSTEP_ID);
+ return QList<Core::Id>();
+}
+
+QString QbsCleanStepFactory::displayNameForId(const Core::Id id) const
+{
+ if (id == Core::Id(Constants::QBS_CLEANSTEP_ID))
+ return tr("Qbs");
+ return QString();
+}
+
+bool QbsCleanStepFactory::canCreate(ProjectExplorer::BuildStepList *parent, const Core::Id id) const
+{
+ if (parent->id() != Core::Id(ProjectExplorer::Constants::BUILDSTEPS_CLEAN)
+ || !qobject_cast<QbsBuildConfiguration *>(parent->parent()))
+ return false;
+ return id == Core::Id(Constants::QBS_CLEANSTEP_ID);
+}
+
+ProjectExplorer::BuildStep *QbsCleanStepFactory::create(ProjectExplorer::BuildStepList *parent, const Core::Id id)
+{
+ if (!canCreate(parent, id))
+ return 0;
+ return new QbsCleanStep(parent);
+}
+
+bool QbsCleanStepFactory::canRestore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) const
+{
+ return canCreate(parent, ProjectExplorer::idFromMap(map));
+}
+
+ProjectExplorer::BuildStep *QbsCleanStepFactory::restore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map)
+{
+ if (!canRestore(parent, map))
+ return 0;
+ QbsCleanStep *bs = new QbsCleanStep(parent);
+ if (!bs->fromMap(map)) {
+ delete bs;
+ return 0;
+ }
+ return bs;
+}
+
+bool QbsCleanStepFactory::canClone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product) const
+{
+ return canCreate(parent, product->id());
+}
+
+ProjectExplorer::BuildStep *QbsCleanStepFactory::clone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product)
+{
+ if (!canClone(parent, product))
+ return 0;
+ return new QbsCleanStep(parent, static_cast<QbsCleanStep *>(product));
+}
+
+} // namespace Internal
+} // namespace QbsProjectManager
diff --git a/src/plugins/qbsprojectmanager/qbscleanstep.h b/src/plugins/qbsprojectmanager/qbscleanstep.h
new file mode 100644
index 0000000000..71a6e0cf83
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbscleanstep.h
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 QBSCLEANSTEP_H
+#define QBSCLEANSTEP_H
+
+#include "qbsbuildconfiguration.h"
+
+#include <projectexplorer/buildstep.h>
+
+#include <api/jobs.h> // qbs
+#include <tools/buildoptions.h> // qbs
+
+// <debug>
+#include <QElapsedTimer>
+// </debug>
+
+namespace QbsProjectManager {
+namespace Internal {
+
+class QbsCleanStepConfigWidget;
+
+class QbsCleanStep : public ProjectExplorer::BuildStep
+{
+ Q_OBJECT
+
+public:
+ QbsCleanStep(ProjectExplorer::BuildStepList *bsl);
+ QbsCleanStep(ProjectExplorer::BuildStepList *bsl, const QbsCleanStep *other);
+ ~QbsCleanStep();
+
+ bool init();
+
+ void run(QFutureInterface<bool> &fi);
+
+ ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
+
+ bool runInGuiThread() const;
+ void cancel();
+
+ bool fromMap(const QVariantMap &map);
+ QVariantMap toMap() const;
+
+ bool dryRun() const;
+ bool keepGoing() const;
+ int maxJobs() const;
+ bool cleanAll() const;
+
+signals:
+ void changed();
+
+private slots:
+ void cleaningDone(bool success);
+ void handleTaskStarted(const QString &desciption, int max);
+ void handleProgress(int value);
+
+private:
+ void createTaskAndOutput(ProjectExplorer::Task::TaskType type,
+ const QString &message, const QString &file, int line);
+
+ void setDryRun(bool dr);
+ void setKeepGoing(bool kg);
+ void setMaxJobs(int jobcount);
+ void setCleanAll(bool ca);
+
+ qbs::BuildOptions m_qbsBuildOptions;
+ bool m_cleanAll;
+
+ QFutureInterface<bool> *m_fi;
+ qbs::CleanJob *m_job;
+ int m_progressBase;
+ bool m_showCompilerOutput;
+ ProjectExplorer::IOutputParser *m_parser;
+
+ friend class QbsCleanStepConfigWidget;
+};
+
+namespace Ui { class QbsCleanStepConfigWidget; }
+
+class QbsCleanStepConfigWidget : public ProjectExplorer::BuildStepConfigWidget
+{
+ Q_OBJECT
+public:
+ QbsCleanStepConfigWidget(QbsCleanStep *step);
+ QString summaryText() const;
+ QString displayName() const;
+
+private slots:
+ void updateState();
+
+ void changeCleanAll(bool ca);
+ void changeDryRun(bool dr);
+ void changeKeepGoing(bool kg);
+ void changeJobCount(int jobcount);
+
+private:
+ Ui::QbsCleanStepConfigWidget *m_ui;
+
+ QbsCleanStep *m_step;
+ QString m_summary;
+};
+
+
+class QbsCleanStepFactory : public ProjectExplorer::IBuildStepFactory
+{
+ Q_OBJECT
+
+public:
+ explicit QbsCleanStepFactory(QObject *parent = 0);
+
+ // used to show the list of possible additons to a target, returns a list of types
+ QList<Core::Id> availableCreationIds(ProjectExplorer::BuildStepList *parent) const;
+ // used to translate the types to names to display to the user
+ 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);
+ // used to recreate the runConfigurations when restoring settings
+ 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 QbsProjectManager
+
+#endif // QBSCLEANSTEP_H
diff --git a/src/plugins/qbsprojectmanager/qbscleanstepconfigwidget.ui b/src/plugins/qbsprojectmanager/qbscleanstepconfigwidget.ui
new file mode 100644
index 0000000000..355f9b883d
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbscleanstepconfigwidget.ui
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>QbsProjectManager::Internal::QbsCleanStepConfigWidget</class>
+ <widget class="QWidget" name="QbsProjectManager::Internal::QbsCleanStepConfigWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>440</width>
+ <height>59</height>
+ </rect>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QCheckBox" name="cleanAllCheckBox">
+ <property name="text">
+ <string>Clean all artifacts</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QFrame" name="frame">
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QCheckBox" name="dryRunCheckBox">
+ <property name="text">
+ <string>Dry run</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="keepGoingCheckBox">
+ <property name="text">
+ <string>Keep Going</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QSpinBox" name="jobSpinBox"/>
+ </item>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>jobs</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/qbsprojectmanager/qbslogsink.cpp b/src/plugins/qbsprojectmanager/qbslogsink.cpp
new file mode 100644
index 0000000000..53f2e279c1
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbslogsink.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 "qbslogsink.h"
+
+#include <logging/logger.h> // qbs
+
+#include <coreplugin/messagemanager.h>
+
+#include <QCoreApplication>
+#include <QMutexLocker>
+#include <QTimer>
+
+namespace QbsProjectManager {
+namespace Internal {
+
+// --------------------------------------------------------------------
+// QbsLogSink:
+// --------------------------------------------------------------------
+
+void QbsLogSink::sendMessages()
+{
+ QStringList toSend;
+ {
+ QMutexLocker l(&m_mutex);
+ toSend = m_messages;
+ m_messages.clear();
+ }
+
+ Core::MessageManager *mm = Core::MessageManager::instance();
+ foreach (const QString &msg, toSend)
+ mm->printToOutputPanePopup(msg);
+}
+
+void QbsLogSink::outputLogMessage(qbs::LoggerLevel level, const qbs::LogMessage &logMessage)
+{
+ QString msg;
+ if (logMessage.printLogLevel) {
+ QByteArray levelTag = qbs::Logger::logLevelTag(level);
+ qbs::Internal::TextColor color = qbs::Internal::TextColorDefault;
+ switch (level) {
+ case qbs::LoggerError:
+ color = qbs::Internal::TextColorRed;
+ break;
+ case qbs::LoggerWarning:
+ color = qbs::Internal::TextColorYellow;
+ break;
+ default:
+ break;
+ }
+ msg = colorize(color, levelTag);
+ }
+
+ msg.append(colorize(logMessage.textColor, logMessage.data));
+
+ {
+ QMutexLocker l(&m_mutex);
+ m_messages.append(msg);
+ }
+ QMetaObject::invokeMethod(this, "sendMessages", Qt::QueuedConnection);
+}
+
+QString QbsLogSink::colorize(qbs::Internal::TextColor color, const QByteArray &text)
+{
+ switch (color) {
+ case qbs::Internal::TextColorBlack:
+ return QString::fromLatin1("<font color=\"rgb(0,0, 0)\">%1</font>").arg(QString::fromLocal8Bit(text));
+ case qbs::Internal::TextColorDarkRed:
+ return QString::fromLatin1("<font color=\"rgb(170,0,0)\">%1</font>").arg(QString::fromLocal8Bit(text));
+ case qbs::Internal::TextColorDarkGreen:
+ return QString::fromLatin1("<font color=\"rgb(0,170,0)\">%1</font>").arg(QString::fromLocal8Bit(text));
+ case qbs::Internal::TextColorDarkBlue:
+ return QString::fromLatin1("<font color=\"rgb(0,0,170)\">%1</font>").arg(QString::fromLocal8Bit(text));
+ case qbs::Internal::TextColorDarkCyan:
+ return QString::fromLatin1("<font color=\"rgb(0,170,170)\">%1</font>").arg(QString::fromLocal8Bit(text));
+ case qbs::Internal::TextColorDarkMagenta:
+ return QString::fromLatin1("<font color=\"rgb(170,0,170)\">%1</font>").arg(QString::fromLocal8Bit(text));
+ case qbs::Internal::TextColorDarkYellow:
+ return QString::fromLatin1("<font color=\"rgb(170,85,0)\">%1</font>").arg(QString::fromLocal8Bit(text));
+ case qbs::Internal::TextColorGray:
+ return QString::fromLatin1("<font color=\"rgb(170,170,170)\">%1</font>").arg(QString::fromLocal8Bit(text));
+ case qbs::Internal::TextColorRed:
+ return QString::fromLatin1("<font color=\"rgb(255,85,85)\">%1</font>").arg(QString::fromLocal8Bit(text));
+ case qbs::Internal::TextColorGreen:
+ return QString::fromLatin1("<font color=\"rgb(85,255,85)\">%1</font>").arg(QString::fromLocal8Bit(text));
+ case qbs::Internal::TextColorBlue:
+ return QString::fromLatin1("<font color=\"rgb(85,85,255)\">%1</font>").arg(QString::fromLocal8Bit(text));
+ case qbs::Internal::TextColorCyan:
+ return QString::fromLatin1("<font color=\"rgb(85,255,255)\">%1</font>").arg(QString::fromLocal8Bit(text));
+ case qbs::Internal::TextColorMagenta:
+ return QString::fromLatin1("<font color=\"rgb(255,85,255)\">%1</font>").arg(QString::fromLocal8Bit(text));
+ case qbs::Internal::TextColorYellow:
+ return QString::fromLatin1("<font color=\"rgb(255,255,85)\">%1</font>").arg(QString::fromLocal8Bit(text));
+ case qbs::Internal::TextColorWhite:
+ return QString::fromLatin1("<font color=\"rgb(255,255,255)\">%1</font>").arg(QString::fromLocal8Bit(text));
+ case qbs::Internal::TextColorBright:
+ case qbs::Internal::TextColorDefault:
+ // fallthrough:
+ default:
+ return QString::fromLocal8Bit(text);
+ }
+}
+
+} // namespace Internal
+} // namespace QbsProjectManager
diff --git a/src/plugins/qbsprojectmanager/qbslogsink.h b/src/plugins/qbsprojectmanager/qbslogsink.h
new file mode 100644
index 0000000000..0a5b67fe86
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbslogsink.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 QBSLOGSINK_H
+#define QBSLOGSINK_H
+
+#include <logging/ilogsink.h> // qbs
+
+#include <QMutex>
+#include <QObject>
+#include <QStringList>
+
+namespace QbsProjectManager {
+namespace Internal {
+
+class QbsLogSink : public QObject, public qbs::ILogSink
+{
+ Q_OBJECT
+
+private slots:
+ void sendMessages();
+
+private:
+ void outputLogMessage(qbs::LoggerLevel level, const qbs::LogMessage &logMessage);
+
+ QString colorize(qbs::TextColor color, const QByteArray &text);
+
+ QStringList m_messages;
+ QMutex m_mutex;
+};
+
+} // namespace Internal
+} // namespace QbsProjectManager
+
+#endif // QBSLOGSINK_H
diff --git a/src/plugins/qbsprojectmanager/qbsnodes.cpp b/src/plugins/qbsprojectmanager/qbsnodes.cpp
new file mode 100644
index 0000000000..c8c00d8248
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsnodes.cpp
@@ -0,0 +1,294 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 "qbsnodes.h"
+
+#include "qbsproject.h"
+
+#include <utils/qtcassert.h>
+
+#include <api/project.h> // qbs
+
+#include <QFileInfo>
+
+// --------------------------------------------------------------------
+// Helpers:
+// --------------------------------------------------------------------
+
+namespace {
+
+ProjectExplorer::FolderNode *findFolder(ProjectExplorer::FolderNode *root, const QString &name)
+{
+ foreach (ProjectExplorer::FolderNode *n, root->subFolderNodes()) {
+ if (n->displayName() == name)
+ return n;
+ }
+ return 0;
+}
+
+} // namespace
+
+namespace QbsProjectManager {
+namespace Internal {
+
+// ----------------------------------------------------------------------
+// QbsFileNode:
+// ----------------------------------------------------------------------
+
+QbsFileNode::QbsFileNode(const QString &filePath, const ProjectExplorer::FileType fileType,
+ bool generated, int line) :
+ ProjectExplorer::FileNode(filePath, fileType, generated),
+ m_line(line)
+{ }
+
+int QbsFileNode::line() const
+{
+ return m_line;
+}
+
+// ---------------------------------------------------------------------------
+// QbsBaseProjectNode:
+// ---------------------------------------------------------------------------
+
+QbsBaseProjectNode::QbsBaseProjectNode(const QString &path) :
+ ProjectExplorer::ProjectNode(path)
+{ }
+
+bool QbsBaseProjectNode::hasBuildTargets() const
+{
+ foreach (ProjectNode *n, subProjectNodes())
+ if (n->hasBuildTargets())
+ return true;
+ return false;
+}
+
+QList<ProjectExplorer::ProjectNode::ProjectAction> QbsBaseProjectNode::supportedActions(ProjectExplorer::Node *node) const
+{
+ Q_UNUSED(node);
+ return QList<ProjectExplorer::ProjectNode::ProjectAction>();
+}
+
+bool QbsBaseProjectNode::canAddSubProject(const QString &proFilePath) const
+{
+ Q_UNUSED(proFilePath);
+ return false;
+}
+
+bool QbsBaseProjectNode::addSubProjects(const QStringList &proFilePaths)
+{
+ Q_UNUSED(proFilePaths);
+ return false;
+}
+
+bool QbsBaseProjectNode::removeSubProjects(const QStringList &proFilePaths)
+{
+ Q_UNUSED(proFilePaths);
+ return false;
+}
+
+bool QbsBaseProjectNode::addFiles(const ProjectExplorer::FileType fileType, const QStringList &filePaths, QStringList *notAdded)
+{
+ Q_UNUSED(fileType);
+ Q_UNUSED(filePaths);
+ Q_UNUSED(notAdded);
+ return false;
+}
+
+bool QbsBaseProjectNode::removeFiles(const ProjectExplorer::FileType fileType, const QStringList &filePaths, QStringList *notRemoved)
+{
+ Q_UNUSED(fileType);
+ Q_UNUSED(filePaths);
+ Q_UNUSED(notRemoved);
+ return false;
+}
+
+bool QbsBaseProjectNode::deleteFiles(const ProjectExplorer::FileType fileType, const QStringList &filePaths)
+{
+ Q_UNUSED(fileType);
+ Q_UNUSED(filePaths);
+ return false;
+}
+
+bool QbsBaseProjectNode::renameFile(const ProjectExplorer::FileType fileType, const QString &filePath, const QString &newFilePath)
+{
+ Q_UNUSED(fileType);
+ Q_UNUSED(filePath);
+ Q_UNUSED(newFilePath);
+ return false;
+}
+
+QList<ProjectExplorer::RunConfiguration *> QbsBaseProjectNode::runConfigurationsFor(ProjectExplorer::Node *node)
+{
+ Q_UNUSED(node);
+ return QList<ProjectExplorer::RunConfiguration *>();
+}
+
+// --------------------------------------------------------------------
+// QbsGroupNode:
+// --------------------------------------------------------------------
+
+QbsGroupNode::QbsGroupNode(const qbs::GroupData *grp, const qbs::ProductData *prd) :
+ QbsBaseProjectNode(prd->location().fileName)
+{
+ setDisplayName(grp->name());
+ group = grp;
+
+ addFileNodes(QList<ProjectExplorer::FileNode *>()
+ << new QbsFileNode(grp->location().fileName,
+ ProjectExplorer::ProjectFileType, false, grp->location().line), this);
+
+ QString basePath = QFileInfo(prd->location().fileName).absolutePath();
+ if (!basePath.endsWith(QLatin1Char('/')))
+ basePath.append(QLatin1Char('/'));
+ foreach (const QString &p, grp->allFilePaths()) {
+ QString path = p;
+ if (path.startsWith(basePath))
+ path = path.mid(basePath.count());
+
+ QStringList pathSegments = path.split(QLatin1Char('/'), QString::SkipEmptyParts);
+ FolderNode *root = this;
+ while (pathSegments.count()) {
+ if (pathSegments.count() == 1) {
+ addFileNodes(QList<ProjectExplorer::FileNode *>()
+ << new ProjectExplorer::FileNode(p, ProjectExplorer::UnknownFileType, false),
+ root);
+ } else {
+ const QString folder = pathSegments.at(0);
+ FolderNode *n = findFolder(root, folder);
+ if (!n) {
+ n = new ProjectExplorer::FolderNode(folder);
+ addFolderNodes(QList<ProjectExplorer::FolderNode *>() << n, root);
+ }
+ root = n;
+ }
+ pathSegments.removeFirst();
+ };
+ }
+}
+
+// --------------------------------------------------------------------
+// QbsProductNode:
+// --------------------------------------------------------------------
+
+QbsProductNode::QbsProductNode(const qbs::ProductData *prd) :
+ QbsBaseProjectNode(prd->location().fileName)
+{
+ setDisplayName(prd->name());
+ product = prd;
+
+ addFileNodes(QList<ProjectExplorer::FileNode *>()
+ << new QbsFileNode(prd->location().fileName,
+ ProjectExplorer::ProjectFileType, false, prd->location().line), this);
+
+ QList<ProjectExplorer::ProjectNode *> toAdd;
+ foreach (const qbs::GroupData &grp, prd->groups())
+ toAdd << new QbsGroupNode(&grp, prd);
+
+ addProjectNodes(toAdd);
+}
+
+// --------------------------------------------------------------------
+// QbsProjectNode:
+// --------------------------------------------------------------------
+
+QbsProjectNode::QbsProjectNode(const QString &projectFile) :
+ QbsBaseProjectNode(projectFile),
+ m_project(0), m_projectData(0)
+{
+ addFileNodes(QList<ProjectExplorer::FileNode *>()
+ << new ProjectExplorer::FileNode(projectFile, ProjectExplorer::ProjectFileType, false), this);
+}
+
+QbsProjectNode::~QbsProjectNode()
+{
+ delete m_projectData;
+ delete m_project;
+}
+
+void QbsProjectNode::update(const qbs::Project *prj)
+{
+ QList<ProjectExplorer::ProjectNode *> toAdd;
+ QList<ProjectExplorer::ProjectNode *> toRemove;
+
+ QList<ProjectExplorer::ProjectNode *> oldNodeList = subProjectNodes();
+
+ delete m_projectData;
+ m_projectData = 0;
+
+ if (prj) {
+ m_projectData = new qbs::ProjectData(prj->projectData());
+ foreach (const qbs::ProductData &prd, m_projectData->products()) {
+ QbsProductNode *qn = findProductNode(prd.name());
+ if (!qn) {
+ toAdd << new QbsProductNode(&prd);
+ } else {
+ oldNodeList.removeOne(qn);
+
+ if (*qn->product != prd) {
+ toRemove << qn;
+ toAdd << new QbsProductNode(&prd);
+ }
+ }
+ }
+ }
+ toRemove.append(oldNodeList);
+
+ if (m_project) {
+ delete m_project;
+ m_project = 0;
+ }
+
+ m_project = prj;
+
+ removeProjectNodes(toRemove);
+ addProjectNodes(toAdd);
+}
+
+const qbs::Project *QbsProjectNode::project() const
+{
+ return m_project;
+}
+
+const qbs::ProjectData *QbsProjectNode::projectData() const
+{
+ return m_projectData;
+}
+
+QbsProductNode *QbsProjectNode::findProductNode(const QString &name)
+{
+ foreach(ProjectExplorer::ProjectNode *n, subProjectNodes()) {
+ QbsProductNode *qn = qobject_cast<QbsProductNode *>(n);
+ if (qn && (qn->product->name() == name))
+ return qn;
+ }
+ return 0;
+}
+
+} // namespace Internal
+} // namespace QbsProjectManager
diff --git a/src/plugins/qbsprojectmanager/qbsnodes.h b/src/plugins/qbsprojectmanager/qbsnodes.h
new file mode 100644
index 0000000000..def620efe0
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsnodes.h
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 QBSNODES_H
+#define QBSNODES_H
+
+#include <projectexplorer/projectnodes.h>
+
+#include <api/projectdata.h>
+
+namespace qbs { class Project; }
+
+namespace QbsProjectManager {
+namespace Internal {
+
+class QbsProjectFile;
+
+// ----------------------------------------------------------------------
+// QbsFileNode:
+// ----------------------------------------------------------------------
+
+class QbsFileNode : public ProjectExplorer::FileNode
+{
+ Q_OBJECT
+public:
+ QbsFileNode(const QString &filePath, const ProjectExplorer::FileType fileType, bool generated, int line);
+ int line() const;
+
+private:
+ int m_line;
+};
+
+// ---------------------------------------------------------------------------
+// QbsBaseProjectNode:
+// ---------------------------------------------------------------------------
+
+class QbsBaseProjectNode : public ProjectExplorer::ProjectNode
+{
+ Q_OBJECT
+
+public:
+ explicit QbsBaseProjectNode(const QString &path);
+
+ bool hasBuildTargets() const;
+
+ QList<ProjectAction> supportedActions(Node *node) const;
+
+ bool canAddSubProject(const QString &proFilePath) const;
+
+ bool addSubProjects(const QStringList &proFilePaths);
+
+ bool removeSubProjects(const QStringList &proFilePaths);
+
+ bool addFiles(const ProjectExplorer::FileType fileType,
+ const QStringList &filePaths,
+ QStringList *notAdded = 0);
+ bool removeFiles(const ProjectExplorer::FileType fileType,
+ const QStringList &filePaths,
+ QStringList *notRemoved = 0);
+ bool deleteFiles(const ProjectExplorer::FileType fileType,
+ const QStringList &filePaths);
+ bool renameFile(const ProjectExplorer::FileType fileType,
+ const QString &filePath,
+ const QString &newFilePath);
+
+ QList<ProjectExplorer::RunConfiguration *> runConfigurationsFor(Node *node);
+};
+
+// --------------------------------------------------------------------
+// QbsGroupNode:
+// --------------------------------------------------------------------
+
+class QbsGroupNode : public QbsBaseProjectNode
+{
+ Q_OBJECT
+
+public:
+ QbsGroupNode(const qbs::GroupData *grp, const qbs::ProductData *prd);
+
+ const qbs::GroupData *group;
+};
+
+// --------------------------------------------------------------------
+// QbsProductNode:
+// --------------------------------------------------------------------
+
+class QbsProductNode : public QbsBaseProjectNode
+{
+ Q_OBJECT
+
+public:
+ explicit QbsProductNode(const qbs::ProductData *prd);
+
+ const qbs::ProductData *product;
+};
+
+// ---------------------------------------------------------------------------
+// QbsProjectNode:
+// ---------------------------------------------------------------------------
+
+class QbsProjectNode : public QbsBaseProjectNode
+{
+ Q_OBJECT
+
+public:
+ explicit QbsProjectNode(const QString &projectFile);
+ ~QbsProjectNode();
+
+ void update(const qbs::Project *prj);
+
+ const qbs::Project *project() const;
+ const qbs::ProjectData *projectData() const;
+
+ QbsProductNode *findProductNode(const QString &name);
+
+private:
+ const qbs::Project *m_project;
+ const qbs::ProjectData *m_projectData;
+};
+} // namespace Internal
+} // namespace QbsProjectManager
+
+#endif // QBSNODES_H
diff --git a/src/plugins/qbsprojectmanager/qbsparser.cpp b/src/plugins/qbsprojectmanager/qbsparser.cpp
new file mode 100644
index 0000000000..dde588f9e8
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsparser.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 "qbsparser.h"
+
+#include <projectexplorer/task.h>
+
+#include <utils/fileutils.h>
+
+#include <QFileInfo>
+
+namespace QbsProjectManager {
+namespace Internal {
+
+QbsParser::QbsParser()
+{
+ setObjectName(QLatin1String("QbsParser"));
+}
+
+void QbsParser::setWorkingDirectory(const QString &workingDirectory)
+{
+ m_workingDirectory = QDir(workingDirectory);
+ IOutputParser::setWorkingDirectory(workingDirectory);
+}
+
+void QbsParser::taskAdded(const ProjectExplorer::Task &task)
+{
+ ProjectExplorer::Task editable(task);
+
+ QString filePath = task.file.toString();
+
+ if (!filePath.isEmpty())
+ editable.file = Utils::FileName::fromUserInput(m_workingDirectory.absoluteFilePath(filePath));
+
+ IOutputParser::taskAdded(editable);
+}
+
+} // namespace Internal
+} // namespace QbsProjectManager
+
diff --git a/src/plugins/qbsprojectmanager/qbsparser.h b/src/plugins/qbsprojectmanager/qbsparser.h
new file mode 100644
index 0000000000..7e50c61949
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsparser.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 QBSPARSER_H
+#define QBSPARSER_H
+
+#include <projectexplorer/ioutputparser.h>
+
+#include <QDir>
+
+namespace QbsProjectManager {
+namespace Internal {
+
+class PROJECTEXPLORER_EXPORT QbsParser : public ProjectExplorer::IOutputParser
+{
+ Q_OBJECT
+
+public:
+ explicit QbsParser();
+
+ void setWorkingDirectory(const QString &workingDirectory);
+
+public slots:
+ void taskAdded(const ProjectExplorer::Task &task);
+
+private:
+ QDir m_workingDirectory;
+};
+
+} // namespace Internal
+} // namespace ProjectExplorer
+
+#endif // QBSPARSER_H
diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp
new file mode 100644
index 0000000000..a416ee0d84
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsproject.cpp
@@ -0,0 +1,660 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 "qbsproject.h"
+
+#include "qbsbuildconfiguration.h"
+#include "qbsprojectfile.h"
+#include "qbsprojectmanagerconstants.h"
+#include "qbsnodes.h"
+
+#include <coreplugin/documentmanager.h>
+#include <utils/qtcassert.h>
+
+#include <language/language.h>
+
+#include <coreplugin/icontext.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/id.h>
+#include <coreplugin/progressmanager/progressmanager.h>
+#include <coreplugin/mimedatabase.h>
+#include <cpptools/cppmodelmanager.h>
+#include <projectexplorer/buildenvironmentwidget.h>
+#include <projectexplorer/kit.h>
+#include <projectexplorer/kitinformation.h>
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/target.h>
+#include <projectexplorer/taskhub.h>
+#include <qtsupport/qtkitinformation.h>
+
+#include <qmljs/qmljsmodelmanagerinterface.h>
+
+#include <api/jobs.h> // qbs
+#include <api/project.h> // qbs
+#include <api/projectdata.h> // qbs
+#include <tools/scripttools.h> // qbs
+
+#include <QFileInfo>
+
+// <debug>
+#include <QDebug>
+// </debug>
+
+// --------------------------------------------------------------------
+// Constants:
+// --------------------------------------------------------------------
+
+static const char CONFIG_CXXFLAGS[] = "cpp.cxxflags";
+static const char CONFIG_DEFINES[] = "cpp.defines";
+static const char CONFIG_INCLUDEPATHS[] = "cpp.includePaths";
+static const char CONFIG_FRAMEWORKPATHS[] = "cpp.frameworkPaths";
+static const char CONFIG_PRECOMPILEDHEADER[] = "modules.cpp.precompiledHeader";
+
+static const char CONFIGURATION_PATH[] = "<configuration>";
+
+// --------------------------------------------------------------------
+// HELPERS:
+// --------------------------------------------------------------------
+
+// FIXME: All this should be in QBS! They do the same thing in JS.
+
+static const char MODULES_KEY[] = "modules";
+
+ProjectExplorer::TaskHub *taskHub()
+{
+ return ProjectExplorer::ProjectExplorerPlugin::instance()->taskHub();
+}
+
+
+static QVariant extract(const QVariantMap &data, const QString &key)
+{
+ QStringList keyParts = key.split(QLatin1Char('.'), QString::SkipEmptyParts);
+ return qbs::Internal::getConfigProperty(data, keyParts);
+}
+
+static void expand(const QVariant &v, QStringList &partial, QSet<QString> &seenSet)
+{
+ if (v.isNull())
+ return;
+
+ QStringList tokenList;
+ if (v.type() == QVariant::StringList)
+ tokenList = v.toStringList();
+ else
+ tokenList << v.toString();
+
+ foreach (const QString &token, tokenList) {
+ if (!seenSet.contains(token)) {
+ partial << token;
+ seenSet.insert(token);
+ }
+ }
+}
+
+static QVariantList modules(const QVariantMap &root)
+{
+ QVariantList result;
+ if (!root.contains(QLatin1String(MODULES_KEY)))
+ return result;
+ const QVariantMap &moduleRoot = root.value(QLatin1String(MODULES_KEY)).toMap();
+ QVariantMap::const_iterator end = moduleRoot.end();
+ for (QVariantMap::const_iterator i = moduleRoot.begin(); i != end; ++i)
+ result << i.value();
+ return result;
+}
+
+static void recursiveAppendAll(const QString &key, const QVariantMap &root,
+ QStringList &partial, QSet<QString> &seenSet)
+{
+ if (root.isEmpty())
+ return;
+ expand(extract(root, key), partial, seenSet);
+ foreach (const QVariant &v, modules(root))
+ recursiveAppendAll(key, v.toMap(), partial, seenSet);
+}
+
+static QStringList appendAll(const QVariantMap &data, const QString &key)
+{
+ QStringList result;
+ QSet<QString> seenSet;
+ recursiveAppendAll(key, data, result, seenSet);
+ return result;
+}
+
+namespace QbsProjectManager {
+namespace Internal {
+
+// --------------------------------------------------------------------
+// QbsProject:
+// --------------------------------------------------------------------
+
+QbsProject::QbsProject(QbsManager *manager, const QString &fileName) :
+ m_manager(manager), m_projectName(QFileInfo(fileName).completeBaseName()), m_fileName(fileName),
+ m_rootProjectNode(new QbsProjectNode(fileName)),
+ m_qbsSetupProjectJob(0),
+ m_qbsUpdateFutureInterface(0),
+ m_currentBc(0)
+{
+ setProjectContext(Core::Context(Constants::PROJECT_ID));
+ setProjectLanguage(Core::Context(ProjectExplorer::Constants::LANG_CXX));
+
+ connect(this, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
+ this, SLOT(changeActiveTarget(ProjectExplorer::Target*)));
+ connect(this, SIGNAL(addedTarget(ProjectExplorer::Target*)),
+ this, SLOT(targetWasAdded(ProjectExplorer::Target*)));
+
+ // <debug>
+ m_reparseTimer.setInterval(200);
+ connect(&m_reparseTimer, SIGNAL(timeout()), this, SLOT(parseCurrentBuildConfiguration()));
+ // </debug>
+
+ updateDocuments(0);
+}
+
+QbsProject::~QbsProject()
+{
+ m_codeModelFuture.cancel();
+}
+
+QString QbsProject::displayName() const
+{
+ return m_projectName;
+}
+
+Core::Id QbsProject::id() const
+{
+ return Core::Id(Constants::PROJECT_ID);
+}
+
+Core::IDocument *QbsProject::document() const
+{
+ foreach (Core::IDocument *doc, m_qbsDocuments) {
+ if (doc->fileName() == m_fileName)
+ return doc;
+ }
+ QTC_ASSERT(false, return 0);
+}
+
+QbsManager *QbsProject::projectManager() const
+{
+ return m_manager;
+}
+
+ProjectExplorer::ProjectNode *QbsProject::rootProjectNode() const
+{
+ return m_rootProjectNode;
+}
+
+QStringList QbsProject::files(ProjectExplorer::Project::FilesMode fileMode) const
+{
+ Q_UNUSED(fileMode);
+ QStringList result;
+ if (m_rootProjectNode && m_rootProjectNode->projectData()) {
+ foreach (const qbs::ProductData &prd, m_rootProjectNode->projectData()->products())
+ foreach (const qbs::GroupData &grp, prd.groups())
+ result.append(grp.allFilePaths());
+ }
+ return result;
+}
+
+void QbsProject::invalidate()
+{
+ prepareForParsing();
+}
+
+qbs::BuildJob *QbsProject::build(const qbs::BuildOptions &opts)
+{
+ if (!m_rootProjectNode || !m_rootProjectNode->project())
+ return 0;
+ return m_rootProjectNode->project()->buildAllProducts(opts);
+}
+
+qbs::CleanJob *QbsProject::clean(const qbs::BuildOptions &opts, bool everything)
+{
+ if (!m_rootProjectNode || !m_rootProjectNode->project())
+ return 0;
+ return m_rootProjectNode->project()->cleanAllProducts(opts, everything ? qbs::Project::CleanupAll
+ : qbs::Project::CleanupTemporaries);
+}
+
+QString QbsProject::profileForTarget(const ProjectExplorer::Target *t) const
+{
+ return m_manager->profileForKit(t->kit());
+}
+
+bool QbsProject::isParsing() const
+{
+ return m_qbsUpdateFutureInterface;
+}
+
+bool QbsProject::hasParseResult() const
+{
+ return m_rootProjectNode->project();
+}
+
+Utils::FileName QbsProject::defaultBuildDirectory() const
+{
+ QFileInfo fi(m_fileName);
+ const QString buildDir = QDir(fi.canonicalPath()).absoluteFilePath(QString::fromLatin1("../%1-build").arg(fi.baseName()));
+ return Utils::FileName::fromString(buildDir);
+}
+
+void QbsProject::handleQbsParsingDone(bool success)
+{
+ QTC_ASSERT(m_qbsSetupProjectJob, return);
+ QTC_ASSERT(m_qbsUpdateFutureInterface, return);
+
+ qbs::Project *project = 0;
+ if (success) {
+ project = new qbs::Project(m_qbsSetupProjectJob->project());
+ } else {
+ generateErrors(m_qbsSetupProjectJob->error());
+ m_qbsUpdateFutureInterface->reportCanceled();
+ }
+ m_qbsSetupProjectJob->deleteLater();
+ m_qbsSetupProjectJob = 0;
+
+ m_qbsUpdateFutureInterface->reportFinished();
+ delete m_qbsUpdateFutureInterface;
+ m_qbsUpdateFutureInterface = 0;
+
+ m_rootProjectNode->update(project);
+
+ updateDocuments(m_rootProjectNode->projectData());
+
+ updateCppCodeModel(m_rootProjectNode->projectData());
+ updateQmlJsCodeModel(m_rootProjectNode->projectData());
+
+ emit projectParsingDone(success);
+}
+
+void QbsProject::handleQbsParsingProgress(int progress)
+{
+ if (m_qbsUpdateFutureInterface)
+ m_qbsUpdateFutureInterface->setProgressValue(m_currentProgressBase + progress);
+}
+
+void QbsProject::handleQbsParsingTaskSetup(const QString &description, int maximumProgressValue)
+{
+ Q_UNUSED(description);
+ if (m_qbsUpdateFutureInterface) {
+ m_currentProgressBase = m_qbsUpdateFutureInterface->progressValue();
+ m_qbsUpdateFutureInterface->setProgressRange(0, m_currentProgressBase + maximumProgressValue);
+ }
+}
+
+void QbsProject::targetWasAdded(ProjectExplorer::Target *t)
+{
+ connect(t, SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
+ this, SLOT(parseCurrentBuildConfiguration()));
+ connect(t, SIGNAL(buildDirectoryChanged()),
+ this, SLOT(parseCurrentBuildConfiguration()));
+}
+
+void QbsProject::changeActiveTarget(ProjectExplorer::Target *t)
+{
+ ProjectExplorer::BuildConfiguration *bc = 0;
+ if (t && t->kit())
+ bc = t->activeBuildConfiguration();
+ buildConfigurationChanged(bc);
+}
+
+void QbsProject::buildConfigurationChanged(ProjectExplorer::BuildConfiguration *bc)
+{
+ if (m_currentBc)
+ disconnect(m_currentBc, SIGNAL(qbsConfigurationChanged()), this, SLOT(parseCurrentBuildConfiguration()));
+
+ m_currentBc = qobject_cast<QbsBuildConfiguration *>(bc);
+ if (m_currentBc) {
+ connect(m_currentBc, SIGNAL(qbsConfigurationChanged()), this, SLOT(parseCurrentBuildConfiguration()));
+ parseCurrentBuildConfiguration();
+ } else {
+ invalidate();
+ }
+}
+
+void QbsProject::parseCurrentBuildConfiguration()
+{
+ if (!activeTarget())
+ return;
+ QbsBuildConfiguration *bc = qobject_cast<QbsBuildConfiguration *>(activeTarget()->activeBuildConfiguration());
+ if (!bc)
+ return;
+ parse(bc->qbsConfiguration(), bc->buildDirectory());
+}
+
+bool QbsProject::fromMap(const QVariantMap &map)
+{
+ if (!Project::fromMap(map))
+ return false;
+
+ ProjectExplorer::KitManager *km = ProjectExplorer::KitManager::instance();
+ if (!activeTarget() && km->defaultKit()) {
+ ProjectExplorer::Target *t = new ProjectExplorer::Target(this, km->defaultKit());
+ t->updateDefaultBuildConfigurations();
+ t->updateDefaultDeployConfigurations();
+ t->updateDefaultRunConfigurations();
+ addTarget(t);
+ }
+
+ return true;
+}
+
+void QbsProject::generateErrors(const qbs::Error &e)
+{
+ foreach (const qbs::ErrorData &data, e.entries())
+ taskHub()->addTask(ProjectExplorer::Task(ProjectExplorer::Task::Error,
+ data.description(),
+ Utils::FileName::fromString(data.file()), data.line(),
+ ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+}
+
+void QbsProject::parse(const QVariantMap &config, const QString &dir)
+{
+ // <debug>
+ // if (!m_reparseTimer.isActive()) m_reparseTimer.start();
+ // </debug>
+
+ QTC_ASSERT(!dir.isNull(), return);
+ prepareForParsing();
+ m_qbsBuildConfig = config;
+ m_qbsBuildRoot = dir;
+
+ // <debug>
+ qDebug() << "QBS: Buildroot:" << m_qbsBuildRoot;
+ // </debug>
+
+ QTC_ASSERT(!m_qbsSetupProjectJob, return);
+ m_qbsSetupProjectJob = qbs::Project::setupProject(m_fileName, m_qbsBuildConfig, m_qbsBuildRoot, 0);
+
+ connect(m_qbsSetupProjectJob, SIGNAL(finished(bool,qbs::AbstractJob*)),
+ this, SLOT(handleQbsParsingDone(bool)));
+ connect(m_qbsSetupProjectJob, SIGNAL(taskStarted(QString,int,qbs::AbstractJob*)),
+ this, SLOT(handleQbsParsingTaskSetup(QString,int)));
+ connect(m_qbsSetupProjectJob, SIGNAL(taskProgress(int,qbs::AbstractJob*)),
+ this, SLOT(handleQbsParsingProgress(int)));
+}
+
+void QbsProject::prepareForParsing()
+{
+ taskHub()->clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
+ if (m_qbsUpdateFutureInterface)
+ m_qbsUpdateFutureInterface->reportCanceled();
+ delete m_qbsUpdateFutureInterface;
+ m_qbsUpdateFutureInterface = 0;
+
+ // FIXME: Christian claims this should work
+ delete m_qbsSetupProjectJob;
+ m_qbsSetupProjectJob = 0;
+
+ m_currentProgressBase = 0;
+ m_qbsUpdateFutureInterface = new QFutureInterface<void>();
+ m_qbsUpdateFutureInterface->setProgressRange(0, 0);
+ Core::ICore::progressManager()->addTask(m_qbsUpdateFutureInterface->future(), tr("Evaluating"),
+ QLatin1String(Constants::QBS_EVALUATE));
+ m_qbsUpdateFutureInterface->reportStarted();
+}
+
+void QbsProject::updateDocuments(const qbs::ProjectData *prj)
+{
+ // Update documents:
+ QSet<QString> newFiles;
+ newFiles.insert(m_fileName); // make sure we always have the project file...
+
+ if (prj) {
+ newFiles.insert(prj->location().fileName);
+ foreach (const qbs::ProductData &prd, prj->products())
+ newFiles.insert(prd.location().fileName);
+ }
+ QSet<QString> oldFiles;
+ foreach (Core::IDocument *doc, m_qbsDocuments)
+ oldFiles.insert(doc->fileName());
+
+ QSet<QString> filesToAdd = newFiles;
+ filesToAdd.subtract(oldFiles);
+ QSet<QString> filesToRemove = oldFiles;
+ filesToRemove.subtract(newFiles);
+
+ QSet<Core::IDocument *> currentDocuments = m_qbsDocuments;
+ foreach (Core::IDocument *doc, currentDocuments) {
+ if (filesToRemove.contains(doc->fileName())) {
+ m_qbsDocuments.remove(doc);
+ delete doc;
+ }
+ }
+ QSet<Core::IDocument *> toAdd;
+ foreach (const QString &f, filesToAdd)
+ toAdd.insert(new QbsProjectFile(this, f));
+
+ Core::DocumentManager::instance()->addDocuments(toAdd.toList());
+ m_qbsDocuments.unite(toAdd);
+}
+
+void QbsProject::updateCppCodeModel(const qbs::ProjectData *prj)
+{
+ ProjectExplorer::Kit *k = 0;
+ QtSupport::BaseQtVersion *qtVersion = 0;
+ ProjectExplorer::ToolChain *tc = 0;
+ if (ProjectExplorer::Target *target = activeTarget())
+ k = target->kit();
+ else
+ k = ProjectExplorer::KitManager::instance()->defaultKit();
+ qtVersion = QtSupport::QtKitInformation::qtVersion(k);
+ tc = ProjectExplorer::ToolChainKitInformation::toolChain(k);
+
+ CPlusPlus::CppModelManagerInterface *modelmanager =
+ CPlusPlus::CppModelManagerInterface::instance();
+
+ if (!modelmanager)
+ return;
+
+ CPlusPlus::CppModelManagerInterface::ProjectInfo pinfo = modelmanager->projectInfo(this);
+ pinfo.clearProjectParts();
+ CPlusPlus::CppModelManagerInterface::ProjectPart::QtVersion qtVersionForPart
+ = CPlusPlus::CppModelManagerInterface::ProjectPart::NoQt;
+ if (qtVersion) {
+ if (qtVersion->qtVersion() < QtSupport::QtVersionNumber(5,0,0))
+ qtVersionForPart = CPlusPlus::CppModelManagerInterface::ProjectPart::Qt4;
+ else
+ qtVersionForPart = CPlusPlus::CppModelManagerInterface::ProjectPart::Qt5;
+ }
+
+ QStringList allFiles;
+ foreach (const qbs::ProductData &prd, prj->products()) {
+ foreach (const qbs::GroupData &grp, prd.groups()) {
+ QVariantMap props = grp.properties();
+
+ QStringList grpIncludePaths;
+ QStringList grpFrameworkPaths;
+ QByteArray grpDefines;
+ bool isCxx11;
+ const QStringList cxxFlags = appendAll(props, QLatin1String(CONFIG_CXXFLAGS));
+
+ // Toolchain specific stuff:
+ QList<ProjectExplorer::HeaderPath> includePaths;
+ if (tc) {
+ includePaths = tc->systemHeaderPaths(cxxFlags, ProjectExplorer::SysRootKitInformation::sysRoot(k));
+ grpDefines += tc->predefinedMacros(cxxFlags);
+ if (tc->compilerFlags(cxxFlags) == ProjectExplorer::ToolChain::STD_CXX11)
+ isCxx11 = true;
+ }
+ foreach (const ProjectExplorer::HeaderPath &headerPath, includePaths) {
+ if (headerPath.kind() == ProjectExplorer::HeaderPath::FrameworkHeaderPath)
+ grpFrameworkPaths.append(headerPath.path());
+ else
+ grpIncludePaths.append(headerPath.path());
+ }
+
+ QStringList list = appendAll(props, QLatin1String(CONFIG_DEFINES));
+ foreach (const QString &def, list)
+ grpDefines += (QByteArray("#define ") + def.toUtf8() + '\n');
+
+ list = appendAll(props, QLatin1String(CONFIG_INCLUDEPATHS));
+ foreach (const QString &p, list) {
+ const QString cp = Utils::FileName::fromUserInput(p).toString();
+ grpIncludePaths.append(cp);
+ }
+
+ list = appendAll(props, QLatin1String(CONFIG_FRAMEWORKPATHS));
+ foreach (const QString &p, list) {
+ const QString cp = Utils::FileName::fromUserInput(p).toString();
+ grpFrameworkPaths.append(cp);
+ }
+
+ const QString pch = extract(props, QLatin1String(CONFIG_PRECOMPILEDHEADER)).toString();
+
+ QStringList cxxSources;
+ QStringList cSources;
+ QStringList headers;
+ QStringList objcSources;
+ cxxSources << QLatin1String(CONFIGURATION_PATH);
+ cSources << QLatin1String(CONFIGURATION_PATH);
+ objcSources << QLatin1String(CONFIGURATION_PATH);
+
+ foreach (const QString &file, grp.allFilePaths()) {
+ QFileInfo fi = QFileInfo(file);
+ if (!fi.exists())
+ continue;
+
+ Core::MimeType t = Core::ICore::mimeDatabase()->findByFile(fi);
+ if (t.isNull())
+ continue;
+ if (t.matchesType(QLatin1String("text/x-chdr")))
+ headers << file;
+ else if (t.matchesType(QLatin1String("text/x-c++src")))
+ cxxSources << file;
+ else if (t.matchesType(QLatin1String("text/x-objcsrc")))
+ objcSources << file;
+ else if (t.matchesType(QLatin1String("text/x-csrc")))
+ cxxSources << file;
+ }
+ allFiles.append(headers);
+ allFiles.append(cSources);
+ allFiles.append(cxxSources);
+ allFiles.append(objcSources);
+
+ if (cxxSources.count() > 1) {
+ CPlusPlus::CppModelManagerInterface::ProjectPart::Ptr part(new CPlusPlus::CppModelManagerInterface::ProjectPart);
+ part->qtVersion = qtVersionForPart;
+ part->language = isCxx11 ? CPlusPlus::CppModelManagerInterface::ProjectPart::CXX11
+ : CPlusPlus::CppModelManagerInterface::ProjectPart::CXX;
+ part->sourceFiles = cxxSources;
+ part->objcSourceFiles = objcSources;
+ part->headerFiles = headers;
+ part->includePaths = grpIncludePaths;
+ part->frameworkPaths = grpFrameworkPaths;
+ part->precompiledHeaders = QStringList(pch);
+ part->defines = grpDefines;
+ pinfo.appendProjectPart(part);
+ }
+ if (cSources.count() > 1) {
+ CPlusPlus::CppModelManagerInterface::ProjectPart::Ptr part(new CPlusPlus::CppModelManagerInterface::ProjectPart);
+ part->qtVersion = CPlusPlus::CppModelManagerInterface::ProjectPart::NoQt;
+ part->language = CPlusPlus::CppModelManagerInterface::ProjectPart::C99; // FIXME: Can we find the exact c version from tc?
+ part->sourceFiles = cxxSources;
+ part->headerFiles = headers;
+ part->includePaths = grpIncludePaths;
+ part->frameworkPaths = grpFrameworkPaths;
+ part->precompiledHeaders = QStringList(pch);
+ part->defines = grpDefines;
+ pinfo.appendProjectPart(part);
+ }
+ }
+ }
+
+ if (pinfo.projectParts().isEmpty())
+ return;
+
+ // Register update the code model:
+ modelmanager->updateProjectInfo(pinfo);
+ m_codeModelFuture = modelmanager->updateSourceFiles(allFiles);
+}
+
+void QbsProject::updateQmlJsCodeModel(const qbs::ProjectData *prj)
+{
+ // FIXME: No information about import directories, so ignore this for now.
+#if 1
+ Q_UNUSED(prj);
+#else
+ QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance();
+ if (!modelManager)
+ return;
+
+ QmlJS::ModelManagerInterface::ProjectInfo projectInfo = modelManager->projectInfo(this);
+ projectInfo.sourceFiles = m_projectFiles->files[QMLType];
+
+ FindQt4ProFiles findQt4ProFiles;
+ QList<Qt4ProFileNode *> proFiles = findQt4ProFiles(rootProjectNode());
+
+ projectInfo.importPaths.clear();
+ foreach (Qt4ProFileNode *node, proFiles) {
+ projectInfo.importPaths.append(node->variableValue(QmlImportPathVar));
+ }
+
+ bool preferDebugDump = false;
+ projectInfo.tryQmlDump = false;
+
+ ProjectExplorer::Target *t = activeTarget();
+ ProjectExplorer::Kit *k = t ? t->kit() : ProjectExplorer::KitManager::instance()->defaultKit();
+ QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(k);
+
+ if (t) {
+ if (Qt4BuildConfiguration *bc = qobject_cast<Qt4BuildConfiguration *>(t->activeBuildConfiguration()))
+ preferDebugDump = bc->qmakeBuildConfiguration() & QtSupport::BaseQtVersion::DebugBuild;
+ } else {
+ if (qtVersion)
+ preferDebugDump = qtVersion->defaultBuildConfig() & QtSupport::BaseQtVersion::DebugBuild;
+ }
+ if (qtVersion && qtVersion->isValid()) {
+ projectInfo.tryQmlDump = qtVersion->type() == QLatin1String(QtSupport::Constants::DESKTOPQT)
+ || qtVersion->type() == QLatin1String(QtSupport::Constants::SIMULATORQT);
+ projectInfo.qtImportsPath = qtVersion->qmakeProperty("QT_INSTALL_IMPORTS");
+ if (!projectInfo.qtImportsPath.isEmpty())
+ projectInfo.importPaths += projectInfo.qtImportsPath;
+ projectInfo.qtVersionString = qtVersion->qtVersionString();
+ }
+ projectInfo.importPaths.removeDuplicates();
+
+ if (projectInfo.tryQmlDump) {
+ QtSupport::QmlDumpTool::pathAndEnvironment(this, qtVersion,
+ ToolChainKitInformation::toolChain(k),
+ preferDebugDump, &projectInfo.qmlDumpPath,
+ &projectInfo.qmlDumpEnvironment);
+ } else {
+ projectInfo.qmlDumpPath.clear();
+ projectInfo.qmlDumpEnvironment.clear();
+ }
+
+ modelManager->updateProjectInfo(projectInfo);
+#endif
+}
+
+} // namespace Internal
+} // namespace QbsProjectManager
diff --git a/src/plugins/qbsprojectmanager/qbsproject.h b/src/plugins/qbsprojectmanager/qbsproject.h
new file mode 100644
index 0000000000..15354b31f2
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsproject.h
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 QBSPROJECT_H
+#define QBSPROJECT_H
+
+#include "qbsprojectmanager.h"
+
+#include <language/language.h>
+#include <tools/buildoptions.h>
+
+#include <projectexplorer/project.h>
+#include <projectexplorer/projectnodes.h>
+#include <projectexplorer/task.h>
+
+#include <QFuture>
+// <debug>
+#include <QTimer>
+// </debug>
+#include <QVariantMap>
+
+namespace qbs {
+class BuildJob;
+class CleanJob;
+class Error;
+class ProjectData;
+class SetupProjectJob;
+} // namespace qbs
+
+namespace Core { class IDocument; }
+namespace ProjectExplorer { class BuildConfiguration; }
+
+namespace QbsProjectManager {
+namespace Internal {
+
+class QbsProjectNode;
+class QbsBuildConfiguration;
+
+class QbsProject : public ProjectExplorer::Project
+{
+ Q_OBJECT
+
+public:
+ QbsProject(QbsManager *manager, const QString &filename);
+ ~QbsProject();
+
+ QString displayName() const;
+ Core::Id id() const;
+ Core::IDocument *document() const;
+ QbsManager *projectManager() const;
+
+ ProjectExplorer::ProjectNode *rootProjectNode() const;
+
+ QStringList files(FilesMode fileMode) const;
+
+ qbs::BuildJob *build(const qbs::BuildOptions &opts);
+ qbs::CleanJob *clean(const qbs::BuildOptions &opts, bool everything);
+
+ static ProjectExplorer::FileType fileTypeFor(const QSet<QString> &tags);
+
+ QString profileForTarget(const ProjectExplorer::Target *t) const;
+ bool isParsing() const;
+ bool hasParseResult() const;
+
+ Utils::FileName defaultBuildDirectory() const;
+
+public slots:
+ void invalidate();
+ void parseCurrentBuildConfiguration();
+
+signals:
+ void projectParsingStarted();
+ void projectParsingDone(bool);
+
+private slots:
+ void handleQbsParsingDone(bool success);
+ void handleQbsParsingProgress(int progress);
+ void handleQbsParsingTaskSetup(const QString &description, int maximumProgressValue);
+
+ void targetWasAdded(ProjectExplorer::Target *t);
+ void changeActiveTarget(ProjectExplorer::Target *t);
+ void buildConfigurationChanged(ProjectExplorer::BuildConfiguration *bc);
+
+private:
+ bool fromMap(const QVariantMap &map);
+
+ void parse(const QVariantMap &config, const QString &dir = QString());
+
+ void generateErrors(const qbs::Error &e);
+ void prepareForParsing();
+ void updateDocuments(const qbs::ProjectData *prj);
+ void updateCppCodeModel(const qbs::ProjectData *prj);
+ void updateQmlJsCodeModel(const qbs::ProjectData *prj);
+
+ QbsManager *const m_manager;
+ const QString m_projectName;
+ const QString m_fileName;
+ QSet<Core::IDocument *> m_qbsDocuments;
+ QbsProjectNode *const m_rootProjectNode;
+
+ qbs::SetupProjectJob *m_qbsSetupProjectJob;
+ QVariantMap m_qbsBuildConfig;
+ QString m_qbsBuildRoot;
+
+ QFutureInterface<void> *m_qbsUpdateFutureInterface;
+ int m_currentProgressBase;
+
+ QFuture<void> m_codeModelFuture;
+
+ QbsBuildConfiguration *m_currentBc;
+
+ // <debug>
+ QTimer m_reparseTimer;
+ // </debug>
+};
+
+} // namespace Internal
+} // namespace QbsProjectManager
+
+#endif // QBSPROJECT_H
diff --git a/src/plugins/qbsprojectmanager/qbsprojectfile.cpp b/src/plugins/qbsprojectmanager/qbsprojectfile.cpp
new file mode 100644
index 0000000000..c63089c53c
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsprojectfile.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 "qbsprojectfile.h"
+
+#include "qbsproject.h"
+#include "qbsprojectmanagerconstants.h"
+
+namespace QbsProjectManager {
+namespace Internal {
+
+QbsProjectFile::QbsProjectFile(QbsProject *parent, QString fileName) : Core::IDocument(parent),
+ m_project(parent),
+ m_fileName(fileName)
+{ }
+
+QbsProjectFile::~QbsProjectFile()
+{ }
+
+bool QbsProjectFile::save(QString *, const QString &, bool)
+{
+ return false;
+}
+
+QString QbsProjectFile::fileName() const
+{
+ return m_fileName;
+}
+
+bool QbsProjectFile::isReadOnly() const
+{
+ return true;
+}
+
+QString QbsProjectFile::defaultPath() const
+{
+ return QString();
+}
+
+QString QbsProjectFile::suggestedFileName() const
+{
+ return QString();
+}
+
+QString QbsProjectFile::mimeType() const
+{
+ return QLatin1String(Constants::MIME_TYPE);
+}
+
+bool QbsProjectFile::isModified() const
+{
+ return false;
+}
+
+bool QbsProjectFile::isSaveAsAllowed() const
+{
+ return false;
+}
+
+Core::IDocument::ReloadBehavior QbsProjectFile::reloadBehavior(ChangeTrigger state, ChangeType type) const
+{
+ Q_UNUSED(state);
+ Q_UNUSED(type);
+ return BehaviorSilent;
+}
+
+bool QbsProjectFile::reload(QString *errorString, ReloadFlag flag, ChangeType type)
+{
+ Q_UNUSED(errorString)
+ Q_UNUSED(flag)
+ if (type == TypePermissions)
+ return true;
+ m_project->parseCurrentBuildConfiguration();
+ return true;
+}
+
+void QbsProjectFile::rename(const QString &newName)
+{
+ // Can't happen
+ Q_UNUSED(newName);
+ Q_ASSERT(false);
+}
+
+} // namespace Internal
+} // namespace QbsProjectManager
+
diff --git a/src/plugins/qbsprojectmanager/qbsprojectfile.h b/src/plugins/qbsprojectmanager/qbsprojectfile.h
new file mode 100644
index 0000000000..cc6ac7ab25
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsprojectfile.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 QBSPROJECTFILE_H
+#define QBSPROJECTFILE_H
+
+#include <coreplugin/idocument.h>
+
+namespace QbsProjectManager {
+namespace Internal {
+
+class QbsProject;
+
+class QbsProjectFile : public Core::IDocument
+{
+ Q_OBJECT
+
+public:
+ QbsProjectFile(QbsProject *parent, QString fileName);
+ ~QbsProjectFile();
+
+ bool save(QString *errorString, const QString &fileName, bool autoSave);
+ QString fileName() const;
+ bool isReadOnly() const;
+
+ QString defaultPath() const;
+ QString suggestedFileName() const;
+ QString mimeType() const;
+
+ bool isModified() const;
+ bool isSaveAsAllowed() const;
+
+ ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const;
+ bool reload(QString *errorString, ReloadFlag flag, ChangeType type);
+ void rename(const QString &newName);
+
+private:
+ QbsProject *m_project;
+ QString m_fileName;
+};
+
+} // namespace Internal
+} // namespace QbsProjectManager
+
+#endif // QBSPROJECTFILE_H
diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanager.cpp b/src/plugins/qbsprojectmanager/qbsprojectmanager.cpp
new file mode 100644
index 0000000000..fc1cb270df
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsprojectmanager.cpp
@@ -0,0 +1,238 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 "qbsprojectmanager.h"
+
+#include "qbslogsink.h"
+#include "qbsproject.h"
+#include "qbsprojectmanagerconstants.h"
+#include "qbsprojectmanagerplugin.h"
+
+#include <projectexplorer/kitinformation.h>
+#include <projectexplorer/kitmanager.h>
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/toolchain.h>
+#include <qtsupport/baseqtversion.h>
+#include <qtsupport/qtkitinformation.h>
+#include <utils/qtcassert.h>
+
+#include <QVariantMap>
+
+// <debug>
+#include <logging/logger.h> // qbs
+// </debug>
+
+// qbs settings structure:
+static const char PROFILE_LIST[] = "preferences/qtcreator/kit/";
+static const char PROFILES_PREFIX[] = "profiles/";
+
+// Qt related settings:
+static const char QTCORE_BINPATH[] = "/qt/core/binPath";
+static const char QTCORE_INCPATH[] = "/qt/core/incPath";
+static const char QTCORE_LIBPATH[] = "/qt/core/libPath";
+static const char QTCORE_VERSION[] = "/qt/core/version";
+static const char QTCORE_NAMESPACE[] = "/qt/core/namespace";
+static const char QTCORE_LIBINFIX[] = "/qt/core/libInfix";
+static const char QTCORE_MKSPEC[] = "/qt/core/mkspecPath";
+
+
+// Toolchain related settings:
+static const char QBS_TARGETOS[] = "/qbs/targetOS";
+static const char QBS_SYSROOT[] = "/qbs/sysroot";
+static const char QBS_ARCHITECTURE[] = "/qbs/architecture";
+static const char QBS_TOOLCHAIN[] = "/qbs/toolchain";
+static const char CPP_TOOLCHAINPATH[] = "/cpp/toolchainInstallPath";
+static const char CPP_COMPILERNAME[] = "/cpp/compilerName";
+
+static const QChar sep = QChar(QLatin1Char('/'));
+
+namespace QbsProjectManager {
+
+qbs::Settings *QbsManager::m_settings = new qbs::Settings;
+
+QbsManager::QbsManager(Internal::QbsProjectManagerPlugin *plugin) :
+ m_plugin(plugin)
+{
+ setObjectName("QbsProjectManager");
+ connect(ProjectExplorer::KitManager::instance(), SIGNAL(kitsChanged()), this, SLOT(pushKitsToQbs()));
+
+ // <debug>
+ qbs::Logger::instance().setLevel(qbs::LoggerError);
+ // </debug>
+ qbs::Logger::instance().setLogSink(new Internal::QbsLogSink);
+}
+
+QbsManager::~QbsManager()
+{
+ delete m_settings;
+}
+
+QString QbsManager::mimeType() const
+{
+ return QLatin1String(Constants::MIME_TYPE);
+}
+
+ProjectExplorer::Project *QbsManager::openProject(const QString &fileName, QString *errorString)
+{
+ Q_UNUSED(errorString);
+
+ // FIXME: This is way too simplistic!
+ return new Internal::QbsProject(this, fileName);
+}
+
+QString QbsManager::profileForKit(const ProjectExplorer::Kit *k) const
+{
+ if (!k)
+ return QString();
+ return m_settings->value(QString::fromLatin1(PROFILE_LIST) + k->id().toString()).toString();
+}
+
+void QbsManager::setProfileForKit(const QString &name, const ProjectExplorer::Kit *k)
+{
+ m_settings->setValue(QString::fromLatin1(PROFILE_LIST) + k->id().toString(), name);
+}
+
+QStringList QbsManager::profileNames() const
+{
+ QStringList keyList = m_settings->allKeys();
+
+ QStringList result;
+ foreach (const QString &key, keyList) {
+ if (!key.startsWith(QString::fromLatin1(PROFILES_PREFIX)))
+ continue;
+ QString profile = key;
+ profile.remove(0, QString::fromLatin1(PROFILES_PREFIX).count());
+ profile = profile.left(profile.indexOf(sep));
+ if (!result.contains(profile))
+ result << profile;
+ }
+ return result;
+}
+
+qbs::Settings *QbsManager::settings()
+{
+ return m_settings;
+}
+
+void QbsManager::addProfile(const QString &name, const QVariantMap &data)
+{
+ const QString base = QLatin1String(PROFILES_PREFIX) + name;
+ foreach (const QString &key, data.keys())
+ m_settings->setValue(base + key, data.value(key));
+}
+
+void QbsManager::removeCreatorProfiles()
+{
+ QStringList keyList = m_settings->allKeys();
+
+ // remove old kit definitions:
+ foreach (const QString &key, keyList) {
+ if (!key.startsWith(QLatin1String(PROFILE_LIST)))
+ continue;
+ const QString toDelete = m_settings->value(key).toString();
+ removeKey(key);
+ removeProfile(toDelete);
+ }
+}
+
+void QbsManager::addProfileFromKit(const ProjectExplorer::Kit *k)
+{
+ QStringList usedProfileNames = profileNames();
+ const QString name = ProjectExplorer::Project::makeUnique(k->fileSystemFriendlyName(), usedProfileNames);
+ setProfileForKit(name, k);
+
+ QVariantMap data;
+ QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(k);
+ if (qt) {
+ data.insert(QLatin1String(QTCORE_BINPATH), qt->binPath().toUserOutput());
+ data.insert(QLatin1String(QTCORE_INCPATH), qt->headerPath().toUserOutput());
+ data.insert(QLatin1String(QTCORE_LIBPATH), qt->libraryPath().toUserOutput());
+ data.insert(QLatin1String(QTCORE_MKSPEC), qt->mkspecsPath().toUserOutput());
+ data.insert(QLatin1String(QTCORE_NAMESPACE), qt->qtNamespace());
+ data.insert(QLatin1String(QTCORE_LIBINFIX), qt->qtLibInfix());
+ data.insert(QLatin1String(QTCORE_VERSION), qt->qtVersionString());
+ }
+
+ if (ProjectExplorer::SysRootKitInformation::hasSysRoot(k))
+ data.insert(QLatin1String(QBS_SYSROOT), ProjectExplorer::SysRootKitInformation::sysRoot(k).toUserOutput());
+
+ ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainKitInformation::toolChain(k);
+ if (tc) {
+ // FIXME/CLARIFY: How to pass the sysroot?
+ ProjectExplorer::Abi targetAbi = tc->targetAbi();
+ QString architecture = ProjectExplorer::Abi::toString(targetAbi.architecture());
+ if (targetAbi.wordWidth() == 64)
+ architecture.append(QLatin1String("_64"));
+ data.insert(QLatin1String(QBS_ARCHITECTURE), architecture);
+
+ if (targetAbi.os() == ProjectExplorer::Abi::WindowsOS) {
+ data.insert(QLatin1String(QBS_TARGETOS), QLatin1String("windows"));
+ data.insert(QLatin1String(QBS_TOOLCHAIN),
+ targetAbi.osFlavor() == ProjectExplorer::Abi::WindowsMSysFlavor ?
+ QLatin1String("mingw") : QLatin1String("msvc"));
+ } else if (targetAbi.os() == ProjectExplorer::Abi::MacOS) {
+ data.insert(QLatin1String(QBS_TARGETOS), QLatin1String("mac"));
+ data.insert(QLatin1String(QBS_TOOLCHAIN), QLatin1String("gcc"));
+ } else if (targetAbi.os() == ProjectExplorer::Abi::LinuxOS) {
+ data.insert(QLatin1String(QBS_TARGETOS), QLatin1String("linux"));
+ data.insert(QLatin1String(QBS_TOOLCHAIN), QLatin1String("gcc"));
+ }
+ Utils::FileName cxx = tc->compilerCommand();
+ data.insert(QLatin1String(CPP_TOOLCHAINPATH), cxx.toFileInfo().absolutePath());
+ data.insert(QLatin1String(CPP_COMPILERNAME), cxx.toFileInfo().fileName());
+ }
+ // FIXME/CLARIFY: Do I need to set qbs/platform? Maybe from devicetype/device?
+ addProfile(name, data);
+}
+
+void QbsManager::removeKey(const QString &key)
+{
+ QStringList keyList = m_settings->allKeys();
+ foreach (const QString &k, keyList) {
+ if (k == key || k.startsWith(key + sep))
+ m_settings->remove(key);
+ }
+}
+
+void QbsManager::removeProfile(const QString &name)
+{
+ removeKey(QString::fromLatin1(PROFILES_PREFIX) + name);
+}
+
+void QbsManager::pushKitsToQbs()
+{
+ // Get all keys
+ removeCreatorProfiles();
+
+ // add definitions from our kits
+ foreach (const ProjectExplorer::Kit *k, ProjectExplorer::KitManager::instance()->kits())
+ addProfileFromKit(k);
+}
+
+} // namespace QbsProjectManager
diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanager.h b/src/plugins/qbsprojectmanager/qbsprojectmanager.h
new file mode 100644
index 0000000000..8a7253a585
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsprojectmanager.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 QBSPROJECTMANAGER_H
+#define QBSPROJECTMANAGER_H
+
+#include "qbsprojectmanager_global.h"
+
+#include <projectexplorer/iprojectmanager.h>
+
+#include <tools/settings.h> // qbs
+
+#include <QString>
+
+namespace ProjectExplorer {
+class Kit;
+class Project;
+class ProjectExplorerPlugin;
+} // namespace ProjectExplorer
+
+namespace QbsProjectManager {
+
+namespace Internal {
+class QbsProject;
+class QbsProjectManagerPlugin;
+} // namespace Internal
+
+class QBSPROJECTMANAGER_EXPORT QbsManager : public ProjectExplorer::IProjectManager
+{
+ Q_OBJECT
+
+public:
+ QbsManager(Internal::QbsProjectManagerPlugin *plugin);
+ ~QbsManager();
+
+ QString mimeType() const;
+ ProjectExplorer::Project *openProject(const QString &fileName, QString *errorString);
+
+ // QBS settings management:
+ QString profileForKit(const ProjectExplorer::Kit *k) const;
+ void setProfileForKit(const QString &name, const ProjectExplorer::Kit *k);
+ QStringList profileNames() const;
+
+ static qbs::Settings *settings();
+
+ void removeKey(const QString &key); // remove a key incl. subkeys
+ void removeProfile(const QString &name);
+
+private slots:
+ void pushKitsToQbs();
+
+private:
+
+ void addProfile(const QString &name, const QVariantMap &data);
+ void removeCreatorProfiles();
+ void addProfileFromKit(const ProjectExplorer::Kit *k);
+
+ Internal::QbsProjectManagerPlugin *m_plugin;
+ static qbs::Settings *m_settings;
+};
+
+} // namespace QbsProjectManager
+
+#endif // QBSPROJECTMANAGER_H
diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanager.pro b/src/plugins/qbsprojectmanager/qbsprojectmanager.pro
new file mode 100644
index 0000000000..40025e5f40
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsprojectmanager.pro
@@ -0,0 +1,53 @@
+TEMPLATE = lib
+TARGET = QbsProjectManager
+
+include(../../qtcreatorplugin.pri)
+include(qbsprojectmanager_dependencies.pri)
+
+isEmpty(QBS_SOURCE_DIR):QBS_SOURCE_DIR=$$PWD/../../../../qbs
+isEmpty(QBS_BUILD_DIR):QBS_BUILD_DIR=$$PWD/../../../../../build/qbs
+
+QBSLIBDIR=$$QBS_BUILD_DIR/lib
+include($$QBS_SOURCE_DIR/src/lib/use.pri)
+
+DEFINES += QBS_SOURCE_DIR=\\\"$$QBS_SOURCE_DIR\\\"
+DEFINES += QBS_BUILD_DIR=\\\"$$QBS_BUILD_DIR\\\"
+
+HEADERS = \
+ qbsbuildconfiguration.h \
+ qbsbuildconfigurationwidget.h \
+ qbsbuildstep.h \
+ qbscleanstep.h \
+ qbslogsink.h \
+ qbsnodes.h \
+ qbsparser.h \
+ qbsproject.h \
+ qbsprojectfile.h \
+ qbsprojectmanager.h \
+ qbsprojectmanager_global.h \
+ qbsprojectmanagerconstants.h \
+ qbsprojectmanagerplugin.h \
+
+SOURCES = \
+ qbsbuildconfiguration.cpp \
+ qbsbuildconfigurationwidget.cpp \
+ qbsbuildstep.cpp \
+ qbscleanstep.cpp \
+ qbslogsink.cpp \
+ qbsnodes.cpp \
+ qbsparser.cpp \
+ qbsproject.cpp \
+ qbsprojectfile.cpp \
+ qbsprojectmanager.cpp \
+ qbsprojectmanagerplugin.cpp \
+
+FORMS = \
+ qbsbuildstepconfigwidget.ui \
+ qbscleanstepconfigwidget.ui \
+
+RESOURCES += \
+ qbsprojectmanager.qrc \
+
+FORMS += \
+
+OTHER_FILES += QbsProjectManager.mimetypes.xml
diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs b/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs
new file mode 100644
index 0000000000..be8eac3e6e
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs
@@ -0,0 +1,31 @@
+import qbs.base 1.0
+
+import "../QtcPlugin.qbs" as QtcPlugin
+
+QtcPlugin {
+ name: "QbsProjectManager"
+
+ Depends { name: "Qt.widgets" }
+ Depends { name: "Core" }
+ Depends { name: "ProjectExplorer" }
+ Depends { name: "CppTools" }
+ Depends { name: "CPlusPlus" }
+ Depends { name: "TextEditor" }
+ Depends { name: "Locator" }
+ Depends { name: "QtSupport" }
+
+ Depends { name: "cpp" }
+ cpp.includePaths: [
+ ".",
+ "..",
+ "../../libs",
+ buildDirectory
+ ]
+
+ files: [
+ "QbsProjectManager.mimetypes.xml",
+ "qbsprojectmanagerplugin.cpp",
+ "qbsprojectmanagerplugin.h"
+ ]
+}
+
diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanager.qrc b/src/plugins/qbsprojectmanager/qbsprojectmanager.qrc
new file mode 100644
index 0000000000..ce38878783
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsprojectmanager.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/qbsproject">
+ <file>QbsProjectManager.mimetypes.xml</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanager_dependencies.pri b/src/plugins/qbsprojectmanager/qbsprojectmanager_dependencies.pri
new file mode 100644
index 0000000000..03f29efcdb
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsprojectmanager_dependencies.pri
@@ -0,0 +1,4 @@
+include(../../plugins/projectexplorer/projectexplorer.pri)
+include(../../plugins/cpptools/cpptools.pri)
+include(../../plugins/texteditor/texteditor.pri)
+include(../../plugins/qtsupport/qtsupport.pri)
diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanager_global.h b/src/plugins/qbsprojectmanager/qbsprojectmanager_global.h
new file mode 100644
index 0000000000..44d556e364
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsprojectmanager_global.h
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 QBSPROJECTMANAGER_GLOBAL_H
+#define QBSPROJECTMANAGER_GLOBAL_H
+
+#include <qglobal.h>
+
+#if defined(QBSPROJECTMANAGER_LIBRARY)
+# define QBSPROJECTMANAGER_EXPORT Q_DECL_EXPORT
+#else
+# define QBSPROJECTMANAGER_EXPORT Q_DECL_IMPORT
+#endif
+
+#endif // QBSPROJECTMANAGER_GLOBAL_H
diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanagerconstants.h b/src/plugins/qbsprojectmanager/qbsprojectmanagerconstants.h
new file mode 100644
index 0000000000..91b9dd664e
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsprojectmanagerconstants.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 QBSPROJECTMANAGERCONSTANTS_H
+#define QBSPROJECTMANAGERCONSTANTS_H
+
+#include <QtGlobal>
+
+namespace QbsProjectManager {
+namespace Constants {
+
+// Contexts
+const char PROJECT_ID[] = "Qbs.QbsProject";
+
+// MIME types:
+const char MIME_TYPE[] = "application/vnd.qtproject.qbsproject";
+
+// Progress reports:
+const char QBS_EVALUATE[] = "Qbs.QbsEvaluate";
+
+// Actions:
+const char ACTION_REPARSE_QBS[] = "Qbs.Reparse";
+const char ACTION_REPARSE_QBS_CONTEXT[] = "Qbs.ReparseCtx";
+
+// Ids:
+const char QBS_BUILDSTEP_ID[] = "Qbs.BuildStep";
+const char QBS_CLEANSTEP_ID[] = "Qbs.CleanStep";
+
+// QBS strings:
+static const char QBS_VARIANT_DEBUG[] = "debug";
+static const char QBS_VARIANT_RELEASE[] = "release";
+
+static const char QBS_CONFIG_VARIANT_KEY[] = "qbs.buildVariant";
+static const char QBS_CONFIG_PROFILE_KEY[] = "profile";
+
+} // namespace Constants
+} // namespace QbsProjectManager
+
+#endif // QBSPROJECTMANAGERCONSTANTS_H
+
diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.cpp b/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.cpp
new file mode 100644
index 0000000000..197ad70ec8
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.cpp
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 "qbsprojectmanagerplugin.h"
+
+#include "qbsbuildconfiguration.h"
+#include "qbsbuildstep.h"
+#include "qbscleanstep.h"
+#include "qbsproject.h"
+#include "qbsprojectmanager.h"
+#include "qbsprojectmanagerconstants.h"
+
+#include <coreplugin/actionmanager/actioncontainer.h>
+#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/mimedatabase.h>
+#include <projectexplorer/buildmanager.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/target.h>
+
+#include <QAction>
+#include <QtPlugin>
+
+namespace QbsProjectManager {
+namespace Internal {
+
+QbsProjectManagerPlugin::QbsProjectManagerPlugin() :
+ m_manager(0),
+ m_projectExplorer(0),
+ m_currentProject(0),
+ m_currentTarget(0),
+ m_currentNode(0)
+{ }
+
+bool QbsProjectManagerPlugin::initialize(const QStringList &arguments, QString *errorMessage)
+{
+ m_manager = new QbsManager(this);
+ m_projectExplorer = ProjectExplorer::ProjectExplorerPlugin::instance();
+ const Core::Context projectContext(::QbsProjectManager::Constants::PROJECT_ID);
+
+ Q_UNUSED(arguments);
+ if (!Core::ICore::mimeDatabase()->addMimeTypes(QLatin1String(":qbsproject/QbsProjectManager.mimetypes.xml"),
+ errorMessage))
+ return false;
+
+ //create and register objects
+ addAutoReleasedObject(m_manager);
+ addAutoReleasedObject(new QbsBuildConfigurationFactory);
+ addAutoReleasedObject(new QbsBuildStepFactory);
+ addAutoReleasedObject(new QbsCleanStepFactory);
+
+ //menus
+ // Build Menu:
+ Core::ActionContainer *mbuild =
+ Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_BUILDPROJECT);
+ // PE Context menu for projects
+ Core::ActionContainer *mproject =
+ Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_PROJECTCONTEXT);
+
+ //register actions
+ Core::Command *command;
+
+ m_reparseQbs = new QAction(tr("Reparse Qbs"), this);
+ command = Core::ActionManager::registerAction(m_reparseQbs, Constants::ACTION_REPARSE_QBS, projectContext);
+ command->setAttribute(Core::Command::CA_Hide);
+ mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_BUILD);
+ connect(m_reparseQbs, SIGNAL(triggered()), this, SLOT(reparseCurrentProject()));
+
+ m_reparseQbsCtx = new QAction(tr("Reparse Qbs"), this);
+ command = Core::ActionManager::registerAction(m_reparseQbsCtx, Constants::ACTION_REPARSE_QBS_CONTEXT, projectContext);
+ command->setAttribute(Core::Command::CA_Hide);
+ mproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD);
+ connect(m_reparseQbsCtx, SIGNAL(triggered()), this, SLOT(reparseCurrentProject()));
+
+ connect(m_projectExplorer, SIGNAL(currentNodeChanged(ProjectExplorer::Node*,ProjectExplorer::Project*)),
+ this, SLOT(updateContextActions(ProjectExplorer::Node*,ProjectExplorer::Project*)));
+
+ connect(m_projectExplorer->buildManager(), SIGNAL(buildStateChanged(ProjectExplorer::Project*)),
+ this, SLOT(buildStateChanged(ProjectExplorer::Project*)));
+
+ updateContextActions(0, 0);
+ updateReparseQbsAction();
+
+ return true;
+}
+
+void QbsProjectManagerPlugin::extensionsInitialized()
+{ }
+
+void QbsProjectManagerPlugin::updateContextActions(ProjectExplorer::Node *node, ProjectExplorer::Project *project)
+{
+ if (m_currentProject) {
+ disconnect(m_currentProject, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
+ this, SLOT(activeTargetChanged()));
+ disconnect(m_currentProject, SIGNAL(projectParsingStarted()),
+ this, SLOT(parsingStateChanged()));
+ disconnect(m_currentProject, SIGNAL(projectParsingDone(bool)),
+ this, SLOT(parsingStateChanged()));
+ }
+
+ m_currentNode = node;
+ m_currentProject = qobject_cast<Internal::QbsProject *>(project);
+ if (m_currentProject) {
+ connect(m_currentProject, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
+ this, SLOT(activeTargetChanged()));
+ connect(m_currentProject, SIGNAL(projectParsingStarted()),
+ this, SLOT(parsingStateChanged()));
+ connect(m_currentProject, SIGNAL(projectParsingDone(bool)),
+ this, SLOT(parsingStateChanged()));
+ }
+
+ activeTargetChanged();
+
+ bool isBuilding = m_projectExplorer->buildManager()->isBuilding(project);
+
+ m_reparseQbsCtx->setEnabled(!isBuilding && m_currentProject && !m_currentProject->isParsing());
+}
+
+void QbsProjectManagerPlugin::updateReparseQbsAction()
+{
+ m_reparseQbs->setEnabled(m_currentProject
+ && !m_projectExplorer->buildManager()->isBuilding(m_currentProject)
+ && !m_currentProject->isParsing());
+}
+
+void QbsProjectManagerPlugin::activeTargetChanged()
+{
+ if (m_currentTarget)
+ disconnect(m_currentTarget, SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
+ this, SLOT(updateReparseQbsAction()));
+
+ m_currentTarget = m_currentProject ? m_currentProject->activeTarget() : 0;
+
+ if (m_currentTarget)
+ connect(m_currentTarget, SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
+ this, SLOT(updateReparseQbsAction()));
+
+ updateReparseQbsAction();
+}
+
+void QbsProjectManagerPlugin::buildStateChanged(ProjectExplorer::Project *project)
+{
+ if (project == m_currentProject) {
+ updateReparseQbsAction();
+ updateContextActions(m_currentNode, m_currentProject);
+ }
+}
+
+void QbsProjectManagerPlugin::parsingStateChanged()
+{
+ if (m_currentProject) {
+ updateReparseQbsAction();
+ updateContextActions(m_currentNode, m_currentProject);
+ }
+}
+
+void QbsProjectManagerPlugin::reparseCurrentProject()
+{
+ if (m_currentProject)
+ m_currentProject->parseCurrentBuildConfiguration();
+}
+
+} // namespace Internal
+} // namespace QbsProjectManager
+
+Q_EXPORT_PLUGIN(QbsProjectManager::Internal::QbsProjectManagerPlugin)
diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.h b/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.h
new file mode 100644
index 0000000000..446653acd2
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 QBSPROJECTPLUGIN_H
+#define QBSPROJECTPLUGIN_H
+
+#include <extensionsystem/iplugin.h>
+
+#include <QObject>
+
+QT_BEGIN_NAMESPACE
+class QAction;
+QT_END_NAMESPACE
+
+namespace ProjectExplorer {
+class Project;
+class ProjectExplorerPlugin;
+class Node;
+class Target;
+} // namespace ProjectExplorer
+
+namespace QbsProjectManager {
+class QbsManager;
+
+namespace Internal {
+
+class QbsProject;
+
+class QbsProjectManagerPlugin : public ExtensionSystem::IPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "QbsProjectManager.json")
+
+public:
+ QbsProjectManagerPlugin();
+
+ bool initialize(const QStringList &arguments, QString *errorMessage);
+
+ void extensionsInitialized();
+
+private slots:
+ void updateContextActions(ProjectExplorer::Node *node, ProjectExplorer::Project *project);
+ void updateReparseQbsAction();
+ void activeTargetChanged();
+ void buildStateChanged(ProjectExplorer::Project *project);
+ void parsingStateChanged();
+
+ void reparseCurrentProject();
+
+private:
+ QbsManager *m_manager;
+ ProjectExplorer::ProjectExplorerPlugin *m_projectExplorer;
+
+ QAction *m_reparseQbs;
+ QAction *m_reparseQbsCtx;
+
+ Internal::QbsProject *m_currentProject;
+ ProjectExplorer::Target *m_currentTarget;
+ ProjectExplorer::Node *m_currentNode;
+};
+
+} // namespace Internal
+} // namespace QbsProject
+
+#endif // QBSPROJECTPLUGIN_H
diff --git a/src/plugins/qmljseditor/QmlJSEditor.mimetypes.xml b/src/plugins/qmljseditor/QmlJSEditor.mimetypes.xml
index 6c17c14689..79da1700bc 100644
--- a/src/plugins/qmljseditor/QmlJSEditor.mimetypes.xml
+++ b/src/plugins/qmljseditor/QmlJSEditor.mimetypes.xml
@@ -7,8 +7,6 @@
<glob pattern="*.qml"/>
<glob pattern="*.qmlproject"/>
<glob pattern="*.qmltypes"/>
- <glob pattern="*.qbs"/>
- <glob pattern="*.qbp"/>
</mime-type>
<mime-type type="application/javascript">
<alias type="application/x-javascript"/>
diff --git a/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp b/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp
index bc9387335b..0d670d72a2 100644
--- a/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp
+++ b/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp
@@ -607,7 +607,7 @@ BuildConfiguration *Qt4BuildConfigurationFactory::create(Target *parent, const C
bool ok = true;
QString buildConfigurationName = name;
- if (buildConfigurationName.isEmpty())
+ if (buildConfigurationName.isNull())
buildConfigurationName = QInputDialog::getText(0,
tr("New Configuration"),
tr("New configuration name:"),
@@ -618,16 +618,16 @@ BuildConfiguration *Qt4BuildConfigurationFactory::create(Target *parent, const C
return 0;
//: Debug build configuration. We recommend not translating it.
- QString defaultFirstName = tr("%1 Debug").arg(version->displayName());
+ QString defaultFirstName = tr("%1 Debug").arg(version->displayName()).trimmed();
QString customFirstName;
if (buildConfigurationName != version->displayName())
- customFirstName = tr("%1 Debug").arg(buildConfigurationName);
+ customFirstName = tr("%1 Debug").arg(buildConfigurationName).trimmed();
//: Release build configuration. We recommend not translating it.
- QString defaultSecondName = tr("%1 Release").arg(version->displayName());
+ QString defaultSecondName = tr("%1 Release").arg(version->displayName()).trimmed();
QString customSecondName;
if (buildConfigurationName != version->displayName())
- customSecondName = tr("%1 Release").arg(buildConfigurationName);
+ customSecondName = tr("%1 Release").arg(buildConfigurationName).trimmed();
BuildConfiguration *bc
= Qt4BuildConfiguration::setup(parent, defaultFirstName, customFirstName,
diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp
index f7b9ef44a8..ad6bdae90c 100644
--- a/src/plugins/qtsupport/baseqtversion.cpp
+++ b/src/plugins/qtsupport/baseqtversion.cpp
@@ -323,6 +323,41 @@ QList<ProjectExplorer::Task> BaseQtVersion::validateKit(const ProjectExplorer::K
return result;
}
+FileName BaseQtVersion::headerPath() const
+{
+ return Utils::FileName::fromUserInput(qmakeProperty("QT_INSTALL_HEADERS"));
+}
+
+FileName BaseQtVersion::libraryPath() const
+{
+ return Utils::FileName::fromUserInput(qmakeProperty("QT_INSTALL_LIBS"));
+}
+
+FileName BaseQtVersion::binPath() const
+{
+ return Utils::FileName::fromUserInput(qmakeProperty("QT_HOST_BINS"));
+}
+
+Utils::FileName QtSupport::BaseQtVersion::mkspecsPath() const
+{
+ Utils::FileName result = Utils::FileName::fromUserInput(qmakeProperty("QT_HOST_DATA"));
+ if (result.isEmpty())
+ result = Utils::FileName::fromUserInput(qmakeProperty("QMAKE_MKSPECS"));
+ else
+ result.appendPath(QLatin1String("mkspecs"));
+ return result;
+}
+
+QString QtSupport::BaseQtVersion::qtNamespace() const
+{
+ return qmakeProperty("QT_NAMESPACE");
+}
+
+QString QtSupport::BaseQtVersion::qtLibInfix() const
+{
+ return qmakeProperty("QT_LIBINFIX");
+}
+
void BaseQtVersion::setId(int id)
{
m_id = id;
diff --git a/src/plugins/qtsupport/baseqtversion.h b/src/plugins/qtsupport/baseqtversion.h
index 4ca6b6c094..931ff82cb2 100644
--- a/src/plugins/qtsupport/baseqtversion.h
+++ b/src/plugins/qtsupport/baseqtversion.h
@@ -191,7 +191,6 @@ public:
static Utils::FileName mkspecDirectoryFromVersionInfo(const QHash<QString, QString> &versionInfo);
static Utils::FileName mkspecFromVersionInfo(const QHash<QString, QString> &versionInfo);
-
virtual bool supportsBinaryDebuggingHelper() const;
virtual QString gdbDebuggingHelperLibrary() const;
virtual QString qmlDebuggingHelperLibrary(bool debugVersion) const;
@@ -220,6 +219,14 @@ public:
virtual QList<ProjectExplorer::Task> validateKit(const ProjectExplorer::Kit *k);
+ Utils::FileName headerPath() const;
+ Utils::FileName libraryPath() const;
+ Utils::FileName binPath() const;
+ Utils::FileName mkspecsPath() const;
+
+ QString qtNamespace() const;
+ QString qtLibInfix() const;
+
protected:
BaseQtVersion();
BaseQtVersion(const Utils::FileName &path, bool isAutodetected = false, const QString &autodetectionSource = QString());