/*************************************************************************** ** ** 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; }