summaryrefslogtreecommitdiff
path: root/src/plugins/qt4projectmanager/qt4project.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/qt4projectmanager/qt4project.cpp')
-rw-r--r--src/plugins/qt4projectmanager/qt4project.cpp897
1 files changed, 897 insertions, 0 deletions
diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp
new file mode 100644
index 0000000000..e642c309f7
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt4project.cpp
@@ -0,0 +1,897 @@
+/***************************************************************************
+**
+** 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 "profilecache.h"
+#include "profilereader.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 &)
+{
+ Core::IFile *file = fileFromCache();
+ return file && file->save();
+}
+
+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
+{
+ Core::IFile *file = fileFromCache();
+ return file && fileFromCache()->isModified();
+}
+
+bool Qt4ProjectFile::isReadOnly() const
+{
+ Core::IFile *file = fileFromCache();
+ return file && fileFromCache()->isReadOnly();
+}
+
+bool Qt4ProjectFile::isSaveAsAllowed() const
+{
+ return false;
+}
+
+void Qt4ProjectFile::modified(Core::IFile::ReloadBehavior *)
+{
+}
+
+Core::IFile *Qt4ProjectFile::fileFromCache() const
+{
+ ProFileCache *cache = m_project->qt4ProjectManager()->proFileCache();
+ Core::IFile *fi = cache->fileInterface(fileName());
+ if (!fi && debug)
+ qWarning() << "Could not retrieve IFile interface from ProFileCache";
+ return fi;
+}
+
+/*!
+ /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_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()
+{
+ delete m_projectFiles;
+}
+
+void Qt4Project::defaultQtVersionChanged()
+{
+ if (qtVersionId(activeBuildConfiguration()) == 0)
+ update();
+}
+
+void Qt4Project::qtVersionsChanged()
+{
+ foreach (QString bc, buildConfigurations()) {
+ if (!qt4ProjectManager()->versionManager()->version(qtVersionId(bc))->isValid()) {
+ setQtVersion(bc, 0);
+ if(bc == activeBuildConfiguration())
+ 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);
+ }
+ }
+
+ 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) {
+ // Nothing to update...
+ } else {
+ pinfo->defines = predefinedMacros;
+ // pinfo->defines += definedMacros; // ### FIXME: me
+ pinfo->includePaths = allIncludePaths;
+ pinfo->frameworkPaths = allFrameworkPaths;
+ pinfo->sourceFiles = files;
+
+ modelmanager->GC();
+ 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(m_manager->proFileCache());
+ 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;
+ 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;
+}