Fixes: fakevim: rough Ctrl-O/Ctrl-I implementation
[qt-creator-color-themes.git] / src / plugins / qt4projectmanager / qt4project.cpp
blob9885221c0c4e2fdc45519d7d12bf72a424caa9e2
1 /***************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Qt Software Information (qt-info@nokia.com)
8 **
9 **
10 ** Non-Open Source Usage
12 ** Licensees may use this file in accordance with the Qt Beta Version
13 ** License Agreement, Agreement version 2.2 provided with the Software or,
14 ** alternatively, in accordance with the terms contained in a written
15 ** agreement between you and Nokia.
17 ** GNU General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU General
20 ** Public License versions 2.0 or 3.0 as published by the Free Software
21 ** Foundation and appearing in the file LICENSE.GPL included in the packaging
22 ** of this file. Please review the following information to ensure GNU
23 ** General Public Licensing requirements will be met:
25 ** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
26 ** http://www.gnu.org/copyleft/gpl.html.
28 ** In addition, as a special exception, Nokia gives you certain additional
29 ** rights. These rights are described in the Nokia Qt GPL Exception
30 ** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
32 ***************************************************************************/
34 #include "qt4project.h"
36 #include "qt4projectmanager.h"
37 #include "profilereader.h"
38 #include "prowriter.h"
39 #include "makestep.h"
40 #include "qmakestep.h"
41 #include "deployhelper.h"
42 #include "qt4runconfiguration.h"
43 #include "qtversionmanager.h"
44 #include "qt4nodes.h"
45 #include "qt4buildconfigwidget.h"
46 #include "qt4buildenvironmentwidget.h"
47 #include "qt4projectmanagerconstants.h"
48 #include "projectloadwizard.h"
49 #include "gdbmacrosbuildstep.h"
51 #include <coreplugin/icore.h>
52 #include <coreplugin/messagemanager.h>
53 #include <coreplugin/coreconstants.h>
54 #include <cpptools/cppmodelmanagerinterface.h>
55 #include <extensionsystem/pluginmanager.h>
56 #include <projectexplorer/nodesvisitor.h>
57 #include <projectexplorer/project.h>
58 #include <projectexplorer/customexecutablerunconfiguration.h>
60 #include <QtCore/QDebug>
61 #include <QtCore/QDir>
62 #include <QtGui/QFileDialog>
64 using namespace Qt4ProjectManager;
65 using namespace Qt4ProjectManager::Internal;
66 using namespace ProjectExplorer;
68 enum { debug = 0 };
70 namespace Qt4ProjectManager {
71 namespace Internal {
73 // Qt4ProjectFiles: Struct for (Cached) lists of files in a project
74 struct Qt4ProjectFiles {
75 void clear();
76 bool equals(const Qt4ProjectFiles &f) const;
78 QStringList files[ProjectExplorer::FileTypeSize];
79 QStringList generatedFiles[ProjectExplorer::FileTypeSize];
80 QStringList proFiles;
83 void Qt4ProjectFiles::clear()
85 for (int i = 0; i < FileTypeSize; ++i) {
86 files[i].clear();
87 generatedFiles[i].clear();
89 proFiles.clear();
92 bool Qt4ProjectFiles::equals(const Qt4ProjectFiles &f) const
94 for (int i = 0; i < FileTypeSize; ++i)
95 if (files[i] != f.files[i] || generatedFiles[i] != f.generatedFiles[i])
96 return false;
97 if (proFiles != f.proFiles)
98 return false;
99 return true;
102 inline bool operator==(const Qt4ProjectFiles &f1, const Qt4ProjectFiles &f2)
103 { return f1.equals(f2); }
105 inline bool operator!=(const Qt4ProjectFiles &f1, const Qt4ProjectFiles &f2)
106 { return !f1.equals(f2); }
108 QDebug operator<<(QDebug d, const Qt4ProjectFiles &f)
110 QDebug nsp = d.nospace();
111 nsp << "Qt4ProjectFiles: proFiles=" << f.proFiles << '\n';
112 for (int i = 0; i < FileTypeSize; ++i)
113 nsp << "Type " << i << " files=" << f.files[i] << " generated=" << f.generatedFiles[i] << '\n';
114 return d;
117 // A visitor to collect all files of a project in a Qt4ProjectFiles struct
118 class ProjectFilesVisitor : public ProjectExplorer::NodesVisitor
120 Q_DISABLE_COPY(ProjectFilesVisitor)
121 ProjectFilesVisitor(Qt4ProjectFiles *files);
122 public:
124 static void findProjectFiles(Qt4ProFileNode *rootNode, Qt4ProjectFiles *files);
126 void visitProjectNode(ProjectNode *projectNode);
127 void visitFolderNode(FolderNode *folderNode);
129 private:
130 Qt4ProjectFiles *m_files;
133 ProjectFilesVisitor::ProjectFilesVisitor(Qt4ProjectFiles *files) :
134 m_files(files)
138 void ProjectFilesVisitor::findProjectFiles(Qt4ProFileNode *rootNode, Qt4ProjectFiles *files)
140 files->clear();
141 ProjectFilesVisitor visitor(files);
142 rootNode->accept(&visitor);
143 for (int i = 0; i < FileTypeSize; ++i) {
144 qSort(files->files[i]);
145 qSort(files->generatedFiles[i]);
147 qSort(files->proFiles);
150 void ProjectFilesVisitor::visitProjectNode(ProjectNode *projectNode)
152 const QString path = projectNode->path();
153 if (!m_files->proFiles.contains(path))
154 m_files->proFiles.append(path);
155 visitFolderNode(projectNode);
158 void ProjectFilesVisitor::visitFolderNode(FolderNode *folderNode)
160 foreach (FileNode *fileNode, folderNode->fileNodes()) {
161 const QString path = fileNode->path();
162 const int type = fileNode->fileType();
163 QStringList &targetList = fileNode->isGenerated() ? m_files->generatedFiles[type] : m_files->files[type];
164 if (!targetList.contains(path))
165 targetList.push_back(path);
172 // ----------- Qt4ProjectFile
173 Qt4ProjectFile::Qt4ProjectFile(Qt4Project *project, const QString &filePath, QObject *parent)
174 : Core::IFile(parent),
175 m_mimeType(QLatin1String(Qt4ProjectManager::Constants::PROFILE_MIMETYPE)),
176 m_project(project),
177 m_filePath(filePath)
181 bool Qt4ProjectFile::save(const QString &)
183 // This is never used
184 return false;
187 QString Qt4ProjectFile::fileName() const
189 return m_filePath;
192 QString Qt4ProjectFile::defaultPath() const
194 return QString();
197 QString Qt4ProjectFile::suggestedFileName() const
199 return QString();
202 QString Qt4ProjectFile::mimeType() const
204 return m_mimeType;
207 bool Qt4ProjectFile::isModified() const
209 return false; // we save after changing anyway
212 bool Qt4ProjectFile::isReadOnly() const
214 QFileInfo fi(m_filePath);
215 return !fi.isWritable();
218 bool Qt4ProjectFile::isSaveAsAllowed() const
220 return false;
223 void Qt4ProjectFile::modified(Core::IFile::ReloadBehavior *)
228 /class Qt4Project
230 Qt4Project manages information about an individual Qt 4 (.pro) project file.
233 Qt4Project::Qt4Project(Qt4Manager *manager, const QString& fileName) :
234 m_manager(manager),
235 m_rootProjectNode(new Qt4ProFileNode(this, fileName, this)),
236 m_nodesWatcher(new Internal::Qt4NodesWatcher(this)),
237 m_fileInfo(new Qt4ProjectFile(this, fileName, this)),
238 m_isApplication(true),
239 m_projectFiles(new Qt4ProjectFiles)
241 m_manager->registerProject(this);
242 m_rootProjectNode->registerWatcher(m_nodesWatcher);
243 connect(m_nodesWatcher, SIGNAL(foldersAdded()), this, SLOT(updateFileList()));
244 connect(m_nodesWatcher, SIGNAL(foldersRemoved()), this, SLOT(updateFileList()));
245 connect(m_nodesWatcher, SIGNAL(filesAdded()), this, SLOT(updateFileList()));
246 connect(m_nodesWatcher, SIGNAL(filesRemoved()), this, SLOT(updateFileList()));
247 connect(m_nodesWatcher, SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *)),
248 this, SLOT(scheduleUpdateCodeModel()));
250 connect(qt4ProjectManager()->versionManager(), SIGNAL(defaultQtVersionChanged()),
251 this, SLOT(defaultQtVersionChanged()));
252 connect(qt4ProjectManager()->versionManager(), SIGNAL(qtVersionsChanged()),
253 this, SLOT(qtVersionsChanged()));
255 m_updateCodeModelTimer.setSingleShot(true);
256 m_updateCodeModelTimer.setInterval(20);
257 connect(&m_updateCodeModelTimer, SIGNAL(timeout()), this, SLOT(updateCodeModel()));
259 m_addUiFilesTimer.setSingleShot(true);
260 m_addUiFilesTimer.setInterval(20);
261 connect(&m_addUiFilesTimer, SIGNAL(timeout()), this, SLOT(addUiFiles()));
264 Qt4Project::~Qt4Project()
266 m_manager->unregisterProject(this);
267 delete m_projectFiles;
270 void Qt4Project::defaultQtVersionChanged()
272 if (qtVersionId(activeBuildConfiguration()) == 0)
273 m_rootProjectNode->update();
276 void Qt4Project::qtVersionsChanged()
278 foreach (QString bc, buildConfigurations()) {
279 if (!qt4ProjectManager()->versionManager()->version(qtVersionId(bc))->isValid()) {
280 setQtVersion(bc, 0);
281 if (bc == activeBuildConfiguration())
282 m_rootProjectNode->update();
287 void Qt4Project::updateFileList()
289 Qt4ProjectFiles newFiles;
290 ProjectFilesVisitor::findProjectFiles(m_rootProjectNode, &newFiles);
291 if (newFiles != *m_projectFiles) {
292 *m_projectFiles = newFiles;
293 emit fileListChanged();
294 if (debug)
295 qDebug() << Q_FUNC_INFO << *m_projectFiles;
299 void Qt4Project::restoreSettingsImpl(PersistentSettingsReader &settingsReader)
301 Project::restoreSettingsImpl(settingsReader);
303 addDefaultBuild();
305 // Ensure that the qt version in each build configuration is valid
306 // or if not, is reset to the default
307 foreach (const QString &bc, buildConfigurations())
308 qtVersionId(bc);
310 update();
312 // restored old runconfigurations
313 if (runConfigurations().isEmpty()) {
314 // Oha no runConfigurations, add some
315 QList<Qt4ProFileNode *> list;
316 collectApplicationProFiles(list, m_rootProjectNode);
318 if (!list.isEmpty()) {
319 foreach (Qt4ProFileNode *node, list) {
320 QSharedPointer<RunConfiguration> rc(new Qt4RunConfiguration(this, node->path()));
321 addRunConfiguration(rc);
323 setActiveRunConfiguration(runConfigurations().first());
324 } else {
325 QSharedPointer<RunConfiguration> rc(new ProjectExplorer::CustomExecutableRunConfiguration(this));
326 addRunConfiguration(rc);
327 setActiveRunConfiguration(rc);
328 m_isApplication = false;
332 // Now connect
333 connect(m_nodesWatcher, SIGNAL(foldersAboutToBeAdded(FolderNode *, const QList<FolderNode*> &)),
334 this, SLOT(foldersAboutToBeAdded(FolderNode *, const QList<FolderNode*> &)));
335 connect(m_nodesWatcher, SIGNAL(foldersAdded()), this, SLOT(checkForNewApplicationProjects()));
337 connect(m_nodesWatcher, SIGNAL(foldersRemoved()), this, SLOT(checkForDeletedApplicationProjects()));
339 connect(m_nodesWatcher, SIGNAL(projectTypeChanged(Qt4ProjectManager::Internal::Qt4ProFileNode *,
340 const Qt4ProjectManager::Internal::Qt4ProjectType,
341 const Qt4ProjectManager::Internal::Qt4ProjectType)),
342 this, SLOT(projectTypeChanged(Qt4ProjectManager::Internal::Qt4ProFileNode *,
343 const Qt4ProjectManager::Internal::Qt4ProjectType,
344 const Qt4ProjectManager::Internal::Qt4ProjectType)));
346 connect(m_nodesWatcher, SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *)),
347 this, SLOT(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *)));
351 void Qt4Project::saveSettingsImpl(ProjectExplorer::PersistentSettingsWriter &writer)
353 Project::saveSettingsImpl(writer);
356 namespace {
357 class FindQt4ProFiles: protected ProjectExplorer::NodesVisitor {
358 QList<Qt4ProFileNode *> m_proFiles;
360 public:
361 QList<Qt4ProFileNode *> operator()(ProjectNode *root)
363 m_proFiles.clear();
364 root->accept(this);
365 return m_proFiles;
368 protected:
369 virtual void visitProjectNode(ProjectNode *projectNode)
371 if (Qt4ProFileNode *pro = qobject_cast<Qt4ProFileNode *>(projectNode))
372 m_proFiles.append(pro);
377 void Qt4Project::addUiFilesToCodeModel(const QStringList &files)
379 // if we already have a full updateCodeModel() scheduled
380 // then we don't need to this seperately
381 // since that one will add also all the ui files
382 if (m_updateCodeModelTimer.isActive())
383 return;
384 m_addUiFilesTimer.start();
385 m_uiFilesToAdd << files;
388 void Qt4Project::addUiFiles()
390 if (m_updateCodeModelTimer.isActive())
391 return;
392 CppTools::CppModelManagerInterface *modelManager =
393 ExtensionSystem::PluginManager::instance()->getObject<CppTools::CppModelManagerInterface>();
394 modelManager->updateSourceFiles(m_uiFilesToAdd);
395 m_uiFilesToAdd.clear();
398 void Qt4Project::scheduleUpdateCodeModel()
400 m_updateCodeModelTimer.start();
403 void Qt4Project::updateCodeModel()
405 if (debug)
406 qDebug()<<"Qt4Project::updateCodeModel()";
408 CppTools::CppModelManagerInterface *modelmanager =
409 ExtensionSystem::PluginManager::instance()
410 ->getObject<CppTools::CppModelManagerInterface>();
412 if (!modelmanager)
413 return;
415 QStringList allIncludePaths;
416 QStringList allFrameworkPaths;
418 const QHash<QString, QString> versionInfo = qtVersion(activeBuildConfiguration())->versionInfo();
419 const QString newQtIncludePath = versionInfo.value(QLatin1String("QT_INSTALL_HEADERS"));
420 const QString newQtLibsPath = versionInfo.value(QLatin1String("QT_INSTALL_LIBS"));
422 QByteArray predefinedMacros;
423 QtVersion::ToolchainType t = qtVersion(activeBuildConfiguration())->toolchainType();
424 if (t == QtVersion::MinGW || t == QtVersion::OTHER) {
425 QStringList list = rootProjectNode()->variableValue(Internal::CxxCompilerVar);
426 QString qmake_cxx = list.isEmpty() ? QString::null : list.first();
427 qmake_cxx = environment(activeBuildConfiguration()).searchInPath(qmake_cxx);
428 m_preproc.setGcc(qmake_cxx);
429 predefinedMacros = m_preproc.predefinedMacros();
430 foreach (HeaderPath headerPath, m_preproc.systemHeaderPaths()) {
431 if (headerPath.kind() == HeaderPath::FrameworkHeaderPath)
432 allFrameworkPaths.append(headerPath.path());
433 else
434 allIncludePaths.append(headerPath.path());
437 } else if (t == QtVersion::MSVC || t == QtVersion::WINCE) {
438 #ifdef QTCREATOR_WITH_MSVC_INCLUDES
439 Environment env = environment(activeBuildConfiguration());
440 allIncludePaths.append(env.value("INCLUDE").split(QLatin1Char(';')));
441 #endif
442 predefinedMacros +=
443 "#define __WIN32__\n"
444 "#define __WIN32\n"
445 "#define _WIN32\n"
446 "#define WIN32\n"
447 "#define __WINNT__\n"
448 "#define __WINNT\n"
449 "#define WINNT\n"
450 "#define _X86_\n"
451 "#define __MSVCRT__\n";
454 allIncludePaths.append(newQtIncludePath);
456 QDir dir(newQtIncludePath);
457 foreach (QFileInfo info, dir.entryInfoList(QDir::Dirs)) {
458 if (! info.fileName().startsWith(QLatin1String("Qt")))
459 continue;
460 allIncludePaths.append(info.absoluteFilePath());
463 #ifdef Q_OS_MAC
464 allFrameworkPaths.append(newQtLibsPath);
465 // put QtXXX.framework/Headers directories in include path since that qmake's behavior
466 QDir frameworkDir(newQtLibsPath);
467 foreach (QFileInfo info, frameworkDir.entryInfoList(QDir::Dirs)) {
468 if (! info.fileName().startsWith(QLatin1String("Qt")))
469 continue;
470 allIncludePaths.append(info.absoluteFilePath()+"/Headers");
472 #endif
474 FindQt4ProFiles findQt4ProFiles;
475 QList<Qt4ProFileNode *> proFiles = findQt4ProFiles(rootProjectNode());
476 QByteArray definedMacros;
478 foreach (Qt4ProFileNode *pro, proFiles) {
479 foreach (const QString def, pro->variableValue(DefinesVar)) {
480 definedMacros += "#define ";
481 const int index = def.indexOf(QLatin1Char('='));
482 if (index == -1) {
483 definedMacros += def.toLatin1();
484 definedMacros += " 1\n";
485 } else {
486 const QString name = def.left(index);
487 const QString value = def.mid(index + 1);
488 definedMacros += name.toLatin1();
489 definedMacros += ' ';
490 definedMacros += value.toLocal8Bit();
491 definedMacros += '\n';
495 const QStringList proIncludePaths = pro->variableValue(IncludePathVar);
496 foreach (QString includePath, proIncludePaths) {
497 if (allIncludePaths.contains(includePath))
498 continue;
500 allIncludePaths.append(includePath);
504 // Add mkspec directory
505 allIncludePaths.append(qtVersion(activeBuildConfiguration())->mkspecPath());
507 QStringList files;
508 files += m_projectFiles->files[HeaderType];
509 files += m_projectFiles->generatedFiles[HeaderType];
510 files += m_projectFiles->files[SourceType];
511 files += m_projectFiles->generatedFiles[SourceType];
513 CppTools::CppModelManagerInterface::ProjectInfo pinfo = modelmanager->projectInfo(this);
515 if (pinfo.defines == predefinedMacros &&
516 pinfo.includePaths == allIncludePaths &&
517 pinfo.frameworkPaths == allFrameworkPaths &&
518 pinfo.sourceFiles == files) {
519 modelmanager->updateProjectInfo(pinfo);
520 } else {
521 pinfo.defines = predefinedMacros;
522 // pinfo->defines += definedMacros; // ### FIXME: me
523 pinfo.includePaths = allIncludePaths;
524 pinfo.frameworkPaths = allFrameworkPaths;
525 pinfo.sourceFiles = files;
527 modelmanager->updateProjectInfo(pinfo);
528 modelmanager->updateSourceFiles(pinfo.sourceFiles);
533 ///*!
534 // Updates complete project
535 // */
536 void Qt4Project::update()
538 // TODO Maybe remove this method completely?
539 m_rootProjectNode->update();
540 //updateCodeModel();
543 ProFileReader *Qt4Project::createProFileReader() const
545 ProFileReader *reader = new ProFileReader();
546 connect(reader, SIGNAL(errorFound(const QString&)),
547 this, SLOT(proFileParseError(const QString&)));
548 QtVersion *version = qtVersion(activeBuildConfiguration());
549 if (version->isValid()) {
550 reader->setQtVersion(version);
552 return reader;
556 Returns whether the project is an application, or has an application as a subproject.
558 bool Qt4Project::isApplication() const
560 return m_isApplication;
563 ProjectExplorer::ProjectExplorerPlugin *Qt4Project::projectExplorer() const
565 return m_manager->projectExplorer();
568 ProjectExplorer::IProjectManager *Qt4Project::projectManager() const
570 return m_manager;
573 Qt4Manager *Qt4Project::qt4ProjectManager() const
575 return m_manager;
578 QString Qt4Project::name() const
580 return QFileInfo(file()->fileName()).completeBaseName();
583 Core::IFile *Qt4Project::file() const
585 return m_fileInfo;
588 QStringList Qt4Project::files(FilesMode fileMode) const
590 QStringList files;
591 for (int i = 0; i < FileTypeSize; ++i) {
592 files += m_projectFiles->files[i];
593 if (fileMode == AllFiles)
594 files += m_projectFiles->generatedFiles[i];
596 return files;
599 QList<ProjectExplorer::Project*> Qt4Project::dependsOn()
601 // NBS implement dependsOn
602 return QList<Project *>();
605 void Qt4Project::addDefaultBuild()
607 if (buildConfigurations().isEmpty()) {
608 // We don't have any buildconfigurations, so this is a new project
609 // The Project Load Wizard is a work of art
610 // It will ask the user what kind of build setup he want
611 // It will add missing Qt Versions
612 // And get the project into a buildable state
614 //TODO have a better check wheter there is already a configuration?
615 QMakeStep *qmakeStep = 0;
616 MakeStep *makeStep = 0;
617 GdbMacrosBuildStep *gdbmacrostep;
619 gdbmacrostep = new GdbMacrosBuildStep(this);
620 insertBuildStep(0, gdbmacrostep);
622 qmakeStep = new QMakeStep(this);
623 qmakeStep->setValue("mkspec", "");
624 insertBuildStep(1, qmakeStep);
626 makeStep = new MakeStep(this);
627 insertBuildStep(2, makeStep);
629 GdbMacrosBuildStep *gdbmacrosCleanStep = new GdbMacrosBuildStep(this);
630 gdbmacrosCleanStep->setValue("clean", true);
631 insertCleanStep(0, gdbmacrosCleanStep);
633 MakeStep* cleanStep = new MakeStep(this);
634 cleanStep->setValue("clean", true);
635 insertCleanStep(1, cleanStep);
637 ProjectLoadWizard wizard(this);
638 wizard.execDialog();
639 } else {
640 // Restoring configuration
641 // Do we already have a gdbmacrobuildstep?
642 // If not add it and disable linking of debugging helper
644 // Check for old link debugging helper setting in each buildConfiguration
645 // We add a gdbmacrosbuildstep if at least one has it
646 // TODO remove migration code from pre beta
647 foreach(const QString &bc, buildConfigurations()) {
648 QVariant v = value(bc, "addQDumper");
649 if (v.isValid() && v.toBool()) {
650 GdbMacrosBuildStep *gdbmacrostep = new GdbMacrosBuildStep(this);
651 insertBuildStep(0, gdbmacrostep);
653 GdbMacrosBuildStep *gdbmacrosCleanStep = new GdbMacrosBuildStep(this);
654 gdbmacrosCleanStep ->setValue("clean", true);
655 insertCleanStep(0, gdbmacrosCleanStep );
656 break;
660 foreach(const QString &bc, buildConfigurations()) {
661 setValue(bc, "addQDumper", QVariant());
666 void Qt4Project::newBuildConfiguration(const QString &buildConfiguration)
668 Q_UNUSED(buildConfiguration);
671 void Qt4Project::proFileParseError(const QString &errorMessage)
673 Core::ICore::instance()->messageManager()->printToOutputPane(errorMessage);
676 Qt4ProFileNode *Qt4Project::rootProjectNode() const
678 return m_rootProjectNode;
681 ProjectExplorer::Environment Qt4Project::baseEnvironment(const QString &buildConfiguration) const
683 Environment env = useSystemEnvironment(buildConfiguration) ? Environment(QProcess::systemEnvironment()) : Environment();
684 env = qtVersion(buildConfiguration)->addToEnvironment(env);
685 return env;
688 ProjectExplorer::Environment Qt4Project::environment(const QString &buildConfiguration) const
690 Environment env = baseEnvironment(buildConfiguration);
691 env.modify(userEnvironmentChanges(buildConfiguration));
692 return env;
695 QString Qt4Project::buildDirectory(const QString &buildConfiguration) const
697 QString workingDirectory;
698 if (value(buildConfiguration, "useShadowBuild").toBool())
699 workingDirectory = value(buildConfiguration, "buildDirectory").toString();
700 if (workingDirectory.isEmpty())
701 workingDirectory = QFileInfo(file()->fileName()).absolutePath();
702 return workingDirectory;
705 void Qt4Project::setUseSystemEnvironment(const QString &buildConfiguration, bool b)
707 setValue(buildConfiguration, "clearSystemEnvironment", !b);
710 bool Qt4Project::useSystemEnvironment(const QString &buildConfiguration) const
712 bool b = !(value(buildConfiguration, "clearSystemEnvironment").isValid() && value(buildConfiguration, "clearSystemEnvironment").toBool());
713 return b;
716 QString Qt4Project::qtDir(const QString &buildConfiguration) const
718 QtVersion *version = qtVersion(buildConfiguration);
719 if (version)
720 return version->path();
721 return QString::null;
724 QtVersion *Qt4Project::qtVersion(const QString &buildConfiguration) const
726 return m_manager->versionManager()->version(qtVersionId(buildConfiguration));
729 int Qt4Project::qtVersionId(const QString &buildConfiguration) const
731 if (debug)
732 qDebug()<<"Looking for qtVersion ID of "<<buildConfiguration;
733 int id = 0;
734 QVariant vid = value(buildConfiguration, "QtVersionId");
735 if (vid.isValid()) {
736 id = vid.toInt();
737 if (m_manager->versionManager()->version(id)->isValid()) {
738 return id;
739 } else {
740 const_cast<Qt4Project *>(this)->setValue(buildConfiguration, "QtVersionId", 0);
741 return 0;
743 } else {
744 // Backward compatibilty, we might have just the name:
745 QString vname = value(buildConfiguration, "QtVersion").toString();
746 if (debug)
747 qDebug()<<" Backward compatibility reading QtVersion"<<vname;
748 if (!vname.isEmpty()) {
749 const QList<QtVersion *> &versions = m_manager->versionManager()->versions();
750 foreach (const QtVersion * const version, versions) {
751 if (version->name() == vname) {
752 if (debug)
753 qDebug()<<"found name in versions";
754 const_cast<Qt4Project *>(this)->setValue(buildConfiguration, "QtVersionId", version->uniqueId());
755 return version->uniqueId();
760 if (debug)
761 qDebug()<<" using qtversion with id ="<<id;
762 // Nothing found, reset to default
763 const_cast<Qt4Project *>(this)->setValue(buildConfiguration, "QtVersionId", id);
764 return id;
767 void Qt4Project::setQtVersion(const QString &buildConfiguration, int id)
769 setValue(buildConfiguration, "QtVersionId", id);
772 BuildStepConfigWidget *Qt4Project::createConfigWidget()
774 return new Qt4BuildConfigWidget(this);
777 QList<BuildStepConfigWidget*> Qt4Project::subConfigWidgets()
779 QList<BuildStepConfigWidget*> subWidgets;
780 subWidgets << new Qt4BuildEnvironmentWidget(this);
781 return subWidgets;
784 QList<ProjectExplorer::EnvironmentItem> Qt4Project::userEnvironmentChanges(const QString &buildConfig) const
786 return EnvironmentItem::fromStringList(value(buildConfig, "userEnvironmentChanges").toStringList());
789 void Qt4Project::setUserEnvironmentChanges(const QString &buildConfig, const QList<ProjectExplorer::EnvironmentItem> &diff)
791 setValue(buildConfig, "userEnvironmentChanges", EnvironmentItem::toStringList(diff));
794 /// **************************
795 /// Qt4ProjectBuildConfigWidget
796 /// **************************
799 void Qt4Project::collectApplicationProFiles(QList<Qt4ProFileNode *> &list, Qt4ProFileNode *node)
801 if (node->projectType() == Internal::ApplicationTemplate
802 || node->projectType() == Internal::ScriptTemplate) {
803 list.append(node);
805 foreach (ProjectNode *n, node->subProjectNodes()) {
806 Qt4ProFileNode *qt4ProFileNode = qobject_cast<Qt4ProFileNode *>(n);
807 if (qt4ProFileNode)
808 collectApplicationProFiles(list, qt4ProFileNode);
812 void Qt4Project::foldersAboutToBeAdded(FolderNode *, const QList<FolderNode*> &nodes)
814 QList<Qt4ProFileNode *> list;
815 foreach (FolderNode *node, nodes) {
816 Qt4ProFileNode *qt4ProFileNode = qobject_cast<Qt4ProFileNode *>(node);
817 if (qt4ProFileNode)
818 collectApplicationProFiles(list, qt4ProFileNode);
820 m_applicationProFileChange = list;
823 void Qt4Project::checkForNewApplicationProjects()
825 // Check all new project nodes
826 // against all runConfigurations
828 foreach (Qt4ProFileNode *qt4proFile, m_applicationProFileChange) {
829 bool found = false;
830 foreach (QSharedPointer<RunConfiguration> rc, runConfigurations()) {
831 QSharedPointer<Qt4RunConfiguration> qtrc = rc.dynamicCast<Qt4RunConfiguration>();
832 if (qtrc && qtrc->proFilePath() == qt4proFile->path()) {
833 found = true;
834 break;
837 if (!found) {
838 QSharedPointer<Qt4RunConfiguration> newRc(new Qt4RunConfiguration(this, qt4proFile->path()));
839 addRunConfiguration(newRc);
840 m_isApplication = true;
845 void Qt4Project::checkForDeletedApplicationProjects()
847 QStringList paths;
848 foreach (Qt4ProFileNode * node, applicationProFiles())
849 paths.append(node->path());
851 qDebug()<<"Still existing paths :"<<paths;
853 QList<QSharedPointer<Qt4RunConfiguration> > removeList;
854 foreach (QSharedPointer<RunConfiguration> rc, runConfigurations()) {
855 if (QSharedPointer<Qt4RunConfiguration> qt4rc = rc.dynamicCast<Qt4RunConfiguration>()) {
856 if (!paths.contains(qt4rc->proFilePath())) {
857 removeList.append(qt4rc);
858 qDebug()<<"Removing runConfiguration for "<<qt4rc->proFilePath();
863 bool resetActiveRunConfiguration = false;
864 QSharedPointer<RunConfiguration> rc(new ProjectExplorer::CustomExecutableRunConfiguration(this));
865 foreach (QSharedPointer<Qt4RunConfiguration> qt4rc, removeList) {
866 removeRunConfiguration(qt4rc);
867 if (activeRunConfiguration() == qt4rc)
868 resetActiveRunConfiguration = true;
871 if (runConfigurations().isEmpty()) {
872 QSharedPointer<RunConfiguration> rc(new ProjectExplorer::CustomExecutableRunConfiguration(this));
873 addRunConfiguration(rc);
874 setActiveRunConfiguration(rc);
875 m_isApplication = false;
876 } else if (resetActiveRunConfiguration) {
877 setActiveRunConfiguration(runConfigurations().first());
881 QList<Qt4ProFileNode *> Qt4Project::applicationProFiles() const
883 QList<Qt4ProFileNode *> list;
884 collectApplicationProFiles(list, rootProjectNode());
885 return list;
888 void Qt4Project::projectTypeChanged(Qt4ProFileNode *node, const Qt4ProjectType oldType, const Qt4ProjectType newType)
890 if (oldType == Internal::ApplicationTemplate
891 || oldType == Internal::ScriptTemplate) {
892 // check wheter we need to delete a Run Configuration
893 checkForDeletedApplicationProjects();
896 if (newType == Internal::ApplicationTemplate
897 || newType == Internal::ScriptTemplate) {
898 // add a new Run Configuration
899 m_applicationProFileChange.clear();
900 m_applicationProFileChange.append(node);
901 checkForNewApplicationProjects();
905 void Qt4Project::proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *node)
907 foreach (QSharedPointer<RunConfiguration> rc, runConfigurations()) {
908 if (QSharedPointer<Qt4RunConfiguration> qt4rc = rc.dynamicCast<Qt4RunConfiguration>()) {
909 if (qt4rc->proFilePath() == node->path()) {
910 qt4rc->updateCachedValues();
917 QMakeStep *Qt4Project::qmakeStep() const
919 QMakeStep *qs = 0;
920 foreach(BuildStep *bs, buildSteps())
921 if ( (qs = qobject_cast<QMakeStep *>(bs)) != 0)
922 return qs;
923 return 0;
926 MakeStep *Qt4Project::makeStep() const
928 MakeStep *qs = 0;
929 foreach(BuildStep *bs, buildSteps())
930 if ((qs = qobject_cast<MakeStep *>(bs)) != 0)
931 return qs;
932 return 0;
935 bool Qt4Project::hasSubNode(Qt4PriFileNode *root, const QString &path)
937 if (root->path() == path)
938 return true;
939 foreach (FolderNode *fn, root->subFolderNodes()) {
940 if (qobject_cast<Qt4ProFileNode *>(fn)) {
941 // we aren't interested in pro file nodes
942 } else if (Qt4PriFileNode *qt4prifilenode = qobject_cast<Qt4PriFileNode *>(fn)) {
943 if (hasSubNode(qt4prifilenode, path))
944 return true;
947 return false;
950 void Qt4Project::findProFile(const QString& fileName, Qt4ProFileNode *root, QList<Qt4ProFileNode *> &list)
952 if (hasSubNode(root, fileName))
953 list.append(root);
955 foreach (FolderNode *fn, root->subFolderNodes())
956 if (Qt4ProFileNode *qt4proFileNode = qobject_cast<Qt4ProFileNode *>(fn))
957 findProFile(fileName, qt4proFileNode, list);
960 void Qt4Project::notifyChanged(const QString &name)
962 if (files(Qt4Project::ExcludeGeneratedFiles).contains(name)) {
963 QList<Qt4ProFileNode *> list;
964 findProFile(name, rootProjectNode(), list);
965 foreach(Qt4ProFileNode *node, list)
966 node->update();