forked from qt-creator/qt-creator
Add Boost.Build Project Manager plug-in
Preparing to contribute the plug-in, see the announcement at http://lists.qt-project.org/pipermail/qt-creator/2015-February/004436.html Change-Id: Ic3920c9b888af5bea1b7742b8ff49984c29a2909 Reviewed-by: Orgad Shaneh <orgads@gmail.com> Reviewed-by: Eike Ziller <eike.ziller@theqtcompany.com> Reviewed-by: Leena Miettinen <riitta-leena.miettinen@theqtcompany.com> Reviewed-by: hjk <hjk@theqtcompany.com>
This commit is contained in:
committed by
Orgad Shaneh
parent
188d4bfdb2
commit
7389250fcd
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
\"Name\" : \"BoostBuildProjectManager\",
|
||||||
|
\"Version\" : \"$$QTCREATOR_VERSION\",
|
||||||
|
\"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\",
|
||||||
|
\"Vendor\" : \"Mateusz Łoskot\",
|
||||||
|
\"Copyright\" : \"2013 (C) Mateusz Łoskot\",
|
||||||
|
\"License\" : [ \"GNU Lesser General Public License, Version 2.1\",
|
||||||
|
\"\",
|
||||||
|
\"This is free software; you can redistribute and/or modify it under the terms\",
|
||||||
|
\"of the GNU Lesser General Public License, Version 2.1 as published\",
|
||||||
|
\"by the Free Software Foundation.\",
|
||||||
|
\"See accompanying fike LICENSE.txt file or\",
|
||||||
|
\"copy at http://www.gnu.org/licenses/lgpl-2.1-standalone.html for more information.\",
|
||||||
|
\"\" ],
|
||||||
|
\"Category\" : \"Build Systems\",
|
||||||
|
\"Description\" : \"Qt Creator plugin for Boost.Build\",
|
||||||
|
\"Url\" : \"https://github.com/mloskot/qt-creator-plugin-boostbuild/\",
|
||||||
|
$$dependencyList
|
||||||
|
}
|
@@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
|
||||||
|
<!--
|
||||||
|
Note the use of character groups, i.e. [Jj]amfile, seems to be impossible.
|
||||||
|
Also, Qt Creator at the moment disobeys this rule specified by freedesktop.org:
|
||||||
|
"Applications MUST match globs case-insensitively,
|
||||||
|
except when the case-sensitive attribute is set to true."
|
||||||
|
as per https://codereview.qt-project.org/#change,72567
|
||||||
|
-->
|
||||||
|
<mime-type type="text/x-boostbuild-project">
|
||||||
|
<sub-class-of type="text/plain"/>
|
||||||
|
<comment>Boost.Build Project file</comment>
|
||||||
|
<glob pattern="Jamroot"/>
|
||||||
|
<glob pattern="jamroot"/>
|
||||||
|
<glob pattern="Jamroot.jam"/>
|
||||||
|
<glob pattern="jamroot.jam"/>
|
||||||
|
<glob pattern="Jamfile"/>
|
||||||
|
<glob pattern="jamfile"/>
|
||||||
|
<glob pattern="Jamfile.v2"/>
|
||||||
|
<glob pattern="jamfile.v2"/>
|
||||||
|
<glob pattern="Jamfile.jam"/>
|
||||||
|
<glob pattern="jamfile.jam"/>
|
||||||
|
</mime-type>
|
||||||
|
<mime-type type="application/vnd.qtcreator.boostbuild.files">
|
||||||
|
<sub-class-of type="text/plain"/>
|
||||||
|
<comment>Boost.Build Project Files</comment>
|
||||||
|
<glob pattern="Jam*.qtcreator.files"/>
|
||||||
|
<glob pattern="jam*.qtcreator.files"/>
|
||||||
|
</mime-type>
|
||||||
|
<mime-type type="application/vnd.qtcreator.boostbuild.includes">
|
||||||
|
<sub-class-of type="text/plain"/>
|
||||||
|
<comment>Boost.Build Project Includes</comment>
|
||||||
|
<glob pattern="Jam*.qtcreator.includes"/>
|
||||||
|
<glob pattern="jam*.qtcreator.includes"/>
|
||||||
|
</mime-type>
|
||||||
|
</mime-info>
|
391
src/plugins/boostbuildprojectmanager/b2buildconfiguration.cpp
Normal file
391
src/plugins/boostbuildprojectmanager/b2buildconfiguration.cpp
Normal file
@@ -0,0 +1,391 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
// Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
//
|
||||||
|
// This file is part of Qt Creator Boost.Build plugin project.
|
||||||
|
//
|
||||||
|
// This is free software; you can redistribute and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License, Version 2.1
|
||||||
|
// as published by the Free Software Foundation.
|
||||||
|
// See accompanying file LICENSE.txt or copy at
|
||||||
|
// http://www.gnu.org/licenses/lgpl-2.1-standalone.html.
|
||||||
|
//
|
||||||
|
#include "b2buildconfiguration.h"
|
||||||
|
#include "b2buildinfo.h"
|
||||||
|
#include "b2buildstep.h"
|
||||||
|
#include "b2project.h"
|
||||||
|
#include "b2projectmanagerconstants.h"
|
||||||
|
#include "b2utility.h"
|
||||||
|
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
|
#include <projectexplorer/buildinfo.h>
|
||||||
|
#include <projectexplorer/buildsteplist.h>
|
||||||
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
|
#include <projectexplorer/kitinformation.h>
|
||||||
|
#include <projectexplorer/project.h>
|
||||||
|
#include <projectexplorer/namedwidget.h>
|
||||||
|
#include <projectexplorer/target.h>
|
||||||
|
|
||||||
|
#include <utils/pathchooser.h>
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/mimetypes/mimedatabase.h>
|
||||||
|
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QFormLayout>
|
||||||
|
#include <QInputDialog>
|
||||||
|
#include <QScopedPointer>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
|
||||||
|
namespace BoostBuildProjectManager {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
BuildConfiguration::BuildConfiguration(Target* parent)
|
||||||
|
: ProjectExplorer::BuildConfiguration(parent, Core::Id(Constants::BUILDCONFIGURATION_ID))
|
||||||
|
{
|
||||||
|
ProjectExplorer::Project const* p = parent->project();
|
||||||
|
Q_ASSERT(p);
|
||||||
|
setWorkingDirectory(p->projectDirectory());
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildConfiguration::BuildConfiguration(Target* parent, BuildConfiguration* source)
|
||||||
|
: ProjectExplorer::BuildConfiguration(parent, source)
|
||||||
|
{
|
||||||
|
if (BuildConfiguration* bc = qobject_cast<BuildConfiguration*>(source))
|
||||||
|
setWorkingDirectory(bc->workingDirectory());
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildConfiguration::BuildConfiguration(Target* parent, Core::Id const id)
|
||||||
|
: ProjectExplorer::BuildConfiguration(parent, id)
|
||||||
|
{
|
||||||
|
ProjectExplorer::Project const* p = parent->project();
|
||||||
|
Q_ASSERT(p);
|
||||||
|
setWorkingDirectory(p->projectDirectory());
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap BuildConfiguration::toMap() const
|
||||||
|
{
|
||||||
|
QVariantMap map(ProjectExplorer::BuildConfiguration::toMap());
|
||||||
|
map.insert(QLatin1String(Constants::BC_KEY_WORKDIR), workingDirectory_.toString());
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BuildConfiguration::fromMap(QVariantMap const& map)
|
||||||
|
{
|
||||||
|
if (!ProjectExplorer::BuildConfiguration::fromMap(map))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QString dir = map.value(QLatin1String(Constants::BC_KEY_WORKDIR)).toString();
|
||||||
|
setWorkingDirectory(Utils::FileName::fromString(dir));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectExplorer::NamedWidget*
|
||||||
|
BuildConfiguration::createConfigWidget()
|
||||||
|
{
|
||||||
|
return new BuildSettingsWidget(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildConfiguration::BuildType
|
||||||
|
BuildConfiguration::buildType() const
|
||||||
|
{
|
||||||
|
BuildType type = Unknown;
|
||||||
|
|
||||||
|
ProjectExplorer::BuildStepList* buildStepList
|
||||||
|
= stepList(Core::Id(ProjectExplorer::Constants::BUILDSTEPS_BUILD));
|
||||||
|
Q_ASSERT(buildStepList);
|
||||||
|
foreach (ProjectExplorer::BuildStep* bs, buildStepList->steps()) {
|
||||||
|
if (BuildStep* bbStep = qobject_cast<BuildStep*>(bs)) {
|
||||||
|
type = bbStep->buildType();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
Utils::FileName BuildConfiguration::workingDirectory() const
|
||||||
|
{
|
||||||
|
Q_ASSERT(!workingDirectory_.isEmpty());
|
||||||
|
return workingDirectory_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildConfiguration::setWorkingDirectory(Utils::FileName const& dir)
|
||||||
|
{
|
||||||
|
if (dir.isEmpty()) {
|
||||||
|
if (Target* t = target()) {
|
||||||
|
QString const dwd
|
||||||
|
= Project::defaultWorkingDirectory(t->project()->projectDirectory().toString());
|
||||||
|
workingDirectory_ = Utils::FileName::fromString(dwd);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
workingDirectory_ = dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_ASSERT(!workingDirectory_.isEmpty());
|
||||||
|
emitWorkingDirectoryChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildConfiguration::emitWorkingDirectoryChanged()
|
||||||
|
{
|
||||||
|
if (workingDirectory() != lastEmmitedWorkingDirectory_) {
|
||||||
|
lastEmmitedWorkingDirectory_= workingDirectory();
|
||||||
|
emit workingDirectoryChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildConfigurationFactory::BuildConfigurationFactory(QObject* parent)
|
||||||
|
: IBuildConfigurationFactory(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
BuildConfigurationFactory::priority(ProjectExplorer::Target const* parent) const
|
||||||
|
{
|
||||||
|
return canHandle(parent) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
BuildConfigurationFactory::priority(ProjectExplorer::Kit const* k
|
||||||
|
, QString const& projectPath) const
|
||||||
|
{
|
||||||
|
BBPM_QDEBUG(k->displayName() << ", " << projectPath);
|
||||||
|
|
||||||
|
Utils::MimeDatabase mdb;
|
||||||
|
Utils::MimeType mimeType = mdb.mimeTypeForFile(QFileInfo(projectPath));
|
||||||
|
|
||||||
|
return (k && mimeType.matchesName(QLatin1String(Constants::MIMETYPE_JAMFILE)))
|
||||||
|
? 0
|
||||||
|
: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<ProjectExplorer::BuildInfo*>
|
||||||
|
BuildConfigurationFactory::availableBuilds(ProjectExplorer::Target const* parent) const
|
||||||
|
{
|
||||||
|
BBPM_QDEBUG("target: " << parent->displayName());
|
||||||
|
|
||||||
|
ProjectExplorer::Project* project = parent->project();
|
||||||
|
QString const projectPath(project->projectDirectory().toString());
|
||||||
|
BBPM_QDEBUG(projectPath);
|
||||||
|
|
||||||
|
QList<ProjectExplorer::BuildInfo*> result;
|
||||||
|
result << createBuildInfo(parent->kit(), projectPath, BuildConfiguration::Debug);
|
||||||
|
result << createBuildInfo(parent->kit(), projectPath, BuildConfiguration::Release);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<ProjectExplorer::BuildInfo*>
|
||||||
|
BuildConfigurationFactory::availableSetups(ProjectExplorer::Kit const* k
|
||||||
|
, QString const& projectPath) const
|
||||||
|
{
|
||||||
|
BBPM_QDEBUG(projectPath);
|
||||||
|
|
||||||
|
QList<ProjectExplorer::BuildInfo*> result;
|
||||||
|
result << createBuildInfo(k, projectPath, BuildConfiguration::Debug);
|
||||||
|
result << createBuildInfo(k, projectPath, BuildConfiguration::Release);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectExplorer::BuildConfiguration*
|
||||||
|
BuildConfigurationFactory::create(ProjectExplorer::Target* parent
|
||||||
|
, ProjectExplorer::BuildInfo const* info) const
|
||||||
|
{
|
||||||
|
QTC_ASSERT(parent, return 0);
|
||||||
|
QTC_ASSERT(info->factory() == this, return 0);
|
||||||
|
QTC_ASSERT(info->kitId == parent->kit()->id(), return 0);
|
||||||
|
QTC_ASSERT(!info->displayName.isEmpty(), return 0);
|
||||||
|
BBPM_QDEBUG(info->displayName);
|
||||||
|
|
||||||
|
Project* project = qobject_cast<Project*>(parent->project());
|
||||||
|
QTC_ASSERT(project, return 0);
|
||||||
|
|
||||||
|
BuildInfo const* bi = static_cast<BuildInfo const*>(info);
|
||||||
|
QScopedPointer<BuildConfiguration> bc(new BuildConfiguration(parent));
|
||||||
|
bc->setDisplayName(bi->displayName);
|
||||||
|
bc->setDefaultDisplayName(bi->displayName);
|
||||||
|
bc->setBuildDirectory(bi->buildDirectory);
|
||||||
|
bc->setWorkingDirectory(bi->workingDirectory);
|
||||||
|
|
||||||
|
BuildStepFactory* stepFactory = BuildStepFactory::getObject();
|
||||||
|
QTC_ASSERT(stepFactory, return 0);
|
||||||
|
|
||||||
|
// Build steps
|
||||||
|
if (ProjectExplorer::BuildStepList* buildSteps
|
||||||
|
= bc->stepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD)) {
|
||||||
|
BuildStep* step = stepFactory->create(buildSteps);
|
||||||
|
QTC_ASSERT(step, return 0);
|
||||||
|
step->setBuildType(bi->buildType);
|
||||||
|
buildSteps->insertStep(0, step);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean steps
|
||||||
|
if (ProjectExplorer::BuildStepList* cleanSteps
|
||||||
|
= bc->stepList(ProjectExplorer::Constants::BUILDSTEPS_CLEAN)) {
|
||||||
|
BuildStep* step = stepFactory->create(cleanSteps);
|
||||||
|
QTC_ASSERT(step, return 0);
|
||||||
|
step->setBuildType(bi->buildType);
|
||||||
|
cleanSteps->insertStep(0, step);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bc.take();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
BuildConfigurationFactory::canClone(ProjectExplorer::Target const* parent
|
||||||
|
, ProjectExplorer::BuildConfiguration* source) const
|
||||||
|
{
|
||||||
|
Q_ASSERT(parent);
|
||||||
|
Q_ASSERT(source);
|
||||||
|
|
||||||
|
return canHandle(parent)
|
||||||
|
? source->id() == Constants::BUILDCONFIGURATION_ID
|
||||||
|
: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildConfiguration*
|
||||||
|
BuildConfigurationFactory::clone(ProjectExplorer::Target* parent
|
||||||
|
, ProjectExplorer::BuildConfiguration* source)
|
||||||
|
{
|
||||||
|
Q_ASSERT(parent);
|
||||||
|
Q_ASSERT(source);
|
||||||
|
|
||||||
|
BuildConfiguration* copy = 0;
|
||||||
|
if (canClone(parent, source)) {
|
||||||
|
BuildConfiguration* old = static_cast<BuildConfiguration*>(source);
|
||||||
|
copy = new BuildConfiguration(parent, old);
|
||||||
|
}
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
BuildConfigurationFactory::canRestore(ProjectExplorer::Target const* parent
|
||||||
|
, QVariantMap const& map) const
|
||||||
|
{
|
||||||
|
Q_ASSERT(parent);
|
||||||
|
|
||||||
|
return canHandle(parent)
|
||||||
|
? ProjectExplorer::idFromMap(map) == Constants::BUILDCONFIGURATION_ID
|
||||||
|
: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildConfiguration*
|
||||||
|
BuildConfigurationFactory::restore(ProjectExplorer::Target *parent
|
||||||
|
, QVariantMap const& map)
|
||||||
|
{
|
||||||
|
Q_ASSERT(parent);
|
||||||
|
|
||||||
|
if (canRestore(parent, map)) {
|
||||||
|
QScopedPointer<BuildConfiguration> bc(new BuildConfiguration(parent));
|
||||||
|
if (bc->fromMap(map))
|
||||||
|
return bc.take();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
BuildConfigurationFactory::canHandle(ProjectExplorer::Target const* t) const
|
||||||
|
{
|
||||||
|
QTC_ASSERT(t, return false);
|
||||||
|
|
||||||
|
return t->project()->supportsKit(t->kit())
|
||||||
|
? t->project()->id() == Constants::PROJECT_ID
|
||||||
|
: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildInfo*
|
||||||
|
BuildConfigurationFactory::createBuildInfo(ProjectExplorer::Kit const* k
|
||||||
|
, QString const& projectPath
|
||||||
|
, BuildConfiguration::BuildType type) const
|
||||||
|
{
|
||||||
|
Q_ASSERT(k);
|
||||||
|
|
||||||
|
BuildInfo* info = new BuildInfo(this);
|
||||||
|
if (type == BuildConfiguration::Release)
|
||||||
|
info->displayName = tr("Release");
|
||||||
|
else
|
||||||
|
info->displayName = tr("Debug");
|
||||||
|
info->typeName = tr("Default (%1)").arg(info->displayName);
|
||||||
|
info->buildType = type;
|
||||||
|
info->buildDirectory = defaultBuildDirectory(projectPath);
|
||||||
|
info->workingDirectory = defaultWorkingDirectory(projectPath);
|
||||||
|
info->kitId = k->id();
|
||||||
|
|
||||||
|
BBPM_QDEBUG(info->typeName << " in " << projectPath);
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*static*/ Utils::FileName
|
||||||
|
BuildConfigurationFactory::defaultBuildDirectory(QString const& top)
|
||||||
|
{
|
||||||
|
return Utils::FileName::fromString(Project::defaultBuildDirectory(top));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*static*/ Utils::FileName
|
||||||
|
BuildConfigurationFactory::defaultWorkingDirectory(QString const& top)
|
||||||
|
{
|
||||||
|
return Utils::FileName::fromString(Project::defaultWorkingDirectory(top));
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildSettingsWidget::BuildSettingsWidget(BuildConfiguration* bc)
|
||||||
|
: bc_(bc)
|
||||||
|
, buildPathChooser_(0)
|
||||||
|
{
|
||||||
|
setDisplayName(tr("Boost.Build Manager"));
|
||||||
|
|
||||||
|
QFormLayout* fl = new QFormLayout(this);
|
||||||
|
fl->setContentsMargins(0, -1, 0, -1);
|
||||||
|
fl->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
|
||||||
|
|
||||||
|
QString const projectPath(bc_->target()->project()->projectDirectory().toString());
|
||||||
|
|
||||||
|
// Working directory
|
||||||
|
workPathChooser_ = new Utils::PathChooser(this);
|
||||||
|
workPathChooser_->setEnabled(true);
|
||||||
|
workPathChooser_->setEnvironment(bc_->environment());
|
||||||
|
workPathChooser_->setBaseDirectory(projectPath);
|
||||||
|
workPathChooser_->setPath(bc_->workingDirectory().toString());
|
||||||
|
fl->addRow(tr("Run Boost.Build in:"), workPathChooser_);
|
||||||
|
|
||||||
|
// Build directory
|
||||||
|
buildPathChooser_ = new Utils::PathChooser(this);
|
||||||
|
buildPathChooser_->setEnabled(true);
|
||||||
|
buildPathChooser_->setEnvironment(bc_->environment());
|
||||||
|
buildPathChooser_->setBaseDirectory(projectPath);
|
||||||
|
buildPathChooser_->setPath(bc_->rawBuildDirectory().toString());
|
||||||
|
fl->addRow(tr("Set build directory to:"), buildPathChooser_);
|
||||||
|
|
||||||
|
connect(workPathChooser_, SIGNAL(changed(QString))
|
||||||
|
, this, SLOT(workingDirectoryChanged()));
|
||||||
|
|
||||||
|
connect(buildPathChooser_, SIGNAL(changed(QString))
|
||||||
|
, this, SLOT(buildDirectoryChanged()));
|
||||||
|
|
||||||
|
connect(bc, SIGNAL(environmentChanged())
|
||||||
|
, this, SLOT(environmentHasChanged()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildSettingsWidget::buildDirectoryChanged()
|
||||||
|
{
|
||||||
|
QTC_ASSERT(bc_, return);
|
||||||
|
bc_->setBuildDirectory(Utils::FileName::fromString(buildPathChooser_->rawPath()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildSettingsWidget::workingDirectoryChanged()
|
||||||
|
{
|
||||||
|
QTC_ASSERT(bc_, return);
|
||||||
|
bc_->setWorkingDirectory(Utils::FileName::fromString(workPathChooser_->rawPath()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildSettingsWidget::environmentHasChanged()
|
||||||
|
{
|
||||||
|
Q_ASSERT(buildPathChooser_);
|
||||||
|
buildPathChooser_->setEnvironment(bc_->environment());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace BoostBuildProjectManager
|
138
src/plugins/boostbuildprojectmanager/b2buildconfiguration.h
Normal file
138
src/plugins/boostbuildprojectmanager/b2buildconfiguration.h
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
//
|
||||||
|
// This file is part of Qt Creator Boost.Build plugin project.
|
||||||
|
//
|
||||||
|
// This is free software; you can redistribute and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License, Version 2.1
|
||||||
|
// as published by the Free Software Foundation.
|
||||||
|
// See accompanying file LICENSE.txt or copy at
|
||||||
|
// http://www.gnu.org/licenses/lgpl-2.1-standalone.html.
|
||||||
|
//
|
||||||
|
#ifndef BBBUILDCONFIGURATION_HPP
|
||||||
|
#define BBBUILDCONFIGURATION_HPP
|
||||||
|
|
||||||
|
// Qt Creator
|
||||||
|
#include <projectexplorer/buildconfiguration.h>
|
||||||
|
#include <projectexplorer/namedwidget.h>
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
// Qt
|
||||||
|
#include <QList>
|
||||||
|
#include <QString>
|
||||||
|
#include <QVariantMap>
|
||||||
|
|
||||||
|
namespace Utils {
|
||||||
|
class FileName;
|
||||||
|
class PathChooser;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace BoostBuildProjectManager {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class BuildInfo;
|
||||||
|
class BuildSettingsWidget;
|
||||||
|
|
||||||
|
class BuildConfiguration : public ProjectExplorer::BuildConfiguration
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
friend class BuildConfigurationFactory;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit BuildConfiguration(ProjectExplorer::Target* parent);
|
||||||
|
|
||||||
|
QVariantMap toMap() const;
|
||||||
|
|
||||||
|
ProjectExplorer::NamedWidget* createConfigWidget();
|
||||||
|
|
||||||
|
BuildType buildType() const;
|
||||||
|
|
||||||
|
Utils::FileName workingDirectory() const;
|
||||||
|
void setWorkingDirectory(Utils::FileName const& dir);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void workingDirectoryChanged();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
BuildConfiguration(ProjectExplorer::Target* parent, BuildConfiguration* source);
|
||||||
|
BuildConfiguration(ProjectExplorer::Target* parent, Core::Id const id);
|
||||||
|
|
||||||
|
bool fromMap(QVariantMap const& map);
|
||||||
|
|
||||||
|
friend class BuildSettingsWidget;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void emitWorkingDirectoryChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Utils::FileName workingDirectory_;
|
||||||
|
Utils::FileName lastEmmitedWorkingDirectory_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BuildConfigurationFactory : public ProjectExplorer::IBuildConfigurationFactory
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit BuildConfigurationFactory(QObject* parent = 0);
|
||||||
|
|
||||||
|
int priority(ProjectExplorer::Target const* parent) const;
|
||||||
|
int priority(ProjectExplorer::Kit const* k, QString const& projectPath) const;
|
||||||
|
|
||||||
|
QList<ProjectExplorer::BuildInfo*>
|
||||||
|
availableBuilds(ProjectExplorer::Target const* parent) const;
|
||||||
|
|
||||||
|
QList<ProjectExplorer::BuildInfo*>
|
||||||
|
availableSetups(ProjectExplorer::Kit const* k, QString const& projectPath) const;
|
||||||
|
|
||||||
|
ProjectExplorer::BuildConfiguration*
|
||||||
|
create(ProjectExplorer::Target* parent
|
||||||
|
, ProjectExplorer::BuildInfo const* info) const;
|
||||||
|
|
||||||
|
bool
|
||||||
|
canClone(ProjectExplorer::Target const* parent
|
||||||
|
, ProjectExplorer::BuildConfiguration* source) const;
|
||||||
|
|
||||||
|
BuildConfiguration*
|
||||||
|
clone(ProjectExplorer::Target* parent, ProjectExplorer::BuildConfiguration* source);
|
||||||
|
|
||||||
|
bool
|
||||||
|
canRestore(ProjectExplorer::Target const* parent, QVariantMap const& map) const;
|
||||||
|
|
||||||
|
BuildConfiguration*
|
||||||
|
restore(ProjectExplorer::Target *parent, QVariantMap const& map);
|
||||||
|
|
||||||
|
static Utils::FileName defaultBuildDirectory(QString const& top);
|
||||||
|
static Utils::FileName defaultWorkingDirectory(QString const& top);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool canHandle(ProjectExplorer::Target const* target) const;
|
||||||
|
|
||||||
|
BuildInfo*
|
||||||
|
createBuildInfo(ProjectExplorer::Kit const* k
|
||||||
|
, QString const& projectPath
|
||||||
|
, BuildConfiguration::BuildType type) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BuildSettingsWidget : public ProjectExplorer::NamedWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
BuildSettingsWidget(BuildConfiguration* bc);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void environmentHasChanged();
|
||||||
|
void buildDirectoryChanged();
|
||||||
|
void workingDirectoryChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
BuildConfiguration* bc_;
|
||||||
|
Utils::PathChooser* workPathChooser_;
|
||||||
|
Utils::PathChooser* buildPathChooser_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace BoostBuildProjectManager
|
||||||
|
|
||||||
|
#endif // BBBUILDCONFIGURATION_HPP
|
26
src/plugins/boostbuildprojectmanager/b2buildinfo.cpp
Normal file
26
src/plugins/boostbuildprojectmanager/b2buildinfo.cpp
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
//
|
||||||
|
// This file is part of Qt Creator Boost.Build plugin project.
|
||||||
|
//
|
||||||
|
// This is free software; you can redistribute and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License, Version 2.1
|
||||||
|
// as published by the Free Software Foundation.
|
||||||
|
// See accompanying file LICENSE.txt or copy at
|
||||||
|
// http://www.gnu.org/licenses/lgpl-2.1-standalone.html.
|
||||||
|
//
|
||||||
|
#include "b2buildinfo.h"
|
||||||
|
#include "b2buildconfiguration.h"
|
||||||
|
#include "b2projectmanagerconstants.h"
|
||||||
|
|
||||||
|
namespace BoostBuildProjectManager {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
BuildInfo::BuildInfo(BuildConfigurationFactory const* f)
|
||||||
|
: ProjectExplorer::BuildInfo(f)
|
||||||
|
, buildType(BuildConfiguration::Debug)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace BoostBuildProjectManager
|
44
src/plugins/boostbuildprojectmanager/b2buildinfo.h
Normal file
44
src/plugins/boostbuildprojectmanager/b2buildinfo.h
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
//
|
||||||
|
// This file is part of Qt Creator Boost.Build plugin project.
|
||||||
|
//
|
||||||
|
// This is free software; you can redistribute and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License, Version 2.1
|
||||||
|
// as published by the Free Software Foundation.
|
||||||
|
// See accompanying file LICENSE.txt or copy at
|
||||||
|
// http://www.gnu.org/licenses/lgpl-2.1-standalone.html.
|
||||||
|
//
|
||||||
|
#ifndef BBBUILDINFO_HPP
|
||||||
|
#define BBBUILDINFO_HPP
|
||||||
|
|
||||||
|
#include "b2buildconfiguration.h"
|
||||||
|
// Qt Creator
|
||||||
|
#include <projectexplorer/buildconfiguration.h>
|
||||||
|
#include <projectexplorer/buildinfo.h>
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
// Qt
|
||||||
|
|
||||||
|
namespace BoostBuildProjectManager {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class BuildConfigurationFactory;
|
||||||
|
|
||||||
|
class BuildInfo : public ProjectExplorer::BuildInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit BuildInfo(BuildConfigurationFactory const* f);
|
||||||
|
|
||||||
|
// Boost.Build option variant={debug|release}
|
||||||
|
// By default, the debug variant is set.
|
||||||
|
BuildConfiguration::BuildType buildType;
|
||||||
|
|
||||||
|
// Boost.Build command working directory.
|
||||||
|
// By default, empty what indicates project path from where Jamfile was opened.
|
||||||
|
Utils::FileName workingDirectory;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace BoostBuildProjectManager
|
||||||
|
|
||||||
|
#endif // BBBUILDINFO_HPP
|
420
src/plugins/boostbuildprojectmanager/b2buildstep.cpp
Normal file
420
src/plugins/boostbuildprojectmanager/b2buildstep.cpp
Normal file
@@ -0,0 +1,420 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
// Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
// Copyright (C) 2013 Openismus GmbH.
|
||||||
|
//
|
||||||
|
// This file is part of Qt Creator Boost.Build plugin project.
|
||||||
|
//
|
||||||
|
// This is free software; you can redistribute and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License, Version 2.1
|
||||||
|
// as published by the Free Software Foundation.
|
||||||
|
// See accompanying file LICENSE.txt or copy at
|
||||||
|
// http://www.gnu.org/licenses/lgpl-2.1-standalone.html.
|
||||||
|
//
|
||||||
|
#include "b2buildconfiguration.h"
|
||||||
|
#include "b2buildstep.h"
|
||||||
|
#include "b2outputparser.h"
|
||||||
|
#include "b2projectmanagerconstants.h"
|
||||||
|
#include "b2utility.h"
|
||||||
|
// Qt Creator
|
||||||
|
#include <extensionsystem/pluginmanager.h>
|
||||||
|
#include <projectexplorer/buildconfiguration.h>
|
||||||
|
#include <projectexplorer/buildstep.h>
|
||||||
|
#include <projectexplorer/buildsteplist.h>
|
||||||
|
#include <projectexplorer/kitinformation.h>
|
||||||
|
#include <projectexplorer/processparameters.h>
|
||||||
|
#include <projectexplorer/project.h>
|
||||||
|
#include <projectexplorer/projectconfiguration.h>
|
||||||
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
|
#include <projectexplorer/target.h>
|
||||||
|
#include <projectexplorer/toolchain.h>
|
||||||
|
#include <utils/environment.h>
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/qtcprocess.h>
|
||||||
|
// Qt
|
||||||
|
#include <QFormLayout>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QScopedPointer>
|
||||||
|
#include <QString>
|
||||||
|
// std
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace BoostBuildProjectManager {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
BuildStep::BuildStep(ProjectExplorer::BuildStepList* bsl)
|
||||||
|
: ProjectExplorer::AbstractProcessStep(bsl, Core::Id(Constants::BUILDSTEP_ID))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildStep::BuildStep(ProjectExplorer::BuildStepList* bsl, BuildStep* bs)
|
||||||
|
: AbstractProcessStep(bsl, bs)
|
||||||
|
, tasks_(bs->tasks_)
|
||||||
|
, arguments_(bs->arguments_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildStep::BuildStep(ProjectExplorer::BuildStepList* bsl, Core::Id const id)
|
||||||
|
: AbstractProcessStep(bsl, id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BuildStep::init()
|
||||||
|
{
|
||||||
|
setDefaultDisplayName(QLatin1String(Constants::BOOSTBUILD));
|
||||||
|
|
||||||
|
tasks_.clear();
|
||||||
|
ProjectExplorer::ToolChain* tc
|
||||||
|
= ProjectExplorer::ToolChainKitInformation::toolChain(target()->kit());
|
||||||
|
if (!tc) {
|
||||||
|
BBPM_QDEBUG("Qt Creator needs compiler");
|
||||||
|
typedef ProjectExplorer::Task Task;
|
||||||
|
Task task(Task::Error
|
||||||
|
, tr("Qt Creator needs a compiler set up to build. Configure a compiler in the kit options.")
|
||||||
|
, Utils::FileName(), -1
|
||||||
|
, ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
|
||||||
|
|
||||||
|
tasks_.append(task);
|
||||||
|
return !tasks_.empty(); // otherwise the tasks will not get reported
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildConfiguration* bc = thisBuildConfiguration();
|
||||||
|
QTC_ASSERT(bc, return false);
|
||||||
|
|
||||||
|
setIgnoreReturnValue(Constants::ReturnValueNotIgnored);
|
||||||
|
|
||||||
|
ProjectExplorer::ProcessParameters* pp = processParameters();
|
||||||
|
pp->setMacroExpander(bc->macroExpander());
|
||||||
|
{
|
||||||
|
// from GenericProjectManager code:
|
||||||
|
// Force output to english for the parsers.
|
||||||
|
// Do this here and not in the toolchain's addToEnvironment() to not
|
||||||
|
// screw up the users run environment.
|
||||||
|
Utils::Environment env = bc->environment();
|
||||||
|
env.set(QLatin1String("LC_ALL"), QLatin1String("C"));
|
||||||
|
pp->setEnvironment(env);
|
||||||
|
}
|
||||||
|
pp->setWorkingDirectory(bc->workingDirectory().toString());
|
||||||
|
pp->setCommand(makeCommand(bc->environment()));
|
||||||
|
pp->setArguments(allArguments());
|
||||||
|
pp->resolveAll();
|
||||||
|
|
||||||
|
// Create Boost.Build parser and chain with existing parsers
|
||||||
|
setOutputParser(new BoostBuildParser());
|
||||||
|
if (ProjectExplorer::IOutputParser* parser = target()->kit()->createOutputParser())
|
||||||
|
appendOutputParser(parser);
|
||||||
|
outputParser()->setWorkingDirectory(pp->effectiveWorkingDirectory());
|
||||||
|
|
||||||
|
BBPM_QDEBUG(displayName() << ", " << bc->buildDirectory().toString()
|
||||||
|
<< ", " << pp->effectiveWorkingDirectory());
|
||||||
|
|
||||||
|
return ProjectExplorer::AbstractProcessStep::init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildStep::run(QFutureInterface<bool>& fi)
|
||||||
|
{
|
||||||
|
BBPM_QDEBUG("running: " << displayName());
|
||||||
|
|
||||||
|
bool canContinue = true;
|
||||||
|
foreach (ProjectExplorer::Task const& t, tasks_) {
|
||||||
|
addTask(t);
|
||||||
|
canContinue = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!canContinue) {
|
||||||
|
emit addOutput(tr("Configuration is faulty. Check the Issues view for details.")
|
||||||
|
, BuildStep::MessageOutput);
|
||||||
|
fi.reportResult(false);
|
||||||
|
emit finished();
|
||||||
|
} else {
|
||||||
|
AbstractProcessStep::run(fi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildConfiguration* BuildStep::thisBuildConfiguration() const
|
||||||
|
{
|
||||||
|
BuildConfiguration* bc = 0;
|
||||||
|
if (ProjectExplorer::BuildConfiguration* bcBase = buildConfiguration()) {
|
||||||
|
bc = qobject_cast<BuildConfiguration*>(bcBase);
|
||||||
|
} else {
|
||||||
|
// TODO: Do we need to do anything with this case?
|
||||||
|
// From QmakeProjectManager:
|
||||||
|
// That means the step is in the deploylist, so we listen to the active build
|
||||||
|
// config changed signal and react...
|
||||||
|
|
||||||
|
bcBase = target()->activeBuildConfiguration();
|
||||||
|
bc = qobject_cast<BuildConfiguration*>(bcBase);
|
||||||
|
}
|
||||||
|
return bc;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectExplorer::BuildStepConfigWidget* BuildStep::createConfigWidget()
|
||||||
|
{
|
||||||
|
return new BuildStepConfigWidget(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BuildStep::immutable() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap BuildStep::toMap() const
|
||||||
|
{
|
||||||
|
QVariantMap map(ProjectExplorer::AbstractProcessStep::toMap());
|
||||||
|
map.insert(QLatin1String(Constants::BS_KEY_ARGUMENTS), additionalArguments());
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BuildStep::fromMap(QVariantMap const& map)
|
||||||
|
{
|
||||||
|
QString const args(map.value(QLatin1String(Constants::BS_KEY_ARGUMENTS)).toString());
|
||||||
|
setAdditionalArguments(args);
|
||||||
|
|
||||||
|
return ProjectExplorer::AbstractProcessStep::fromMap(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString BuildStep::makeCommand(Utils::Environment const& env) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(env);
|
||||||
|
return QLatin1String(Constants::COMMAND_BB2);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString BuildStep::additionalArguments() const
|
||||||
|
{
|
||||||
|
return Utils::QtcProcess::joinArgs(arguments_);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString BuildStep::allArguments() const
|
||||||
|
{
|
||||||
|
QStringList args(arguments_);
|
||||||
|
|
||||||
|
// Collect implicit arguments not specified by user directly as option=value pair
|
||||||
|
if (ProjectExplorer::BuildConfiguration* bc = buildConfiguration()) {
|
||||||
|
QString const builddir(bc->buildDirectory().toString());
|
||||||
|
if (!builddir.isEmpty())
|
||||||
|
args.append(QLatin1String("--build-dir=") + builddir);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Utils::QtcProcess::joinArgs(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildStep::appendAdditionalArgument(QString const& arg)
|
||||||
|
{
|
||||||
|
// TODO: use map or find duplicates?
|
||||||
|
arguments_.append(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildStep::setAdditionalArguments(QString const& args)
|
||||||
|
{
|
||||||
|
Utils::QtcProcess::SplitError err;
|
||||||
|
QStringList argsList = Utils::QtcProcess::splitArgs(args, Utils::HostOsInfo::hostOs(), false, &err);
|
||||||
|
if (err == Utils::QtcProcess::SplitOk) {
|
||||||
|
arguments_ = argsList;
|
||||||
|
emit argumentsChanged(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectExplorer::BuildConfiguration::BuildType
|
||||||
|
BuildStep::buildType() const
|
||||||
|
{
|
||||||
|
// TODO: what is user inputs "variant = release" or mixed-case value?
|
||||||
|
return arguments_.contains(QLatin1String("variant=release"))
|
||||||
|
? BuildConfiguration::Release
|
||||||
|
: BuildConfiguration::Debug;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BuildStep::setBuildType(ProjectExplorer::BuildConfiguration::BuildType type)
|
||||||
|
{
|
||||||
|
// TODO: Move literals to constants
|
||||||
|
QString arg(QLatin1String("variant="));
|
||||||
|
if (type == BuildConfiguration::Release)
|
||||||
|
arg += QLatin1String("release");
|
||||||
|
else
|
||||||
|
arg += QLatin1String("debug");
|
||||||
|
|
||||||
|
appendAdditionalArgument(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildStepFactory::BuildStepFactory(QObject* parent)
|
||||||
|
: IBuildStepFactory(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*static*/ BuildStepFactory* BuildStepFactory::getObject()
|
||||||
|
{
|
||||||
|
return ExtensionSystem::PluginManager::getObject<BuildStepFactory>();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<Core::Id>
|
||||||
|
BuildStepFactory::availableCreationIds(ProjectExplorer::BuildStepList* parent) const
|
||||||
|
{
|
||||||
|
return canHandle(parent)
|
||||||
|
? QList<Core::Id>() << Core::Id(Constants::BUILDSTEP_ID)
|
||||||
|
: QList<Core::Id>();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString BuildStepFactory::displayNameForId(Core::Id const id) const
|
||||||
|
{
|
||||||
|
BBPM_QDEBUG("id: " << id.toString());
|
||||||
|
|
||||||
|
QString name;
|
||||||
|
if (id == Constants::BUILDSTEP_ID) {
|
||||||
|
name = tr("Boost.Build"
|
||||||
|
, "Display name for BoostBuildProjectManager::BuildStep id.");
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BuildStepFactory::canCreate(ProjectExplorer::BuildStepList* parent
|
||||||
|
, Core::Id const id) const
|
||||||
|
{
|
||||||
|
return canHandle(parent) && Core::Id(Constants::BUILDSTEP_ID) == id;
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildStep*
|
||||||
|
BuildStepFactory::create(ProjectExplorer::BuildStepList* parent)
|
||||||
|
{
|
||||||
|
ProjectExplorer::BuildStep* step = create(parent, Constants::BUILDSTEP_ID);
|
||||||
|
return qobject_cast<BuildStep*>(step);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectExplorer::BuildStep*
|
||||||
|
BuildStepFactory::create(ProjectExplorer::BuildStepList* parent, Core::Id const id)
|
||||||
|
{
|
||||||
|
BBPM_QDEBUG("id: " << id.toString());
|
||||||
|
if (!canCreate(parent, id))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
BuildStep* step = new BuildStep(parent);
|
||||||
|
|
||||||
|
if (parent->id() == ProjectExplorer::Constants::BUILDSTEPS_CLEAN)
|
||||||
|
step->appendAdditionalArgument(QLatin1String("--clean"));
|
||||||
|
|
||||||
|
return step;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BuildStepFactory::canClone(ProjectExplorer::BuildStepList *parent
|
||||||
|
, ProjectExplorer::BuildStep *source) const
|
||||||
|
{
|
||||||
|
return canCreate(parent, source->id());
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectExplorer::BuildStep*
|
||||||
|
BuildStepFactory::clone(ProjectExplorer::BuildStepList* parent
|
||||||
|
, ProjectExplorer::BuildStep* source)
|
||||||
|
{
|
||||||
|
return canClone(parent, source)
|
||||||
|
? new BuildStep(parent, static_cast<BuildStep*>(source))
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BuildStepFactory::canRestore(ProjectExplorer::BuildStepList* parent
|
||||||
|
, QVariantMap const& map) const
|
||||||
|
{
|
||||||
|
return canCreate(parent, ProjectExplorer::idFromMap(map));
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectExplorer::BuildStep*
|
||||||
|
BuildStepFactory::restore(ProjectExplorer::BuildStepList* parent
|
||||||
|
, QVariantMap const& map)
|
||||||
|
{
|
||||||
|
Q_ASSERT(parent);
|
||||||
|
|
||||||
|
if (canRestore(parent, map)) {
|
||||||
|
QScopedPointer<BuildStep> bs(new BuildStep(parent));
|
||||||
|
if (bs->fromMap(map))
|
||||||
|
return bs.take();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BuildStepFactory::canHandle(ProjectExplorer::BuildStepList* parent) const
|
||||||
|
{
|
||||||
|
QTC_ASSERT(parent, return false);
|
||||||
|
return parent->target()->project()->id() == Constants::PROJECT_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildStepConfigWidget::BuildStepConfigWidget(BuildStep* step)
|
||||||
|
: step_(step)
|
||||||
|
{
|
||||||
|
QFormLayout *fl = new QFormLayout(this);
|
||||||
|
fl->setMargin(0);
|
||||||
|
fl->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
|
||||||
|
setLayout(fl);
|
||||||
|
|
||||||
|
arguments_ = new QLineEdit(this);
|
||||||
|
arguments_->setText(step_->additionalArguments());
|
||||||
|
fl->addRow(tr("Arguments:"), arguments_);
|
||||||
|
|
||||||
|
updateDetails();
|
||||||
|
|
||||||
|
connect(arguments_, SIGNAL(textChanged(QString))
|
||||||
|
, step, SLOT(setAdditionalArguments(QString)));
|
||||||
|
connect(step, SIGNAL(argumentsChanged(QString))
|
||||||
|
, this, SLOT(updateDetails()));
|
||||||
|
connect(step_->project(), SIGNAL(environmentChanged())
|
||||||
|
, this, SLOT(updateDetails()));
|
||||||
|
|
||||||
|
if (BuildConfiguration* bc = step_->thisBuildConfiguration()) {
|
||||||
|
connect(bc, SIGNAL(buildDirectoryChanged())
|
||||||
|
, this, SLOT(updateDetails()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildStepConfigWidget::~BuildStepConfigWidget()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QString BuildStepConfigWidget::displayName() const
|
||||||
|
{
|
||||||
|
return tr(Constants::BOOSTBUILD
|
||||||
|
, "BoostBuildProjectManager::BuildStep display name.");
|
||||||
|
}
|
||||||
|
|
||||||
|
QString BuildStepConfigWidget::summaryText() const
|
||||||
|
{
|
||||||
|
return summaryText_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildStepConfigWidget::setSummaryText(QString const& text)
|
||||||
|
{
|
||||||
|
if (text != summaryText_) {
|
||||||
|
summaryText_ = text;
|
||||||
|
emit updateSummary();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildStepConfigWidget::updateDetails()
|
||||||
|
{
|
||||||
|
ProjectExplorer::ToolChain* tc
|
||||||
|
= ProjectExplorer::ToolChainKitInformation::toolChain(step_->target()->kit());
|
||||||
|
if (!tc) {
|
||||||
|
setSummaryText(tr("<b>%1:</b> %2")
|
||||||
|
.arg(QLatin1String(Constants::BOOSTBUILD))
|
||||||
|
.arg(ProjectExplorer::ToolChainKitInformation::msgNoToolChainInTarget()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildConfiguration* bc = step_->thisBuildConfiguration();
|
||||||
|
QTC_ASSERT(bc, return;);
|
||||||
|
|
||||||
|
ProjectExplorer::ProcessParameters params;
|
||||||
|
params.setMacroExpander(bc->macroExpander());
|
||||||
|
params.setEnvironment(bc->environment());
|
||||||
|
params.setWorkingDirectory(bc->workingDirectory().toString());
|
||||||
|
params.setCommand(step_->makeCommand(bc->environment()));
|
||||||
|
params.setArguments(step_->allArguments());
|
||||||
|
|
||||||
|
if (params.commandMissing()) {
|
||||||
|
setSummaryText(tr("<b>%1:</b> %2 not found in the environment.")
|
||||||
|
.arg(QLatin1String(Constants::BOOSTBUILD))
|
||||||
|
.arg(params.command())); // Override display text
|
||||||
|
} else {
|
||||||
|
setSummaryText(params.summary(displayName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace BoostBuildProjectManager
|
162
src/plugins/boostbuildprojectmanager/b2buildstep.h
Normal file
162
src/plugins/boostbuildprojectmanager/b2buildstep.h
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
//
|
||||||
|
// This file is part of Qt Creator Boost.Build plugin project.
|
||||||
|
//
|
||||||
|
// This is free software; you can redistribute and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License, Version 2.1
|
||||||
|
// as published by the Free Software Foundation.
|
||||||
|
// See accompanying file LICENSE.txt or copy at
|
||||||
|
// http://www.gnu.org/licenses/lgpl-2.1-standalone.html.
|
||||||
|
//
|
||||||
|
#ifndef BBBUILDSTEP_HPP
|
||||||
|
#define BBBUILDSTEP_HPP
|
||||||
|
|
||||||
|
// Qt Creator
|
||||||
|
#include <projectexplorer/abstractprocessstep.h>
|
||||||
|
#include <projectexplorer/buildconfiguration.h>
|
||||||
|
#include <projectexplorer/buildstep.h>
|
||||||
|
#include <projectexplorer/task.h>
|
||||||
|
// Qt
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QList>
|
||||||
|
#include <QString>
|
||||||
|
#include <QVariantMap>
|
||||||
|
|
||||||
|
namespace ProjectExplorer {
|
||||||
|
class Project;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Utils {
|
||||||
|
class Environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace BoostBuildProjectManager {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class BuildConfiguration;
|
||||||
|
|
||||||
|
class BuildStep : public ProjectExplorer::AbstractProcessStep
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
friend class BuildStepFactory;
|
||||||
|
friend class BuildStepConfigWidget;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit BuildStep(ProjectExplorer::BuildStepList* bsl);
|
||||||
|
|
||||||
|
bool init();
|
||||||
|
|
||||||
|
void run(QFutureInterface<bool>& interface);
|
||||||
|
|
||||||
|
ProjectExplorer::BuildStepConfigWidget* createConfigWidget();
|
||||||
|
|
||||||
|
bool immutable() const;
|
||||||
|
|
||||||
|
QVariantMap toMap() const;
|
||||||
|
|
||||||
|
bool fromMap(QVariantMap const& map);
|
||||||
|
|
||||||
|
QString makeCommand(Utils::Environment const& env) const;
|
||||||
|
|
||||||
|
QString additionalArguments() const;
|
||||||
|
|
||||||
|
QString allArguments() const;
|
||||||
|
|
||||||
|
void appendAdditionalArgument(QString const& arg);
|
||||||
|
|
||||||
|
ProjectExplorer::BuildConfiguration::BuildType
|
||||||
|
buildType() const;
|
||||||
|
|
||||||
|
void setBuildType(ProjectExplorer::BuildConfiguration::BuildType type);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void setAdditionalArguments(QString const& list);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void argumentsChanged(QString const& list);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
BuildStep(ProjectExplorer::BuildStepList* bsl, BuildStep* bs);
|
||||||
|
BuildStep(ProjectExplorer::BuildStepList* bsl, Core::Id const id);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BuildConfiguration* thisBuildConfiguration() const;
|
||||||
|
|
||||||
|
QList<ProjectExplorer::Task> tasks_;
|
||||||
|
QStringList arguments_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Factory used to create instances of BuildStep.
|
||||||
|
class BuildStepFactory : public ProjectExplorer::IBuildStepFactory
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
BuildStepFactory(QObject* parent = 0);
|
||||||
|
|
||||||
|
static BuildStepFactory* getObject();
|
||||||
|
|
||||||
|
QList<Core::Id>
|
||||||
|
availableCreationIds(ProjectExplorer::BuildStepList* bc) const;
|
||||||
|
|
||||||
|
QString
|
||||||
|
displayNameForId(const Core::Id id) const;
|
||||||
|
|
||||||
|
bool
|
||||||
|
canCreate(ProjectExplorer::BuildStepList* parent, Core::Id const id) const;
|
||||||
|
|
||||||
|
BuildStep*
|
||||||
|
create(ProjectExplorer::BuildStepList* parent);
|
||||||
|
|
||||||
|
ProjectExplorer::BuildStep*
|
||||||
|
create(ProjectExplorer::BuildStepList* parent, Core::Id const id);
|
||||||
|
|
||||||
|
bool
|
||||||
|
canClone(ProjectExplorer::BuildStepList *parent
|
||||||
|
, ProjectExplorer::BuildStep *source) const;
|
||||||
|
|
||||||
|
ProjectExplorer::BuildStep*
|
||||||
|
clone(ProjectExplorer::BuildStepList* parent, ProjectExplorer::BuildStep* source);
|
||||||
|
|
||||||
|
bool
|
||||||
|
canRestore(ProjectExplorer::BuildStepList* parent, QVariantMap const& map) const;
|
||||||
|
|
||||||
|
ProjectExplorer::BuildStep*
|
||||||
|
restore(ProjectExplorer::BuildStepList* parent, QVariantMap const& map);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
bool
|
||||||
|
canHandle(ProjectExplorer::BuildStepList* parent) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BuildStepConfigWidget : public ProjectExplorer::BuildStepConfigWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit BuildStepConfigWidget(BuildStep* buildStep);
|
||||||
|
~BuildStepConfigWidget();
|
||||||
|
QString displayName() const;
|
||||||
|
QString summaryText() const;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
void updateDetails();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setSummaryText(const QString &text);
|
||||||
|
|
||||||
|
ProjectExplorer::BuildConfiguration* bc_;
|
||||||
|
BuildStep* step_;
|
||||||
|
QString summaryText_;
|
||||||
|
QLineEdit* arguments_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace BoostBuildProjectManager
|
||||||
|
|
||||||
|
#endif // BBBUILDSTEP_HPP
|
||||||
|
|
272
src/plugins/boostbuildprojectmanager/b2openprojectwizard.cpp
Normal file
272
src/plugins/boostbuildprojectmanager/b2openprojectwizard.cpp
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
// Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
//
|
||||||
|
// This file is part of Qt Creator Boost.Build plugin project.
|
||||||
|
//
|
||||||
|
// This is free software; you can redistribute and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License, Version 2.1
|
||||||
|
// as published by the Free Software Foundation.
|
||||||
|
// See accompanying file LICENSE.txt or copy at
|
||||||
|
// http://www.gnu.org/licenses/lgpl-2.1-standalone.html.
|
||||||
|
//
|
||||||
|
#include "b2openprojectwizard.h"
|
||||||
|
#include "b2project.h"
|
||||||
|
#include "b2projectmanagerconstants.h"
|
||||||
|
#include "b2utility.h"
|
||||||
|
#include "filesselectionwizardpage.h"
|
||||||
|
// Qt Creator
|
||||||
|
#include <coreplugin/iwizardfactory.h>
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
|
#include <projectexplorer/customwizard/customwizard.h>
|
||||||
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
|
#include <utils/pathchooser.h>
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/mimetypes/mimedatabase.h>
|
||||||
|
// Qt
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QFormLayout>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
namespace BoostBuildProjectManager {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
OpenProjectWizard::OpenProjectWizard(Project const* const project)
|
||||||
|
: project_(project)
|
||||||
|
, projectOpened_(false)
|
||||||
|
{
|
||||||
|
// Project instance has been created, but it's only partially initialised and
|
||||||
|
// rest of the initialization takes place after this wizard completes.
|
||||||
|
Q_ASSERT(project_);
|
||||||
|
|
||||||
|
setDisplayName(tr("Open %1 Project").arg(BBPM_C(BOOSTBUILD)));
|
||||||
|
setId(BBPM_C(PROJECT_WIZARD_ID));
|
||||||
|
setWizardKind(ProjectWizard); // affects dir vs file path and sub-projects handling
|
||||||
|
|
||||||
|
// TODO: do we need categories or flags?
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OpenProjectWizard::run(QString const& platform, QVariantMap const& extraValues)
|
||||||
|
{
|
||||||
|
QVariantMap extraValuesCopy(extraValues);
|
||||||
|
|
||||||
|
// Project name should be passed by caller, but,
|
||||||
|
// since we have Project instance handy, double-check.
|
||||||
|
if (!extraValuesCopy.contains(BBPM_C(P_KEY_PROJECTNAME)))
|
||||||
|
extraValuesCopy.insert(BBPM_C(P_KEY_PROJECTNAME), project_->displayName());
|
||||||
|
|
||||||
|
projectOpened_ = false;
|
||||||
|
outputValues_.clear();
|
||||||
|
|
||||||
|
runWizard(project_->projectFilePath().toString(), 0, platform, extraValuesCopy);
|
||||||
|
|
||||||
|
return projectOpened_;
|
||||||
|
}
|
||||||
|
|
||||||
|
Core::BaseFileWizard *OpenProjectWizard::create(QWidget* parent, Core::WizardDialogParameters const& parameters) const
|
||||||
|
{
|
||||||
|
OpenProjectWizardDialog* wizard(new OpenProjectWizardDialog(parent
|
||||||
|
, parameters.defaultPath(), parameters.extraValues()
|
||||||
|
, const_cast<OpenProjectWizard*>(this)->outputValues_));
|
||||||
|
|
||||||
|
foreach (QWizardPage* p, parameters.extensionPages())
|
||||||
|
wizard->addPage(p);
|
||||||
|
|
||||||
|
return wizard;
|
||||||
|
}
|
||||||
|
|
||||||
|
Core::GeneratedFiles
|
||||||
|
OpenProjectWizard::generateFiles(QWizard const* wizard, QString* errorMessage) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(errorMessage)
|
||||||
|
Q_ASSERT(project_);
|
||||||
|
|
||||||
|
OpenProjectWizardDialog const* openWizard
|
||||||
|
= qobject_cast<OpenProjectWizardDialog const*>(wizard);
|
||||||
|
|
||||||
|
QDir const projectDir(openWizard->path());
|
||||||
|
|
||||||
|
// Set up MIME filters for C/C++ headers
|
||||||
|
QStringList headerFilters;
|
||||||
|
QStringList const headerMimeTypes = QStringList()
|
||||||
|
<< QLatin1String("text/x-chdr") << QLatin1String("text/x-c++hdr");
|
||||||
|
|
||||||
|
Utils::MimeDatabase mdb;
|
||||||
|
foreach (QString const& headerMime, headerMimeTypes) {
|
||||||
|
Utils::MimeType mime = mdb.mimeTypeForName(headerMime);
|
||||||
|
foreach (QString const& gp, mime.globPatterns())
|
||||||
|
headerFilters.append(gp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate list of include paths.
|
||||||
|
// If any C/C++ headers in any directory from paths, add it to include paths,
|
||||||
|
// used for C/C++ parsing only.
|
||||||
|
QStringList includePaths;
|
||||||
|
QStringList const paths = openWizard->selectedPaths();
|
||||||
|
foreach (QString const& path, paths) {
|
||||||
|
QFileInfo const fileInfo(path);
|
||||||
|
QDir const thisDir(fileInfo.absoluteFilePath());
|
||||||
|
if (!thisDir.entryList(headerFilters, QDir::Files).isEmpty()) {
|
||||||
|
QString const relative = projectDir.relativeFilePath(thisDir.path());
|
||||||
|
includePaths.append(relative.isEmpty() ? QLatin1String(".") : relative);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate list of sources
|
||||||
|
QStringList sources = openWizard->selectedFiles();
|
||||||
|
Utility::makeRelativePaths(projectDir.absolutePath(), sources);
|
||||||
|
|
||||||
|
Core::GeneratedFile generatedFilesFile(project_->filesFilePath());
|
||||||
|
generatedFilesFile.setContents(sources.join(QLatin1String("\n")));
|
||||||
|
|
||||||
|
Core::GeneratedFile generatedIncludesFile(project_->includesFilePath());
|
||||||
|
generatedIncludesFile.setContents(includePaths.join(QLatin1String("\n")));
|
||||||
|
|
||||||
|
Core::GeneratedFiles files;
|
||||||
|
files.append(generatedFilesFile);
|
||||||
|
files.append(generatedIncludesFile);
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
OpenProjectWizard::postGenerateFiles(QWizard const* wizard
|
||||||
|
, Core::GeneratedFiles const& files, QString* errorMessage)
|
||||||
|
{
|
||||||
|
Q_UNUSED(wizard);
|
||||||
|
|
||||||
|
projectOpened_
|
||||||
|
= ProjectExplorer::CustomProjectWizard::postGenerateOpen(files, errorMessage);
|
||||||
|
|
||||||
|
return projectOpened_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
OpenProjectWizardDialog::OpenProjectWizardDialog(QWidget* parent
|
||||||
|
, QString const& projectFile
|
||||||
|
, QVariantMap const& extraValues, QVariantMap& outputValues)
|
||||||
|
: Core::BaseFileWizard(parent)
|
||||||
|
, outputValues_(outputValues)
|
||||||
|
, extraValues_(extraValues)
|
||||||
|
, projectFile_(projectFile)
|
||||||
|
{
|
||||||
|
setWindowTitle(tr("Open %1 Project").arg(BBPM_C(BOOSTBUILD)));
|
||||||
|
|
||||||
|
pathsPage_ = new PathsSelectionWizardPage(this);
|
||||||
|
pathsPage_->setTitle(tr("Project Name and Paths"));
|
||||||
|
int const pathsPageId = addPage(pathsPage_);
|
||||||
|
wizardProgress()->item(pathsPageId)->setTitle(tr("Location"));
|
||||||
|
|
||||||
|
filesPage_ = new FilesSelectionWizardPage(this);
|
||||||
|
filesPage_->setTitle(tr("File Selection"));
|
||||||
|
int const filesPageId = addPage(filesPage_);
|
||||||
|
wizardProgress()->item(filesPageId)->setTitle(tr("Files"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString OpenProjectWizardDialog::path() const
|
||||||
|
{
|
||||||
|
QFileInfo const projectFileInfo(projectFile());
|
||||||
|
QTC_ASSERT(projectFileInfo.isFile(), return QString());
|
||||||
|
|
||||||
|
return projectFileInfo.absoluteDir().absolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString OpenProjectWizardDialog::projectFile() const
|
||||||
|
{
|
||||||
|
return projectFile_;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString OpenProjectWizardDialog::projectName() const
|
||||||
|
{
|
||||||
|
return pathsPage_->projectName();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString OpenProjectWizardDialog::defaultProjectName() const
|
||||||
|
{
|
||||||
|
return extraValues_.value(BBPM_C(P_KEY_PROJECTNAME)).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList OpenProjectWizardDialog::selectedFiles() const
|
||||||
|
{
|
||||||
|
return filesPage_->selectedFiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList OpenProjectWizardDialog::selectedPaths() const
|
||||||
|
{
|
||||||
|
return filesPage_->selectedPaths();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenProjectWizardDialog::setProjectName(QString const& name)
|
||||||
|
{
|
||||||
|
outputValues_.insert(QLatin1String(Constants::P_KEY_PROJECTNAME), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
PathsSelectionWizardPage::PathsSelectionWizardPage(OpenProjectWizardDialog* wizard)
|
||||||
|
: QWizardPage(wizard)
|
||||||
|
, wizard_(wizard)
|
||||||
|
{
|
||||||
|
QFormLayout *fl = new QFormLayout();
|
||||||
|
setLayout(fl);
|
||||||
|
|
||||||
|
QLabel* pathLabel = new QLabel(this);
|
||||||
|
pathLabel->setText(tr("Opening the following Jamfile as a project:"));
|
||||||
|
fl->addRow(pathLabel);
|
||||||
|
|
||||||
|
QLineEdit* pathLine = new QLineEdit(this);
|
||||||
|
pathLine->setReadOnly(true);
|
||||||
|
pathLine->setDisabled(true);
|
||||||
|
pathLine->setText(wizard_->projectFile());
|
||||||
|
fl->addRow(pathLine);
|
||||||
|
|
||||||
|
QString projectName(Utility::parseJamfileProjectName(wizard_->projectFile()));
|
||||||
|
if (projectName.isEmpty())
|
||||||
|
projectName = wizard_->defaultProjectName();
|
||||||
|
|
||||||
|
nameLineEdit_ = new QLineEdit(this);
|
||||||
|
connect(nameLineEdit_, &QLineEdit::textChanged
|
||||||
|
, wizard_, &OpenProjectWizardDialog::setProjectName);
|
||||||
|
nameLineEdit_->setText(projectName);
|
||||||
|
fl->addRow(tr("Project name:"), nameLineEdit_);
|
||||||
|
|
||||||
|
QLabel* defaultsLabel = new QLabel(this);
|
||||||
|
defaultsLabel->setText(tr("Default Boost.Build runtime locations:"));
|
||||||
|
fl->addRow(defaultsLabel);
|
||||||
|
|
||||||
|
QLineEdit* workingLine = new QLineEdit(this);
|
||||||
|
workingLine->setReadOnly(true);
|
||||||
|
workingLine->setDisabled(true);
|
||||||
|
workingLine->setText(Project::defaultWorkingDirectory(wizard_->projectFile()));
|
||||||
|
fl->addRow(tr("Working directory:"), workingLine);
|
||||||
|
|
||||||
|
QLineEdit* buildLine = new QLineEdit(this);
|
||||||
|
buildLine->setReadOnly(true);
|
||||||
|
buildLine->setDisabled(true);
|
||||||
|
buildLine->setText(Project::defaultBuildDirectory(wizard_->projectFile()));
|
||||||
|
fl->addRow(tr("Build directory:"), buildLine);
|
||||||
|
|
||||||
|
// TODO: indicate if we can find Boost.Build executable?
|
||||||
|
|
||||||
|
QString const info(tr(
|
||||||
|
"This allows you to use Qt Creator as an IDE to edit and navigate C++ code, "
|
||||||
|
"run %1 command, work through compilation issues, "
|
||||||
|
"configure executable targets to run and debug.")
|
||||||
|
.arg(QLatin1String(Constants::BOOSTBUILD)));
|
||||||
|
QLabel* infoLabel = new QLabel(this);
|
||||||
|
infoLabel->setWordWrap(true);
|
||||||
|
infoLabel->setText(info);
|
||||||
|
fl->addRow(infoLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PathsSelectionWizardPage::projectName() const
|
||||||
|
{
|
||||||
|
return nameLineEdit_->text();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace BoostBuildProjectManager
|
127
src/plugins/boostbuildprojectmanager/b2openprojectwizard.h
Normal file
127
src/plugins/boostbuildprojectmanager/b2openprojectwizard.h
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
// Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
//
|
||||||
|
// This file is part of Qt Creator Boost.Build plugin project.
|
||||||
|
//
|
||||||
|
// This is free software; you can redistribute and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License, Version 2.1
|
||||||
|
// as published by the Free Software Foundation.
|
||||||
|
// See accompanying file LICENSE.txt or copy at
|
||||||
|
// http://www.gnu.org/licenses/lgpl-2.1-standalone.html.
|
||||||
|
//
|
||||||
|
#ifndef BBOPENPROJECTWIZARD_HPP
|
||||||
|
#define BBOPENPROJECTWIZARD_HPP
|
||||||
|
|
||||||
|
// Qt Creator
|
||||||
|
#include <coreplugin/basefilewizard.h>
|
||||||
|
#include <coreplugin/basefilewizardfactory.h>
|
||||||
|
#include <coreplugin/generatedfile.h>
|
||||||
|
#include <utils/wizard.h>
|
||||||
|
// Qt
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QVBoxLayout;
|
||||||
|
class QLabel;
|
||||||
|
class QTreeView;
|
||||||
|
class QLineEdit;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace Utils {
|
||||||
|
class PathChooser;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace BoostBuildProjectManager {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class Project;
|
||||||
|
class PathsSelectionWizardPage;
|
||||||
|
class FilesSelectionWizardPage;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// NOTE: The Boost.Build wizard is based on Core::BaseFileWizard which seems to be
|
||||||
|
// dedicated to build "New Project" wizards. So, the plugin uses the base class in
|
||||||
|
// unconventional, matching its features to Boost.Build wizard needs, like:
|
||||||
|
// - no parent QWidget is used
|
||||||
|
// - platform name is set from default Kit display name, usually it's "Desktop"
|
||||||
|
// - extra values QVariantMap may carry custom data
|
||||||
|
// CAUTION: This wizard may stop building or start failing in run-time,
|
||||||
|
// if Qt Creator changes the base class significantly.
|
||||||
|
class OpenProjectWizard : public Core::BaseFileWizardFactory
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
OpenProjectWizard(Project const* const project);
|
||||||
|
|
||||||
|
bool run(QString const& platform, QVariantMap const& extraValues);
|
||||||
|
|
||||||
|
QVariantMap outputValues() const { return outputValues_; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
Core::BaseFileWizard*
|
||||||
|
create(QWidget* parent, Core::WizardDialogParameters const& parameters) const;
|
||||||
|
|
||||||
|
Core::GeneratedFiles
|
||||||
|
generateFiles(QWizard const* baseWizard, QString* errorMessage) const;
|
||||||
|
|
||||||
|
bool
|
||||||
|
postGenerateFiles(QWizard const* wizard
|
||||||
|
, Core::GeneratedFiles const& files, QString* errorMessage);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Project const* const project_;
|
||||||
|
QVariantMap outputValues_;
|
||||||
|
bool projectOpened_;
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
class OpenProjectWizardDialog : public Core::BaseFileWizard
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
OpenProjectWizardDialog(QWidget* parent, QString const& projectFile
|
||||||
|
, QVariantMap const& extraValues, QVariantMap& outputValues);
|
||||||
|
|
||||||
|
QString path() const;
|
||||||
|
QString projectFile() const;
|
||||||
|
QString projectName() const;
|
||||||
|
QString defaultProjectName() const;
|
||||||
|
|
||||||
|
QStringList selectedFiles() const;
|
||||||
|
QStringList selectedPaths() const;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void setProjectName(QString const& name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QVariantMap& outputValues_;
|
||||||
|
QVariantMap extraValues_;
|
||||||
|
QString projectFile_;
|
||||||
|
PathsSelectionWizardPage* pathsPage_;
|
||||||
|
FilesSelectionWizardPage* filesPage_;
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
class PathsSelectionWizardPage : public QWizardPage
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit PathsSelectionWizardPage(OpenProjectWizardDialog* wizard);
|
||||||
|
|
||||||
|
QString projectName() const;
|
||||||
|
void setProjectName(QString const& name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
OpenProjectWizardDialog* wizard_;
|
||||||
|
QLineEdit* nameLineEdit_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace BoostBuildProjectManager
|
||||||
|
|
||||||
|
#endif // BBOPENPROJECTWIZARD_HPP
|
197
src/plugins/boostbuildprojectmanager/b2outputparser.cpp
Normal file
197
src/plugins/boostbuildprojectmanager/b2outputparser.cpp
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
//
|
||||||
|
// This file is part of Qt Creator Boost.Build plugin project.
|
||||||
|
//
|
||||||
|
// This is free software; you can redistribute and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License, Version 2.1
|
||||||
|
// as published by the Free Software Foundation.
|
||||||
|
// See accompanying file LICENSE.txt or copy at
|
||||||
|
// http://www.gnu.org/licenses/lgpl-2.1-standalone.html.
|
||||||
|
//
|
||||||
|
#include "b2outputparser.h"
|
||||||
|
#include "b2utility.h"
|
||||||
|
#include "external/projectexplorer/gccparser.h"
|
||||||
|
#include "external/projectexplorer/ldparser.h"
|
||||||
|
#include "external/projectexplorer/clangparser.h"
|
||||||
|
// Qt Creator
|
||||||
|
#include <projectexplorer/ioutputparser.h>
|
||||||
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
|
#include <projectexplorer/task.h>
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
// Qt
|
||||||
|
#include <QRegExp>
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringRef>
|
||||||
|
|
||||||
|
namespace BoostBuildProjectManager {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
char const* const RxToolsetFromCommand = "^([\\w-]+)(?:\\.)([\\w-]+).+$";
|
||||||
|
char const* const RxToolsetFromWarning = "^warning\\:.+toolset.+\\\"([\\w-]+)\\\".*$";
|
||||||
|
// TODO: replace filename with full path? ^\*\*passed\*\*\s(.+\.test)
|
||||||
|
char const* const RxTestPassed = "^\\*\\*passed\\*\\*\\s+(.+\\.test)\\s*$";
|
||||||
|
char const* const RxTestFailed = "^\\.\\.\\.failed\\s+testing\\.capture-output\\s+(.+\\.run)\\.\\.\\.$";
|
||||||
|
char const* const RxTestFailedAsExpected = "^\\(failed-as-expected\\)\\s+(.+\\.o)\\s*$";
|
||||||
|
char const* const RxTestFileLineN = "(\\.[ch][px]*)\\(([0-9]+)\\)"; // replace \\1:\\2
|
||||||
|
char const* const RxTestFileObj = "\\W(\\w+)(\\.o)";
|
||||||
|
}
|
||||||
|
|
||||||
|
BoostBuildParser::BoostBuildParser()
|
||||||
|
: rxToolsetNameCommand_(QLatin1String(RxToolsetFromCommand))
|
||||||
|
, rxToolsetNameWarning_(QLatin1String(RxToolsetFromWarning))
|
||||||
|
, rxTestPassed_(QLatin1String(RxTestPassed))
|
||||||
|
, rxTestFailed_(QLatin1String(RxTestFailed))
|
||||||
|
, rxTestFailedAsExpected_(QLatin1String(RxTestFailedAsExpected))
|
||||||
|
, rxTestFileLineN_(QLatin1String(RxTestFileLineN))
|
||||||
|
, rxTestFileObj_(QLatin1String(RxTestFileObj))
|
||||||
|
, lineMode_(Common)
|
||||||
|
{
|
||||||
|
rxToolsetNameCommand_.setMinimal(true);
|
||||||
|
QTC_CHECK(rxToolsetNameCommand_.isValid());
|
||||||
|
|
||||||
|
rxToolsetNameWarning_.setMinimal(true);
|
||||||
|
QTC_CHECK(rxToolsetNameWarning_.isValid());
|
||||||
|
|
||||||
|
rxTestPassed_.setMinimal(true);
|
||||||
|
QTC_CHECK(rxTestPassed_.isValid());
|
||||||
|
|
||||||
|
rxTestFailed_.setMinimal(true);
|
||||||
|
QTC_CHECK(rxTestFailed_.isValid());
|
||||||
|
|
||||||
|
rxTestFailedAsExpected_.setMinimal(true);
|
||||||
|
QTC_CHECK(rxTestFailedAsExpected_.isValid());
|
||||||
|
|
||||||
|
rxTestFileLineN_.setMinimal(true);
|
||||||
|
QTC_CHECK(rxTestFileLineN_.isValid());
|
||||||
|
}
|
||||||
|
|
||||||
|
QString BoostBuildParser::findToolset(QString const& line) const
|
||||||
|
{
|
||||||
|
QString name;
|
||||||
|
if (rxToolsetNameWarning_.indexIn(line) > -1)
|
||||||
|
name = rxToolsetNameWarning_.cap(1);
|
||||||
|
else if (rxToolsetNameCommand_.indexIn(line) > -1)
|
||||||
|
name = rxToolsetNameCommand_.cap(1);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BoostBuildParser::setToolsetParser(QString const& toolsetName)
|
||||||
|
{
|
||||||
|
if (!toolsetName.isEmpty() && toolsetName_.isEmpty()) {
|
||||||
|
if (QStringRef(&toolsetName, 0, 3) == QLatin1String("gcc")) {
|
||||||
|
appendOutputParser(new ProjectExplorer::GccParser());
|
||||||
|
toolsetName_ = toolsetName;
|
||||||
|
} else if (QStringRef(&toolsetName, 0, 5) == QLatin1String("clang")) {
|
||||||
|
// clang-xxx found (e.g. clang-linux)
|
||||||
|
appendOutputParser(new ProjectExplorer::ClangParser());
|
||||||
|
toolsetName_ = toolsetName;
|
||||||
|
} else {
|
||||||
|
// TODO: Add more toolsets (Intel, VC++, etc.)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BoostBuildParser::stdOutput(QString const& rawLine)
|
||||||
|
{
|
||||||
|
setToolsetParser(findToolset(rawLine));
|
||||||
|
|
||||||
|
QString const line
|
||||||
|
= rightTrimmed(rawLine).replace(rxTestFileLineN_, QLatin1String("\\1:\\2"));
|
||||||
|
if (!toolsetName_.isEmpty() && line.startsWith(toolsetName_))
|
||||||
|
lineMode_ = Toolset;
|
||||||
|
else if (line.startsWith(QLatin1String("testing"))
|
||||||
|
|| line.startsWith(QLatin1String("(failed-as-expected)")))
|
||||||
|
lineMode_ = Testing;
|
||||||
|
else if (line.startsWith(QLatin1String("common")))
|
||||||
|
lineMode_ = Common;
|
||||||
|
|
||||||
|
// TODO: Why forwarding stdOutput to ProjectExplorer::IOutputParser::stdError?
|
||||||
|
// Because of a bug (or feature?) in Boost.Build:
|
||||||
|
// stdout and stderr not forwarded to respective channels
|
||||||
|
// https://svn.boost.org/trac/boost/ticket/9485
|
||||||
|
|
||||||
|
if (lineMode_ == Toolset) {
|
||||||
|
ProjectExplorer::IOutputParser::stdError(line);
|
||||||
|
} else if (lineMode_ == Testing) {
|
||||||
|
if (rxTestPassed_.indexIn(line) > -1) {
|
||||||
|
BBPM_QDEBUG(rxTestPassed_.capturedTexts());
|
||||||
|
// TODO: issue #3
|
||||||
|
ProjectExplorer::Task task(ProjectExplorer::Task::Unknown
|
||||||
|
, rxTestPassed_.cap(0)
|
||||||
|
, Utils::FileName::fromString(rxTestPassed_.cap(1))
|
||||||
|
, -1 // line
|
||||||
|
, ProjectExplorer::Constants::TASK_CATEGORY_COMPILE);
|
||||||
|
setTask(task);
|
||||||
|
lineMode_ = Common;
|
||||||
|
} else if (rxTestFailed_.indexIn(line) > -1) {
|
||||||
|
BBPM_QDEBUG(rxTestFailed_.capturedTexts());
|
||||||
|
|
||||||
|
// Report summary task for "...failed testing.capture-output /myfile.run"
|
||||||
|
ProjectExplorer::Task task(ProjectExplorer::Task::Error
|
||||||
|
, rxTestFailed_.cap(0)
|
||||||
|
, Utils::FileName::fromString(rxTestFailed_.cap(1))
|
||||||
|
, -1 // line
|
||||||
|
, ProjectExplorer::Constants::TASK_CATEGORY_COMPILE);
|
||||||
|
setTask(task);
|
||||||
|
|
||||||
|
lineMode_ = Common;
|
||||||
|
} else if (rxTestFailedAsExpected_.indexIn(line) > -1) {
|
||||||
|
BBPM_QDEBUG(rxTestFailedAsExpected_.capturedTexts());
|
||||||
|
|
||||||
|
// TODO: Handling of "(failed-as-expected)" is not great, might be confusing.
|
||||||
|
// Boost.Build spits out compile command first, so compilation errors arrive
|
||||||
|
// and are parsed immediately (issue tasks are created)
|
||||||
|
// due to lineMode_==Toolset.
|
||||||
|
// Then, "(failed-as-expected)" status arrives and there seem to be no way to
|
||||||
|
// look back and clear all the issue tasks created for compilation errors.
|
||||||
|
// TODO: Ask Volodya if b2 could announce "testing." before compile command
|
||||||
|
// for a compile-time test.
|
||||||
|
|
||||||
|
QString fileName(rxTestFailedAsExpected_.cap(1));
|
||||||
|
if (rxTestFileObj_.indexIn(fileName))
|
||||||
|
fileName = rxTestFileObj_.cap(1) + QLatin1String(".cpp");// FIXME:hardcoded ext
|
||||||
|
|
||||||
|
// ATM, we can only indicate in UI that test failed-as-expected
|
||||||
|
ProjectExplorer::Task task(ProjectExplorer::Task::Error
|
||||||
|
, rxTestFailedAsExpected_.cap(0)
|
||||||
|
, Utils::FileName::fromString(fileName)
|
||||||
|
, -1 // line
|
||||||
|
, ProjectExplorer::Constants::TASK_CATEGORY_COMPILE);
|
||||||
|
setTask(task);
|
||||||
|
|
||||||
|
lineMode_ = Common;
|
||||||
|
} else {
|
||||||
|
// Parses compilation errors of run-time tests, creates issue tasks
|
||||||
|
ProjectExplorer::IOutputParser::stdError(line);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
doFlush();
|
||||||
|
ProjectExplorer::IOutputParser::stdOutput(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BoostBuildParser::stdError(QString const& line)
|
||||||
|
{
|
||||||
|
setToolsetParser(findToolset(line));
|
||||||
|
ProjectExplorer::IOutputParser::stdError(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BoostBuildParser::doFlush()
|
||||||
|
{
|
||||||
|
if (!lastTask_.isNull()) {
|
||||||
|
ProjectExplorer::Task t = lastTask_;
|
||||||
|
lastTask_.clear();
|
||||||
|
emit addTask(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BoostBuildParser::setTask(ProjectExplorer::Task const& task)
|
||||||
|
{
|
||||||
|
doFlush();
|
||||||
|
lastTask_ = task;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace BoostBuildProjectManager
|
64
src/plugins/boostbuildprojectmanager/b2outputparser.h
Normal file
64
src/plugins/boostbuildprojectmanager/b2outputparser.h
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
//
|
||||||
|
// This file is part of Qt Creator Boost.Build plugin project.
|
||||||
|
//
|
||||||
|
// This is free software; you can redistribute and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License, Version 2.1
|
||||||
|
// as published by the Free Software Foundation.
|
||||||
|
// See accompanying file LICENSE.txt or copy at
|
||||||
|
// http://www.gnu.org/licenses/lgpl-2.1-standalone.html.
|
||||||
|
//
|
||||||
|
#ifndef BBOUTPUTPARSER_HPP
|
||||||
|
#define BBOUTPUTPARSER_HPP
|
||||||
|
|
||||||
|
// Qt Creator
|
||||||
|
#include <projectexplorer/ioutputparser.h>
|
||||||
|
#include <projectexplorer/task.h>
|
||||||
|
// Qt
|
||||||
|
#include <QPointer>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace BoostBuildProjectManager {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class BoostBuildParser : public ProjectExplorer::IOutputParser
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
BoostBuildParser();
|
||||||
|
|
||||||
|
void stdOutput(QString const& line);
|
||||||
|
void stdError(QString const& line);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void doFlush();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
QString findToolset(QString const& line) const;
|
||||||
|
void setToolsetParser(QString const& toolsetName);
|
||||||
|
void setTask(ProjectExplorer::Task const& task);
|
||||||
|
|
||||||
|
QRegExp rxToolsetNameCommand_; // ".compile." command line
|
||||||
|
QRegExp rxToolsetNameWarning_; // "warning: " status line
|
||||||
|
QRegExp rxTestPassed_; // "**passed**" status line
|
||||||
|
QRegExp rxTestFailed_; // "...failed testing" status line
|
||||||
|
QRegExp rxTestFailedAsExpected_; // "(failed-as-expected)" status line
|
||||||
|
QRegExp rxTestFileLineN_; // file.cpp(XX) => file.cpp:XX
|
||||||
|
QRegExp rxTestFileObj_; // file.o => file.cpp
|
||||||
|
QString toolsetName_;
|
||||||
|
|
||||||
|
// Boost.Build command mode relates to first command token in line.
|
||||||
|
enum LineMode { Common, Toolset, Testing };
|
||||||
|
LineMode lineMode_;
|
||||||
|
|
||||||
|
ProjectExplorer::Task lastTask_;
|
||||||
|
QPointer<ProjectExplorer::IOutputParser> parser_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace BoostBuildProjectManager
|
||||||
|
|
||||||
|
#endif // BBOUTPUTPARSER_HPP
|
306
src/plugins/boostbuildprojectmanager/b2project.cpp
Normal file
306
src/plugins/boostbuildprojectmanager/b2project.cpp
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
// Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
//
|
||||||
|
// This file is part of Qt Creator Boost.Build plugin project.
|
||||||
|
//
|
||||||
|
// This is free software; you can redistribute and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License, Version 2.1
|
||||||
|
// as published by the Free Software Foundation.
|
||||||
|
// See accompanying file LICENSE.txt or copy at
|
||||||
|
// http://www.gnu.org/licenses/lgpl-2.1-standalone.html.
|
||||||
|
//
|
||||||
|
#include "b2buildconfiguration.h"
|
||||||
|
#include "b2buildstep.h"
|
||||||
|
#include "b2openprojectwizard.h"
|
||||||
|
#include "b2project.h"
|
||||||
|
#include "b2projectfile.h"
|
||||||
|
#include "b2projectmanager.h"
|
||||||
|
#include "b2projectmanagerconstants.h"
|
||||||
|
#include "b2projectnode.h"
|
||||||
|
#include "b2utility.h"
|
||||||
|
// Qt Creator
|
||||||
|
#include <app/app_version.h>
|
||||||
|
#include <coreplugin/icontext.h>
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
|
#include <coreplugin/generatedfile.h>
|
||||||
|
#include <coreplugin/progressmanager/progressmanager.h>
|
||||||
|
#include <cpptools/cppmodelmanager.h>
|
||||||
|
#include <cpptools/cppprojects.h>
|
||||||
|
#include <cpptools/cpptoolsconstants.h>
|
||||||
|
#include <projectexplorer/kit.h>
|
||||||
|
#include <projectexplorer/kitinformation.h>
|
||||||
|
#include <projectexplorer/kitmanager.h>
|
||||||
|
#include <projectexplorer/project.h>
|
||||||
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
|
#include <projectexplorer/projectnodes.h>
|
||||||
|
#include <projectexplorer/target.h>
|
||||||
|
#include <qtsupport/customexecutablerunconfiguration.h>
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
#include <utils/QtConcurrentTools>
|
||||||
|
// Qt
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
namespace BoostBuildProjectManager {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
Project::Project(ProjectManager* manager, QString const& fileName)
|
||||||
|
: manager_(manager)
|
||||||
|
, filePath_(fileName)
|
||||||
|
, projectFile_(new ProjectFile(this, filePath_)) // enables projectDirectory()
|
||||||
|
, projectNode_(new ProjectNode(this, projectFile_))
|
||||||
|
{
|
||||||
|
Q_ASSERT(manager_);
|
||||||
|
Q_ASSERT(!filePath_.isEmpty());
|
||||||
|
|
||||||
|
setProjectContext(Core::Context(Constants::PROJECT_CONTEXT));
|
||||||
|
setProjectLanguages(Core::Context(ProjectExplorer::Constants::LANG_CXX));
|
||||||
|
#if defined(IDE_VERSION_MAJOR) && (IDE_VERSION_MAJOR == 3 && IDE_VERSION_MINOR > 0)
|
||||||
|
setId(Constants::PROJECT_ID);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QFileInfo const projectFileInfo(filePath_);
|
||||||
|
QDir const projectDir(projectFileInfo.dir());
|
||||||
|
projectName_ = defaultProjectName(filePath_);
|
||||||
|
filesFilePath_ = QFileInfo(projectDir
|
||||||
|
, filePath_ + QLatin1String(Constants::EXT_JAMFILE_FILES)).absoluteFilePath();
|
||||||
|
includesFilePath_ = QFileInfo(projectDir
|
||||||
|
, filePath_ + QLatin1String(Constants::EXT_JAMFILE_INCLUDES)).absoluteFilePath();
|
||||||
|
|
||||||
|
projectNode_->setDisplayName(displayName());
|
||||||
|
|
||||||
|
manager_->registerProject(this);
|
||||||
|
|
||||||
|
// TODO: Add file watchers
|
||||||
|
//projectFileWatcher_->addPath(projectFilePath);
|
||||||
|
//connect(projectFileWatcher_, SIGNAL(fileChanged(QString)), this, SLOT(refresh()));
|
||||||
|
|
||||||
|
BBPM_QDEBUG("created project: " << displayName() << " in " << projectDirectory());
|
||||||
|
}
|
||||||
|
|
||||||
|
Project::~Project()
|
||||||
|
{
|
||||||
|
manager_->unregisterProject(this);
|
||||||
|
delete projectNode_;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Project::displayName() const
|
||||||
|
{
|
||||||
|
return projectName_;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(IDE_VERSION_MAJOR) && (IDE_VERSION_MAJOR == 3 && IDE_VERSION_MINOR == 0)
|
||||||
|
Core::Id Project::id() const
|
||||||
|
{
|
||||||
|
return Core::Id(Constants::PROJECT_ID);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Core::IDocument* Project::document() const
|
||||||
|
{
|
||||||
|
return projectFile_;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectExplorer::IProjectManager* Project::projectManager() const
|
||||||
|
{
|
||||||
|
return manager_;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectExplorer::ProjectNode* Project::rootProjectNode() const
|
||||||
|
{
|
||||||
|
return projectNode_;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList Project::files(FilesMode fileMode) const
|
||||||
|
{
|
||||||
|
// TODO: handle ExcludeGeneratedFiles, but what files exactly?
|
||||||
|
// *.qtcreator.files, *.qtcreator.includes and *.user?
|
||||||
|
Q_UNUSED(fileMode);
|
||||||
|
return files_;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList Project::files() const
|
||||||
|
{
|
||||||
|
return files(FilesMode::AllFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Project::filesFilePath() const
|
||||||
|
{
|
||||||
|
Q_ASSERT(!filesFilePath_.isEmpty());
|
||||||
|
return filesFilePath_;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Project::includesFilePath() const
|
||||||
|
{
|
||||||
|
Q_ASSERT(!includesFilePath_.isEmpty());
|
||||||
|
return includesFilePath_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Project::needsConfiguration() const
|
||||||
|
{
|
||||||
|
// TODO: Does Boost.Build project require any configuration on loading?
|
||||||
|
// - Kit selection
|
||||||
|
// - build/stage directory
|
||||||
|
// - targets listing
|
||||||
|
// CMakeProjectManager seems to request configuration in fromMap()
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*static*/
|
||||||
|
QString Project::defaultProjectName(QString const& fileName)
|
||||||
|
{
|
||||||
|
QFileInfo const fileInfo(fileName);
|
||||||
|
return fileInfo.absoluteDir().dirName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*static*/
|
||||||
|
QString Project::defaultBuildDirectory(QString const& top)
|
||||||
|
{
|
||||||
|
Utils::FileName fn(Utils::FileName::fromString(defaultWorkingDirectory(top)));
|
||||||
|
fn.appendPath(BBPM_C(BUILD_DIR_NAME));
|
||||||
|
return fn.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*static*/
|
||||||
|
QString Project::defaultWorkingDirectory(QString const& top)
|
||||||
|
{
|
||||||
|
// Accepts both, project file or project directory, as top.
|
||||||
|
return ProjectExplorer::Project::projectDirectory(Utils::FileName::fromString(top)).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Project::setProjectName(QString const& name)
|
||||||
|
{
|
||||||
|
if (projectName_ != name) {
|
||||||
|
projectName_ = name;
|
||||||
|
projectNode_->setDisplayName(projectName_);
|
||||||
|
// TODO: signal?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap Project::toMap() const
|
||||||
|
{
|
||||||
|
QVariantMap map(ProjectExplorer::Project::toMap());
|
||||||
|
map.insert(QLatin1String(Constants::P_KEY_PROJECTNAME), projectName_);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is called at the very beginning to restore the settings
|
||||||
|
// from .user file, if there is any with previous settings stored.
|
||||||
|
bool Project::fromMap(QVariantMap const& map)
|
||||||
|
{
|
||||||
|
BBPM_QDEBUG(displayName());
|
||||||
|
QTC_ASSERT(projectNode_, return false);
|
||||||
|
|
||||||
|
if (!ProjectExplorer::Project::fromMap(map))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QVariantMap extraValues(map);
|
||||||
|
if (!extraValues.contains(BBPM_C(P_KEY_PROJECTNAME)))
|
||||||
|
extraValues.insert(BBPM_C(P_KEY_PROJECTNAME), projectName_);
|
||||||
|
setProjectName(map.value(BBPM_C(P_KEY_PROJECTNAME)).toString());
|
||||||
|
|
||||||
|
// Check required auxiliary files, run wizard of necessary
|
||||||
|
if (!QFileInfo(filesFilePath()).exists() || !QFileInfo(includesFilePath()).exists()) {
|
||||||
|
ProjectExplorer::Kit* defaultKit = ProjectExplorer::KitManager::defaultKit();
|
||||||
|
Q_ASSERT(defaultKit);
|
||||||
|
|
||||||
|
OpenProjectWizard wizard(this);
|
||||||
|
if (!wizard.run(defaultKit->displayName(), extraValues))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QVariantMap outputValues = wizard.outputValues();
|
||||||
|
setProjectName(outputValues.value(BBPM_C(P_KEY_PROJECTNAME)).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up active ProjectConfiguration (aka Target).
|
||||||
|
// NOTE: Call setActiveBuildConfiguration when creating new build configurations.
|
||||||
|
if (!activeTarget()) {
|
||||||
|
// Create project configuration from scratch
|
||||||
|
|
||||||
|
// TODO: Map the Kit to Boost.Build toolset option value
|
||||||
|
ProjectExplorer::Kit* defaultKit = ProjectExplorer::KitManager::defaultKit();
|
||||||
|
Q_ASSERT(defaultKit);
|
||||||
|
|
||||||
|
// Creates as many {Build|Run|Deploy}Configurations for as corresponding
|
||||||
|
// factories report as available.
|
||||||
|
// For example, BuildConfigurationFactory::availableBuilds => Debug and Release
|
||||||
|
ProjectExplorer::Target* target = createTarget(defaultKit);
|
||||||
|
QTC_ASSERT(target, return false);
|
||||||
|
|
||||||
|
addTarget(target);
|
||||||
|
} else {
|
||||||
|
// Configure project from settings sorced from .user file
|
||||||
|
// TODO: Do we need to handle anything from .user here? Do we need this case?
|
||||||
|
BBPM_QDEBUG(displayName() << "has user file");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanity check (taken from GenericProjectManager):
|
||||||
|
// We need both a BuildConfiguration and a RunConfiguration!
|
||||||
|
QList<ProjectExplorer::Target*> targetList = targets();
|
||||||
|
foreach (ProjectExplorer::Target* t, targetList) {
|
||||||
|
if (!t->activeBuildConfiguration()) {
|
||||||
|
removeTarget(t);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!t->activeRunConfiguration())
|
||||||
|
t->addRunConfiguration(new QtSupport::CustomExecutableRunConfiguration(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
QTC_ASSERT(hasActiveBuildSettings(), return false);
|
||||||
|
QTC_ASSERT(activeTarget() != 0, return false);
|
||||||
|
|
||||||
|
// Trigger loading project tree and parsing sources
|
||||||
|
refresh();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Project::refresh()
|
||||||
|
{
|
||||||
|
QTC_ASSERT(QFileInfo(filesFilePath()).exists(), return);
|
||||||
|
QTC_ASSERT(QFileInfo(includesFilePath()).exists(), return);
|
||||||
|
|
||||||
|
QSet<QString> oldFileList;
|
||||||
|
oldFileList = files_.toSet();
|
||||||
|
|
||||||
|
// Parse project:
|
||||||
|
// The manager does not parse Jamfile files.
|
||||||
|
// Only generates and parses list of source files in Jamfile.${JAMFILE_FILES_EXT}
|
||||||
|
QString const projectPath(projectDirectory().toString());
|
||||||
|
filesRaw_ = Utility::readLines(filesFilePath());
|
||||||
|
files_ = Utility::makeAbsolutePaths(projectPath, filesRaw_);
|
||||||
|
|
||||||
|
QStringList includePaths =
|
||||||
|
Utility::makeAbsolutePaths(projectPath,
|
||||||
|
Utility::readLines(includesFilePath()));
|
||||||
|
|
||||||
|
emit fileListChanged();
|
||||||
|
|
||||||
|
projectNode_->refresh(oldFileList);
|
||||||
|
|
||||||
|
// TODO: Does it make sense to move this to separate asynchronous task?
|
||||||
|
// TODO: extract updateCppCodeModel
|
||||||
|
CppTools::CppModelManager *modelmanager =
|
||||||
|
CppTools::CppModelManager::instance();
|
||||||
|
if (modelmanager) {
|
||||||
|
CppTools::ProjectInfo pinfo(this);
|
||||||
|
|
||||||
|
CppTools::ProjectPartBuilder builder(pinfo);
|
||||||
|
//builder.setDefines(); // TODO: waiting for Jamfile parser
|
||||||
|
builder.setIncludePaths(QStringList() << projectDirectory().toString() << includePaths);
|
||||||
|
|
||||||
|
const QList<Core::Id> languages = builder.createProjectPartsForFiles(files_);
|
||||||
|
foreach (Core::Id language, languages)
|
||||||
|
setProjectLanguage(language, true);
|
||||||
|
|
||||||
|
cppModelFuture_.cancel();
|
||||||
|
pinfo.finish();
|
||||||
|
cppModelFuture_ = modelmanager->updateProjectInfo(pinfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace BoostBuildProjectManager
|
106
src/plugins/boostbuildprojectmanager/b2project.h
Normal file
106
src/plugins/boostbuildprojectmanager/b2project.h
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
//
|
||||||
|
// This file is part of Qt Creator Boost.Build plugin project.
|
||||||
|
//
|
||||||
|
// This is free software; you can redistribute and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License, Version 2.1
|
||||||
|
// as published by the Free Software Foundation.
|
||||||
|
// See accompanying file LICENSE.txt or copy at
|
||||||
|
// http://www.gnu.org/licenses/lgpl-2.1-standalone.html.
|
||||||
|
//
|
||||||
|
#ifndef BBPROJECT_HPP
|
||||||
|
#define BBPROJECT_HPP
|
||||||
|
|
||||||
|
// Qt Creator
|
||||||
|
#include <app/app_version.h>
|
||||||
|
#include <coreplugin/idocument.h>
|
||||||
|
#include <projectexplorer/project.h>
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
// Qt
|
||||||
|
#include <QString>
|
||||||
|
#include <QFuture>
|
||||||
|
#include <QFutureInterface>
|
||||||
|
|
||||||
|
namespace BoostBuildProjectManager {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class ProjectFile;
|
||||||
|
class ProjectManager;
|
||||||
|
class ProjectNode;
|
||||||
|
|
||||||
|
// Represents a project node in the project explorer.
|
||||||
|
class Project : public ProjectExplorer::Project
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
Project(ProjectManager* manager, QString const& fileName);
|
||||||
|
~Project();
|
||||||
|
|
||||||
|
#if defined(IDE_VERSION_MAJOR) && (IDE_VERSION_MAJOR == 3 && IDE_VERSION_MINOR == 0)
|
||||||
|
Core::Id id() const;
|
||||||
|
#endif
|
||||||
|
QString displayName() const;
|
||||||
|
Core::IDocument* document() const;
|
||||||
|
ProjectExplorer::IProjectManager* projectManager() const;
|
||||||
|
ProjectExplorer::ProjectNode* rootProjectNode() const;
|
||||||
|
QStringList files(FilesMode fileMode) const;
|
||||||
|
|
||||||
|
bool needsConfiguration() const;
|
||||||
|
|
||||||
|
void refresh();
|
||||||
|
|
||||||
|
QString filesFilePath() const;
|
||||||
|
QStringList files() const;
|
||||||
|
|
||||||
|
QString includesFilePath() const;
|
||||||
|
|
||||||
|
static QString defaultProjectName(QString const& fileName);
|
||||||
|
static QString defaultBuildDirectory(QString const& top);
|
||||||
|
static QString defaultWorkingDirectory(QString const& top);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
QVariantMap toMap() const;
|
||||||
|
|
||||||
|
// Deserializes all project data from the map object
|
||||||
|
// Calls the base ProjectExplorer::Project::fromMap function first.
|
||||||
|
bool fromMap(QVariantMap const& map);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void setProjectName(QString const& name);
|
||||||
|
|
||||||
|
// Corresponding project manager passed to the constructor
|
||||||
|
ProjectManager* manager_;
|
||||||
|
|
||||||
|
// By default, name of directory with Jamfile.
|
||||||
|
// Boost.Build treats each Jamfile is a separate project,
|
||||||
|
// where hierarchy of Jamfiles makes hierarchy of projects.
|
||||||
|
QString projectName_;
|
||||||
|
|
||||||
|
// Jamfile passed to the constructor (Jamroot, Jamfile, Jamfile.v2).
|
||||||
|
QString filePath_;
|
||||||
|
|
||||||
|
// Auxiliary file Jamfile.${JAMFILE_FILES_EXT} with list of source files.
|
||||||
|
// Role of this file is similar to the .files file in the GenericProjectManager,
|
||||||
|
// hence managing of this file is implemented in very similar manner.
|
||||||
|
QString filesFilePath_;
|
||||||
|
QStringList files_;
|
||||||
|
QStringList filesRaw_;
|
||||||
|
QHash<QString, QString> entriesRaw_;
|
||||||
|
|
||||||
|
// Auxiliary file Jamfile.${JAMFILE_INCLUDES_EXT} with list of source files.
|
||||||
|
QString includesFilePath_;
|
||||||
|
|
||||||
|
ProjectFile* projectFile_;
|
||||||
|
ProjectNode* projectNode_;
|
||||||
|
|
||||||
|
QFuture<void> cppModelFuture_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace BoostBuildProjectManager
|
||||||
|
|
||||||
|
#endif // BBPROJECT_HPP
|
80
src/plugins/boostbuildprojectmanager/b2projectfile.cpp
Normal file
80
src/plugins/boostbuildprojectmanager/b2projectfile.cpp
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
//
|
||||||
|
// This file is part of Qt Creator Boost.Build plugin project.
|
||||||
|
//
|
||||||
|
// This is free software; you can redistribute and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License, Version 2.1
|
||||||
|
// as published by the Free Software Foundation.
|
||||||
|
// See accompanying file LICENSE.txt or copy at
|
||||||
|
// http://www.gnu.org/licenses/lgpl-2.1-standalone.html.
|
||||||
|
//
|
||||||
|
#include "b2project.h"
|
||||||
|
#include "b2projectfile.h"
|
||||||
|
#include "b2projectmanagerconstants.h"
|
||||||
|
#include "b2utility.h"
|
||||||
|
|
||||||
|
namespace BoostBuildProjectManager {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
ProjectFile::ProjectFile(Project* project, QString const& fileName)
|
||||||
|
: Core::IDocument(project)
|
||||||
|
, project_(project)
|
||||||
|
{
|
||||||
|
Q_ASSERT(!fileName.isEmpty());
|
||||||
|
|
||||||
|
setFilePath(Utils::FileName::fromString(fileName));
|
||||||
|
|
||||||
|
BBPM_QDEBUG(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProjectFile::save(QString* errorString, QString const& fileName, bool autoSave)
|
||||||
|
{
|
||||||
|
Q_UNUSED(errorString);
|
||||||
|
Q_UNUSED(fileName);
|
||||||
|
Q_UNUSED(autoSave);
|
||||||
|
|
||||||
|
BBPM_QDEBUG("TODO");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ProjectFile::defaultPath() const
|
||||||
|
{
|
||||||
|
BBPM_QDEBUG("TODO");
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ProjectFile::suggestedFileName() const
|
||||||
|
{
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ProjectFile::mimeType() const
|
||||||
|
{
|
||||||
|
BBPM_QDEBUG("TODO");
|
||||||
|
return QLatin1String(Constants::MIMETYPE_JAMFILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProjectFile::isModified() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProjectFile::isSaveAsAllowed() const
|
||||||
|
{
|
||||||
|
BBPM_QDEBUG("TODO");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProjectFile::reload(QString* errorString, ReloadFlag flag, ChangeType type)
|
||||||
|
{
|
||||||
|
Q_UNUSED(errorString);
|
||||||
|
Q_UNUSED(flag);
|
||||||
|
Q_UNUSED(type);
|
||||||
|
|
||||||
|
BBPM_QDEBUG("TODO");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace AutotoolsProjectManager
|
47
src/plugins/boostbuildprojectmanager/b2projectfile.h
Normal file
47
src/plugins/boostbuildprojectmanager/b2projectfile.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
//
|
||||||
|
// This file is part of Qt Creator Boost.Build plugin project.
|
||||||
|
//
|
||||||
|
// This is free software; you can redistribute and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License, Version 2.1
|
||||||
|
// as published by the Free Software Foundation.
|
||||||
|
// See accompanying file LICENSE.txt or copy at
|
||||||
|
// http://www.gnu.org/licenses/lgpl-2.1-standalone.html.
|
||||||
|
//
|
||||||
|
#ifndef BBPROJECTFILE_HPP
|
||||||
|
#define BBPROJECTFILE_HPP
|
||||||
|
|
||||||
|
#include <coreplugin/idocument.h>
|
||||||
|
|
||||||
|
namespace BoostBuildProjectManager {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class Project;
|
||||||
|
|
||||||
|
// Describes the root of a project for use in Project class.
|
||||||
|
// In the context of Boost.Build the implementation is mostly empty,
|
||||||
|
// as the modification of a project is done by editing Jamfile.v2 files.
|
||||||
|
class ProjectFile : public Core::IDocument
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ProjectFile(Project* project, QString const& fileName);
|
||||||
|
|
||||||
|
bool save(QString* errorString, QString const& fileName, bool autoSave);
|
||||||
|
QString defaultPath() const;
|
||||||
|
QString suggestedFileName() const;
|
||||||
|
QString mimeType() const;
|
||||||
|
bool isModified() const;
|
||||||
|
bool isSaveAsAllowed() const;
|
||||||
|
bool reload(QString* errorString, ReloadFlag flag, ChangeType type);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Project* project_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace AutotoolsProjectManager
|
||||||
|
|
||||||
|
#endif // BBPROJECTFILE_HPP
|
64
src/plugins/boostbuildprojectmanager/b2projectmanager.cpp
Normal file
64
src/plugins/boostbuildprojectmanager/b2projectmanager.cpp
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
//
|
||||||
|
// This file is part of Qt Creator Boost.Build plugin project.
|
||||||
|
//
|
||||||
|
// This is free software; you can redistribute and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License, Version 2.1
|
||||||
|
// as published by the Free Software Foundation.
|
||||||
|
// See accompanying file LICENSE.txt or copy at
|
||||||
|
// http://www.gnu.org/licenses/lgpl-2.1-standalone.html.
|
||||||
|
//
|
||||||
|
#include "b2projectmanager.h"
|
||||||
|
#include "b2projectmanagerconstants.h"
|
||||||
|
#include "b2project.h"
|
||||||
|
#include "b2utility.h"
|
||||||
|
// Qt Creator
|
||||||
|
#include <projectexplorer/iprojectmanager.h>
|
||||||
|
// Qt
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace BoostBuildProjectManager {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
ProjectManager::ProjectManager()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ProjectManager::mimeType() const
|
||||||
|
{
|
||||||
|
BBPM_QDEBUG(Constants::MIMETYPE_PROJECT);
|
||||||
|
|
||||||
|
return QLatin1String(Constants::MIMETYPE_PROJECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectExplorer::Project*
|
||||||
|
ProjectManager::openProject(QString const& fileName, QString* errorString)
|
||||||
|
{
|
||||||
|
BBPM_QDEBUG("opening project:" << fileName);
|
||||||
|
|
||||||
|
if (!QFileInfo(fileName).isFile()) {
|
||||||
|
if (errorString)
|
||||||
|
*errorString = tr("Failed opening project \"%1\": Project is not a file.")
|
||||||
|
.arg(fileName);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Project(this, fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProjectManager::registerProject(Project* project)
|
||||||
|
{
|
||||||
|
Q_ASSERT(project);
|
||||||
|
projects_.append(project);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProjectManager::unregisterProject(Project* project)
|
||||||
|
{
|
||||||
|
Q_ASSERT(project);
|
||||||
|
projects_.removeAll(project);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace BoostBuildProjectManager
|
54
src/plugins/boostbuildprojectmanager/b2projectmanager.h
Normal file
54
src/plugins/boostbuildprojectmanager/b2projectmanager.h
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
//
|
||||||
|
// This file is part of Qt Creator Boost.Build plugin project.
|
||||||
|
//
|
||||||
|
// This is free software; you can redistribute and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License, Version 2.1
|
||||||
|
// as published by the Free Software Foundation.
|
||||||
|
// See accompanying file LICENSE.txt or copy at
|
||||||
|
// http://www.gnu.org/licenses/lgpl-2.1-standalone.html.
|
||||||
|
//
|
||||||
|
#ifndef BBPROJECTMANAGER_HPP
|
||||||
|
#define BBPROJECTMANAGER_HPP
|
||||||
|
|
||||||
|
// Qt Creator
|
||||||
|
#include <projectexplorer/iprojectmanager.h>
|
||||||
|
// Qt
|
||||||
|
#include <QList>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace ProjectExplorer {
|
||||||
|
class Project;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace BoostBuildProjectManager {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class Project;
|
||||||
|
|
||||||
|
// Sole implementation of the IProjectManager class for the extension.
|
||||||
|
class ProjectManager : public ProjectExplorer::IProjectManager
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ProjectManager();
|
||||||
|
|
||||||
|
QString mimeType() const;
|
||||||
|
|
||||||
|
// Creates new instance of Project class.
|
||||||
|
ProjectExplorer::Project*
|
||||||
|
openProject(QString const& fileName, QString* errorString);
|
||||||
|
|
||||||
|
void registerProject(Project* project);
|
||||||
|
void unregisterProject(Project* project);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<Project*> projects_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace BoostBuildProjectManager
|
||||||
|
|
||||||
|
#endif // BBPROJECTMANAGER_HPP
|
@@ -0,0 +1,23 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
//
|
||||||
|
// This file is part of Qt Creator Boost.Build plugin project.
|
||||||
|
//
|
||||||
|
// This is free software; you can redistribute and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License, Version 2.1
|
||||||
|
// as published by the Free Software Foundation.
|
||||||
|
// See accompanying file LICENSE.txt or copy at
|
||||||
|
// http://www.gnu.org/licenses/lgpl-2.1-standalone.html.
|
||||||
|
//
|
||||||
|
#ifndef BBPROJECTMANAGER_GLOBAL_HPP
|
||||||
|
#define BBPROJECTMANAGER_GLOBAL_HPP
|
||||||
|
|
||||||
|
#include <QtGlobal>
|
||||||
|
|
||||||
|
#if defined(BOOSTBUILDPROJECTMANAGER_LIBRARY)
|
||||||
|
# define BOOSTBUILDPROJECTMANAGER_EXPORT Q_DECL_EXPORT
|
||||||
|
#else
|
||||||
|
# define BOOSTBUILDPROJECTMANAGER_EXPORT Q_DECL_IMPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // BBPROJECTMANAGER_GLOBAL_HPP
|
@@ -0,0 +1,68 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
//
|
||||||
|
// This file is part of Qt Creator Boost.Build plugin project.
|
||||||
|
//
|
||||||
|
// This is free software; you can redistribute and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License, Version 2.1
|
||||||
|
// as published by the Free Software Foundation.
|
||||||
|
// See accompanying file LICENSE.txt or copy at
|
||||||
|
// http://www.gnu.org/licenses/lgpl-2.1-standalone.html.
|
||||||
|
//
|
||||||
|
#ifndef BBPROJECTMANAGERCONSTANTS_HPP
|
||||||
|
#define BBPROJECTMANAGERCONSTANTS_HPP
|
||||||
|
|
||||||
|
#include <qglobal.h>
|
||||||
|
|
||||||
|
namespace BoostBuildProjectManager {
|
||||||
|
namespace Constants {
|
||||||
|
|
||||||
|
char const BOOSTBUILD[] = "Boost.Build";
|
||||||
|
|
||||||
|
char const PROJECT_CONTEXT[] = "BoostBuildProjectManager.ProjectContext";
|
||||||
|
char const PROJECT_ID[] = "BoostBuildProjectManager.Project";
|
||||||
|
char const PROJECT_WIZARD_ID[] = "BoostBuildProjectManager.Project.Wizard";
|
||||||
|
char const PROJECT_READER_TASK_ID[] = "BoostBuildProjectManager.ProjectReader.Task";
|
||||||
|
|
||||||
|
char const BUILDCONFIGURATION_ID[] = "BoostBuildProjectManager.BuildConfiguration";
|
||||||
|
char const BUILDSTEP_ID[] = "BoostBuildProjectManager.BuildStep";
|
||||||
|
|
||||||
|
// Keys for class map registry
|
||||||
|
char const P_KEY_PROJECTNAME[] = "BoostBuildProjectManager.Project.ProjectName";
|
||||||
|
char const BC_KEY_WORKDIR[] = "BoostBuildProjectManager.BuildConfiguration.WorkingDirectory";
|
||||||
|
char const BS_KEY_CLEAN[] = "BoostBuildProjectManager.BuildStep.Clean";
|
||||||
|
char const BS_KEY_ARGUMENTS[] = "BoostBuildProjectManager.BuildStep.AdditionalArguments";
|
||||||
|
|
||||||
|
// MIME types and file patterns
|
||||||
|
char const MIMETYPE_PROJECT[] = "text/x-boostbuild-project";
|
||||||
|
char const MIMETYPE_JAMFILE[] = "application/vnd.boostbuild.v2";
|
||||||
|
char const MIMETYPE_JAMFILE_FILES[] = "application/vnd.qtcreator.boostbuild.files";
|
||||||
|
const char MIMETYPE_JAMFILE_INCLUDES[] = "application/vnd.qtcreator.boostbuild.includes";
|
||||||
|
char const EXT_JAMFILE_FILES[] = ".qtcreator.files";
|
||||||
|
char const EXT_JAMFILE_INCLUDES[] = ".qtcreator.includes";
|
||||||
|
|
||||||
|
// Command and options
|
||||||
|
char const COMMAND_BB2[] = "b2";
|
||||||
|
char const COMMAND_BJAM[] = "bjam";
|
||||||
|
|
||||||
|
char const VARIANT_DEBUG[] = QT_TR_NOOP("Debug");
|
||||||
|
char const VARIANT_RELEASE[] = QT_TR_NOOP("Release");
|
||||||
|
|
||||||
|
// ${BOOST}/tools/build/v2/doc/src/architecture.xml
|
||||||
|
// Since Boost.Build almost always generates targets under the "bin"
|
||||||
|
char const BUILD_DIR_NAME[] = "bin";
|
||||||
|
|
||||||
|
// FileSelectionWizardPage
|
||||||
|
char const HIDE_FILE_FILTER_SETTING[] = "BoostBuildProjectManager/FileFilter";
|
||||||
|
char const HIDE_FILE_FILTER_DEFAULT[] = "Makefile*; *.o; *.obj; *~; *.files; *.config; *.creator; *.user; *.includes; *.autosave";
|
||||||
|
char const SHOW_FILE_FILTER_SETTING[] = "BoostBuildProjectManager/ShowFileFilter";
|
||||||
|
char const SHOW_FILE_FILTER_DEFAULT[] = "*.c; *.cc; *.cpp; *.cp; *.cxx; *.c++; *.h; *.hh; *.h; *.hxx;";
|
||||||
|
|
||||||
|
// Meaningful names for common boolean values
|
||||||
|
bool const FileNotGenerated = false;
|
||||||
|
bool const ReturnValueNotIgnored = false;
|
||||||
|
|
||||||
|
} // namespace Constants
|
||||||
|
} // namespace BoostBuildProjectManager
|
||||||
|
|
||||||
|
#endif // BBPROJECTMANAGERCONSTANTS_HPP
|
@@ -0,0 +1,83 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
//
|
||||||
|
// This file is part of Qt Creator Boost.Build plugin project.
|
||||||
|
//
|
||||||
|
// This is free software; you can redistribute and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License, Version 2.1
|
||||||
|
// as published by the Free Software Foundation.
|
||||||
|
// See accompanying file LICENSE.txt or copy at
|
||||||
|
// http://www.gnu.org/licenses/lgpl-2.1-standalone.html.
|
||||||
|
//
|
||||||
|
#include "b2buildconfiguration.h"
|
||||||
|
#include "b2buildstep.h"
|
||||||
|
#include "b2projectmanager.h"
|
||||||
|
#include "b2projectmanagerplugin.h"
|
||||||
|
#include "b2projectmanagerconstants.h"
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
|
#include <coreplugin/icontext.h>
|
||||||
|
#include <coreplugin/actionmanager/actionmanager.h>
|
||||||
|
#include <coreplugin/actionmanager/command.h>
|
||||||
|
#include <coreplugin/actionmanager/actioncontainer.h>
|
||||||
|
#include <coreplugin/coreconstants.h>
|
||||||
|
#include <utils/mimetypes/mimedatabase.h>
|
||||||
|
// Qt
|
||||||
|
#include <QAction>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QMenu>
|
||||||
|
|
||||||
|
#include <QtPlugin>
|
||||||
|
|
||||||
|
namespace BoostBuildProjectManager { namespace Internal {
|
||||||
|
|
||||||
|
BoostBuildPlugin::BoostBuildPlugin()
|
||||||
|
{
|
||||||
|
// Create your members
|
||||||
|
}
|
||||||
|
|
||||||
|
BoostBuildPlugin::~BoostBuildPlugin()
|
||||||
|
{
|
||||||
|
// Unregister objects from the plugin manager's object pool
|
||||||
|
// Delete members
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BoostBuildPlugin::initialize(QStringList const& arguments, QString* errorString)
|
||||||
|
{
|
||||||
|
Q_UNUSED(arguments)
|
||||||
|
Q_UNUSED(errorString)
|
||||||
|
|
||||||
|
// Register objects in the plugin manager's object pool
|
||||||
|
// Load settings
|
||||||
|
// Add actions to menus
|
||||||
|
// Connect to other plugins' signals
|
||||||
|
// In the initialize function, a plugin can be sure that the plugins it
|
||||||
|
// depends on have initialized their members.
|
||||||
|
|
||||||
|
QLatin1String const mimeTypes(":boostbuildproject/BoostBuildProjectManager.mimetypes.xml");
|
||||||
|
Utils::MimeDatabase::addMimeTypes(mimeTypes);
|
||||||
|
|
||||||
|
addAutoReleasedObject(new BuildStepFactory);
|
||||||
|
addAutoReleasedObject(new BuildConfigurationFactory);
|
||||||
|
//TODO addAutoReleasedObject(new RunConfigurationFactory);
|
||||||
|
addAutoReleasedObject(new ProjectManager);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BoostBuildPlugin::extensionsInitialized()
|
||||||
|
{
|
||||||
|
// Retrieve objects from the plugin manager's object pool
|
||||||
|
// In the extensionsInitialized function, a plugin can be sure that all
|
||||||
|
// plugins that depend on it are completely initialized.
|
||||||
|
}
|
||||||
|
|
||||||
|
ExtensionSystem::IPlugin::ShutdownFlag BoostBuildPlugin::aboutToShutdown()
|
||||||
|
{
|
||||||
|
// Save settings
|
||||||
|
// Disconnect from signals that are not needed during shutdown
|
||||||
|
// Hide UI (if you add UI that is not in the main window directly)
|
||||||
|
return SynchronousShutdown;
|
||||||
|
}
|
||||||
|
|
||||||
|
}}
|
@@ -0,0 +1,48 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
//
|
||||||
|
// This file is part of Qt Creator Boost.Build plugin project.
|
||||||
|
//
|
||||||
|
// This is free software; you can redistribute and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License, Version 2.1
|
||||||
|
// as published by the Free Software Foundation.
|
||||||
|
// See accompanying file LICENSE.txt or copy at
|
||||||
|
// http://www.gnu.org/licenses/lgpl-2.1-standalone.html.
|
||||||
|
//
|
||||||
|
#ifndef BBPROJECTMANAGERPLUGIN_HPP
|
||||||
|
#define BBPROJECTMANAGERPLUGIN_HPP
|
||||||
|
|
||||||
|
#include "b2projectmanager_global.h"
|
||||||
|
|
||||||
|
#include <extensionsystem/iplugin.h>
|
||||||
|
|
||||||
|
namespace BoostBuildProjectManager {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
|
||||||
|
// Sole implementation of the IPlugin class for the extension.
|
||||||
|
class BoostBuildPlugin : public ExtensionSystem::IPlugin
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "BoostBuildProjectManager.json")
|
||||||
|
|
||||||
|
public:
|
||||||
|
BoostBuildPlugin();
|
||||||
|
~BoostBuildPlugin();
|
||||||
|
|
||||||
|
// Called as second step of the plugins loading.
|
||||||
|
// The initialize functions are called in root-to-leaf order of the dependency tree.
|
||||||
|
bool initialize(QStringList const& arguments, QString* errorString);
|
||||||
|
|
||||||
|
// Called as final step of the plugins loading.
|
||||||
|
// At this point, all dependencies along the plugin dependency tree
|
||||||
|
// have been initialized completely.
|
||||||
|
void extensionsInitialized();
|
||||||
|
|
||||||
|
ShutdownFlag aboutToShutdown();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace BoostBuildProjectManager
|
||||||
|
|
||||||
|
#endif // BBPROJECTMANAGERPLUGIN_HPP
|
260
src/plugins/boostbuildprojectmanager/b2projectnode.cpp
Normal file
260
src/plugins/boostbuildprojectmanager/b2projectnode.cpp
Normal file
@@ -0,0 +1,260 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
// Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
//
|
||||||
|
// This file is part of Qt Creator Boost.Build plugin project.
|
||||||
|
//
|
||||||
|
// This is free software; you can redistribute and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License, Version 2.1
|
||||||
|
// as published by the Free Software Foundation.
|
||||||
|
// See accompanying file LICENSE.txt or copy at
|
||||||
|
// http://www.gnu.org/licenses/lgpl-2.1-standalone.html.
|
||||||
|
//
|
||||||
|
#include "b2projectnode.h"
|
||||||
|
#include "b2project.h"
|
||||||
|
#include "b2utility.h"
|
||||||
|
// Qt Creator
|
||||||
|
#include <coreplugin/idocument.h>
|
||||||
|
#include <projectexplorer/projectnodes.h>
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
// Qt
|
||||||
|
#include <QFutureInterface>
|
||||||
|
#include <QHash>
|
||||||
|
#include <QList>
|
||||||
|
#include <QSet>
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
namespace BoostBuildProjectManager {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
ProjectNode::ProjectNode(Project* project, Core::IDocument* projectFile)
|
||||||
|
: ProjectExplorer::ProjectNode(projectFile->filePath())
|
||||||
|
, project_(project)
|
||||||
|
, projectFile_(projectFile)
|
||||||
|
{
|
||||||
|
// TODO: setDisplayName(QFileInfo(projectFile->filePath()).completeBaseName());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProjectNode::hasBuildTargets() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<ProjectExplorer::ProjectAction>
|
||||||
|
ProjectNode::supportedActions(Node* node) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(node);
|
||||||
|
|
||||||
|
// TODO: Jamfiles (auto)editing not supported, does it make sense to manage files?
|
||||||
|
return QList<ProjectExplorer::ProjectAction>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProjectNode::canAddSubProject(QString const& filePath) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(filePath)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProjectNode::addSubProjects(QStringList const& filePaths)
|
||||||
|
{
|
||||||
|
Q_UNUSED(filePaths)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProjectNode::removeSubProjects(QStringList const& filePath)
|
||||||
|
{
|
||||||
|
Q_UNUSED(filePath)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProjectNode::addFiles(QStringList const& filePaths, QStringList* notAdded = 0)
|
||||||
|
{
|
||||||
|
Q_UNUSED(filePaths);
|
||||||
|
Q_UNUSED(notAdded);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProjectNode::removeFiles(QStringList const& filePaths, QStringList* notRemoved = 0)
|
||||||
|
{
|
||||||
|
Q_UNUSED(filePaths);
|
||||||
|
Q_UNUSED(notRemoved);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProjectNode::deleteFiles(QStringList const& filePaths)
|
||||||
|
{
|
||||||
|
Q_UNUSED(filePaths);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProjectNode::renameFile(QString const& filePath, QString const& newFilePath)
|
||||||
|
{
|
||||||
|
Q_UNUSED(filePath);
|
||||||
|
Q_UNUSED(newFilePath);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<ProjectExplorer::RunConfiguration*> ProjectNode::runConfigurationsFor(Node* node)
|
||||||
|
{
|
||||||
|
Q_UNUSED(node);
|
||||||
|
return QList<ProjectExplorer::RunConfiguration*>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProjectNode::refresh(QSet<QString> oldFileList)
|
||||||
|
{
|
||||||
|
// The idea of refreshing files in project explorer taken from GenericProjectManager
|
||||||
|
|
||||||
|
// Only do this once, at first run.
|
||||||
|
if (oldFileList.isEmpty()) {
|
||||||
|
using ProjectExplorer::FileNode;
|
||||||
|
FileNode* projectFileNode = new FileNode(project_->projectFilePath()
|
||||||
|
, ProjectExplorer::ProjectFileType
|
||||||
|
, Constants::FileNotGenerated);
|
||||||
|
|
||||||
|
FileNode* filesFileNode = new FileNode(Utils::FileName::fromString(project_->filesFilePath())
|
||||||
|
, ProjectExplorer::ProjectFileType
|
||||||
|
, Constants::FileNotGenerated);
|
||||||
|
|
||||||
|
FileNode* includesFileNode = new FileNode(Utils::FileName::fromString(project_->includesFilePath())
|
||||||
|
, ProjectExplorer::ProjectFileType
|
||||||
|
, Constants::FileNotGenerated);
|
||||||
|
|
||||||
|
addFileNodes(QList<FileNode*>()
|
||||||
|
<< projectFileNode << filesFileNode << includesFileNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
oldFileList.remove(project_->filesFilePath());
|
||||||
|
oldFileList.remove(project_->includesFilePath());
|
||||||
|
|
||||||
|
QSet<QString> newFileList = project_->files().toSet();
|
||||||
|
newFileList.remove(project_->filesFilePath());
|
||||||
|
newFileList.remove(project_->includesFilePath());
|
||||||
|
|
||||||
|
// Calculate set of added and removed files
|
||||||
|
QSet<QString> removed = oldFileList;
|
||||||
|
removed.subtract(newFileList);
|
||||||
|
QSet<QString> added = newFileList;
|
||||||
|
added.subtract(oldFileList);
|
||||||
|
|
||||||
|
typedef QHash<QString, QStringList> FilesInPaths;
|
||||||
|
typedef FilesInPaths::ConstIterator FilesInPathsIterator;
|
||||||
|
using ProjectExplorer::FileNode;
|
||||||
|
using ProjectExplorer::FileType;
|
||||||
|
QString const baseDir = QFileInfo(path().toString()).absolutePath();
|
||||||
|
|
||||||
|
// Process all added files
|
||||||
|
FilesInPaths filesInPaths = Utility::sortFilesIntoPaths(baseDir, added);
|
||||||
|
for (FilesInPathsIterator it = filesInPaths.constBegin(),
|
||||||
|
cend = filesInPaths.constEnd(); it != cend; ++it) {
|
||||||
|
// Create node
|
||||||
|
QString const& filePath = it.key();
|
||||||
|
QStringList parts;
|
||||||
|
if (!filePath.isEmpty())
|
||||||
|
parts = filePath.split(QLatin1Char('/'));
|
||||||
|
|
||||||
|
FolderNode* folder = findFolderByName(parts, parts.size());
|
||||||
|
if (!folder)
|
||||||
|
folder = createFolderByName(parts, parts.size());
|
||||||
|
|
||||||
|
// Attach content to node
|
||||||
|
QList<FileNode*> fileNodes;
|
||||||
|
foreach (QString const& file, it.value()) {
|
||||||
|
// TODO: handle various types, mime to FileType
|
||||||
|
FileType fileType = ProjectExplorer::SourceType;
|
||||||
|
FileNode* fileNode = new FileNode(Utils::FileName::fromString(file), fileType, Constants::FileNotGenerated);
|
||||||
|
fileNodes.append(fileNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
addFileNodes(fileNodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process all removed files
|
||||||
|
filesInPaths = Utility::sortFilesIntoPaths(baseDir, removed);
|
||||||
|
for (FilesInPathsIterator it = filesInPaths.constBegin(),
|
||||||
|
cend = filesInPaths.constEnd(); it != cend; ++it) {
|
||||||
|
// Create node
|
||||||
|
QString const& filePath = it.key();
|
||||||
|
QStringList parts;
|
||||||
|
if (!filePath.isEmpty())
|
||||||
|
parts = filePath.split(QLatin1Char('/'));
|
||||||
|
FolderNode* folder = findFolderByName(parts, parts.size());
|
||||||
|
|
||||||
|
QList<FileNode*> fileNodes;
|
||||||
|
foreach (QString const& file, it.value()) {
|
||||||
|
foreach (FileNode* fn, folder->fileNodes())
|
||||||
|
if (fn->path() == Utils::FileName::fromString(file))
|
||||||
|
fileNodes.append(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeFileNodes(fileNodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
foreach (FolderNode* fn, subFolderNodes())
|
||||||
|
removeEmptySubFolders(this, fn);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProjectNode::removeEmptySubFolders(FolderNode* parent, FolderNode* subParent)
|
||||||
|
{
|
||||||
|
foreach (FolderNode* fn, subParent->subFolderNodes())
|
||||||
|
removeEmptySubFolders(subParent, fn);
|
||||||
|
|
||||||
|
if (subParent->subFolderNodes().isEmpty() && subParent->fileNodes().isEmpty())
|
||||||
|
removeFolderNodes(QList<FolderNode*>() << subParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString appendPathComponents(QStringList const& components, int const end)
|
||||||
|
{
|
||||||
|
QString folderName;
|
||||||
|
for (int i = 0; i < end; ++i) {
|
||||||
|
folderName.append(components.at(i));
|
||||||
|
folderName += QLatin1Char('/');
|
||||||
|
}
|
||||||
|
return folderName;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectExplorer::FolderNode*
|
||||||
|
ProjectNode::createFolderByName(QStringList const& components, int const end)
|
||||||
|
{
|
||||||
|
if (end == 0)
|
||||||
|
return this;
|
||||||
|
|
||||||
|
using ProjectExplorer::FolderNode;
|
||||||
|
QString const baseDir = QFileInfo(path().toString()).path();
|
||||||
|
QString const folderName = appendPathComponents(components, end);
|
||||||
|
FolderNode* folder = new FolderNode(Utils::FileName::fromString(baseDir + QLatin1Char('/') + folderName));
|
||||||
|
folder->setDisplayName(components.at(end - 1));
|
||||||
|
|
||||||
|
FolderNode* parent = findFolderByName(components, end - 1);
|
||||||
|
if (!parent)
|
||||||
|
parent = createFolderByName(components, end - 1);
|
||||||
|
addFolderNodes(QList<FolderNode*>() << folder);
|
||||||
|
|
||||||
|
return folder;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectExplorer::FolderNode*
|
||||||
|
ProjectNode::findFolderByName(QStringList const& components, int const end) const
|
||||||
|
{
|
||||||
|
if (end == 0)
|
||||||
|
return const_cast<ProjectNode*>(this);
|
||||||
|
|
||||||
|
using ProjectExplorer::FolderNode;
|
||||||
|
FolderNode *parent = findFolderByName(components, end - 1);
|
||||||
|
if (!parent)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
QString const folderName = appendPathComponents(components, end);
|
||||||
|
QString const baseDir = QFileInfo(path().toString()).path();
|
||||||
|
foreach (FolderNode* fn, parent->subFolderNodes()) {
|
||||||
|
if (fn->path() == Utils::FileName::fromString(baseDir + QLatin1Char('/') + folderName))
|
||||||
|
return fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace BoostBuildProjectManager
|
77
src/plugins/boostbuildprojectmanager/b2projectnode.h
Normal file
77
src/plugins/boostbuildprojectmanager/b2projectnode.h
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
// Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
//
|
||||||
|
// This file is part of Qt Creator Boost.Build plugin project.
|
||||||
|
//
|
||||||
|
// This is free software; you can redistribute and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License, Version 2.1
|
||||||
|
// as published by the Free Software Foundation.
|
||||||
|
// See accompanying file LICENSE.txt or copy at
|
||||||
|
// http://www.gnu.org/licenses/lgpl-2.1-standalone.html.
|
||||||
|
//
|
||||||
|
#ifndef BBPROJECTNODE_HPP
|
||||||
|
#define BBPROJECTNODE_HPP
|
||||||
|
|
||||||
|
// Qt Creator
|
||||||
|
#include <projectexplorer/projectnodes.h>
|
||||||
|
// Qt
|
||||||
|
#include <QFutureInterface>
|
||||||
|
#include <QList>
|
||||||
|
#include <QSet>
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class IDocument;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ProjectExplorer {
|
||||||
|
class RunConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace BoostBuildProjectManager {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class Project;
|
||||||
|
|
||||||
|
// An in-memory presentation of a Project.
|
||||||
|
// Represents a file or a folder of the project tree.
|
||||||
|
// No special operations (addFiles(), removeFiles(), renameFile(), etc.) are offered.
|
||||||
|
class ProjectNode : public ProjectExplorer::ProjectNode
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
ProjectNode(Project* project, Core::IDocument* projectFile);
|
||||||
|
|
||||||
|
bool hasBuildTargets() const;
|
||||||
|
QList<ProjectExplorer::ProjectAction> supportedActions(Node* node) const;
|
||||||
|
bool canAddSubProject(QString const& filePath) const;
|
||||||
|
bool addSubProjects(QStringList const& filePaths);
|
||||||
|
bool removeSubProjects(QStringList const& filePaths);
|
||||||
|
bool addFiles(QStringList const& filePaths, QStringList* notAdded /*= 0*/);
|
||||||
|
bool removeFiles(QStringList const& filePaths, QStringList* notRemoved /*= 0*/);
|
||||||
|
bool deleteFiles(QStringList const& filePaths);
|
||||||
|
bool renameFile(QString const& filePath, QString const& newFilePath);
|
||||||
|
QList<ProjectExplorer::RunConfiguration*> runConfigurationsFor(Node* node);
|
||||||
|
|
||||||
|
void refresh(QSet<QString> oldFileList);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
ProjectExplorer::FolderNode*
|
||||||
|
createFolderByName(QStringList const& components, int end);
|
||||||
|
|
||||||
|
ProjectExplorer::FolderNode*
|
||||||
|
findFolderByName(QStringList const& components, int end) const;
|
||||||
|
|
||||||
|
void removeEmptySubFolders(FolderNode* parent, FolderNode* subParent);
|
||||||
|
|
||||||
|
Project* project_;
|
||||||
|
Core::IDocument* projectFile_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace BoostBuildProjectManager
|
||||||
|
|
||||||
|
#endif // BBPROJECTNODE_HPP
|
151
src/plugins/boostbuildprojectmanager/b2utility.cpp
Normal file
151
src/plugins/boostbuildprojectmanager/b2utility.cpp
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
// Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
//
|
||||||
|
// This file is part of Qt Creator Boost.Build plugin project.
|
||||||
|
//
|
||||||
|
// This is free software; you can redistribute and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License, Version 2.1
|
||||||
|
// as published by the Free Software Foundation.
|
||||||
|
// See accompanying file LICENSE.txt or copy at
|
||||||
|
// http://www.gnu.org/licenses/lgpl-2.1-standalone.html.
|
||||||
|
//
|
||||||
|
#include "b2utility.h"
|
||||||
|
// Qt Creator
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
// Qt
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QHash>
|
||||||
|
#include <QList>
|
||||||
|
#include <QRegExp>
|
||||||
|
#include <QSet>
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
namespace BoostBuildProjectManager {
|
||||||
|
namespace Utility {
|
||||||
|
|
||||||
|
QStringList readLines(QString const& filePath)
|
||||||
|
{
|
||||||
|
QFileInfo const fileInfo(filePath);
|
||||||
|
QStringList lines;
|
||||||
|
|
||||||
|
QFile file(fileInfo.absoluteFilePath());
|
||||||
|
if (file.open(QFile::ReadOnly)) {
|
||||||
|
QTextStream stream(&file);
|
||||||
|
|
||||||
|
forever {
|
||||||
|
QString line = stream.readLine();
|
||||||
|
if (line.isNull())
|
||||||
|
break;
|
||||||
|
|
||||||
|
lines.append(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList makeAbsolutePaths(QString const& basePath, QStringList const& paths)
|
||||||
|
{
|
||||||
|
QDir const baseDir(basePath);
|
||||||
|
|
||||||
|
QFileInfo fileInfo;
|
||||||
|
QStringList absolutePaths;
|
||||||
|
foreach (QString const& path, paths) {
|
||||||
|
QString trimmedPath = path.trimmed();
|
||||||
|
if (!trimmedPath.isEmpty()) {
|
||||||
|
trimmedPath = Utils::FileName::fromUserInput(trimmedPath).toString();
|
||||||
|
|
||||||
|
fileInfo.setFile(baseDir, trimmedPath);
|
||||||
|
if (fileInfo.exists()) {
|
||||||
|
QString const absPath = fileInfo.absoluteFilePath();
|
||||||
|
Q_ASSERT(!absPath.isEmpty());
|
||||||
|
absolutePaths.append(absPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
absolutePaths.removeDuplicates();
|
||||||
|
return absolutePaths;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList& makeRelativePaths(QString const& basePath, QStringList& paths)
|
||||||
|
{
|
||||||
|
QDir const baseDir(basePath);
|
||||||
|
for (QStringList::iterator it = paths.begin(), end = paths.end(); it != end; ++it)
|
||||||
|
*it = baseDir.relativeFilePath(*it);
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<QString, QStringList> sortFilesIntoPaths(QString const& basePath
|
||||||
|
, QSet<QString> const& files)
|
||||||
|
{
|
||||||
|
QHash<QString, QStringList> filesInPath;
|
||||||
|
QDir const baseDir(basePath);
|
||||||
|
|
||||||
|
foreach (QString const& absoluteFileName, files) {
|
||||||
|
QFileInfo const fileInfo(absoluteFileName);
|
||||||
|
Utils::FileName absoluteFilePath = Utils::FileName::fromString(fileInfo.path());
|
||||||
|
QString relativeFilePath;
|
||||||
|
|
||||||
|
if (absoluteFilePath.isChildOf(baseDir)) {
|
||||||
|
relativeFilePath = absoluteFilePath.relativeChildPath(
|
||||||
|
Utils::FileName::fromString(basePath)).toString();
|
||||||
|
} else {
|
||||||
|
// `file' is not part of the project.
|
||||||
|
relativeFilePath = baseDir.relativeFilePath(absoluteFilePath.toString());
|
||||||
|
if (relativeFilePath.endsWith(QLatin1Char('/')))
|
||||||
|
relativeFilePath.chop(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
filesInPath[relativeFilePath].append(absoluteFileName);
|
||||||
|
}
|
||||||
|
return filesInPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parses Jamfile and looks for project rule to extract project name.
|
||||||
|
// Boost.Build project rule has the following syntax:
|
||||||
|
// project id : attributes ;
|
||||||
|
// The project definition can span across multiple lines, including empty lines.
|
||||||
|
// but each syntax token must be separated with a whitespace..
|
||||||
|
QString parseJamfileProjectName(QString const& fileName)
|
||||||
|
{
|
||||||
|
QString projectName;
|
||||||
|
QFile file(fileName);
|
||||||
|
if (file.exists()) {
|
||||||
|
// Jamfile project rule tokens to search for
|
||||||
|
QString const ruleBeg(QLatin1String("project"));
|
||||||
|
QChar const ruleEnd(QLatin1Char(';'));
|
||||||
|
QChar const attrSep(QLatin1Char(':'));
|
||||||
|
QChar const tokenSep(QLatin1Char(' ')); // used to ensure tokens separation
|
||||||
|
QString projectDef; // buffer for complete project definition
|
||||||
|
|
||||||
|
file.open(QIODevice::ReadOnly | QIODevice::Text);
|
||||||
|
QTextStream stream(&file);
|
||||||
|
while (!stream.atEnd()) {
|
||||||
|
QString const line(stream.readLine());
|
||||||
|
if (projectDef.isEmpty() && line.trimmed().startsWith(ruleBeg))
|
||||||
|
projectDef.append(line + tokenSep);
|
||||||
|
else if (!projectDef.isEmpty())
|
||||||
|
projectDef.append(line + tokenSep);
|
||||||
|
|
||||||
|
if (projectDef.contains(attrSep) || projectDef.contains(ruleEnd))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!projectDef.isEmpty()) {
|
||||||
|
QRegExp rx(QLatin1String("\\s*project\\s+([a-zA-Z\\-\\/]+)\\s+[\\:\\;]?"));
|
||||||
|
rx.setMinimal(true);
|
||||||
|
QTC_CHECK(rx.isValid());
|
||||||
|
if (rx.indexIn(projectDef) > -1)
|
||||||
|
projectName = rx.cap(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return projectName;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Utility
|
||||||
|
} // namespace BoostBuildProjectManager
|
60
src/plugins/boostbuildprojectmanager/b2utility.h
Normal file
60
src/plugins/boostbuildprojectmanager/b2utility.h
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
// Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
//
|
||||||
|
// This file is part of Qt Creator Boost.Build plugin project.
|
||||||
|
//
|
||||||
|
// This is free software; you can redistribute and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License, Version 2.1
|
||||||
|
// as published by the Free Software Foundation.
|
||||||
|
// See accompanying file LICENSE.txt or copy at
|
||||||
|
// http://www.gnu.org/licenses/lgpl-2.1-standalone.html.
|
||||||
|
//
|
||||||
|
#ifndef BBUTILITY_HPP
|
||||||
|
#define BBUTILITY_HPP
|
||||||
|
|
||||||
|
#include "b2projectmanagerconstants.h"
|
||||||
|
// Qt
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QHash>
|
||||||
|
#include <QSet>
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#ifdef _DEBUG
|
||||||
|
|
||||||
|
#define BBPM_QDEBUG(msg) \
|
||||||
|
qDebug() \
|
||||||
|
<< "[" << BoostBuildProjectManager::Constants::BOOSTBUILD << "] " \
|
||||||
|
<< "(" << __PRETTY_FUNCTION__ << ")"; \
|
||||||
|
qDebug().nospace() << "\t" << msg
|
||||||
|
|
||||||
|
#else
|
||||||
|
#define BBPM_QDEBUG(msg)
|
||||||
|
|
||||||
|
#endif // _DEBUG
|
||||||
|
|
||||||
|
#define BBPM_C(CONSTANT) QLatin1String(BoostBuildProjectManager::Constants::CONSTANT)
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
namespace BoostBuildProjectManager {
|
||||||
|
namespace Utility {
|
||||||
|
|
||||||
|
// Read all lines from a file.
|
||||||
|
QStringList readLines(QString const& absoluteFileName);
|
||||||
|
|
||||||
|
// Converts the path from relative to the project to an absolute path.
|
||||||
|
QStringList makeAbsolutePaths(QString const& basePath, QStringList const& paths);
|
||||||
|
|
||||||
|
QStringList& makeRelativePaths(QString const& basePath, QStringList& paths);
|
||||||
|
|
||||||
|
QHash<QString, QStringList> sortFilesIntoPaths(QString const& basePath
|
||||||
|
, QSet<QString> const& files);
|
||||||
|
|
||||||
|
QString parseJamfileProjectName(QString const& fileName);
|
||||||
|
|
||||||
|
} // namespace Utility
|
||||||
|
} // namespace BoostBuildProjectManager
|
||||||
|
|
||||||
|
#endif // BBUTILITY_HPP
|
@@ -0,0 +1,5 @@
|
|||||||
|
<RCC>
|
||||||
|
<qresource prefix="/boostbuildproject">
|
||||||
|
<file>BoostBuildProjectManager.mimetypes.xml</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
@@ -0,0 +1,46 @@
|
|||||||
|
include(../../qtcreatorplugin.pri)
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
b2buildconfiguration.h \
|
||||||
|
b2buildinfo.h \
|
||||||
|
b2buildstep.h \
|
||||||
|
b2openprojectwizard.h \
|
||||||
|
b2outputparser.h \
|
||||||
|
b2project.h \
|
||||||
|
b2projectfile.h \
|
||||||
|
b2projectmanager.h \
|
||||||
|
b2projectmanager_global.h \
|
||||||
|
b2projectmanagerconstants.h \
|
||||||
|
b2projectmanagerplugin.h \
|
||||||
|
b2projectnode.h \
|
||||||
|
b2utility.h \
|
||||||
|
filesselectionwizardpage.h \
|
||||||
|
selectablefilesmodel.h \
|
||||||
|
external/projectexplorer/clangparser.h \
|
||||||
|
external/projectexplorer/gccparser.h \
|
||||||
|
external/projectexplorer/ldparser.h
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
b2buildconfiguration.cpp \
|
||||||
|
b2buildinfo.cpp \
|
||||||
|
b2buildstep.cpp \
|
||||||
|
b2openprojectwizard.cpp \
|
||||||
|
b2outputparser.cpp \
|
||||||
|
b2project.cpp \
|
||||||
|
b2projectfile.cpp \
|
||||||
|
b2projectmanager.cpp \
|
||||||
|
b2projectmanagerplugin.cpp \
|
||||||
|
b2projectnode.cpp \
|
||||||
|
b2utility.cpp \
|
||||||
|
filesselectionwizardpage.cpp \
|
||||||
|
selectablefilesmodel.cpp \
|
||||||
|
external/projectexplorer/clangparser.cpp \
|
||||||
|
external/projectexplorer/gccparser.cpp \
|
||||||
|
external/projectexplorer/ldparser.cpp
|
||||||
|
|
||||||
|
RESOURCES += \
|
||||||
|
boostbuildproject.qrc
|
||||||
|
|
||||||
|
OTHER_FILES += \
|
||||||
|
$${QTC_PLUGIN_NAME}.mimetypes.xml \
|
||||||
|
$${QTC_PLUGIN_NAME}.pluginspec.in
|
@@ -0,0 +1,12 @@
|
|||||||
|
QTC_PLUGIN_NAME = BoostBuildProjectManager
|
||||||
|
QTC_LIB_DEPENDS += \
|
||||||
|
extensionsystem \
|
||||||
|
utils
|
||||||
|
QTC_PLUGIN_DEPENDS += \
|
||||||
|
coreplugin \
|
||||||
|
projectexplorer \
|
||||||
|
cpptools \
|
||||||
|
texteditor \
|
||||||
|
qtsupport
|
||||||
|
QTC_TEST_DEPENDS += \
|
||||||
|
cppeditor
|
270
src/plugins/boostbuildprojectmanager/external/projectexplorer/clangparser.cpp
vendored
Normal file
270
src/plugins/boostbuildprojectmanager/external/projectexplorer/clangparser.cpp
vendored
Normal file
@@ -0,0 +1,270 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License Version 2.1 by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.txt 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 "clangparser.h"
|
||||||
|
#include "ldparser.h"
|
||||||
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
|
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
|
||||||
|
// opt. drive letter + filename: (2 brackets)
|
||||||
|
static const char * const FILE_PATTERN = "(<command line>|([A-Za-z]:)?[^:]+\\.[^:]+)";
|
||||||
|
|
||||||
|
ClangParser::ClangParser() :
|
||||||
|
m_commandRegExp(QLatin1String("^clang(\\+\\+)?: +(fatal +)?(warning|error|note): (.*)$")),
|
||||||
|
m_inLineRegExp(QLatin1String("^In (.*) included from (.*):(\\d+):$")),
|
||||||
|
m_messageRegExp(QLatin1String("^") + QLatin1String(FILE_PATTERN) + QLatin1String("(:(\\d+):\\d+|\\((\\d+)\\) *): +(fatal +)?(error|warning|note): (.*)$")),
|
||||||
|
m_summaryRegExp(QLatin1String("^\\d+ (warnings?|errors?)( and \\d (warnings?|errors?))? generated.$")),
|
||||||
|
m_codesignRegExp(QLatin1String("^Code ?Sign error: (.*)$")),
|
||||||
|
m_expectSnippet(false)
|
||||||
|
{
|
||||||
|
setObjectName(QLatin1String("ClangParser"));
|
||||||
|
|
||||||
|
appendOutputParser(new LdParser);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClangParser::stdError(const QString &line)
|
||||||
|
{
|
||||||
|
const QString lne = rightTrimmed(line);
|
||||||
|
if (m_summaryRegExp.indexIn(lne) > -1) {
|
||||||
|
doFlush();
|
||||||
|
m_expectSnippet = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_commandRegExp.indexIn(lne) > -1) {
|
||||||
|
m_expectSnippet = true;
|
||||||
|
Task task(Task::Error,
|
||||||
|
m_commandRegExp.cap(4),
|
||||||
|
Utils::FileName(), /* filename */
|
||||||
|
-1, /* line */
|
||||||
|
Constants::TASK_CATEGORY_COMPILE);
|
||||||
|
if (m_commandRegExp.cap(3) == QLatin1String("warning"))
|
||||||
|
task.type = Task::Warning;
|
||||||
|
else if (m_commandRegExp.cap(3) == QLatin1String("note"))
|
||||||
|
task.type = Task::Unknown;
|
||||||
|
newTask(task);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_inLineRegExp.indexIn(lne) > -1) {
|
||||||
|
m_expectSnippet = true;
|
||||||
|
newTask(Task(Task::Unknown,
|
||||||
|
lne.trimmed(),
|
||||||
|
Utils::FileName::fromUserInput(m_inLineRegExp.cap(2)), /* filename */
|
||||||
|
m_inLineRegExp.cap(3).toInt(), /* line */
|
||||||
|
Constants::TASK_CATEGORY_COMPILE));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_messageRegExp.indexIn(lne) > -1) {
|
||||||
|
m_expectSnippet = true;
|
||||||
|
bool ok = false;
|
||||||
|
int lineNo = m_messageRegExp.cap(4).toInt(&ok);
|
||||||
|
if (!ok)
|
||||||
|
lineNo = m_messageRegExp.cap(5).toInt(&ok);
|
||||||
|
Task task(Task::Error,
|
||||||
|
m_messageRegExp.cap(8),
|
||||||
|
Utils::FileName::fromUserInput(m_messageRegExp.cap(1)), /* filename */
|
||||||
|
lineNo,
|
||||||
|
Core::Id(Constants::TASK_CATEGORY_COMPILE));
|
||||||
|
if (m_messageRegExp.cap(7) == QLatin1String("warning"))
|
||||||
|
task.type = Task::Warning;
|
||||||
|
else if (m_messageRegExp.cap(7) == QLatin1String("note"))
|
||||||
|
task.type = Task::Unknown;
|
||||||
|
newTask(task);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_codesignRegExp.indexIn(lne) > -1) {
|
||||||
|
m_expectSnippet = true;
|
||||||
|
Task task(Task::Error,
|
||||||
|
m_codesignRegExp.cap(1),
|
||||||
|
Utils::FileName(),
|
||||||
|
-1,
|
||||||
|
Core::Id(Constants::TASK_CATEGORY_COMPILE));
|
||||||
|
newTask(task);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_expectSnippet) {
|
||||||
|
amendDescription(lne, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IOutputParser::stdError(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unit tests:
|
||||||
|
|
||||||
|
#ifdef WITH_TESTS_NOTDISABLED
|
||||||
|
# include <QTest>
|
||||||
|
|
||||||
|
# include "projectexplorer.h"
|
||||||
|
# include "metatypedeclarations.h"
|
||||||
|
# include "outputparser_test.h"
|
||||||
|
|
||||||
|
void ProjectExplorerPlugin::testClangOutputParser_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QString>("input");
|
||||||
|
QTest::addColumn<OutputParserTester::Channel>("inputChannel");
|
||||||
|
QTest::addColumn<QString>("childStdOutLines");
|
||||||
|
QTest::addColumn<QString>("childStdErrLines");
|
||||||
|
QTest::addColumn<QList<ProjectExplorer::Task> >("tasks");
|
||||||
|
QTest::addColumn<QString>("outputLines");
|
||||||
|
|
||||||
|
const Core::Id categoryCompile = Constants::TASK_CATEGORY_COMPILE;
|
||||||
|
|
||||||
|
QTest::newRow("pass-through stdout")
|
||||||
|
<< QString::fromLatin1("Sometext") << OutputParserTester::STDOUT
|
||||||
|
<< QString::fromLatin1("Sometext\n") << QString()
|
||||||
|
<< QList<ProjectExplorer::Task>()
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("pass-through stderr")
|
||||||
|
<< QString::fromLatin1("Sometext") << OutputParserTester::STDERR
|
||||||
|
<< QString() << QString::fromLatin1("Sometext\n")
|
||||||
|
<< QList<ProjectExplorer::Task>()
|
||||||
|
<< QString();
|
||||||
|
|
||||||
|
QTest::newRow("clang++ warning")
|
||||||
|
<< QString::fromLatin1("clang++: warning: argument unused during compilation: '-mthreads'")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< (QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Warning,
|
||||||
|
QLatin1String("argument unused during compilation: '-mthreads'"),
|
||||||
|
Utils::FileName(), -1,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("clang++ error")
|
||||||
|
<< QString::fromLatin1("clang++: error: no input files [err_drv_no_input_files]")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< (QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("no input files [err_drv_no_input_files]"),
|
||||||
|
Utils::FileName(), -1,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("complex warning")
|
||||||
|
<< QString::fromLatin1("In file included from ..\\..\\..\\QtSDK1.1\\Desktop\\Qt\\4.7.3\\mingw\\include/QtCore/qnamespace.h:45:\n"
|
||||||
|
"..\\..\\..\\QtSDK1.1\\Desktop\\Qt\\4.7.3\\mingw\\include/QtCore/qglobal.h(1425) : warning: unknown attribute 'dllimport' ignored [-Wunknown-attributes]\n"
|
||||||
|
"class Q_CORE_EXPORT QSysInfo {\n"
|
||||||
|
" ^")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< (QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("In file included from ..\\..\\..\\QtSDK1.1\\Desktop\\Qt\\4.7.3\\mingw\\include/QtCore/qnamespace.h:45:"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("..\\..\\..\\QtSDK1.1\\Desktop\\Qt\\4.7.3\\mingw\\include/QtCore/qnamespace.h")), 45,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Warning,
|
||||||
|
QLatin1String("unknown attribute 'dllimport' ignored [-Wunknown-attributes]\n"
|
||||||
|
"class Q_CORE_EXPORT QSysInfo {\n"
|
||||||
|
" ^"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("..\\..\\..\\QtSDK1.1\\Desktop\\Qt\\4.7.3\\mingw\\include/QtCore/qglobal.h")), 1425,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("note")
|
||||||
|
<< QString::fromLatin1("..\\..\\..\\QtSDK1.1\\Desktop\\Qt\\4.7.3\\mingw\\include/QtCore/qglobal.h:1289:27: note: instantiated from:\n"
|
||||||
|
"# define Q_CORE_EXPORT Q_DECL_IMPORT\n"
|
||||||
|
" ^")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< (QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("instantiated from:\n"
|
||||||
|
"# define Q_CORE_EXPORT Q_DECL_IMPORT\n"
|
||||||
|
" ^"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("..\\..\\..\\QtSDK1.1\\Desktop\\Qt\\4.7.3\\mingw\\include/QtCore/qglobal.h")), 1289,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("fatal error")
|
||||||
|
<< QString::fromLatin1("/usr/include/c++/4.6/utility:68:10: fatal error: 'bits/c++config.h' file not found\n"
|
||||||
|
"#include <bits/c++config.h>\n"
|
||||||
|
" ^")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< (QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("'bits/c++config.h' file not found\n"
|
||||||
|
"#include <bits/c++config.h>\n"
|
||||||
|
" ^"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("/usr/include/c++/4.6/utility")), 68,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
|
||||||
|
QTest::newRow("line confusion")
|
||||||
|
<< QString::fromLatin1("/home/code/src/creator/src/plugins/coreplugin/manhattanstyle.cpp:567:51: warning: ?: has lower precedence than +; + will be evaluated first [-Wparentheses]\n"
|
||||||
|
" int x = option->rect.x() + horizontal ? 2 : 6;\n"
|
||||||
|
" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< (QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Warning,
|
||||||
|
QLatin1String("?: has lower precedence than +; + will be evaluated first [-Wparentheses]\n"
|
||||||
|
" int x = option->rect.x() + horizontal ? 2 : 6;\n"
|
||||||
|
" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("/home/code/src/creator/src/plugins/coreplugin/manhattanstyle.cpp")), 567,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("code sign error")
|
||||||
|
<< QString::fromLatin1("Check dependencies\n"
|
||||||
|
"Code Sign error: No matching provisioning profiles found: No provisioning profiles with a valid signing identity (i.e. certificate and private key pair) were found.\n"
|
||||||
|
"CodeSign error: code signing is required for product type 'Application' in SDK 'iOS 7.0'")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString::fromLatin1("Check dependencies\n")
|
||||||
|
<< (QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("No matching provisioning profiles found: No provisioning profiles with a valid signing identity (i.e. certificate and private key pair) were found."),
|
||||||
|
Utils::FileName(), -1,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("code signing is required for product type 'Application' in SDK 'iOS 7.0'"),
|
||||||
|
Utils::FileName(), -1,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProjectExplorerPlugin::testClangOutputParser()
|
||||||
|
{
|
||||||
|
OutputParserTester testbench;
|
||||||
|
testbench.appendOutputParser(new ClangParser);
|
||||||
|
QFETCH(QString, input);
|
||||||
|
QFETCH(OutputParserTester::Channel, inputChannel);
|
||||||
|
QFETCH(QList<Task>, tasks);
|
||||||
|
QFETCH(QString, childStdOutLines);
|
||||||
|
QFETCH(QString, childStdErrLines);
|
||||||
|
QFETCH(QString, outputLines);
|
||||||
|
|
||||||
|
testbench.testParsing(input, inputChannel,
|
||||||
|
tasks, childStdOutLines, childStdErrLines,
|
||||||
|
outputLines);
|
||||||
|
}
|
||||||
|
#endif
|
59
src/plugins/boostbuildprojectmanager/external/projectexplorer/clangparser.h
vendored
Normal file
59
src/plugins/boostbuildprojectmanager/external/projectexplorer/clangparser.h
vendored
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef CLANGPARSER_H
|
||||||
|
#define CLANGPARSER_H
|
||||||
|
|
||||||
|
#include "gccparser.h"
|
||||||
|
#include <projectexplorer/task.h>
|
||||||
|
|
||||||
|
#include <QRegExp>
|
||||||
|
|
||||||
|
namespace ProjectExplorer {
|
||||||
|
|
||||||
|
class ClangParser : public ProjectExplorer::GccParser
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ClangParser();
|
||||||
|
void stdError(const QString &line);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QRegExp m_commandRegExp;
|
||||||
|
QRegExp m_inLineRegExp;
|
||||||
|
QRegExp m_messageRegExp;
|
||||||
|
QRegExp m_summaryRegExp;
|
||||||
|
QRegExp m_codesignRegExp;
|
||||||
|
bool m_expectSnippet;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ProjectExplorer
|
||||||
|
|
||||||
|
#endif // CLANGPARSER_H
|
880
src/plugins/boostbuildprojectmanager/external/projectexplorer/gccparser.cpp
vendored
Normal file
880
src/plugins/boostbuildprojectmanager/external/projectexplorer/gccparser.cpp
vendored
Normal file
@@ -0,0 +1,880 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License Version 2.1 by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.txt 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 "gccparser.h"
|
||||||
|
#include "ldparser.h"
|
||||||
|
#include <projectexplorer/task.h>
|
||||||
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
|
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
|
||||||
|
// opt. drive letter + filename: (2 brackets)
|
||||||
|
static const char FILE_PATTERN[] = "(<command[ -]line>|([A-Za-z]:)?[^:]+):";
|
||||||
|
static const char COMMAND_PATTERN[] = "^(.*[\\\\/])?([a-z0-9]+-[a-z0-9]+-[a-z0-9]+-)?(gcc|g\\+\\+)(-[0-9\\.]+)?(\\.exe)?: ";
|
||||||
|
|
||||||
|
GccParser::GccParser()
|
||||||
|
{
|
||||||
|
setObjectName(QLatin1String("GCCParser"));
|
||||||
|
m_regExp.setPattern(QLatin1Char('^') + QLatin1String(FILE_PATTERN)
|
||||||
|
+ QLatin1String("(\\d+):(\\d+:)?\\s+((fatal |#)?(warning|error|note):?\\s)?([^\\s].+)$"));
|
||||||
|
m_regExp.setMinimal(true);
|
||||||
|
QTC_CHECK(m_regExp.isValid());
|
||||||
|
|
||||||
|
m_regExpIncluded.setPattern(QString::fromLatin1("\\bfrom\\s") + QLatin1String(FILE_PATTERN)
|
||||||
|
+ QLatin1String("(\\d+)(:\\d+)?[,:]?$"));
|
||||||
|
m_regExpIncluded.setMinimal(true);
|
||||||
|
QTC_CHECK(m_regExpIncluded.isValid());
|
||||||
|
|
||||||
|
// optional path with trailing slash
|
||||||
|
// optional arm-linux-none-thingy
|
||||||
|
// name of executable
|
||||||
|
// optional trailing version number
|
||||||
|
// optional .exe postfix
|
||||||
|
m_regExpGccNames.setPattern(QLatin1String(COMMAND_PATTERN));
|
||||||
|
m_regExpGccNames.setMinimal(true);
|
||||||
|
QTC_CHECK(m_regExpGccNames.isValid());
|
||||||
|
|
||||||
|
appendOutputParser(new LdParser);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GccParser::stdError(const QString &line)
|
||||||
|
{
|
||||||
|
QString lne = rightTrimmed(line);
|
||||||
|
|
||||||
|
// Blacklist some lines to not handle them:
|
||||||
|
if (lne.startsWith(QLatin1String("TeamBuilder ")) ||
|
||||||
|
lne.startsWith(QLatin1String("distcc["))) {
|
||||||
|
IOutputParser::stdError(line);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle misc issues:
|
||||||
|
if (lne.startsWith(QLatin1String("ERROR:")) ||
|
||||||
|
lne == QLatin1String("* cpp failed")) {
|
||||||
|
newTask(Task(Task::Error,
|
||||||
|
lne /* description */,
|
||||||
|
Utils::FileName() /* filename */,
|
||||||
|
-1 /* linenumber */,
|
||||||
|
Constants::TASK_CATEGORY_COMPILE));
|
||||||
|
return;
|
||||||
|
} else if (m_regExpGccNames.indexIn(lne) > -1) {
|
||||||
|
QString description = lne.mid(m_regExpGccNames.matchedLength());
|
||||||
|
Task task(Task::Error,
|
||||||
|
description,
|
||||||
|
Utils::FileName(), /* filename */
|
||||||
|
-1, /* line */
|
||||||
|
Constants::TASK_CATEGORY_COMPILE);
|
||||||
|
if (description.startsWith(QLatin1String("warning: "))) {
|
||||||
|
task.type = Task::Warning;
|
||||||
|
task.description = description.mid(9);
|
||||||
|
} else if (description.startsWith(QLatin1String("fatal: "))) {
|
||||||
|
task.description = description.mid(7);
|
||||||
|
}
|
||||||
|
newTask(task);
|
||||||
|
return;
|
||||||
|
} else if (m_regExp.indexIn(lne) > -1) {
|
||||||
|
Utils::FileName filename = Utils::FileName::fromUserInput(m_regExp.cap(1));
|
||||||
|
int lineno = m_regExp.cap(3).toInt();
|
||||||
|
Task task(Task::Unknown,
|
||||||
|
m_regExp.cap(8) /* description */,
|
||||||
|
filename, lineno,
|
||||||
|
Constants::TASK_CATEGORY_COMPILE);
|
||||||
|
if (m_regExp.cap(7) == QLatin1String("warning"))
|
||||||
|
task.type = Task::Warning;
|
||||||
|
else if (m_regExp.cap(7) == QLatin1String("error") ||
|
||||||
|
task.description.startsWith(QLatin1String("undefined reference to")) ||
|
||||||
|
task.description.startsWith(QLatin1String("multiple definition of")))
|
||||||
|
task.type = Task::Error;
|
||||||
|
|
||||||
|
// Prepend "#warning" or "#error" if that triggered the match on (warning|error)
|
||||||
|
// We want those to show how the warning was triggered
|
||||||
|
if (m_regExp.cap(5).startsWith(QLatin1Char('#')))
|
||||||
|
task.description = m_regExp.cap(5) + task.description;
|
||||||
|
|
||||||
|
newTask(task);
|
||||||
|
return;
|
||||||
|
} else if (m_regExpIncluded.indexIn(lne) > -1) {
|
||||||
|
newTask(Task(Task::Unknown,
|
||||||
|
lne.trimmed() /* description */,
|
||||||
|
Utils::FileName::fromUserInput(m_regExpIncluded.cap(1)) /* filename */,
|
||||||
|
m_regExpIncluded.cap(3).toInt() /* linenumber */,
|
||||||
|
Constants::TASK_CATEGORY_COMPILE));
|
||||||
|
return;
|
||||||
|
} else if (lne.startsWith(QLatin1Char(' '))) {
|
||||||
|
amendDescription(lne, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
doFlush();
|
||||||
|
IOutputParser::stdError(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GccParser::stdOutput(const QString &line)
|
||||||
|
{
|
||||||
|
doFlush();
|
||||||
|
IOutputParser::stdOutput(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GccParser::newTask(const Task &task)
|
||||||
|
{
|
||||||
|
doFlush();
|
||||||
|
m_currentTask = task;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GccParser::doFlush()
|
||||||
|
{
|
||||||
|
if (m_currentTask.isNull())
|
||||||
|
return;
|
||||||
|
Task t = m_currentTask;
|
||||||
|
m_currentTask.clear();
|
||||||
|
emit addTask(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GccParser::amendDescription(const QString &desc, bool monospaced)
|
||||||
|
{
|
||||||
|
if (m_currentTask.isNull())
|
||||||
|
return;
|
||||||
|
int start = m_currentTask.description.count() + 1;
|
||||||
|
m_currentTask.description.append(QLatin1Char('\n'));
|
||||||
|
m_currentTask.description.append(desc);
|
||||||
|
if (monospaced) {
|
||||||
|
QTextLayout::FormatRange fr;
|
||||||
|
fr.start = start;
|
||||||
|
fr.length = desc.count() + 1;
|
||||||
|
fr.format.setFontFamily(QLatin1String("Monospaced"));
|
||||||
|
fr.format.setFontStyleHint(QFont::TypeWriter);
|
||||||
|
m_currentTask.formats.append(fr);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unit tests:
|
||||||
|
|
||||||
|
#ifdef WITH_TESTS_NOTDISABLED
|
||||||
|
# include <QTest>
|
||||||
|
|
||||||
|
# include "projectexplorer.h"
|
||||||
|
# include "metatypedeclarations.h"
|
||||||
|
# include "outputparser_test.h"
|
||||||
|
|
||||||
|
void ProjectExplorerPlugin::testGccOutputParsers_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QString>("input");
|
||||||
|
QTest::addColumn<OutputParserTester::Channel>("inputChannel");
|
||||||
|
QTest::addColumn<QString>("childStdOutLines");
|
||||||
|
QTest::addColumn<QString>("childStdErrLines");
|
||||||
|
QTest::addColumn<QList<ProjectExplorer::Task> >("tasks");
|
||||||
|
QTest::addColumn<QString>("outputLines");
|
||||||
|
|
||||||
|
const Core::Id categoryCompile = Constants::TASK_CATEGORY_COMPILE;
|
||||||
|
|
||||||
|
QTest::newRow("pass-through stdout")
|
||||||
|
<< QString::fromLatin1("Sometext") << OutputParserTester::STDOUT
|
||||||
|
<< QString::fromLatin1("Sometext\n") << QString()
|
||||||
|
<< QList<ProjectExplorer::Task>()
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("pass-through stderr")
|
||||||
|
<< QString::fromLatin1("Sometext") << OutputParserTester::STDERR
|
||||||
|
<< QString() << QString::fromLatin1("Sometext\n")
|
||||||
|
<< QList<ProjectExplorer::Task>()
|
||||||
|
<< QString();
|
||||||
|
|
||||||
|
QTest::newRow("ar output")
|
||||||
|
<< QString::fromLatin1("../../../../x86/i686-unknown-linux-gnu/bin/i686-unknown-linux-gnu-ar: creating lib/libSkyView.a") << OutputParserTester::STDERR
|
||||||
|
<< QString() << QString::fromLatin1("../../../../x86/i686-unknown-linux-gnu/bin/i686-unknown-linux-gnu-ar: creating lib/libSkyView.a\n")
|
||||||
|
<< QList<ProjectExplorer::Task>()
|
||||||
|
<< QString();
|
||||||
|
|
||||||
|
QTest::newRow("GCCE error")
|
||||||
|
<< QString::fromLatin1("/temp/test/untitled8/main.cpp: In function `int main(int, char**)':\n"
|
||||||
|
"/temp/test/untitled8/main.cpp:9: error: `sfasdf' undeclared (first use this function)\n"
|
||||||
|
"/temp/test/untitled8/main.cpp:9: error: (Each undeclared identifier is reported only once for each function it appears in.)")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< (QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("In function `int main(int, char**)':"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("/temp/test/untitled8/main.cpp")), -1,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("`sfasdf' undeclared (first use this function)"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("/temp/test/untitled8/main.cpp")), 9,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("(Each undeclared identifier is reported only once for each function it appears in.)"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("/temp/test/untitled8/main.cpp")), 9,
|
||||||
|
categoryCompile)
|
||||||
|
)
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("GCCE warning")
|
||||||
|
<< QString::fromLatin1("/src/corelib/global/qglobal.h:1635: warning: inline function `QDebug qDebug()' used but never defined")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< (QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Warning,
|
||||||
|
QLatin1String("inline function `QDebug qDebug()' used but never defined"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("/src/corelib/global/qglobal.h")), 1635,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("warning")
|
||||||
|
<< QString::fromLatin1("main.cpp:7:2: warning: Some warning")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< (QList<ProjectExplorer::Task>() << Task(Task::Warning,
|
||||||
|
QLatin1String("Some warning"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("main.cpp")), 7,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("GCCE #error")
|
||||||
|
<< QString::fromLatin1("C:\\temp\\test\\untitled8\\main.cpp:7: #error Symbian error")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< (QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("#error Symbian error"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("C:\\temp\\test\\untitled8\\main.cpp")), 7,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
// Symbian reports #warning(s) twice (using different syntax).
|
||||||
|
QTest::newRow("GCCE #warning1")
|
||||||
|
<< QString::fromLatin1("C:\\temp\\test\\untitled8\\main.cpp:8: warning: #warning Symbian warning")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< (QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Warning,
|
||||||
|
QLatin1String("#warning Symbian warning"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("C:\\temp\\test\\untitled8\\main.cpp")), 8,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("GCCE #warning2")
|
||||||
|
<< QString::fromLatin1("/temp/test/untitled8/main.cpp:8:2: warning: #warning Symbian warning")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< (QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Warning,
|
||||||
|
QLatin1String("#warning Symbian warning"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("/temp/test/untitled8/main.cpp")), 8,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("Undefined reference (debug)")
|
||||||
|
<< QString::fromLatin1("main.o: In function `main':\n"
|
||||||
|
"C:\\temp\\test\\untitled8/main.cpp:8: undefined reference to `MainWindow::doSomething()'\n"
|
||||||
|
"collect2: ld returned 1 exit status")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< (QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("In function `main':"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("main.o")), -1,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("undefined reference to `MainWindow::doSomething()'"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("C:\\temp\\test\\untitled8/main.cpp")), 8,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("collect2: ld returned 1 exit status"),
|
||||||
|
Utils::FileName(), -1,
|
||||||
|
categoryCompile)
|
||||||
|
)
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("Undefined reference (release)")
|
||||||
|
<< QString::fromLatin1("main.o: In function `main':\n"
|
||||||
|
"C:\\temp\\test\\untitled8/main.cpp:(.text+0x40): undefined reference to `MainWindow::doSomething()'\n"
|
||||||
|
"collect2: ld returned 1 exit status")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< (QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("In function `main':"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("main.o")), -1,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("undefined reference to `MainWindow::doSomething()'"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("C:\\temp\\test\\untitled8/main.cpp")), -1,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("collect2: ld returned 1 exit status"),
|
||||||
|
Utils::FileName(), -1,
|
||||||
|
categoryCompile)
|
||||||
|
)
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("linker: dll format not recognized")
|
||||||
|
<< QString::fromLatin1("c:\\Qt\\4.6\\lib/QtGuid4.dll: file not recognized: File format not recognized")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< (QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("file not recognized: File format not recognized"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("c:\\Qt\\4.6\\lib/QtGuid4.dll")), -1,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("Invalid rpath")
|
||||||
|
<< QString::fromLatin1("g++: /usr/local/lib: No such file or directory")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< (QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("/usr/local/lib: No such file or directory"),
|
||||||
|
Utils::FileName(), -1,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
|
||||||
|
QTest::newRow("Invalid rpath")
|
||||||
|
<< QString::fromLatin1("../../../../master/src/plugins/debugger/gdb/gdbengine.cpp: In member function 'void Debugger::Internal::GdbEngine::handleBreakInsert2(const Debugger::Internal::GdbResponse&)':\n"
|
||||||
|
"../../../../master/src/plugins/debugger/gdb/gdbengine.cpp:2114: warning: unused variable 'index'\n"
|
||||||
|
"../../../../master/src/plugins/debugger/gdb/gdbengine.cpp:2115: warning: unused variable 'handler'")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< (QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("In member function 'void Debugger::Internal::GdbEngine::handleBreakInsert2(const Debugger::Internal::GdbResponse&)':"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("../../../../master/src/plugins/debugger/gdb/gdbengine.cpp")), -1,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Warning,
|
||||||
|
QLatin1String("unused variable 'index'"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("../../../../master/src/plugins/debugger/gdb/gdbengine.cpp")), 2114,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Warning,
|
||||||
|
QLatin1String("unused variable 'handler'"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("../../../../master/src/plugins/debugger/gdb/gdbengine.cpp")), 2115,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("gnumakeparser.cpp errors")
|
||||||
|
<< QString::fromLatin1("/home/code/src/creator/src/plugins/projectexplorer/gnumakeparser.cpp: In member function 'void ProjectExplorer::ProjectExplorerPlugin::testGnuMakeParserTaskMangling_data()':\n"
|
||||||
|
"/home/code/src/creator/src/plugins/projectexplorer/gnumakeparser.cpp:264: error: expected primary-expression before ':' token\n"
|
||||||
|
"/home/code/src/creator/src/plugins/projectexplorer/gnumakeparser.cpp:264: error: expected ';' before ':' token")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< (QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("In member function 'void ProjectExplorer::ProjectExplorerPlugin::testGnuMakeParserTaskMangling_data()':"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("/home/code/src/creator/src/plugins/projectexplorer/gnumakeparser.cpp")), -1,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("expected primary-expression before ':' token"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("/home/code/src/creator/src/plugins/projectexplorer/gnumakeparser.cpp")), 264,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("expected ';' before ':' token"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("/home/code/src/creator/src/plugins/projectexplorer/gnumakeparser.cpp")), 264,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("distcc error(QTCREATORBUG-904)")
|
||||||
|
<< QString::fromLatin1("distcc[73168] (dcc_get_hostlist) Warning: no hostlist is set; can't distribute work\n"
|
||||||
|
"distcc[73168] (dcc_build_somewhere) Warning: failed to distribute, running locally instead")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString::fromLatin1("distcc[73168] (dcc_get_hostlist) Warning: no hostlist is set; can't distribute work\n"
|
||||||
|
"distcc[73168] (dcc_build_somewhere) Warning: failed to distribute, running locally instead\n")
|
||||||
|
<< QList<ProjectExplorer::Task>()
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("ld warning (QTCREATORBUG-905)")
|
||||||
|
<< QString::fromLatin1("ld: warning: Core::IEditor* QVariant::value<Core::IEditor*>() const has different visibility (hidden) in .obj/debug-shared/openeditorsview.o and (default) in .obj/debug-shared/editormanager.o")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< ( QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Warning,
|
||||||
|
QLatin1String("Core::IEditor* QVariant::value<Core::IEditor*>() const has different visibility (hidden) in .obj/debug-shared/openeditorsview.o and (default) in .obj/debug-shared/editormanager.o"),
|
||||||
|
Utils::FileName(), -1,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("ld fatal")
|
||||||
|
<< QString::fromLatin1("ld: fatal: Symbol referencing errors. No output written to testproject")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< ( QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("Symbol referencing errors. No output written to testproject"),
|
||||||
|
Utils::FileName(), -1,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("Teambuilder issues")
|
||||||
|
<< QString::fromLatin1("TeamBuilder Client:: error: could not find Scheduler, running Job locally...")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString::fromLatin1("TeamBuilder Client:: error: could not find Scheduler, running Job locally...\n")
|
||||||
|
<< QList<ProjectExplorer::Task>()
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("note")
|
||||||
|
<< QString::fromLatin1("/home/dev/creator/share/qtcreator/debugger/dumper.cpp:1079: note: initialized from here")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< ( QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("initialized from here"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("/home/dev/creator/share/qtcreator/debugger/dumper.cpp")), 1079,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("static member function")
|
||||||
|
<< QString::fromLatin1("/Qt/4.6.2-Symbian/s60sdk/epoc32/include/stdapis/stlport/stl/_tree.c: In static member function 'static std::_Rb_tree_node_base* std::_Rb_global<_Dummy>::_Rebalance_for_erase(std::_Rb_tree_node_base*, std::_Rb_tree_node_base*&, std::_Rb_tree_node_base*&, std::_Rb_tree_node_base*&)':\n"
|
||||||
|
"/Qt/4.6.2-Symbian/s60sdk/epoc32/include/stdapis/stlport/stl/_tree.c:194: warning: suggest explicit braces to avoid ambiguous 'else'")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< ( QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("In static member function 'static std::_Rb_tree_node_base* std::_Rb_global<_Dummy>::_Rebalance_for_erase(std::_Rb_tree_node_base*, std::_Rb_tree_node_base*&, std::_Rb_tree_node_base*&, std::_Rb_tree_node_base*&)':"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("/Qt/4.6.2-Symbian/s60sdk/epoc32/include/stdapis/stlport/stl/_tree.c")), -1,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Warning,
|
||||||
|
QLatin1String("suggest explicit braces to avoid ambiguous 'else'"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("/Qt/4.6.2-Symbian/s60sdk/epoc32/include/stdapis/stlport/stl/_tree.c")), 194,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("rm false positive")
|
||||||
|
<< QString::fromLatin1("rm: cannot remove `release/moc_mainwindow.cpp': No such file or directory")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString(QLatin1String("rm: cannot remove `release/moc_mainwindow.cpp': No such file or directory\n"))
|
||||||
|
<< QList<ProjectExplorer::Task>()
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("ranlib false positive")
|
||||||
|
<< QString::fromLatin1("ranlib: file: libSupport.a(HashTable.o) has no symbols")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString(QLatin1String("ranlib: file: libSupport.a(HashTable.o) has no symbols\n"))
|
||||||
|
<< QList<ProjectExplorer::Task>()
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("ld: missing library")
|
||||||
|
<< QString::fromLatin1("/usr/bin/ld: cannot find -ldoesnotexist")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< ( QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("cannot find -ldoesnotexist"),
|
||||||
|
Utils::FileName(), -1,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("In function")
|
||||||
|
<< QString::fromLatin1("../../scriptbug/main.cpp: In function void foo(i) [with i = double]:\n"
|
||||||
|
"../../scriptbug/main.cpp:22: instantiated from here\n"
|
||||||
|
"../../scriptbug/main.cpp:8: warning: unused variable c")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< ( QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("In function void foo(i) [with i = double]:"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("../../scriptbug/main.cpp")), -1,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("instantiated from here"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("../../scriptbug/main.cpp")), 22,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Warning,
|
||||||
|
QLatin1String("unused variable c"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("../../scriptbug/main.cpp")), 8,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("instanciated from here")
|
||||||
|
<< QString::fromLatin1("main.cpp:10: instantiated from here ")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< ( QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("instantiated from here"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("main.cpp")), 10,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("In constructor")
|
||||||
|
<< QString::fromLatin1("/dev/creator/src/plugins/find/basetextfind.h: In constructor 'Find::BaseTextFind::BaseTextFind(QTextEdit*)':")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< ( QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("In constructor 'Find::BaseTextFind::BaseTextFind(QTextEdit*)':"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("/dev/creator/src/plugins/find/basetextfind.h")), -1,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
|
||||||
|
QTest::newRow("At global scope")
|
||||||
|
<< QString::fromLatin1("../../scriptbug/main.cpp: At global scope:\n"
|
||||||
|
"../../scriptbug/main.cpp: In instantiation of void bar(i) [with i = double]:\n"
|
||||||
|
"../../scriptbug/main.cpp:8: instantiated from void foo(i) [with i = double]\n"
|
||||||
|
"../../scriptbug/main.cpp:22: instantiated from here\n"
|
||||||
|
"../../scriptbug/main.cpp:5: warning: unused parameter v")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< ( QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("At global scope:"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("../../scriptbug/main.cpp")), -1,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("In instantiation of void bar(i) [with i = double]:"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("../../scriptbug/main.cpp")), -1,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("instantiated from void foo(i) [with i = double]"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("../../scriptbug/main.cpp")), 8,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("instantiated from here"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("../../scriptbug/main.cpp")), 22,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Warning,
|
||||||
|
QLatin1String("unused parameter v"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("../../scriptbug/main.cpp")), 5,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
|
||||||
|
QTest::newRow("gcc 4.5 fatal error")
|
||||||
|
<< QString::fromLatin1("/home/code/test.cpp:54:38: fatal error: test.moc: No such file or directory")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< ( QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("test.moc: No such file or directory"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("/home/code/test.cpp")), 54,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
|
||||||
|
QTest::newRow("QTCREATORBUG-597")
|
||||||
|
<< QString::fromLatin1("debug/qplotaxis.o: In function `QPlotAxis':\n"
|
||||||
|
"M:\\Development\\x64\\QtPlot/qplotaxis.cpp:26: undefined reference to `vtable for QPlotAxis'\n"
|
||||||
|
"M:\\Development\\x64\\QtPlot/qplotaxis.cpp:26: undefined reference to `vtable for QPlotAxis'\n"
|
||||||
|
"collect2: ld returned 1 exit status")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< ( QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("In function `QPlotAxis':"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("debug/qplotaxis.o")), -1,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("undefined reference to `vtable for QPlotAxis'"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("M:\\Development\\x64\\QtPlot/qplotaxis.cpp")), 26,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("undefined reference to `vtable for QPlotAxis'"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("M:\\Development\\x64\\QtPlot/qplotaxis.cpp")), 26,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("collect2: ld returned 1 exit status"),
|
||||||
|
Utils::FileName(), -1,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
|
||||||
|
QTest::newRow("instantiated from here should not be an error")
|
||||||
|
<< QString::fromLatin1("../stl/main.cpp: In member function typename _Vector_base<_Tp, _Alloc>::_Tp_alloc_type::const_reference Vector<_Tp, _Alloc>::at(int) [with _Tp = Point, _Alloc = Allocator<Point>]:\n"
|
||||||
|
"../stl/main.cpp:38: instantiated from here\n"
|
||||||
|
"../stl/main.cpp:31: warning: returning reference to temporary\n"
|
||||||
|
"../stl/main.cpp: At global scope:\n"
|
||||||
|
"../stl/main.cpp:31: warning: unused parameter index")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< ( QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("In member function typename _Vector_base<_Tp, _Alloc>::_Tp_alloc_type::const_reference Vector<_Tp, _Alloc>::at(int) [with _Tp = Point, _Alloc = Allocator<Point>]:"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("../stl/main.cpp")), -1,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("instantiated from here"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("../stl/main.cpp")), 38,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Warning,
|
||||||
|
QLatin1String("returning reference to temporary"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("../stl/main.cpp")), 31,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("At global scope:"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("../stl/main.cpp")), -1,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Warning,
|
||||||
|
QLatin1String("unused parameter index"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("../stl/main.cpp")), 31,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
|
||||||
|
QTest::newRow("GCCE from lines")
|
||||||
|
<< QString::fromLatin1("In file included from C:/Symbian_SDK/epoc32/include/e32cmn.h:6792,\n"
|
||||||
|
" from C:/Symbian_SDK/epoc32/include/e32std.h:25,\n"
|
||||||
|
"C:/Symbian_SDK/epoc32/include/e32cmn.inl: In member function 'SSecureId::operator const TSecureId&() const':\n"
|
||||||
|
"C:/Symbian_SDK/epoc32/include/e32cmn.inl:7094: warning: returning reference to temporary")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< ( QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("In file included from C:/Symbian_SDK/epoc32/include/e32cmn.h:6792,"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("C:/Symbian_SDK/epoc32/include/e32cmn.h")), 6792,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("from C:/Symbian_SDK/epoc32/include/e32std.h:25,"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("C:/Symbian_SDK/epoc32/include/e32std.h")), 25,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("In member function 'SSecureId::operator const TSecureId&() const':"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("C:/Symbian_SDK/epoc32/include/e32cmn.inl")), -1,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Warning,
|
||||||
|
QLatin1String("returning reference to temporary"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("C:/Symbian_SDK/epoc32/include/e32cmn.inl")), 7094,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
|
||||||
|
QTest::newRow("QTCREATORBUG-2206")
|
||||||
|
<< QString::fromLatin1("../../../src/XmlUg/targetdelete.c: At top level:")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< ( QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("At top level:"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("../../../src/XmlUg/targetdelete.c")), -1,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
|
||||||
|
QTest::newRow("GCCE 4: commandline, includes")
|
||||||
|
<< QString::fromLatin1("In file included from /Symbian/SDK/EPOC32/INCLUDE/GCCE/GCCE.h:15,\n"
|
||||||
|
" from <command line>:26:\n"
|
||||||
|
"/Symbian/SDK/epoc32/include/variant/Symbian_OS.hrh:1134:26: warning: no newline at end of file")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< ( QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("In file included from /Symbian/SDK/EPOC32/INCLUDE/GCCE/GCCE.h:15,"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("/Symbian/SDK/EPOC32/INCLUDE/GCCE/GCCE.h")), 15,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("from <command line>:26:"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("<command line>")), 26,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Warning,
|
||||||
|
QLatin1String("no newline at end of file"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("/Symbian/SDK/epoc32/include/variant/Symbian_OS.hrh")), 1134,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
|
||||||
|
QTest::newRow("Linker fail (release build)")
|
||||||
|
<< QString::fromLatin1("release/main.o:main.cpp:(.text+0x42): undefined reference to `MainWindow::doSomething()'")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< ( QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("undefined reference to `MainWindow::doSomething()'"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("main.cpp")), -1,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
|
||||||
|
QTest::newRow("enumeration warning")
|
||||||
|
<< QString::fromLatin1("../../../src/shared/proparser/profileevaluator.cpp: In member function 'ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateConditionalFunction(const ProString&, const ProStringList&)':\n"
|
||||||
|
"../../../src/shared/proparser/profileevaluator.cpp:2817:9: warning: case value '0' not in enumerated type 'ProFileEvaluator::Private::TestFunc'")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< ( QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("In member function 'ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateConditionalFunction(const ProString&, const ProStringList&)':"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("../../../src/shared/proparser/profileevaluator.cpp")), -1,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Warning,
|
||||||
|
QLatin1String("case value '0' not in enumerated type 'ProFileEvaluator::Private::TestFunc'"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("../../../src/shared/proparser/profileevaluator.cpp")), 2817,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
|
||||||
|
QTest::newRow("include with line:column info")
|
||||||
|
<< QString::fromLatin1("In file included from <command-line>:0:0:\n"
|
||||||
|
"./mw.h:4:0: warning: \"STUPID_DEFINE\" redefined")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< ( QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("In file included from <command-line>:0:0:"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("<command-line>")), 0,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Warning,
|
||||||
|
QLatin1String("\"STUPID_DEFINE\" redefined"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("./mw.h")), 4,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("instanciation with line:column info")
|
||||||
|
<< QString::fromLatin1("file.h: In function 'void UnitTest::CheckEqual(UnitTest::TestResults&, const Expected&, const Actual&, const UnitTest::TestDetails&) [with Expected = unsigned int, Actual = int]':\n"
|
||||||
|
"file.cpp:87:10: instantiated from here\n"
|
||||||
|
"file.h:21:5: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< ( QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("In function 'void UnitTest::CheckEqual(UnitTest::TestResults&, const Expected&, const Actual&, const UnitTest::TestDetails&) [with Expected = unsigned int, Actual = int]':"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("file.h")), -1,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("instantiated from here"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("file.cpp")), 87,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Warning,
|
||||||
|
QLatin1String("comparison between signed and unsigned integer expressions [-Wsign-compare]"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("file.h")), 21,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
QTest::newRow("linker error") // QTCREATORBUG-3107
|
||||||
|
<< QString::fromLatin1("cns5k_ins_parser_tests.cpp:(.text._ZN20CNS5kINSParserEngine21DropBytesUntilStartedEP14CircularBufferIhE[CNS5kINSParserEngine::DropBytesUntilStarted(CircularBuffer<unsigned char>*)]+0x6d): undefined reference to `CNS5kINSPacket::SOH_BYTE'")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< ( QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("undefined reference to `CNS5kINSPacket::SOH_BYTE'"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("cns5k_ins_parser_tests.cpp")), -1,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
|
||||||
|
QTest::newRow("uic warning")
|
||||||
|
<< QString::fromLatin1("mainwindow.ui: Warning: The name 'pushButton' (QPushButton) is already in use, defaulting to 'pushButton1'.")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< ( QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Warning,
|
||||||
|
QLatin1String("The name 'pushButton' (QPushButton) is already in use, defaulting to 'pushButton1'."),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("mainwindow.ui")), -1,
|
||||||
|
Constants::TASK_CATEGORY_COMPILE))
|
||||||
|
<< QString();
|
||||||
|
|
||||||
|
QTest::newRow("libimf warning")
|
||||||
|
<< QString::fromLatin1("libimf.so: warning: warning: feupdateenv is not implemented and will always fail")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< ( QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Warning,
|
||||||
|
QLatin1String("warning: feupdateenv is not implemented and will always fail"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("libimf.so")), -1,
|
||||||
|
Constants::TASK_CATEGORY_COMPILE))
|
||||||
|
<< QString();
|
||||||
|
|
||||||
|
QTest::newRow("gcc 4.8")
|
||||||
|
<< QString::fromLatin1("In file included from /home/code/src/creator/src/libs/extensionsystem/pluginerrorview.cpp:31:0:\n"
|
||||||
|
".uic/ui_pluginerrorview.h:14:25: fatal error: QtGui/QAction: No such file or directory\n"
|
||||||
|
" #include <QtGui/QAction>\n"
|
||||||
|
" ^")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< ( QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("In file included from /home/code/src/creator/src/libs/extensionsystem/pluginerrorview.cpp:31:0:"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("/home/code/src/creator/src/libs/extensionsystem/pluginerrorview.cpp")), 31,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("QtGui/QAction: No such file or directory\n"
|
||||||
|
" #include <QtGui/QAction>\n"
|
||||||
|
" ^"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String(".uic/ui_pluginerrorview.h")), 14,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
|
||||||
|
QTest::newRow("qtcreatorbug-9195")
|
||||||
|
<< QString::fromLatin1("In file included from /usr/include/qt4/QtCore/QString:1:0,\n"
|
||||||
|
" from main.cpp:3:\n"
|
||||||
|
"/usr/include/qt4/QtCore/qstring.h: In function 'void foo()':\n"
|
||||||
|
"/usr/include/qt4/QtCore/qstring.h:597:5: error: 'QString::QString(const char*)' is private\n"
|
||||||
|
"main.cpp:7:22: error: within this context")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< ( QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("In file included from /usr/include/qt4/QtCore/QString:1:0,"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("/usr/include/qt4/QtCore/QString")), 1,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("from main.cpp:3:"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("main.cpp")), 3,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("In function 'void foo()':"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("/usr/include/qt4/QtCore/qstring.h")), -1,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("'QString::QString(const char*)' is private"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("/usr/include/qt4/QtCore/qstring.h")), 597,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("within this context"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("main.cpp")), 7,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
|
||||||
|
QTest::newRow("ld: Multiple definition error")
|
||||||
|
<< QString::fromLatin1("foo.o: In function `foo()':\n"
|
||||||
|
"/home/user/test/foo.cpp:2: multiple definition of `foo()'\n"
|
||||||
|
"bar.o:/home/user/test/bar.cpp:4: first defined here\n"
|
||||||
|
"collect2: error: ld returned 1 exit status")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< (QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("In function `foo()':"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("foo.o")), -1,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("multiple definition of `foo()'"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("/home/user/test/foo.cpp")), 2,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("first defined here"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("/home/user/test/bar.cpp")), 4,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("collect2: error: ld returned 1 exit status"),
|
||||||
|
Utils::FileName(), -1,
|
||||||
|
categoryCompile)
|
||||||
|
)
|
||||||
|
<< QString();
|
||||||
|
|
||||||
|
QTest::newRow("ld: .data section")
|
||||||
|
<< QString::fromLatin1("foo.o:(.data+0x0): multiple definition of `foo'\n"
|
||||||
|
"bar.o:(.data+0x0): first defined here\n"
|
||||||
|
"collect2: error: ld returned 1 exit status")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< (QList<ProjectExplorer::Task>()
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("multiple definition of `foo'"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("foo.o")), -1,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Unknown,
|
||||||
|
QLatin1String("first defined here"),
|
||||||
|
Utils::FileName::fromUserInput(QLatin1String("bar.o")), -1,
|
||||||
|
categoryCompile)
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QLatin1String("collect2: error: ld returned 1 exit status"),
|
||||||
|
Utils::FileName(), -1,
|
||||||
|
categoryCompile)
|
||||||
|
)
|
||||||
|
<< QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProjectExplorerPlugin::testGccOutputParsers()
|
||||||
|
{
|
||||||
|
OutputParserTester testbench;
|
||||||
|
testbench.appendOutputParser(new GccParser);
|
||||||
|
QFETCH(QString, input);
|
||||||
|
QFETCH(OutputParserTester::Channel, inputChannel);
|
||||||
|
QFETCH(QList<Task>, tasks);
|
||||||
|
QFETCH(QString, childStdOutLines);
|
||||||
|
QFETCH(QString, childStdErrLines);
|
||||||
|
QFETCH(QString, outputLines);
|
||||||
|
|
||||||
|
testbench.testParsing(input, inputChannel,
|
||||||
|
tasks, childStdOutLines, childStdErrLines,
|
||||||
|
outputLines);
|
||||||
|
}
|
||||||
|
#endif
|
67
src/plugins/boostbuildprojectmanager/external/projectexplorer/gccparser.h
vendored
Normal file
67
src/plugins/boostbuildprojectmanager/external/projectexplorer/gccparser.h
vendored
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef GCCPARSER_H
|
||||||
|
#define GCCPARSER_H
|
||||||
|
|
||||||
|
#include <projectexplorer/ioutputparser.h>
|
||||||
|
|
||||||
|
#include <projectexplorer/task.h>
|
||||||
|
|
||||||
|
#include <QRegExp>
|
||||||
|
|
||||||
|
namespace ProjectExplorer {
|
||||||
|
|
||||||
|
class GccParser : public ProjectExplorer::IOutputParser
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
GccParser();
|
||||||
|
|
||||||
|
void stdError(const QString &line);
|
||||||
|
void stdOutput(const QString &line);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void newTask(const Task &task);
|
||||||
|
void doFlush();
|
||||||
|
|
||||||
|
void amendDescription(const QString &desc, bool monospaced);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QRegExp m_regExp;
|
||||||
|
QRegExp m_regExpIncluded;
|
||||||
|
QRegExp m_regExpGccNames;
|
||||||
|
|
||||||
|
Task m_currentTask;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ProjectExplorer
|
||||||
|
|
||||||
|
#endif // GCCPARSER_H
|
126
src/plugins/boostbuildprojectmanager/external/projectexplorer/ldparser.cpp
vendored
Normal file
126
src/plugins/boostbuildprojectmanager/external/projectexplorer/ldparser.cpp
vendored
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License Version 2.1 by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.txt 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 "ldparser.h"
|
||||||
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
|
#include <projectexplorer/task.h>
|
||||||
|
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
// opt. drive letter + filename: (2 brackets)
|
||||||
|
const char * const FILE_PATTERN = "(([A-Za-z]:)?[^:]+\\.[^:]+):";
|
||||||
|
// line no. or elf segment + offset (1 bracket)
|
||||||
|
// const char * const POSITION_PATTERN = "(\\d+|\\(\\.[^:]+[+-]0x[a-fA-F0-9]+\\):)";
|
||||||
|
const char * const POSITION_PATTERN = "(\\d+|\\(\\..+[+-]0x[a-fA-F0-9]+\\)):";
|
||||||
|
const char * const COMMAND_PATTERN = "^(.*[\\\\/])?([a-z0-9]+-[a-z0-9]+-[a-z0-9]+-)?(ld|gold)(-[0-9\\.]+)?(\\.exe)?: ";
|
||||||
|
}
|
||||||
|
|
||||||
|
LdParser::LdParser()
|
||||||
|
{
|
||||||
|
setObjectName(QLatin1String("LdParser"));
|
||||||
|
m_regExpLinker.setPattern(QLatin1Char('^') +
|
||||||
|
QString::fromLatin1(FILE_PATTERN) + QLatin1Char('(') +
|
||||||
|
QString::fromLatin1(FILE_PATTERN) + QLatin1String(")?(") +
|
||||||
|
QLatin1String(POSITION_PATTERN) + QLatin1String(")?\\s(.+)$"));
|
||||||
|
m_regExpLinker.setMinimal(true);
|
||||||
|
QTC_CHECK(m_regExpLinker.isValid());
|
||||||
|
|
||||||
|
m_regExpGccNames.setPattern(QLatin1String(COMMAND_PATTERN));
|
||||||
|
m_regExpGccNames.setMinimal(true);
|
||||||
|
QTC_CHECK(m_regExpGccNames.isValid());
|
||||||
|
}
|
||||||
|
|
||||||
|
void LdParser::stdError(const QString &line)
|
||||||
|
{
|
||||||
|
QString lne = rightTrimmed(line);
|
||||||
|
if (lne.startsWith(QLatin1String("TeamBuilder "))
|
||||||
|
|| lne.startsWith(QLatin1String("distcc["))
|
||||||
|
|| lne.contains(QLatin1String("ar: creating "))) {
|
||||||
|
IOutputParser::stdError(line);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lne.startsWith(QLatin1String("collect2:"))) {
|
||||||
|
emit addTask(Task(Task::Error,
|
||||||
|
lne /* description */,
|
||||||
|
Utils::FileName() /* filename */,
|
||||||
|
-1 /* linenumber */,
|
||||||
|
Constants::TASK_CATEGORY_COMPILE));
|
||||||
|
return;
|
||||||
|
} else if (m_regExpGccNames.indexIn(lne) > -1) {
|
||||||
|
QString description = lne.mid(m_regExpGccNames.matchedLength());
|
||||||
|
Task task(Task::Error,
|
||||||
|
description,
|
||||||
|
Utils::FileName(), /* filename */
|
||||||
|
-1, /* line */
|
||||||
|
Constants::TASK_CATEGORY_COMPILE);
|
||||||
|
if (description.startsWith(QLatin1String("warning: "))) {
|
||||||
|
task.type = Task::Warning;
|
||||||
|
task.description = description.mid(9);
|
||||||
|
} else if (description.startsWith(QLatin1String("fatal: "))) {
|
||||||
|
task.description = description.mid(7);
|
||||||
|
}
|
||||||
|
emit addTask(task);
|
||||||
|
return;
|
||||||
|
} else if (m_regExpLinker.indexIn(lne) > -1) {
|
||||||
|
bool ok;
|
||||||
|
int lineno = m_regExpLinker.cap(7).toInt(&ok);
|
||||||
|
if (!ok)
|
||||||
|
lineno = -1;
|
||||||
|
Utils::FileName filename = Utils::FileName::fromUserInput(m_regExpLinker.cap(1));
|
||||||
|
const QString sourceFileName = m_regExpLinker.cap(4);
|
||||||
|
if (!sourceFileName.isEmpty()
|
||||||
|
&& !sourceFileName.startsWith(QLatin1String("(.text"))
|
||||||
|
&& !sourceFileName.startsWith(QLatin1String("(.data"))) {
|
||||||
|
filename = Utils::FileName::fromUserInput(sourceFileName);
|
||||||
|
}
|
||||||
|
QString description = m_regExpLinker.cap(8).trimmed();
|
||||||
|
Task task(Task::Error, description, filename, lineno,
|
||||||
|
Constants::TASK_CATEGORY_COMPILE);
|
||||||
|
if (description.startsWith(QLatin1String("At global scope")) ||
|
||||||
|
description.startsWith(QLatin1String("At top level")) ||
|
||||||
|
description.startsWith(QLatin1String("instantiated from ")) ||
|
||||||
|
description.startsWith(QLatin1String("In ")) ||
|
||||||
|
description.startsWith(QLatin1String("first defined here"))) {
|
||||||
|
task.type = Task::Unknown;
|
||||||
|
}
|
||||||
|
if (description.startsWith(QLatin1String("warning: "), Qt::CaseInsensitive)) {
|
||||||
|
task.type = Task::Warning;
|
||||||
|
task.description = description.mid(9);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit addTask(task);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IOutputParser::stdError(line);
|
||||||
|
}
|
54
src/plugins/boostbuildprojectmanager/external/projectexplorer/ldparser.h
vendored
Normal file
54
src/plugins/boostbuildprojectmanager/external/projectexplorer/ldparser.h
vendored
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef LDPARSER_H
|
||||||
|
#define LDPARSER_H
|
||||||
|
|
||||||
|
#include <projectexplorer/ioutputparser.h>
|
||||||
|
|
||||||
|
#include <QRegExp>
|
||||||
|
|
||||||
|
namespace ProjectExplorer {
|
||||||
|
|
||||||
|
class LdParser : public ProjectExplorer::IOutputParser
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
LdParser();
|
||||||
|
void stdError(const QString &line);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QRegExp m_regExpLinker;
|
||||||
|
QRegExp m_regExpGccNames;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ProjectExplorer
|
||||||
|
|
||||||
|
#endif // GCCPARSER_H
|
@@ -0,0 +1,232 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
**
|
||||||
|
** This file, as part of Qt Creator Plugin for Boost.Build,
|
||||||
|
** was modified to accommodate OpenProjectWizard requirements.
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License Version 2.1 by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.txt 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 "filesselectionwizardpage.h"
|
||||||
|
|
||||||
|
#include "b2openprojectwizard.h"
|
||||||
|
#include "b2projectmanagerconstants.h"
|
||||||
|
#include "selectablefilesmodel.h"
|
||||||
|
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
|
#include <utils/pathchooser.h>
|
||||||
|
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QFileInfo>
|
||||||
|
|
||||||
|
namespace BoostBuildProjectManager {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
FilesSelectionWizardPage::FilesSelectionWizardPage(OpenProjectWizardDialog *openProjectWizard, QWidget *parent)
|
||||||
|
: QWizardPage(parent), m_openProjectWizardDialog(openProjectWizard), m_model(0), m_finished(false)
|
||||||
|
{
|
||||||
|
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||||
|
|
||||||
|
createShowFileFilterControls(layout);
|
||||||
|
createHideFileFilterControls(layout);
|
||||||
|
createChooseBaseDirControls(layout);
|
||||||
|
createApplyButton(layout);
|
||||||
|
|
||||||
|
m_view = new QTreeView;
|
||||||
|
m_view->setMinimumSize(500, 400);
|
||||||
|
m_view->setHeaderHidden(true);
|
||||||
|
m_view->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
|
||||||
|
m_label = new QLabel;
|
||||||
|
m_label->setMaximumWidth(500);
|
||||||
|
|
||||||
|
layout->addWidget(m_view);
|
||||||
|
layout->addWidget(m_label);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilesSelectionWizardPage::createHideFileFilterControls(QVBoxLayout *layout)
|
||||||
|
{
|
||||||
|
QHBoxLayout *hbox = new QHBoxLayout;
|
||||||
|
m_hideFilesFilterLabel = new QLabel;
|
||||||
|
m_hideFilesFilterLabel->setText(tr("Hide files matching:"));
|
||||||
|
|
||||||
|
m_hideFilesFilterLabel->hide();
|
||||||
|
hbox->addWidget(m_hideFilesFilterLabel);
|
||||||
|
m_hideFilesfilterLineEdit = new QLineEdit;
|
||||||
|
|
||||||
|
const QString filter = Core::ICore::settings()->value(QLatin1String(Constants::HIDE_FILE_FILTER_SETTING),
|
||||||
|
QLatin1String(Constants::HIDE_FILE_FILTER_DEFAULT)).toString();
|
||||||
|
m_hideFilesfilterLineEdit->setText(filter);
|
||||||
|
m_hideFilesfilterLineEdit->hide();
|
||||||
|
hbox->addWidget(m_hideFilesfilterLineEdit);
|
||||||
|
layout->addLayout(hbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilesSelectionWizardPage::createShowFileFilterControls(QVBoxLayout *layout)
|
||||||
|
{
|
||||||
|
QHBoxLayout *hbox = new QHBoxLayout;
|
||||||
|
m_showFilesFilterLabel = new QLabel;
|
||||||
|
m_showFilesFilterLabel->setText(tr("Show files matching:"));
|
||||||
|
m_showFilesFilterLabel->hide();
|
||||||
|
hbox->addWidget(m_showFilesFilterLabel);
|
||||||
|
m_showFilesfilterLineEdit = new QLineEdit;
|
||||||
|
|
||||||
|
const QString filter = Core::ICore::settings()->value(QLatin1String(Constants::SHOW_FILE_FILTER_SETTING),
|
||||||
|
QLatin1String(Constants::SHOW_FILE_FILTER_DEFAULT)).toString();
|
||||||
|
m_showFilesfilterLineEdit->setText(filter);
|
||||||
|
m_showFilesfilterLineEdit->hide();
|
||||||
|
hbox->addWidget(m_showFilesfilterLineEdit);
|
||||||
|
layout->addLayout(hbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilesSelectionWizardPage::createChooseBaseDirControls(QVBoxLayout *layout)
|
||||||
|
{
|
||||||
|
QHBoxLayout *hbox = new QHBoxLayout;
|
||||||
|
m_baseDirLabel = new QLabel;
|
||||||
|
m_baseDirLabel->setText(tr("Base directory:"));
|
||||||
|
m_baseDirLabel->hide();
|
||||||
|
hbox->addWidget(m_baseDirLabel);
|
||||||
|
|
||||||
|
m_lastBaseDir = m_openProjectWizardDialog->path();
|
||||||
|
m_baseDirChooser = new Utils::PathChooser;
|
||||||
|
m_baseDirChooser->setEnabled(true);
|
||||||
|
m_baseDirChooser->setBaseDirectory(m_lastBaseDir);
|
||||||
|
m_baseDirChooser->setPath(m_lastBaseDir);
|
||||||
|
connect(m_baseDirChooser, SIGNAL(changed(QString)), this, SLOT(baseDirectoryChanged()));
|
||||||
|
hbox->addWidget(m_baseDirChooser);
|
||||||
|
|
||||||
|
layout->addLayout(hbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilesSelectionWizardPage::createApplyButton(QVBoxLayout *layout)
|
||||||
|
{
|
||||||
|
QHBoxLayout *hbox = new QHBoxLayout;
|
||||||
|
|
||||||
|
QSpacerItem *horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||||
|
hbox->addItem(horizontalSpacer);
|
||||||
|
|
||||||
|
m_applyFilterButton = new QPushButton(tr("Apply Filter"), this);
|
||||||
|
m_applyFilterButton->hide();
|
||||||
|
hbox->addWidget(m_applyFilterButton);
|
||||||
|
layout->addLayout(hbox);
|
||||||
|
|
||||||
|
connect(m_applyFilterButton, SIGNAL(clicked()), this, SLOT(applyFilter()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilesSelectionWizardPage::initializePage()
|
||||||
|
{
|
||||||
|
m_view->setModel(0);
|
||||||
|
delete m_model;
|
||||||
|
m_model = new SelectableFilesModel(m_lastBaseDir, this);
|
||||||
|
connect(m_model, SIGNAL(parsingProgress(QString)),
|
||||||
|
this, SLOT(parsingProgress(QString)));
|
||||||
|
connect(m_model, SIGNAL(parsingFinished()),
|
||||||
|
this, SLOT(parsingFinished()));
|
||||||
|
m_model->startParsing();
|
||||||
|
|
||||||
|
m_hideFilesFilterLabel->setVisible(false);
|
||||||
|
m_hideFilesfilterLineEdit->setVisible(false);
|
||||||
|
|
||||||
|
m_showFilesFilterLabel->setVisible(false);
|
||||||
|
m_showFilesfilterLineEdit->setVisible(false);
|
||||||
|
|
||||||
|
m_applyFilterButton->setVisible(false);
|
||||||
|
m_view->setVisible(false);
|
||||||
|
m_label->setVisible(true);
|
||||||
|
m_view->setModel(m_model);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilesSelectionWizardPage::cleanupPage()
|
||||||
|
{
|
||||||
|
m_model->cancel();
|
||||||
|
m_model->waitForFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilesSelectionWizardPage::parsingProgress(const QString &text)
|
||||||
|
{
|
||||||
|
m_label->setText(tr("Generating file list...\n\n%1").arg(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilesSelectionWizardPage::parsingFinished()
|
||||||
|
{
|
||||||
|
m_finished = true;
|
||||||
|
|
||||||
|
m_hideFilesFilterLabel->setVisible(true);
|
||||||
|
m_hideFilesfilterLineEdit->setVisible(true);
|
||||||
|
|
||||||
|
m_showFilesFilterLabel->setVisible(true);
|
||||||
|
m_showFilesfilterLineEdit->setVisible(true);
|
||||||
|
|
||||||
|
m_applyFilterButton->setVisible(true);
|
||||||
|
m_view->setVisible(true);
|
||||||
|
m_label->setVisible(false);
|
||||||
|
m_view->expand(m_view->model()->index(0,0, QModelIndex()));
|
||||||
|
emit completeChanged();
|
||||||
|
applyFilter();
|
||||||
|
// work around qt
|
||||||
|
m_openProjectWizardDialog->setTitleFormat(m_openProjectWizardDialog->titleFormat());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FilesSelectionWizardPage::isComplete() const
|
||||||
|
{
|
||||||
|
return m_finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList FilesSelectionWizardPage::selectedPaths() const
|
||||||
|
{
|
||||||
|
return m_model ? m_model->selectedPaths() : QStringList();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList FilesSelectionWizardPage::selectedFiles() const
|
||||||
|
{
|
||||||
|
return m_model ? m_model->selectedFiles() : QStringList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilesSelectionWizardPage::applyFilter()
|
||||||
|
{
|
||||||
|
const QString showFilesFilter = m_showFilesfilterLineEdit->text();
|
||||||
|
Core::ICore::settings()->setValue(QLatin1String(Constants::SHOW_FILE_FILTER_SETTING), showFilesFilter);
|
||||||
|
|
||||||
|
const QString hideFilesFilter = m_hideFilesfilterLineEdit->text();
|
||||||
|
Core::ICore::settings()->setValue(QLatin1String(Constants::HIDE_FILE_FILTER_SETTING), hideFilesFilter);
|
||||||
|
|
||||||
|
m_model->applyFilter(showFilesFilter, hideFilesFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilesSelectionWizardPage::baseDirectoryChanged()
|
||||||
|
{
|
||||||
|
QString const baseDir(m_baseDirChooser->path());
|
||||||
|
if (baseDir != m_lastBaseDir && QFileInfo(baseDir).isDir())
|
||||||
|
{
|
||||||
|
m_lastBaseDir = baseDir;
|
||||||
|
initializePage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace BoostBuildProjectManager
|
106
src/plugins/boostbuildprojectmanager/filesselectionwizardpage.h
Normal file
106
src/plugins/boostbuildprojectmanager/filesselectionwizardpage.h
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
**
|
||||||
|
** This file, as part of Qt Creator Plugin for Boost.Build,
|
||||||
|
** was modified to accommodate OpenProjectWizard requirements.
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License Version 2.1 by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.txt 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 FILESSELECTIONWIZARDPAGE_HPP
|
||||||
|
#define FILESSELECTIONWIZARDPAGE_HPP
|
||||||
|
|
||||||
|
#include <QWizardPage>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QVBoxLayout;
|
||||||
|
class QLabel;
|
||||||
|
class QTreeView;
|
||||||
|
class QLineEdit;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace Utils {
|
||||||
|
class PathChooser;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace BoostBuildProjectManager {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class OpenProjectWizardDialog;
|
||||||
|
class SelectableFilesModel;
|
||||||
|
|
||||||
|
// TODO: Submit feature request to Qt Creator to make the FileSelectionWizardPage
|
||||||
|
// a reusable component.
|
||||||
|
class FilesSelectionWizardPage : public QWizardPage
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
FilesSelectionWizardPage(OpenProjectWizardDialog *openProjectWizard, QWidget *parent = 0);
|
||||||
|
bool isComplete() const;
|
||||||
|
void initializePage();
|
||||||
|
void cleanupPage();
|
||||||
|
QStringList selectedFiles() const;
|
||||||
|
QStringList selectedPaths() const;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void applyFilter();
|
||||||
|
void parsingProgress(const QString &text);
|
||||||
|
void parsingFinished();
|
||||||
|
void baseDirectoryChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void createHideFileFilterControls(QVBoxLayout *layout);
|
||||||
|
void createShowFileFilterControls(QVBoxLayout *layout);
|
||||||
|
void createChooseBaseDirControls(QVBoxLayout *layout);
|
||||||
|
void createApplyButton(QVBoxLayout *layout);
|
||||||
|
|
||||||
|
OpenProjectWizardDialog *m_openProjectWizardDialog;
|
||||||
|
SelectableFilesModel *m_model;
|
||||||
|
|
||||||
|
QLabel *m_hideFilesFilterLabel;
|
||||||
|
QLineEdit *m_hideFilesfilterLineEdit;
|
||||||
|
|
||||||
|
QLabel *m_showFilesFilterLabel;
|
||||||
|
QLineEdit *m_showFilesfilterLineEdit;
|
||||||
|
|
||||||
|
QPushButton *m_applyFilterButton;
|
||||||
|
|
||||||
|
QLabel* m_baseDirLabel;
|
||||||
|
Utils::PathChooser* m_baseDirChooser;
|
||||||
|
QString m_lastBaseDir;
|
||||||
|
|
||||||
|
QTreeView *m_view;
|
||||||
|
QLabel *m_label;
|
||||||
|
bool m_finished;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace BoostBuildProjectManager
|
||||||
|
|
||||||
|
#endif // FILESSELECTIONWIZARDPAGE_HPP
|
681
src/plugins/boostbuildprojectmanager/selectablefilesmodel.cpp
Normal file
681
src/plugins/boostbuildprojectmanager/selectablefilesmodel.cpp
Normal file
@@ -0,0 +1,681 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
**
|
||||||
|
** This file, as part of Qt Creator Plugin for Boost.Build,
|
||||||
|
** was modified to accommodate OpenProjectWizard requirements.
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License Version 2.1 by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.txt 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 "selectablefilesmodel.h"
|
||||||
|
#include "b2projectmanagerconstants.h"
|
||||||
|
|
||||||
|
#include <coreplugin/fileiconprovider.h>
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
|
|
||||||
|
#include <utils/QtConcurrentTools>
|
||||||
|
|
||||||
|
#include <QDialogButtonBox>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QTreeView>
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
|
namespace BoostBuildProjectManager {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
SelectableFilesModel::SelectableFilesModel(const QString &baseDir, QObject *parent)
|
||||||
|
: QAbstractItemModel(parent), m_root(0), m_baseDir(baseDir), m_allFiles(true)
|
||||||
|
{
|
||||||
|
Q_ASSERT(QFileInfo(m_baseDir).isDir());
|
||||||
|
|
||||||
|
// Dummy tree
|
||||||
|
m_root = new Tree;
|
||||||
|
m_root->name = QLatin1String("/");
|
||||||
|
m_root->parent = 0;
|
||||||
|
m_root->fullPath = m_baseDir;
|
||||||
|
m_root->isDir = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableFilesModel::setInitialMarkedFiles(const QStringList &files)
|
||||||
|
{
|
||||||
|
m_files = files.toSet();
|
||||||
|
m_outOfBaseDirFiles.clear();
|
||||||
|
QString base = m_baseDir + QLatin1Char('/');
|
||||||
|
foreach (const QString &file, m_files)
|
||||||
|
if (!file.startsWith(base))
|
||||||
|
m_outOfBaseDirFiles.append(file);
|
||||||
|
|
||||||
|
m_allFiles = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableFilesModel::init()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableFilesModel::startParsing()
|
||||||
|
{
|
||||||
|
// Build a tree in a future
|
||||||
|
m_rootForFuture = new Tree;
|
||||||
|
m_rootForFuture->name = QLatin1String("/");
|
||||||
|
m_rootForFuture->parent = 0;
|
||||||
|
m_rootForFuture->fullPath = m_baseDir;
|
||||||
|
m_rootForFuture->isDir = true;
|
||||||
|
|
||||||
|
connect(&m_watcher, SIGNAL(finished()), this, SLOT(buildTreeFinished()));
|
||||||
|
m_watcher.setFuture(QtConcurrent::run(&SelectableFilesModel::run, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableFilesModel::run(QFutureInterface<void> &fi)
|
||||||
|
{
|
||||||
|
m_futureCount = 0;
|
||||||
|
buildTree(m_baseDir, m_rootForFuture, fi);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableFilesModel::buildTreeFinished()
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
deleteTree(m_root);
|
||||||
|
m_root = m_rootForFuture;
|
||||||
|
m_rootForFuture = 0;
|
||||||
|
endResetModel();
|
||||||
|
emit parsingFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableFilesModel::waitForFinished()
|
||||||
|
{
|
||||||
|
m_watcher.waitForFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableFilesModel::cancel()
|
||||||
|
{
|
||||||
|
m_watcher.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SelectableFilesModel::filter(Tree *t)
|
||||||
|
{
|
||||||
|
if (t->isDir)
|
||||||
|
return false;
|
||||||
|
if (m_files.contains(t->fullPath))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool showFilterMatch = false;
|
||||||
|
|
||||||
|
//First loop through show file filters and
|
||||||
|
//if any of them match, cotinue checking.
|
||||||
|
foreach (const Glob &g, m_showFilesFilter) {
|
||||||
|
if (g.isMatch(t->name)) {
|
||||||
|
showFilterMatch = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//If none of the "show file" filters match just return
|
||||||
|
if (!showFilterMatch)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
foreach (const Glob &g, m_hideFilesFilter) {
|
||||||
|
if (g.isMatch(t->name))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableFilesModel::buildTree(const QString &baseDir, Tree *tree, QFutureInterface<void> &fi)
|
||||||
|
{
|
||||||
|
const QFileInfoList fileInfoList = QDir(baseDir).entryInfoList(QDir::Files |
|
||||||
|
QDir::Dirs |
|
||||||
|
QDir::NoDotAndDotDot);
|
||||||
|
bool allChecked = true;
|
||||||
|
bool allUnchecked = true;
|
||||||
|
foreach (const QFileInfo &fileInfo, fileInfoList) {
|
||||||
|
if (m_futureCount % 100) {
|
||||||
|
emit parsingProgress(fileInfo.absoluteFilePath());
|
||||||
|
if (fi.isCanceled())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
++m_futureCount;
|
||||||
|
if (fileInfo.isDir()) {
|
||||||
|
if (fileInfo.isSymLink())
|
||||||
|
continue;
|
||||||
|
Tree *t = new Tree;
|
||||||
|
t->parent = tree;
|
||||||
|
t->name = fileInfo.fileName();
|
||||||
|
t->fullPath = fileInfo.filePath();
|
||||||
|
t->isDir = true;
|
||||||
|
buildTree(fileInfo.filePath(), t, fi);
|
||||||
|
allChecked &= t->checked == Qt::Checked;
|
||||||
|
allUnchecked &= t->checked == Qt::Unchecked;
|
||||||
|
tree->childDirectories.append(t);
|
||||||
|
} else {
|
||||||
|
Tree *t = new Tree;
|
||||||
|
t->parent = tree;
|
||||||
|
t->name = fileInfo.fileName();
|
||||||
|
t->checked = m_allFiles || m_files.contains(fileInfo.absoluteFilePath()) ? Qt::Checked : Qt::Unchecked;
|
||||||
|
t->fullPath = fileInfo.filePath();
|
||||||
|
t->isDir = false;
|
||||||
|
allChecked &= t->checked == Qt::Checked;
|
||||||
|
allUnchecked &= t->checked == Qt::Unchecked;
|
||||||
|
tree->files.append(t);
|
||||||
|
if (!filter(t))
|
||||||
|
tree->visibleFiles.append(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tree->childDirectories.isEmpty() && tree->visibleFiles.isEmpty())
|
||||||
|
tree->checked = Qt::Unchecked;
|
||||||
|
else if (allChecked)
|
||||||
|
tree->checked = Qt::Checked;
|
||||||
|
else if (allUnchecked)
|
||||||
|
tree->checked = Qt::Unchecked;
|
||||||
|
else
|
||||||
|
tree->checked = Qt::PartiallyChecked;
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectableFilesModel::~SelectableFilesModel()
|
||||||
|
{
|
||||||
|
deleteTree(m_root);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableFilesModel::deleteTree(Tree *tree)
|
||||||
|
{
|
||||||
|
foreach (Tree *t, tree->childDirectories)
|
||||||
|
deleteTree(t);
|
||||||
|
foreach (Tree *t, tree->files)
|
||||||
|
deleteTree(t);
|
||||||
|
delete tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SelectableFilesModel::columnCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(parent)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SelectableFilesModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
if (!parent.isValid())
|
||||||
|
return 1;
|
||||||
|
Tree *parentT = static_cast<Tree *>(parent.internalPointer());
|
||||||
|
return parentT->childDirectories.size() + parentT->visibleFiles.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex SelectableFilesModel::index(int row, int column, const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
if (!parent.isValid())
|
||||||
|
return createIndex(row, column, m_root);
|
||||||
|
Tree *parentT = static_cast<Tree *>(parent.internalPointer());
|
||||||
|
if (row < parentT->childDirectories.size())
|
||||||
|
return createIndex(row, column, parentT->childDirectories.at(row));
|
||||||
|
else
|
||||||
|
return createIndex(row, column, parentT->visibleFiles.at(row - parentT->childDirectories.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex SelectableFilesModel::parent(const QModelIndex &child) const
|
||||||
|
{
|
||||||
|
if (!child.isValid())
|
||||||
|
return QModelIndex();
|
||||||
|
Tree *parent = static_cast<Tree *>(child.internalPointer())->parent;
|
||||||
|
if (!parent)
|
||||||
|
return QModelIndex();
|
||||||
|
if (!parent->parent) //then the parent is the root
|
||||||
|
return createIndex(0, 0, parent);
|
||||||
|
// figure out where the parent is
|
||||||
|
int pos = parent->parent->childDirectories.indexOf(parent);
|
||||||
|
if (pos == -1)
|
||||||
|
pos = parent->parent->childDirectories.size() + parent->parent->visibleFiles.indexOf(parent);
|
||||||
|
return createIndex(pos, 0, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant SelectableFilesModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return QVariant();
|
||||||
|
Tree *t = static_cast<Tree *>(index.internalPointer());
|
||||||
|
if (role == Qt::DisplayRole)
|
||||||
|
return t->name;
|
||||||
|
if (role == Qt::CheckStateRole)
|
||||||
|
return t->checked;
|
||||||
|
if (role == Qt::DecorationRole) {
|
||||||
|
if (t->icon.isNull())
|
||||||
|
t->icon = Core::FileIconProvider::icon(t->fullPath);
|
||||||
|
return t->icon;
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SelectableFilesModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||||
|
{
|
||||||
|
if (role == Qt::CheckStateRole) {
|
||||||
|
// We can do that!
|
||||||
|
Tree *t = static_cast<Tree *>(index.internalPointer());
|
||||||
|
t->checked = Qt::CheckState(value.toInt());
|
||||||
|
propagateDown(index);
|
||||||
|
propagateUp(index);
|
||||||
|
emit dataChanged(index, index);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableFilesModel::propagateUp(const QModelIndex &index)
|
||||||
|
{
|
||||||
|
QModelIndex parent = index.parent();
|
||||||
|
if (!parent.isValid())
|
||||||
|
return;
|
||||||
|
Tree *parentT = static_cast<Tree *>(parent.internalPointer());
|
||||||
|
if (!parentT)
|
||||||
|
return;
|
||||||
|
bool allChecked = true;
|
||||||
|
bool allUnchecked = true;
|
||||||
|
for (int i = 0; i < parentT->childDirectories.size(); ++i) {
|
||||||
|
allChecked &= parentT->childDirectories.at(i)->checked == Qt::Checked;
|
||||||
|
allUnchecked &= parentT->childDirectories.at(i)->checked == Qt::Unchecked;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < parentT->visibleFiles.size(); ++i) {
|
||||||
|
allChecked &= parentT->visibleFiles.at(i)->checked == Qt::Checked;
|
||||||
|
allUnchecked &= parentT->visibleFiles.at(i)->checked == Qt::Unchecked;
|
||||||
|
}
|
||||||
|
Qt::CheckState newState = Qt::PartiallyChecked;
|
||||||
|
if (parentT->childDirectories.isEmpty() && parentT->visibleFiles.isEmpty())
|
||||||
|
newState = Qt::Unchecked;
|
||||||
|
else if (allChecked)
|
||||||
|
newState = Qt::Checked;
|
||||||
|
else if (allUnchecked)
|
||||||
|
newState = Qt::Unchecked;
|
||||||
|
if (parentT->checked != newState) {
|
||||||
|
parentT->checked = newState;
|
||||||
|
emit dataChanged(parent, parent);
|
||||||
|
propagateUp(parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableFilesModel::propagateDown(const QModelIndex &index)
|
||||||
|
{
|
||||||
|
Tree *t = static_cast<Tree *>(index.internalPointer());
|
||||||
|
for (int i = 0; i<t->childDirectories.size(); ++i) {
|
||||||
|
t->childDirectories[i]->checked = t->checked;
|
||||||
|
propagateDown(index.child(i, 0));
|
||||||
|
}
|
||||||
|
for (int i = 0; i<t->files.size(); ++i)
|
||||||
|
t->files[i]->checked = t->checked;
|
||||||
|
|
||||||
|
int rows = rowCount(index);
|
||||||
|
if (rows)
|
||||||
|
emit dataChanged(index.child(0, 0), index.child(rows-1, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags SelectableFilesModel::flags(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(index);
|
||||||
|
return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList SelectableFilesModel::selectedPaths() const
|
||||||
|
{
|
||||||
|
QStringList result;
|
||||||
|
collectPaths(m_root, &result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableFilesModel::collectPaths(Tree *root, QStringList *result) const
|
||||||
|
{
|
||||||
|
if (root->checked == Qt::Unchecked)
|
||||||
|
return;
|
||||||
|
result->append(root->fullPath);
|
||||||
|
foreach (Tree *t, root->childDirectories)
|
||||||
|
collectPaths(t, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList SelectableFilesModel::selectedFiles() const
|
||||||
|
{
|
||||||
|
QStringList result = m_outOfBaseDirFiles;
|
||||||
|
collectFiles(m_root, &result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList SelectableFilesModel::preservedFiles() const
|
||||||
|
{
|
||||||
|
return m_outOfBaseDirFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableFilesModel::collectFiles(Tree *root, QStringList *result) const
|
||||||
|
{
|
||||||
|
if (root->checked == Qt::Unchecked)
|
||||||
|
return;
|
||||||
|
foreach (Tree *t, root->childDirectories)
|
||||||
|
collectFiles(t, result);
|
||||||
|
foreach (Tree *t, root->visibleFiles)
|
||||||
|
if (t->checked == Qt::Checked)
|
||||||
|
result->append(t->fullPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<Glob> SelectableFilesModel::parseFilter(const QString &filter)
|
||||||
|
{
|
||||||
|
QList<Glob> result;
|
||||||
|
QStringList list = filter.split(QLatin1Char(';'), QString::SkipEmptyParts);
|
||||||
|
foreach (const QString &e, list) {
|
||||||
|
QString entry = e.trimmed();
|
||||||
|
Glob g;
|
||||||
|
if (entry.indexOf(QLatin1Char('*')) == -1 && entry.indexOf(QLatin1Char('?')) == -1) {
|
||||||
|
g.mode = Glob::EXACT;
|
||||||
|
g.matchString = entry;
|
||||||
|
} else if (entry.startsWith(QLatin1Char('*')) && entry.indexOf(QLatin1Char('*'), 1) == -1
|
||||||
|
&& entry.indexOf(QLatin1Char('?'), 1) == -1) {
|
||||||
|
g.mode = Glob::ENDSWITH;
|
||||||
|
g.matchString = entry.mid(1);
|
||||||
|
} else {
|
||||||
|
g.mode = Glob::REGEXP;
|
||||||
|
g.matchRegexp = QRegExp(entry, Qt::CaseInsensitive, QRegExp::Wildcard);
|
||||||
|
}
|
||||||
|
result.append(g);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableFilesModel::applyFilter(const QString &showFilesfilter, const QString &hideFilesfilter)
|
||||||
|
{
|
||||||
|
m_showFilesFilter = parseFilter(showFilesfilter);
|
||||||
|
m_hideFilesFilter = parseFilter(hideFilesfilter);
|
||||||
|
applyFilter(createIndex(0, 0, m_root));
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::CheckState SelectableFilesModel::applyFilter(const QModelIndex &index)
|
||||||
|
{
|
||||||
|
bool allChecked = true;
|
||||||
|
bool allUnchecked = true;
|
||||||
|
Tree *t = static_cast<Tree *>(index.internalPointer());
|
||||||
|
|
||||||
|
for (int i=0; i < t->childDirectories.size(); ++i) {
|
||||||
|
Qt::CheckState childCheckState = applyFilter(index.child(i, 0));
|
||||||
|
if (childCheckState == Qt::Checked)
|
||||||
|
allUnchecked = false;
|
||||||
|
else if (childCheckState == Qt::Unchecked)
|
||||||
|
allChecked = false;
|
||||||
|
else
|
||||||
|
allChecked = allUnchecked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int visibleIndex = 0;
|
||||||
|
int visibleEnd = t->visibleFiles.size();
|
||||||
|
int startOfBlock = 0;
|
||||||
|
|
||||||
|
bool removeBlock = false;
|
||||||
|
// first remove filtered out rows..
|
||||||
|
for (;visibleIndex < visibleEnd; ++visibleIndex) {
|
||||||
|
if (startOfBlock == visibleIndex) {
|
||||||
|
removeBlock = filter(t->visibleFiles.at(visibleIndex));
|
||||||
|
} else if (removeBlock != filter(t->visibleFiles.at(visibleIndex))) {
|
||||||
|
if (removeBlock) {
|
||||||
|
beginRemoveRows(index, startOfBlock, visibleIndex - 1);
|
||||||
|
for (int i=startOfBlock; i < visibleIndex; ++i)
|
||||||
|
t->visibleFiles[i]->checked = Qt::Unchecked;
|
||||||
|
t->visibleFiles.erase(t->visibleFiles.begin() + startOfBlock,
|
||||||
|
t->visibleFiles.begin() + visibleIndex);
|
||||||
|
endRemoveRows();
|
||||||
|
visibleIndex = startOfBlock; // start again at startOfBlock
|
||||||
|
visibleEnd = t->visibleFiles.size();
|
||||||
|
}
|
||||||
|
removeBlock = filter(t->visibleFiles.at(visibleIndex));
|
||||||
|
startOfBlock = visibleIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (removeBlock) {
|
||||||
|
beginRemoveRows(index, startOfBlock, visibleEnd - 1);
|
||||||
|
for (int i=startOfBlock; i < visibleEnd; ++i)
|
||||||
|
t->visibleFiles[i]->checked = Qt::Unchecked;
|
||||||
|
t->visibleFiles.erase(t->visibleFiles.begin() + startOfBlock,
|
||||||
|
t->visibleFiles.begin() + visibleEnd);
|
||||||
|
endRemoveRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Figure out which rows should be visible
|
||||||
|
QList<Tree *> newRows;
|
||||||
|
for (int i=0; i < t->files.size(); ++i)
|
||||||
|
if (!filter(t->files.at(i)))
|
||||||
|
newRows.append(t->files.at(i));
|
||||||
|
// now add them!
|
||||||
|
startOfBlock = 0;
|
||||||
|
visibleIndex = 0;
|
||||||
|
visibleEnd = t->visibleFiles.size();
|
||||||
|
int newIndex = 0;
|
||||||
|
int newEnd = newRows.size();
|
||||||
|
while (true) {
|
||||||
|
while (visibleIndex < visibleEnd && newIndex < newEnd &&
|
||||||
|
t->visibleFiles.at(visibleIndex) == newRows.at(newIndex)) {
|
||||||
|
++newIndex;
|
||||||
|
++visibleIndex;
|
||||||
|
}
|
||||||
|
if (visibleIndex >= visibleEnd || newIndex >= newEnd)
|
||||||
|
break;
|
||||||
|
startOfBlock = newIndex;
|
||||||
|
while (newIndex < newEnd &&
|
||||||
|
t->visibleFiles.at(visibleIndex) != newRows.at(newIndex)) {
|
||||||
|
++newIndex;
|
||||||
|
}
|
||||||
|
// end of block = newIndex
|
||||||
|
beginInsertRows(index, visibleIndex, visibleIndex + newIndex-startOfBlock-1);
|
||||||
|
for (int i= newIndex - 1; i >= startOfBlock; --i)
|
||||||
|
t->visibleFiles.insert(visibleIndex, newRows.at(i));
|
||||||
|
endInsertRows();
|
||||||
|
visibleIndex = visibleIndex + newIndex-startOfBlock;
|
||||||
|
visibleEnd = visibleEnd + newIndex-startOfBlock;
|
||||||
|
if (newIndex >= newEnd)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (newIndex != newEnd) {
|
||||||
|
beginInsertRows(index, visibleIndex, visibleIndex + newEnd-newIndex-1);
|
||||||
|
for (int i=newEnd-1; i >=newIndex; --i)
|
||||||
|
t->visibleFiles.insert(visibleIndex, newRows.at(i));
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=0; i < t->visibleFiles.size(); ++i) {
|
||||||
|
if (t->visibleFiles.at(i)->checked == Qt::Checked)
|
||||||
|
allUnchecked = false;
|
||||||
|
else
|
||||||
|
allChecked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::CheckState newState = Qt::PartiallyChecked;
|
||||||
|
if (t->childDirectories.isEmpty() && t->visibleFiles.isEmpty())
|
||||||
|
newState = Qt::Unchecked;
|
||||||
|
else if (allChecked)
|
||||||
|
newState = Qt::Checked;
|
||||||
|
else if (allUnchecked)
|
||||||
|
newState = Qt::Unchecked;
|
||||||
|
if (t->checked != newState) {
|
||||||
|
t->checked = newState;
|
||||||
|
emit dataChanged(index, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newState;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////
|
||||||
|
// SelectableFilesDialog
|
||||||
|
//////////
|
||||||
|
|
||||||
|
SelectableFilesDialog::SelectableFilesDialog(const QString &path, const QStringList files, QWidget *parent)
|
||||||
|
: QDialog(parent)
|
||||||
|
{
|
||||||
|
QVBoxLayout *layout = new QVBoxLayout();
|
||||||
|
setLayout(layout);
|
||||||
|
setWindowTitle(tr("Edit Files"));
|
||||||
|
|
||||||
|
m_view = new QTreeView(this);
|
||||||
|
|
||||||
|
createShowFileFilterControls(layout);
|
||||||
|
createHideFileFilterControls(layout);
|
||||||
|
createApplyButton(layout);
|
||||||
|
|
||||||
|
m_selectableFilesModel = new SelectableFilesModel(path, this);
|
||||||
|
m_selectableFilesModel->setInitialMarkedFiles(files);
|
||||||
|
m_view->setModel(m_selectableFilesModel);
|
||||||
|
m_view->setMinimumSize(500, 400);
|
||||||
|
m_view->setHeaderHidden(true);
|
||||||
|
m_view->hide();
|
||||||
|
layout->addWidget(m_view);
|
||||||
|
|
||||||
|
m_preservedFiles = new QLabel;
|
||||||
|
m_preservedFiles->hide();
|
||||||
|
layout->addWidget(m_preservedFiles);
|
||||||
|
|
||||||
|
m_progressLabel = new QLabel(this);
|
||||||
|
m_progressLabel->setMaximumWidth(500);
|
||||||
|
layout->addWidget(m_progressLabel);
|
||||||
|
|
||||||
|
QDialogButtonBox *buttonBox = new QDialogButtonBox(Qt::Horizontal, this);
|
||||||
|
buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||||
|
connect(buttonBox, SIGNAL(accepted()),
|
||||||
|
this, SLOT(accept()));
|
||||||
|
connect(buttonBox, SIGNAL(rejected()),
|
||||||
|
this, SLOT(reject()));
|
||||||
|
layout->addWidget(buttonBox);
|
||||||
|
|
||||||
|
connect(m_selectableFilesModel, SIGNAL(parsingProgress(QString)),
|
||||||
|
this, SLOT(parsingProgress(QString)));
|
||||||
|
connect(m_selectableFilesModel, SIGNAL(parsingFinished()),
|
||||||
|
this, SLOT(parsingFinished()));
|
||||||
|
|
||||||
|
m_selectableFilesModel->startParsing();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableFilesDialog::createHideFileFilterControls(QVBoxLayout *layout)
|
||||||
|
{
|
||||||
|
QHBoxLayout *hbox = new QHBoxLayout;
|
||||||
|
m_hideFilesFilterLabel = new QLabel;
|
||||||
|
m_hideFilesFilterLabel->setText(tr("Hide files matching:"));
|
||||||
|
m_hideFilesFilterLabel->hide();
|
||||||
|
hbox->addWidget(m_hideFilesFilterLabel);
|
||||||
|
m_hideFilesfilterLineEdit = new QLineEdit;
|
||||||
|
|
||||||
|
const QString filter = Core::ICore::settings()->value(QLatin1String(Constants::HIDE_FILE_FILTER_SETTING),
|
||||||
|
QLatin1String(Constants::HIDE_FILE_FILTER_DEFAULT)).toString();
|
||||||
|
m_hideFilesfilterLineEdit->setText(filter);
|
||||||
|
m_hideFilesfilterLineEdit->hide();
|
||||||
|
hbox->addWidget(m_hideFilesfilterLineEdit);
|
||||||
|
layout->addLayout(hbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableFilesDialog::createShowFileFilterControls(QVBoxLayout *layout)
|
||||||
|
{
|
||||||
|
QHBoxLayout *hbox = new QHBoxLayout;
|
||||||
|
m_showFilesFilterLabel = new QLabel;
|
||||||
|
m_showFilesFilterLabel->setText(tr("Show files matching:"));
|
||||||
|
m_showFilesFilterLabel->hide();
|
||||||
|
hbox->addWidget(m_showFilesFilterLabel);
|
||||||
|
m_showFilesfilterLineEdit = new QLineEdit;
|
||||||
|
|
||||||
|
const QString filter = Core::ICore::settings()->value(QLatin1String(Constants::SHOW_FILE_FILTER_SETTING),
|
||||||
|
QLatin1String(Constants::SHOW_FILE_FILTER_DEFAULT)).toString();
|
||||||
|
m_showFilesfilterLineEdit->setText(filter);
|
||||||
|
m_showFilesfilterLineEdit->hide();
|
||||||
|
hbox->addWidget(m_showFilesfilterLineEdit);
|
||||||
|
layout->addLayout(hbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableFilesDialog::createApplyButton(QVBoxLayout *layout)
|
||||||
|
{
|
||||||
|
QHBoxLayout *hbox = new QHBoxLayout;
|
||||||
|
|
||||||
|
QSpacerItem *horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||||
|
hbox->addItem(horizontalSpacer);
|
||||||
|
|
||||||
|
m_applyFilterButton = new QPushButton(tr("Apply Filter"), this);
|
||||||
|
m_applyFilterButton->hide();
|
||||||
|
hbox->addWidget(m_applyFilterButton);
|
||||||
|
layout->addLayout(hbox);
|
||||||
|
|
||||||
|
connect(m_applyFilterButton, SIGNAL(clicked()), this, SLOT(applyFilter()));
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectableFilesDialog::~SelectableFilesDialog()
|
||||||
|
{
|
||||||
|
m_selectableFilesModel->cancel();
|
||||||
|
m_selectableFilesModel->waitForFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableFilesDialog::parsingProgress(const QString &fileName)
|
||||||
|
{
|
||||||
|
m_progressLabel->setText(tr("Generating file list...\n\n%1").arg(fileName));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableFilesDialog::parsingFinished()
|
||||||
|
{
|
||||||
|
m_hideFilesFilterLabel->show();
|
||||||
|
m_hideFilesfilterLineEdit->show();
|
||||||
|
|
||||||
|
m_showFilesFilterLabel->show();
|
||||||
|
m_showFilesfilterLineEdit->show();
|
||||||
|
|
||||||
|
m_applyFilterButton->show();
|
||||||
|
m_view->show();
|
||||||
|
m_progressLabel->hide();
|
||||||
|
m_view->expand(QModelIndex());
|
||||||
|
smartExpand(m_selectableFilesModel->index(0,0, QModelIndex()));
|
||||||
|
applyFilter();
|
||||||
|
const QStringList &preservedFiles = m_selectableFilesModel->preservedFiles();
|
||||||
|
if (preservedFiles.isEmpty()) {
|
||||||
|
m_preservedFiles->hide();
|
||||||
|
} else {
|
||||||
|
m_preservedFiles->show();
|
||||||
|
m_preservedFiles->setText(tr("Not showing %n files that are outside of the base directory.\nThese files are preserved.", 0, preservedFiles.count()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableFilesDialog::smartExpand(const QModelIndex &index)
|
||||||
|
{
|
||||||
|
if (m_view->model()->data(index, Qt::CheckStateRole) == Qt::PartiallyChecked) {
|
||||||
|
m_view->expand(index);
|
||||||
|
int rows = m_view->model()->rowCount(index);
|
||||||
|
for (int i = 0; i < rows; ++i)
|
||||||
|
smartExpand(index.child(i, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList SelectableFilesDialog::selectedFiles() const
|
||||||
|
{
|
||||||
|
return m_selectableFilesModel->selectedFiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableFilesDialog::applyFilter()
|
||||||
|
{
|
||||||
|
const QString showFilesFilter = m_showFilesfilterLineEdit->text();
|
||||||
|
Core::ICore::settings()->setValue(QLatin1String(Constants::SHOW_FILE_FILTER_SETTING), showFilesFilter);
|
||||||
|
|
||||||
|
const QString hideFilesFilter = m_hideFilesfilterLineEdit->text();
|
||||||
|
Core::ICore::settings()->setValue(QLatin1String(Constants::HIDE_FILE_FILTER_SETTING), hideFilesFilter);
|
||||||
|
|
||||||
|
m_selectableFilesModel->applyFilter(showFilesFilter, hideFilesFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace BoostBuildProjectManager
|
||||||
|
|
||||||
|
|
189
src/plugins/boostbuildprojectmanager/selectablefilesmodel.h
Normal file
189
src/plugins/boostbuildprojectmanager/selectablefilesmodel.h
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
|
||||||
|
**
|
||||||
|
** This file, as part of Qt Creator Plugin for Boost.Build,
|
||||||
|
** was modified to accommodate OpenProjectWizard requirements.
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License Version 2.1 by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.txt 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 SELECTABLEFILESMODEL_HPP
|
||||||
|
#define SELECTABLEFILESMODEL_HPP
|
||||||
|
|
||||||
|
#include <QAbstractItemModel>
|
||||||
|
#include <QSet>
|
||||||
|
#include <QFutureInterface>
|
||||||
|
#include <QFutureWatcher>
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QTreeView>
|
||||||
|
#include <QLabel>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QVBoxLayout;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace BoostBuildProjectManager {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
struct Tree
|
||||||
|
{
|
||||||
|
QString name;
|
||||||
|
Qt::CheckState checked;
|
||||||
|
bool isDir;
|
||||||
|
QList<Tree *> childDirectories;
|
||||||
|
QList<Tree *> files;
|
||||||
|
QList<Tree *> visibleFiles;
|
||||||
|
QIcon icon;
|
||||||
|
QString fullPath;
|
||||||
|
Tree *parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Glob
|
||||||
|
{
|
||||||
|
enum Mode { EXACT, ENDSWITH, REGEXP };
|
||||||
|
Mode mode;
|
||||||
|
QString matchString;
|
||||||
|
mutable QRegExp matchRegexp;
|
||||||
|
|
||||||
|
bool isMatch(const QString &text) const
|
||||||
|
{
|
||||||
|
if (mode == Glob::EXACT) {
|
||||||
|
if (text == matchString)
|
||||||
|
return true;
|
||||||
|
} else if (mode == Glob::ENDSWITH) {
|
||||||
|
if (text.endsWith(matchString))
|
||||||
|
return true;
|
||||||
|
} else if (mode == Glob::REGEXP) {
|
||||||
|
if (matchRegexp.exactMatch(text))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class SelectableFilesModel : public QAbstractItemModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
SelectableFilesModel(const QString &baseDir, QObject *parent);
|
||||||
|
~SelectableFilesModel();
|
||||||
|
|
||||||
|
void setInitialMarkedFiles(const QStringList &files);
|
||||||
|
|
||||||
|
int columnCount(const QModelIndex &parent) const;
|
||||||
|
int rowCount(const QModelIndex &parent) const;
|
||||||
|
QModelIndex index(int row, int column, const QModelIndex &parent) const;
|
||||||
|
QModelIndex parent(const QModelIndex &child) const;
|
||||||
|
|
||||||
|
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
|
||||||
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||||
|
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||||
|
|
||||||
|
QStringList selectedFiles() const;
|
||||||
|
QStringList selectedPaths() const;
|
||||||
|
QStringList preservedFiles() const;
|
||||||
|
|
||||||
|
// only call this once
|
||||||
|
void startParsing();
|
||||||
|
void waitForFinished();
|
||||||
|
void cancel();
|
||||||
|
void applyFilter(const QString &selectFilesfilter, const QString &hideFilesfilter);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void parsingFinished();
|
||||||
|
void parsingProgress(const QString &filename);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void buildTreeFinished();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<Glob> parseFilter(const QString &filter);
|
||||||
|
Qt::CheckState applyFilter(const QModelIndex &index);
|
||||||
|
bool filter(Tree *t);
|
||||||
|
void init();
|
||||||
|
void run(QFutureInterface<void> &fi);
|
||||||
|
void collectFiles(Tree *root, QStringList *result) const;
|
||||||
|
void collectPaths(Tree *root, QStringList *result) const;
|
||||||
|
void buildTree(const QString &baseDir, Tree *tree, QFutureInterface<void> &fi);
|
||||||
|
void deleteTree(Tree *tree);
|
||||||
|
void propagateUp(const QModelIndex &index);
|
||||||
|
void propagateDown(const QModelIndex &index);
|
||||||
|
Tree *m_root;
|
||||||
|
// Used in the future thread need to all not used after calling startParsing
|
||||||
|
QString m_baseDir;
|
||||||
|
QSet<QString> m_files;
|
||||||
|
QStringList m_outOfBaseDirFiles;
|
||||||
|
QFutureWatcher<void> m_watcher;
|
||||||
|
Tree *m_rootForFuture;
|
||||||
|
int m_futureCount;
|
||||||
|
bool m_allFiles;
|
||||||
|
|
||||||
|
QList<Glob> m_hideFilesFilter;
|
||||||
|
QList<Glob> m_showFilesFilter;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SelectableFilesDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
SelectableFilesDialog(const QString &path, const QStringList files, QWidget *parent);
|
||||||
|
~SelectableFilesDialog();
|
||||||
|
QStringList selectedFiles() const;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void applyFilter();
|
||||||
|
void parsingProgress(const QString &fileName);
|
||||||
|
void parsingFinished();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void smartExpand(const QModelIndex &index);
|
||||||
|
void createShowFileFilterControls(QVBoxLayout *layout);
|
||||||
|
void createHideFileFilterControls(QVBoxLayout *layout);
|
||||||
|
void createApplyButton(QVBoxLayout *layout);
|
||||||
|
SelectableFilesModel *m_selectableFilesModel;
|
||||||
|
|
||||||
|
QLabel *m_hideFilesFilterLabel;
|
||||||
|
QLineEdit *m_hideFilesfilterLineEdit;
|
||||||
|
|
||||||
|
QLabel *m_showFilesFilterLabel;
|
||||||
|
QLineEdit *m_showFilesfilterLineEdit;
|
||||||
|
|
||||||
|
QPushButton *m_applyFilterButton;
|
||||||
|
|
||||||
|
QTreeView *m_view;
|
||||||
|
QLabel *m_preservedFiles;
|
||||||
|
QLabel *m_progressLabel;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace BoostBuildProjectManager
|
||||||
|
|
||||||
|
#endif // SELECTABLEFILESMODEL_HPP
|
||||||
|
|
@@ -29,6 +29,7 @@ SUBDIRS = \
|
|||||||
designer \
|
designer \
|
||||||
resourceeditor \
|
resourceeditor \
|
||||||
genericprojectmanager \
|
genericprojectmanager \
|
||||||
|
boostbuildprojectmanager \
|
||||||
qmljseditor \
|
qmljseditor \
|
||||||
qmlprojectmanager \
|
qmlprojectmanager \
|
||||||
glsleditor \
|
glsleditor \
|
||||||
|
Reference in New Issue
Block a user