-
Roberto Raggi authoredRoberto Raggi authored
qt4project.cpp 29.42 KiB
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.2, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#include "qt4project.h"
#include "qt4projectmanager.h"
#include "profilereader.h"
#include "prowriter.h"
#include "makestep.h"
#include "qmakestep.h"
#include "deployhelper.h"
#include "qt4runconfiguration.h"
#include "qtversionmanager.h"
#include "qt4nodes.h"
#include "qt4buildconfigwidget.h"
#include "qt4buildenvironmentwidget.h"
#include "qt4projectmanagerconstants.h"
#include "projectloadwizard.h"
#include "gdbmacrosbuildstep.h"
#include <coreplugin/messagemanager.h>
#include <coreplugin/coreconstants.h>
#include <cpptools/cppmodelmanagerinterface.h>
#include <projectexplorer/nodesvisitor.h>
#include <projectexplorer/project.h>
#include <projectexplorer/customexecutablerunconfiguration.h>
#include <QtGui/QFileDialog>
#include <QtCore/QDir>
#include <QtCore/QDebug>
using namespace Qt4ProjectManager;
using namespace Qt4ProjectManager::Internal;
using namespace ProjectExplorer;
using Core::VariableManager;
enum { debug = 0 };
namespace Qt4ProjectManager {
namespace Internal {
// Qt4ProjectFiles: Struct for (Cached) lists of files in a project
struct Qt4ProjectFiles {
void clear();
bool equals(const Qt4ProjectFiles &f) const;
QStringList files[ProjectExplorer::FileTypeSize];
QStringList generatedFiles[ProjectExplorer::FileTypeSize];
QStringList proFiles;
};
void Qt4ProjectFiles::clear()
{
for (int i = 0; i < FileTypeSize; ++i) {
files[i].clear();
generatedFiles[i].clear();
}
proFiles.clear();
}
bool Qt4ProjectFiles::equals(const Qt4ProjectFiles &f) const
{
for (int i = 0; i < FileTypeSize; ++i)
if (files[i] != f.files[i] || generatedFiles[i] != f.generatedFiles[i])
return false;
if (proFiles != f.proFiles)
return false;
return true;
}
inline bool operator==(const Qt4ProjectFiles &f1, const Qt4ProjectFiles &f2)
{ return f1.equals(f2); }
inline bool operator!=(const Qt4ProjectFiles &f1, const Qt4ProjectFiles &f2)
{ return !f1.equals(f2); }
QDebug operator<<(QDebug d, const Qt4ProjectFiles &f)
{
QDebug nsp = d.nospace();
nsp << "Qt4ProjectFiles: proFiles=" << f.proFiles << '\n';
for (int i = 0; i < FileTypeSize; ++i)
nsp << "Type " << i << " files=" << f.files[i] << " generated=" << f.generatedFiles[i] << '\n';
return d;
}
// A visitor to collect all files of a project in a Qt4ProjectFiles struct
class ProjectFilesVisitor : public ProjectExplorer::NodesVisitor
{
Q_DISABLE_COPY(ProjectFilesVisitor)
ProjectFilesVisitor(Qt4ProjectFiles *files);
public:
static void findProjectFiles(Qt4ProFileNode *rootNode, Qt4ProjectFiles *files);
void visitProjectNode(ProjectNode *projectNode);
void visitFolderNode(FolderNode *folderNode);
private:
Qt4ProjectFiles *m_files;
};
ProjectFilesVisitor::ProjectFilesVisitor(Qt4ProjectFiles *files) :
m_files(files)
{
}
void ProjectFilesVisitor::findProjectFiles(Qt4ProFileNode *rootNode, Qt4ProjectFiles *files)
{
files->clear();
ProjectFilesVisitor visitor(files);
rootNode->accept(&visitor);
for (int i = 0; i < FileTypeSize; ++i) {
qSort(files->files[i]);
qSort(files->generatedFiles[i]);
}
qSort(files->proFiles);
}
void ProjectFilesVisitor::visitProjectNode(ProjectNode *projectNode)
{
const QString path = projectNode->path();
if (!m_files->proFiles.contains(path))
m_files->proFiles.append(path);
visitFolderNode(projectNode);
}
void ProjectFilesVisitor::visitFolderNode(FolderNode *folderNode)
{
foreach (FileNode *fileNode, folderNode->fileNodes()) {
const QString path = fileNode->path();
const int type = fileNode->fileType();
QStringList &targetList = fileNode->isGenerated() ? m_files->generatedFiles[type] : m_files->files[type];
if (!targetList.contains(path))
targetList.push_back(path);
}
}
}
}
// ----------- Qt4ProjectFile
Qt4ProjectFile::Qt4ProjectFile(Qt4Project *project, const QString &filePath, QObject *parent)
: Core::IFile(parent),
m_mimeType(QLatin1String(Qt4ProjectManager::Constants::PROFILE_MIMETYPE)),
m_project(project),
m_filePath(filePath)
{
}
bool Qt4ProjectFile::save(const QString &)
{
// This is never used
return false;
}
QString Qt4ProjectFile::fileName() const
{
return m_filePath;
}
QString Qt4ProjectFile::defaultPath() const
{
return QString();
}
QString Qt4ProjectFile::suggestedFileName() const
{
return QString();
}
QString Qt4ProjectFile::mimeType() const
{
return m_mimeType;
}
bool Qt4ProjectFile::isModified() const
{
return false; // we save after changing anyway
}
bool Qt4ProjectFile::isReadOnly() const
{
QFileInfo fi(m_filePath);
return !fi.isWritable();
}
bool Qt4ProjectFile::isSaveAsAllowed() const
{
return false;
}
void Qt4ProjectFile::modified(Core::IFile::ReloadBehavior *)
{
}
/*!
/class Qt4Project
Qt4Project manages information about an individual Qt 4 (.pro) project file.
*/
Qt4Project::Qt4Project(Qt4Manager *manager, const QString& fileName) :
m_manager(manager),
m_rootProjectNode(new Qt4ProFileNode(this, fileName, this)),
m_nodesWatcher(new Internal::Qt4NodesWatcher(this)),
m_fileInfo(new Qt4ProjectFile(this, fileName, this)),
m_isApplication(true),
m_projectFiles(new Qt4ProjectFiles)
{
m_manager->registerProject(this);
m_rootProjectNode->registerWatcher(m_nodesWatcher);
connect(m_nodesWatcher, SIGNAL(foldersAdded()), this, SLOT(updateFileList()));
connect(m_nodesWatcher, SIGNAL(foldersRemoved()), this, SLOT(updateFileList()));
connect(m_nodesWatcher, SIGNAL(filesAdded()), this, SLOT(updateFileList()));
connect(m_nodesWatcher, SIGNAL(filesRemoved()), this, SLOT(updateFileList()));
connect(m_nodesWatcher, SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *)),
this, SLOT(scheduleUpdateCodeModel()));
connect(qt4ProjectManager()->versionManager(), SIGNAL(defaultQtVersionChanged()),
this, SLOT(defaultQtVersionChanged()));
connect(qt4ProjectManager()->versionManager(), SIGNAL(qtVersionsChanged()),
this, SLOT(qtVersionsChanged()));
m_updateCodeModelTimer.setSingleShot(true);
m_updateCodeModelTimer.setInterval(20);
connect(&m_updateCodeModelTimer, SIGNAL(timeout()), this, SLOT(updateCodeModel()));
}
Qt4Project::~Qt4Project()
{
m_manager->unregisterProject(this);
delete m_projectFiles;
}
void Qt4Project::defaultQtVersionChanged()
{
if (qtVersionId(activeBuildConfiguration()) == 0)
m_rootProjectNode->update();
}
void Qt4Project::qtVersionsChanged()
{
foreach (QString bc, buildConfigurations()) {
if (!qt4ProjectManager()->versionManager()->version(qtVersionId(bc))->isValid()) {
setQtVersion(bc, 0);
if (bc == activeBuildConfiguration())
m_rootProjectNode->update();
}
}
}
void Qt4Project::updateFileList()
{
Qt4ProjectFiles newFiles;
ProjectFilesVisitor::findProjectFiles(m_rootProjectNode, &newFiles);
if (newFiles != *m_projectFiles) {
*m_projectFiles = newFiles;
emit fileListChanged();
if (debug)
qDebug() << Q_FUNC_INFO << *m_projectFiles;
}
}
void Qt4Project::restoreSettingsImpl(PersistentSettingsReader &settingsReader)
{
Project::restoreSettingsImpl(settingsReader);
addDefaultBuild();
// Ensure that the qt version in each build configuration is valid
// or if not, is reset to the default
foreach (const QString &bc, buildConfigurations())
qtVersionId(bc);
update();
// restored old runconfigurations
if (runConfigurations().isEmpty()) {
// Oha no runConfigurations, add some
QList<Qt4ProFileNode *> list;
collectApplicationProFiles(list, m_rootProjectNode);
if (!list.isEmpty()) {
foreach (Qt4ProFileNode *node, list) {
QSharedPointer<RunConfiguration> rc(new Qt4RunConfiguration(this, node->path()));
addRunConfiguration(rc);
}
setActiveRunConfiguration(runConfigurations().first());
} else {
QSharedPointer<RunConfiguration> rc(new ProjectExplorer::CustomExecutableRunConfiguration(this));
addRunConfiguration(rc);
setActiveRunConfiguration(rc);
m_isApplication = false;
}
}
// Now connect
connect(m_nodesWatcher, SIGNAL(foldersAboutToBeAdded(FolderNode *, const QList<FolderNode*> &)),
this, SLOT(foldersAboutToBeAdded(FolderNode *, const QList<FolderNode*> &)));
connect(m_nodesWatcher, SIGNAL(foldersAdded()), this, SLOT(checkForNewApplicationProjects()));
connect(m_nodesWatcher, SIGNAL(foldersRemoved()), this, SLOT(checkForDeletedApplicationProjects()));
connect(m_nodesWatcher, SIGNAL(projectTypeChanged(Qt4ProjectManager::Internal::Qt4ProFileNode *,
const Qt4ProjectManager::Internal::Qt4ProjectType,
const Qt4ProjectManager::Internal::Qt4ProjectType)),
this, SLOT(projectTypeChanged(Qt4ProjectManager::Internal::Qt4ProFileNode *,
const Qt4ProjectManager::Internal::Qt4ProjectType,
const Qt4ProjectManager::Internal::Qt4ProjectType)));
connect(m_nodesWatcher, SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *)),
this, SLOT(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *)));
}
void Qt4Project::saveSettingsImpl(ProjectExplorer::PersistentSettingsWriter &writer)
{
Project::saveSettingsImpl(writer);
}
namespace {
class FindQt4ProFiles: protected ProjectExplorer::NodesVisitor {
QList<Qt4ProFileNode *> m_proFiles;
public:
QList<Qt4ProFileNode *> operator()(ProjectNode *root)
{
m_proFiles.clear();
root->accept(this);
return m_proFiles;
}
protected:
virtual void visitProjectNode(ProjectNode *projectNode)
{
if (Qt4ProFileNode *pro = qobject_cast<Qt4ProFileNode *>(projectNode))
m_proFiles.append(pro);
}
};
}
void Qt4Project::scheduleUpdateCodeModel()
{
m_updateCodeModelTimer.start();
}
void Qt4Project::updateCodeModel()
{
if (debug)
qDebug()<<"Qt4Project::updateCodeModel()";
CppTools::CppModelManagerInterface *modelmanager =
m_manager->pluginManager()->getObject<CppTools::CppModelManagerInterface>();
if (! modelmanager)
return;
QStringList allIncludePaths;
QStringList allFrameworkPaths;
const QHash<QString, QString> versionInfo = qtVersion(activeBuildConfiguration())->versionInfo();
const QString newQtIncludePath = versionInfo.value(QLatin1String("QT_INSTALL_HEADERS"));
const QString newQtLibsPath = versionInfo.value(QLatin1String("QT_INSTALL_LIBS"));
QByteArray predefinedMacros;
QtVersion::ToolchainType t = qtVersion(activeBuildConfiguration())->toolchainType();
if (t == QtVersion::MinGW || t == QtVersion::OTHER) {
QStringList list = rootProjectNode()->variableValue(Internal::CxxCompilerVar);
QString qmake_cxx = list.isEmpty() ? QString::null : list.first();
qmake_cxx = environment(activeBuildConfiguration()).searchInPath(qmake_cxx);
m_preproc.setGcc(qmake_cxx);
predefinedMacros = m_preproc.predefinedMacros();
foreach (HeaderPath headerPath, m_preproc.systemHeaderPaths()) {
if (headerPath.kind() == HeaderPath::FrameworkHeaderPath)
allFrameworkPaths.append(headerPath.path());
else
allIncludePaths.append(headerPath.path());
}
} else if (t == QtVersion::MSVC || t == QtVersion::WINCE) {
#ifdef QTCREATOR_WITH_MSVC_INCLUDES
Environment env = environment(activeBuildConfiguration());
allIncludePaths.append(env.value("INCLUDE").split(QLatin1Char(';')));
#endif
predefinedMacros +=
"#define __WIN32__\n"
"#define __WIN32\n"
"#define _WIN32\n"
"#define WIN32\n"
"#define __WINNT__\n"
"#define __WINNT\n"
"#define WINNT\n"
"#define _X86_\n"
"#define __MSVCRT__\n";
}
allIncludePaths.append(newQtIncludePath);
QDir dir(newQtIncludePath);
foreach (QFileInfo info, dir.entryInfoList(QDir::Dirs)) {
if (! info.fileName().startsWith(QLatin1String("Qt")))
continue;
allIncludePaths.append(info.absoluteFilePath());
}
#ifdef Q_OS_MAC
allFrameworkPaths.append(newQtLibsPath);
// put QtXXX.framework/Headers directories in include path since that qmake's behavior
QDir frameworkDir(newQtLibsPath);
foreach (QFileInfo info, frameworkDir.entryInfoList(QDir::Dirs)) {
if (! info.fileName().startsWith(QLatin1String("Qt")))
continue;
allIncludePaths.append(info.absoluteFilePath()+"/Headers");
}
#endif
FindQt4ProFiles findQt4ProFiles;
QList<Qt4ProFileNode *> proFiles = findQt4ProFiles(rootProjectNode());
QByteArray definedMacros;
foreach (Qt4ProFileNode *pro, proFiles) {
foreach (const QString def, pro->variableValue(DefinesVar)) {
definedMacros += "#define ";
const int index = def.indexOf(QLatin1Char('='));
if (index == -1) {
definedMacros += def.toLatin1();
definedMacros += " 1\n";
} else {
const QString name = def.left(index);
const QString value = def.mid(index + 1);
definedMacros += name.toLatin1();
definedMacros += ' ';
definedMacros += value.toLocal8Bit();
definedMacros += '\n';
}
}
const QStringList proIncludePaths = pro->variableValue(IncludePathVar);
foreach (QString includePath, proIncludePaths) {
if (allIncludePaths.contains(includePath))
continue;
allIncludePaths.append(includePath);
}
}
// Add mkspec directory
allIncludePaths.append(qtVersion(activeBuildConfiguration())->mkspecPath());
QStringList files;
files += m_projectFiles->files[HeaderType];
files += m_projectFiles->generatedFiles[HeaderType];
files += m_projectFiles->files[SourceType];
files += m_projectFiles->generatedFiles[SourceType];
CppTools::CppModelManagerInterface::ProjectInfo pinfo = modelmanager->projectInfo(this);
if (pinfo.defines == predefinedMacros &&
pinfo.includePaths == allIncludePaths &&
pinfo.frameworkPaths == allFrameworkPaths &&
pinfo.sourceFiles == files) {
modelmanager->updateProjectInfo(pinfo);
} else {
pinfo.defines = predefinedMacros;
// pinfo->defines += definedMacros; // ### FIXME: me
pinfo.includePaths = allIncludePaths;
pinfo.frameworkPaths = allFrameworkPaths;
pinfo.sourceFiles = files;
modelmanager->updateProjectInfo(pinfo);
modelmanager->updateSourceFiles(pinfo.sourceFiles);
}
}
///*!
// Updates complete project
// */
void Qt4Project::update()
{
// TODO Maybe remove this method completely?
m_rootProjectNode->update();
//updateCodeModel();
}
ProFileReader *Qt4Project::createProFileReader() const
{
ProFileReader *reader = new ProFileReader();
connect(reader, SIGNAL(errorFound(const QString&)),
this, SLOT(proFileParseError(const QString&)));
QtVersion *version = qtVersion(activeBuildConfiguration());
if (version->isValid()) {
reader->setQtVersion(version);
}
return reader;
}
/*!
Returns whether the project is an application, or has an application as a subproject.
*/
bool Qt4Project::isApplication() const
{
return m_isApplication;
}
ProjectExplorer::ProjectExplorerPlugin *Qt4Project::projectExplorer() const
{
return m_manager->projectExplorer();
}
ProjectExplorer::IProjectManager *Qt4Project::projectManager() const
{
return m_manager;
}
Qt4Manager *Qt4Project::qt4ProjectManager() const
{
return m_manager;
}
QString Qt4Project::name() const
{
return QFileInfo(file()->fileName()).completeBaseName();
}
Core::IFile *Qt4Project::file() const
{
return m_fileInfo;
}
QStringList Qt4Project::files(FilesMode fileMode) const
{
QStringList files;
for (int i = 0; i < FileTypeSize; ++i) {
files += m_projectFiles->files[i];
if (fileMode == AllFiles)
files += m_projectFiles->generatedFiles[i];
}
files += m_projectFiles->proFiles;
return files;
}
QList<Core::IFile *> Qt4Project::dependencies()
{
QList<Core::IFile *> result;
// TODO profile cache is no longer
// ProFileCache *cache = m_manager->proFileCache();
// foreach (const QString &file, cache->dependencies(m_rootProjectNode)) {
// result << cache->fileInterface(file);
// }
return result;
}
QList<ProjectExplorer::Project*> Qt4Project::dependsOn()
{
// NBS implement dependsOn
return QList<Project *>();
}
void Qt4Project::addDefaultBuild()
{
if (buildConfigurations().isEmpty()) {
// We don't have any buildconfigurations, so this is a new project
// The Project Load Wizard is a work of art
// It will ask the user what kind of build setup he want
// It will add missing Qt Versions
// And get the project into a buildable state
//TODO have a better check wheter there is already a configuration?
QMakeStep *qmakeStep = 0;
MakeStep *makeStep = 0;
GdbMacrosBuildStep *gdbmacrostep;
gdbmacrostep = new GdbMacrosBuildStep(this);
insertBuildStep(0, gdbmacrostep);
qmakeStep = new QMakeStep(this);
qmakeStep->setValue("mkspec", "");
insertBuildStep(1, qmakeStep);
makeStep = new MakeStep(this);
insertBuildStep(2, makeStep);
MakeStep* cleanStep = new MakeStep(this);
cleanStep->setValue("clean", true);
insertCleanStep(0, cleanStep);
ProjectLoadWizard wizard(this);
wizard.execDialog();
} else {
// Restoring configuration
// Do we already have a gdbmacrobuildstep?
// If not add it and disable linking of debugging helper
// TODO
}
}
void Qt4Project::newBuildConfiguration(const QString &buildConfiguration)
{
Q_UNUSED(buildConfiguration);
}
void Qt4Project::proFileParseError(const QString &errorMessage)
{
m_manager->core()->messageManager()->printToOutputPane(errorMessage);
}
Qt4ProFileNode *Qt4Project::rootProjectNode() const
{
return m_rootProjectNode;
}
ProjectExplorer::Environment Qt4Project::baseEnvironment(const QString &buildConfiguration) const
{
Environment env = useSystemEnvironment(buildConfiguration) ? Environment(QProcess::systemEnvironment()) : Environment();
env = qtVersion(buildConfiguration)->addToEnvironment(env);
return env;
}
ProjectExplorer::Environment Qt4Project::environment(const QString &buildConfiguration) const
{
Environment env = baseEnvironment(buildConfiguration);
env.modify(userEnvironmentChanges(buildConfiguration));
return env;
}
QString Qt4Project::buildDirectory(const QString &buildConfiguration) const
{
QString workingDirectory;
if (value(buildConfiguration, "useShadowBuild").toBool())
workingDirectory = value(buildConfiguration, "buildDirectory").toString();
if (workingDirectory.isEmpty())
workingDirectory = QFileInfo(file()->fileName()).absolutePath();
return workingDirectory;
}
void Qt4Project::setUseSystemEnvironment(const QString &buildConfiguration, bool b)
{
setValue(buildConfiguration, "clearSystemEnvironment", !b);
}
bool Qt4Project::useSystemEnvironment(const QString &buildConfiguration) const
{
bool b = !(value(buildConfiguration, "clearSystemEnvironment").isValid() && value(buildConfiguration, "clearSystemEnvironment").toBool());
return b;
}
QString Qt4Project::qtDir(const QString &buildConfiguration) const
{
QtVersion *version = qtVersion(buildConfiguration);
if (version)
return version->path();
return QString::null;
}
QtVersion *Qt4Project::qtVersion(const QString &buildConfiguration) const
{
return m_manager->versionManager()->version(qtVersionId(buildConfiguration));
}
int Qt4Project::qtVersionId(const QString &buildConfiguration) const
{
if (debug)
qDebug()<<"Looking for qtVersion ID of "<<buildConfiguration;
int id = 0;
QVariant vid = value(buildConfiguration, "QtVersionId");
if (vid.isValid()) {
id = vid.toInt();
if (m_manager->versionManager()->version(id)->isValid()) {
return id;
} else {
const_cast<Qt4Project *>(this)->setValue(buildConfiguration, "QtVersionId", 0);
return 0;
}
} else {
// Backward compatibilty, we might have just the name:
QString vname = value(buildConfiguration, "QtVersion").toString();
if (debug)
qDebug()<<" Backward compatibility reading QtVersion"<<vname;
if (!vname.isEmpty()) {
const QList<QtVersion *> &versions = m_manager->versionManager()->versions();
foreach (const QtVersion * const version, versions) {
if (version->name() == vname) {
if (debug)
qDebug()<<"found name in versions";
const_cast<Qt4Project *>(this)->setValue(buildConfiguration, "QtVersionId", version->uniqueId());
return version->uniqueId();
}
}
}
}
if (debug)
qDebug()<<" using qtversion with id ="<<id;
// Nothing found, reset to default
const_cast<Qt4Project *>(this)->setValue(buildConfiguration, "QtVersionId", id);
return id;
}
void Qt4Project::setQtVersion(const QString &buildConfiguration, int id)
{
setValue(buildConfiguration, "QtVersionId", id);
}
BuildStepConfigWidget *Qt4Project::createConfigWidget()
{
return new Qt4BuildConfigWidget(this);
}
QList<BuildStepConfigWidget*> Qt4Project::subConfigWidgets()
{
QList<BuildStepConfigWidget*> subWidgets;
subWidgets << new Qt4BuildEnvironmentWidget(this);
return subWidgets;
}
QList<ProjectExplorer::EnvironmentItem> Qt4Project::userEnvironmentChanges(const QString &buildConfig) const
{
return EnvironmentItem::fromStringList(value(buildConfig, "userEnvironmentChanges").toStringList());
}
void Qt4Project::setUserEnvironmentChanges(const QString &buildConfig, const QList<ProjectExplorer::EnvironmentItem> &diff)
{
setValue(buildConfig, "userEnvironmentChanges", EnvironmentItem::toStringList(diff));
}
/// **************************
/// Qt4ProjectBuildConfigWidget
/// **************************
void Qt4Project::collectApplicationProFiles(QList<Qt4ProFileNode *> &list, Qt4ProFileNode *node)
{
if (node->projectType() == Internal::ApplicationTemplate
|| node->projectType() == Internal::ScriptTemplate) {
list.append(node);
}
foreach (ProjectNode *n, node->subProjectNodes()) {
Qt4ProFileNode *qt4ProFileNode = qobject_cast<Qt4ProFileNode *>(n);
if (qt4ProFileNode)
collectApplicationProFiles(list, qt4ProFileNode);
}
}
void Qt4Project::foldersAboutToBeAdded(FolderNode *, const QList<FolderNode*> &nodes)
{
QList<Qt4ProFileNode *> list;
foreach (FolderNode *node, nodes) {
Qt4ProFileNode *qt4ProFileNode = qobject_cast<Qt4ProFileNode *>(node);
if (qt4ProFileNode)
collectApplicationProFiles(list, qt4ProFileNode);
}
m_applicationProFileChange = list;
}
void Qt4Project::checkForNewApplicationProjects()
{
// Check all new project nodes
// against all runConfigurations
foreach (Qt4ProFileNode *qt4proFile, m_applicationProFileChange) {
bool found = false;
foreach (QSharedPointer<RunConfiguration> rc, runConfigurations()) {
QSharedPointer<Qt4RunConfiguration> qtrc = rc.dynamicCast<Qt4RunConfiguration>();
if (qtrc && qtrc->proFilePath() == qt4proFile->path()) {
found = true;
break;
}
}
if (!found) {
QSharedPointer<Qt4RunConfiguration> newRc(new Qt4RunConfiguration(this, qt4proFile->path()));
addRunConfiguration(newRc);
m_isApplication = true;
}
}
}
void Qt4Project::checkForDeletedApplicationProjects()
{
QStringList paths;
foreach (Qt4ProFileNode * node, applicationProFiles())
paths.append(node->path());
qDebug()<<"Still existing paths :"<<paths;
QList<QSharedPointer<Qt4RunConfiguration> > removeList;
foreach (QSharedPointer<RunConfiguration> rc, runConfigurations()) {
if (QSharedPointer<Qt4RunConfiguration> qt4rc = rc.dynamicCast<Qt4RunConfiguration>()) {
if (!paths.contains(qt4rc->proFilePath())) {
removeList.append(qt4rc);
qDebug()<<"Removing runConfiguration for "<<qt4rc->proFilePath();
}
}
}
bool resetActiveRunConfiguration = false;
QSharedPointer<RunConfiguration> rc(new ProjectExplorer::CustomExecutableRunConfiguration(this));
foreach (QSharedPointer<Qt4RunConfiguration> qt4rc, removeList) {
removeRunConfiguration(qt4rc);
if (activeRunConfiguration() == qt4rc)
resetActiveRunConfiguration = true;
}
if (runConfigurations().isEmpty()) {
QSharedPointer<RunConfiguration> rc(new ProjectExplorer::CustomExecutableRunConfiguration(this));
addRunConfiguration(rc);
setActiveRunConfiguration(rc);
m_isApplication = false;
} else if (resetActiveRunConfiguration) {
setActiveRunConfiguration(runConfigurations().first());
}
}
QList<Qt4ProFileNode *> Qt4Project::applicationProFiles() const
{
QList<Qt4ProFileNode *> list;
collectApplicationProFiles(list, rootProjectNode());
return list;
}
void Qt4Project::projectTypeChanged(Qt4ProFileNode *node, const Qt4ProjectType oldType, const Qt4ProjectType newType)
{
if (oldType == Internal::ApplicationTemplate
|| oldType == Internal::ScriptTemplate) {
// check wheter we need to delete a Run Configuration
checkForDeletedApplicationProjects();
}
if (newType == Internal::ApplicationTemplate
|| newType == Internal::ScriptTemplate) {
// add a new Run Configuration
m_applicationProFileChange.clear();
m_applicationProFileChange.append(node);
checkForNewApplicationProjects();
}
}
void Qt4Project::proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *node)
{
foreach (QSharedPointer<RunConfiguration> rc, runConfigurations()) {
if (QSharedPointer<Qt4RunConfiguration> qt4rc = rc.dynamicCast<Qt4RunConfiguration>()) {
if (qt4rc->proFilePath() == node->path()) {
qt4rc->updateCachedValues();
}
}
}
}
QMakeStep *Qt4Project::qmakeStep() const
{
QMakeStep *qs = 0;
foreach(BuildStep *bs, buildSteps())
if ( (qs = qobject_cast<QMakeStep *>(bs)) != 0)
return qs;
return 0;
}
MakeStep *Qt4Project::makeStep() const
{
MakeStep *qs = 0;
foreach(BuildStep *bs, buildSteps())
if ((qs = qobject_cast<MakeStep *>(bs)) != 0)
return qs;
return 0;
}
bool Qt4Project::hasSubNode(Qt4PriFileNode *root, const QString &path)
{
if (root->path() == path)
return true;
foreach (FolderNode *fn, root->subFolderNodes()) {
if (qobject_cast<Qt4ProFileNode *>(fn)) {
// we aren't interested in pro file nodes
} else if (Qt4PriFileNode *qt4prifilenode = qobject_cast<Qt4PriFileNode *>(fn)) {
if (hasSubNode(qt4prifilenode, path))
return true;
}
}
return false;
}
void Qt4Project::findProFile(const QString& fileName, Qt4ProFileNode *root, QList<Qt4ProFileNode *> &list)
{
if (hasSubNode(root, fileName))
list.append(root);
foreach (FolderNode *fn, root->subFolderNodes())
if (Qt4ProFileNode *qt4proFileNode = qobject_cast<Qt4ProFileNode *>(fn))
findProFile(fileName, qt4proFileNode, list);
}
void Qt4Project::notifyChanged(const QString &name)
{
if (files(Qt4Project::ExcludeGeneratedFiles).contains(name)) {
QList<Qt4ProFileNode *> list;
findProFile(name, rootProjectNode(), list);
foreach(Qt4ProFileNode *node, list)
node->update();
}
}