Newer
Older
/**************************************************************************
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
** If you are unsure which license is appropriate for your use, please
**************************************************************************/
#include "makestep.h"
#include "qmakestep.h"
#include "qt4runconfiguration.h"
#include "qt4nodes.h"
#include "qt4projectconfigwidget.h"
#include "qt4buildenvironmentwidget.h"
#include "qt4projectmanagerconstants.h"
#include "projectloadwizard.h"
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/customexecutablerunconfiguration.h>
#include <projectexplorer/nodesvisitor.h>
#include <projectexplorer/project.h>
#include <utils/qtcassert.h>
#include <QtCore/QDir>
#include <QtGui/QFileDialog>
#include <QtGui/QInputDialog>
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
using namespace Qt4ProjectManager;
using namespace Qt4ProjectManager::Internal;
using namespace ProjectExplorer;
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
QFileInfo fi(m_filePath);
return !fi.isWritable();
}
bool Qt4ProjectFile::isSaveAsAllowed() const
{
return false;
}
void Qt4ProjectFile::modified(Core::IFile::ReloadBehavior *)
{
}
/*!
Qt4Project manages information about an individual Qt 4 (.pro) project file.
*/
Qt4Project::Qt4Project(Qt4Manager *manager, const QString& fileName) :
m_manager(manager),
m_fileInfo(new Qt4ProjectFile(this, fileName, this)),
m_isApplication(true),
m_projectFiles(new Qt4ProjectFiles),
m_proFileOption(0),
m_asyncUpdateFutureInterface(0),
m_pendingEvaluateFuturesCount(0),
m_asyncUpdateState(NoState),
m_cancelEvaluate(false)
m_asyncUpdateTimer.setSingleShot(true);
m_asyncUpdateTimer.setInterval(3000);
connect(&m_asyncUpdateTimer, SIGNAL(timeout()), this, SLOT(asyncUpdate()));
setSupportedTargetIds(QtVersionManager::instance()->supportedTargetIds());
delete m_projectFiles;
}
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;
}
}
bool Qt4Project::fromMap(const QVariantMap &map)
if (!Project::fromMap(map))
return false;
// Prune targets without buildconfigurations:
// This can happen esp. when updating from a old version of Qt Creator
QList<Target *>ts(targets());
foreach (Target *t, ts) {
if (t->buildConfigurations().isEmpty()) {
qWarning() << "Removing" << t->id() << "since it has no buildconfigurations!";
}
// Add buildconfigurations so we can parse the pro-files.
if (targets().isEmpty())
if (targets().isEmpty()) {
qWarning() << "Unable to create targets!";
return false;
}
Q_ASSERT(activeTarget());
Q_ASSERT(activeTarget()->activeBuildConfiguration());
m_manager->registerProject(this);
m_rootProjectNode = new Qt4ProFileNode(this, m_fileInfo->fileName(), this);
m_rootProjectNode->registerWatcher(m_nodesWatcher);
update();
updateFileList();
// This might be incorrect, need a full update
checkForNewApplicationProjects();
checkForDeletedApplicationProjects();
foreach (Target *t, targets())
onAddedTarget(t);
setSupportedTargetIds(QtVersionManager::instance()->supportedTargetIds());
// Setup Qt versions supported (== possible targets).
connect(this, SIGNAL(addedTarget(ProjectExplorer::Target*)),
this, SLOT(onAddedTarget(ProjectExplorer::Target*)));
connect(QtVersionManager::instance(), SIGNAL(qtVersionsChanged(QList<int>)),
this, SLOT(qtVersionsChanged()));
connect(m_nodesWatcher, SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *)),
this, SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *)));
connect(this, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
this, SLOT(activeTargetWasChanged()));
Qt4TargetFactory *Qt4Project::targetFactory() const
return static_cast<Qt4Target *>(Project::activeTarget());
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::onAddedTarget(ProjectExplorer::Target *t)
{
Q_ASSERT(t);
Qt4Target *qt4target = qobject_cast<Qt4Target *>(t);
Q_ASSERT(qt4target);
connect(qt4target, SIGNAL(buildDirectoryInitialized()),
this, SIGNAL(buildDirectoryInitialized()));
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
connect(qt4target, SIGNAL(proFileEvaluateNeeded(Qt4ProjectManager::Internal::Qt4Target*)),
this, SLOT(proFileEvaluateNeeded(Qt4ProjectManager::Internal::Qt4Target*)));
}
void Qt4Project::proFileEvaluateNeeded(Qt4ProjectManager::Internal::Qt4Target *target)
{
if (activeTarget() == target)
scheduleAsyncUpdate();
}
/// equalFileList compares two file lists ignoring
/// <configuration> without generating temporary lists
bool Qt4Project::equalFileList(const QStringList &a, const QStringList &b)
{
if (abs(a.length() - b.length()) > 1)
return false;
QStringList::const_iterator ait = a.constBegin();
QStringList::const_iterator bit = b.constBegin();
QStringList::const_iterator aend = a.constEnd();
QStringList::const_iterator bend = b.constEnd();
while (ait != aend && bit != bend) {
if (*ait == QLatin1String("<configuration>"))
++ait;
else if (*bit == QLatin1String("<configuration>"))
++bit;
else if (*ait == *bit)
++ait, ++bit;
else
return false;
}
return (ait == aend && bit == bend);
void Qt4Project::updateCodeModel()
{
if (debug)
qDebug()<<"Qt4Project::updateCodeModel()";
if (!activeTarget() || !activeTarget()->activeBuildConfiguration())
return;
Qt4BuildConfiguration *activeBC = activeTarget()->activeBuildConfiguration();

hjk
committed
ExtensionSystem::PluginManager::instance()
->getObject<CppTools::CppModelManagerInterface>();

hjk
committed
if (!modelmanager)
// Collect global headers/defines
QStringList predefinedIncludePaths;
QStringList predefinedFrameworkPaths;
QByteArray predefinedMacros;
if (tc) {
predefinedMacros = tc->predefinedMacros();
//qDebug()<<tc->predefinedMacros();
//qDebug()<<"";
//qDebug()<<"System Header Paths";
//foreach(const HeaderPath &hp, tc->systemHeaderPaths())
// qDebug()<<hp.path();
foreach (const HeaderPath &headerPath, tc->systemHeaderPaths()) {
if (headerPath.kind() == HeaderPath::FrameworkHeaderPath)
predefinedFrameworkPaths.append(headerPath.path());
else
predefinedIncludePaths.append(headerPath.path());
}
FindQt4ProFiles findQt4ProFiles;
QList<Qt4ProFileNode *> proFiles = findQt4ProFiles(rootProjectNode());
QByteArray allDefinedMacros = predefinedMacros;
QStringList allIncludePaths;
// Collect per .pro file information
m_codeModelInfo.clear();
Internal::CodeModelInfo info;
info.defines = predefinedMacros;
info.frameworkPaths = predefinedFrameworkPaths;
info.precompiledHeader = pro->variableValue(PrecompiledHeaderVar);
allPrecompileHeaders.append(info.precompiledHeader);
// Add custom defines
foreach (const QString &def, pro->variableValue(DefinesVar)) {
info.defines += "#define ";
const int index = def.indexOf(QLatin1Char('='));
if (index == -1) {
allDefinedMacros += def.toLatin1();
allDefinedMacros += " 1\n";
info.defines += def.toLatin1();
info.defines += " 1\n";
} else {
const QString name = def.left(index);
const QString value = def.mid(index + 1);
allDefinedMacros += name.toLatin1();
allDefinedMacros += ' ';
allDefinedMacros += value.toLocal8Bit();
allDefinedMacros += '\n';
info.defines += name.toLatin1();
info.defines += ' ';
info.defines += value.toLocal8Bit();
info.defines += '\n';
}
}
const QStringList proIncludePaths = pro->variableValue(IncludePathVar);
foreach (const QString &includePath, proIncludePaths) {
if (!allIncludePaths.contains(includePath))
allIncludePaths.append(includePath);
if (!info.includes.contains(includePath))
info.includes.append(includePath);
{ // Pkg Config support
QStringList pkgConfig = pro->variableValue(PkgConfigVar);
if (!pkgConfig.isEmpty()) {
pkgConfig.prepend("--cflags-only-I");
QProcess process;
process.start("pkg-config", pkgConfig);
process.waitForFinished();
QString result = process.readAllStandardOutput();
foreach(const QString &part, result.trimmed().split(' ', QString::SkipEmptyParts)) {
info.includes.append(part.mid(2)); // Chop off "-I"
// Add mkspec directory
info.includes.append(activeBC->qtVersion()->mkspecPath());
info.includes.append(predefinedIncludePaths);
// qDebug()<<"Dumping code model information";
// qDebug()<<"for .pro file"<< pro->path();
// qDebug()<<info.defines;
// qDebug()<<info.includes;
// qDebug()<<info.frameworkPaths;
// qDebug()<<"\n";
#if 0
//Disable for now, we need better .pro file parsing first, and code model
//support to access this information
// TODO this is wastefull
// only save it per .pro file, and on being asked
// search for the .pro file that has that file
foreach (FileNode *fileNode, pro->fileNodes()) {
const QString path = fileNode->path();
const int type = fileNode->fileType();
if (type == HeaderType || type == SourceType) {
m_codeModelInfo.insert(path, info);
}
allIncludePaths.append(activeBC->qtVersion()->mkspecPath());
allIncludePaths.append(predefinedIncludePaths);
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);
//qDebug()<<"Using precompiled header"<<allPrecompileHeaders;
bool fileList = equalFileList(pinfo.sourceFiles, files);
if (pinfo.defines == allDefinedMacros
&& pinfo.includePaths == allIncludePaths
&& pinfo.frameworkPaths == allFrameworkPaths
&& pinfo.precompiledHeaders == allPrecompileHeaders) {
pinfo.sourceFiles.clear();
if (pinfo.defines != allDefinedMacros
|| pinfo.includePaths != allIncludePaths
|| pinfo.frameworkPaths != allFrameworkPaths
|| pinfo.precompiledHeaders != allPrecompileHeaders)
{
pinfo.sourceFiles.append(QLatin1String("<configuration>"));
}
//pinfo.defines = predefinedMacros;
pinfo.defines = allDefinedMacros;
pinfo.includePaths = allIncludePaths;
pinfo.frameworkPaths = allFrameworkPaths;
pinfo.precompiledHeaders = allPrecompileHeaders;
modelmanager->updateProjectInfo(pinfo);
m_codeModelFuture = modelmanager->updateSourceFiles(pinfo.sourceFiles);
void Qt4Project::qtVersionsChanged()
{
setSupportedTargetIds(QtVersionManager::instance()->supportedTargetIds());
}
QByteArray Qt4Project::predefinedMacros(const QString &fileName) const
{
QMap<QString, CodeModelInfo>::const_iterator it = m_codeModelInfo.constFind(fileName);
if (it == m_codeModelInfo.constEnd())
return QByteArray();
else
return (*it).defines;
QStringList Qt4Project::includePaths(const QString &fileName) const
{
QMap<QString, CodeModelInfo>::const_iterator it = m_codeModelInfo.constFind(fileName);
if (it == m_codeModelInfo.constEnd())
return QStringList();
else
return (*it).includes;
}
QStringList Qt4Project::frameworkPaths(const QString &fileName) const
{
QMap<QString, CodeModelInfo>::const_iterator it = m_codeModelInfo.constFind(fileName);
if (it == m_codeModelInfo.constEnd())
return QStringList();
else
return (*it).frameworkPaths;
}
///*!
// Updates complete project
// */
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
qDebug()<<"State is now Base";
m_asyncUpdateState = Base;
}
void Qt4Project::scheduleAsyncUpdate(Qt4ProFileNode *node)
{
qDebug()<<"schduleAsyncUpdate (node)";
Q_ASSERT(m_asyncUpdateState != NoState);
if (m_cancelEvaluate) {
qDebug()<<" Already canceling, nothing to do";
// A cancel is in progress
// That implies that a full update is going to happen afterwards
// So we don't need to do anything
return;
}
if (m_asyncUpdateState == AsyncFullUpdatePending) {
// Just postpone
qDebug()<<" full update pending, restarting timer";
m_asyncUpdateTimer.start();
} else if (m_asyncUpdateState == AsyncPartialUpdatePending
|| m_asyncUpdateState == Base) {
qDebug()<<" adding node to async update list, setting state to AsyncPartialUpdatePending";
// Add the node
m_asyncUpdateState = AsyncPartialUpdatePending;
QList<Internal::Qt4ProFileNode *>::iterator it;
bool add = true;
qDebug()<<"scheduleAsyncUpdate();"<<m_partialEvaluate.size()<<"nodes";
it = m_partialEvaluate.begin();
while (it != m_partialEvaluate.end()) {
if (*it == node) {
add = false;
break;
} else if (node->isParent(*it)) { // We already have the parent in the list, nothing to do
add = false;
break;
} else if ((*it)->isParent(node)) { // The node is the parent of a child already in the list
it = m_partialEvaluate.erase(it);
} else {
++it;
}
}
if (add)
m_partialEvaluate.append(node);
// and start the timer anew
m_asyncUpdateTimer.start();
} else if (m_asyncUpdateState == AsyncUpdateInProgress) {
// A update is in progress
// And this slot only gets called if a file changed on disc
// So we'll play it safe and schedule a complete evaluate
// This might trigger if due to version control a few files
// change a partial update gets in progress and then another
// batch of changes come in, which triggers a full update
// even if that's not really needed
qDebug()<<" Async update in progress, scheduling new one afterwards";
scheduleAsyncUpdate();
}
}
void Qt4Project::scheduleAsyncUpdate()
{
qDebug()<<"scheduleAsyncUpdate";
Q_ASSERT(m_asyncUpdateState != NoState);
if (m_cancelEvaluate) { // we are in progress of canceling
// and will start the evaluation after that
qDebug()<<" canceling is in progress, doing nothing";
return;
}
if (m_asyncUpdateState == AsyncUpdateInProgress) {
qDebug()<<" update in progress, canceling and setting state to full update pending";
m_cancelEvaluate = true;
m_asyncUpdateState = AsyncFullUpdatePending;
return;
}
qDebug()<<" starting timer for full update, setting state to full update pending";
m_partialEvaluate.clear();
m_asyncUpdateState = AsyncFullUpdatePending;
m_asyncUpdateTimer.start();
}
void Qt4Project::incrementPendingEvaluateFutures()
{
++m_pendingEvaluateFuturesCount;
qDebug()<<"incrementPendingEvaluateFutures to"<<m_pendingEvaluateFuturesCount;
m_asyncUpdateFutureInterface->setProgressRange(m_asyncUpdateFutureInterface->progressMinimum(),
m_asyncUpdateFutureInterface->progressMaximum() + 1);
}
void Qt4Project::decrementPendingEvaluateFutures()
{
--m_pendingEvaluateFuturesCount;
qDebug()<<"decrementPendingEvaluateFutures to"<<m_pendingEvaluateFuturesCount;
m_asyncUpdateFutureInterface->setProgressValue(m_asyncUpdateFutureInterface->progressValue() + 1);
if (m_pendingEvaluateFuturesCount == 0) {
qDebug()<<" WOHOO, no pending futures, cleaning up";
// We are done!
qDebug()<<" reporting finished";
m_asyncUpdateFutureInterface->reportFinished();
delete m_asyncUpdateFutureInterface;
m_asyncUpdateFutureInterface = 0;
m_cancelEvaluate = false;
// After beeing done, we need to call:
updateFileList();
updateCodeModel();
checkForNewApplicationProjects();
checkForDeletedApplicationProjects();
// TODO clear the profile cache ?
if (m_asyncUpdateState == AsyncFullUpdatePending || m_asyncUpdateState == AsyncPartialUpdatePending) {
qDebug()<<" Oh update is pending start the timer";
m_asyncUpdateTimer.start();
} else {
qDebug()<<" Setting state to Base";
m_asyncUpdateState = Base;
}
}
}
bool Qt4Project::wasEvaluateCanceled()
{
return m_cancelEvaluate;
}
void Qt4Project::asyncUpdate()
{
qDebug()<<"async update, timer expired, doing now";
Q_ASSERT(!m_asyncUpdateFutureInterface);
m_asyncUpdateFutureInterface = new QFutureInterface<void>();
Core::ProgressManager *progressManager = Core::ICore::instance()->progressManager();
progressManager->addTask(m_asyncUpdateFutureInterface->future(), tr("Evaluate"), Constants::PROFILE_EVALUATE);
qDebug()<<" adding task";
m_asyncUpdateFutureInterface->setProgressRange(0, 0);
m_asyncUpdateFutureInterface->reportStarted();
if (m_asyncUpdateState == AsyncFullUpdatePending) {
qDebug()<<" full update, starting with root node";
m_rootProjectNode->asyncUpdate();
} else {
qDebug()<<" partial update,"<<m_partialEvaluate.size()<<"nodes to update";
foreach(Qt4ProFileNode *node, m_partialEvaluate)
node->asyncUpdate();
}
m_partialEvaluate.clear();
qDebug()<<" Setting state to AsyncUpdateInProgress";
m_asyncUpdateState = AsyncUpdateInProgress;
}
/*!
Returns whether the project is an application, or has an application as a subproject.
*/
bool Qt4Project::isApplication() const
{
return m_isApplication;
}
ProjectExplorer::IProjectManager *Qt4Project::projectManager() const
{
return m_manager;
}
Qt4Manager *Qt4Project::qt4ProjectManager() const
{
return m_manager;
}
QString Qt4Project::displayName() const
{
return QFileInfo(file()->fileName()).completeBaseName();
}
QString Qt4Project::id() const
{
return QLatin1String("Qt4ProjectManager.Qt4Project");
}
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];
}
return files;
}
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
// Find the folder that contains a file a certain type (recurse down)
static FolderNode *folderOf(FolderNode *in, FileType fileType, const QString &fileName)
{
foreach(FileNode *fn, in->fileNodes())
if (fn->fileType() == fileType && fn->path() == fileName)
return in;
foreach(FolderNode *folder, in->subFolderNodes())
if (FolderNode *pn = folderOf(folder, fileType, fileName))
return pn;
return 0;
}
// Find the Qt4ProFileNode that contains a file of a certain type.
// First recurse down to folder, then find the pro-file.
static Qt4ProFileNode *proFileNodeOf(Qt4ProFileNode *in, FileType fileType, const QString &fileName)
{
for (FolderNode *folder = folderOf(in, fileType, fileName); folder; folder = folder->parentFolderNode())
if (Qt4ProFileNode *proFile = qobject_cast<Qt4ProFileNode *>(folder))
return proFile;
return 0;
}
QString Qt4Project::generatedUiHeader(const QString &formFile) const
{
// Look in sub-profiles as SessionManager::projectForFile returns
// the top-level project only.
if (m_rootProjectNode)
if (const Qt4ProFileNode *pro = proFileNodeOf(m_rootProjectNode, FormType, formFile))
return Qt4ProFileNode::uiHeaderFile(pro->uiDirectory(), formFile);
return QString();
}
QList<ProjectExplorer::Project*> Qt4Project::dependsOn()
{
// NBS implement dependsOn
return QList<Project *>();
}
void Qt4Project::addDefaultBuild()
{
// TODO this could probably refactored
// That is the ProjectLoadWizard divided into useful bits
// and this code then called here, instead of that strange forwarding
// to a wizard, which doesn't even show up
ProjectLoadWizard wizard(this);
wizard.execDialog();
}
void Qt4Project::proFileParseError(const QString &errorMessage)
{

hjk
committed
Core::ICore::instance()->messageManager()->printToOutputPane(errorMessage);
ProFileReader *Qt4Project::createProFileReader(Qt4ProFileNode *qt4ProFileNode)
{
if (!m_proFileOption) {
m_proFileOption = new ProFileOption;
m_proFileOptionRefCnt = 0;
if (activeTarget() &&
activeTarget()->activeBuildConfiguration()) {
QtVersion *version = activeTarget()->activeBuildConfiguration()->qtVersion();
if (version->isValid())
m_proFileOption->properties = version->versionInfo();
}
ProFileCacheManager::instance()->incRefCount();
m_proFileOption->cache = ProFileCacheManager::instance()->cache();
}
++m_proFileOptionRefCnt;
ProFileReader *reader = new ProFileReader(m_proFileOption);
connect(reader, SIGNAL(errorFound(QString)),
this, SLOT(proFileParseError(QString)));
reader->setOutputDir(qt4ProFileNode->buildDir());
return reader;
}
void Qt4Project::destroyProFileReader(ProFileReader *reader)
{
delete reader;
if (!--m_proFileOptionRefCnt) {
QString dir = QFileInfo(m_fileInfo->fileName()).absolutePath();
if (!dir.endsWith(QLatin1Char('/')))
dir += QLatin1Char('/');
m_proFileOption->cache->discardFiles(dir);
delete m_proFileOption;
m_proFileOption = 0;
ProFileCacheManager::instance()->decRefCount();
}
}
Qt4ProFileNode *Qt4Project::rootProjectNode() const
{
return m_rootProjectNode;
}
return new Qt4ProjectConfigWidget(this);
QList<BuildConfigWidget*> Qt4Project::subConfigWidgets()
subWidgets << new Qt4BuildEnvironmentWidget(this);
return subWidgets;
}
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::checkForNewApplicationProjects()
{
// Check all new project nodes
// against all runConfigurations in all targets.
foreach (Qt4ProFileNode *qt4proFile, applicationProFiles()) {
foreach (Target *target, targets()) {
Qt4Target *qt4Target = static_cast<Qt4Target *>(target);
bool found = false;
foreach (RunConfiguration *rc, target->runConfigurations()) {
Qt4RunConfiguration *qtrc = qobject_cast<Qt4RunConfiguration *>(rc);
if (qtrc && qtrc->proFilePath() == qt4proFile->path()) {
found = true;
break;
}
}
if (!found) {
qt4Target->addRunConfigurationForPath(qt4proFile->path());
m_isApplication = true;
}
}
}
}
void Qt4Project::checkForDeletedApplicationProjects()
{
QStringList paths;
foreach (Qt4ProFileNode * node, applicationProFiles())
paths.append(node->path());
// qDebug()<<"Still existing paths :"<<paths;
QList<Qt4RunConfiguration *> removeList;
foreach (Target *target, targets()) {
foreach (RunConfiguration *rc, target->runConfigurations()) {
if (Qt4RunConfiguration *qt4rc = qobject_cast<Qt4RunConfiguration *>(rc)) {
if (!paths.contains(qt4rc->proFilePath())) {
removeList.append(qt4rc);
}
foreach (Qt4RunConfiguration *qt4rc, removeList)
target->removeRunConfiguration(qt4rc);
if (target->runConfigurations().isEmpty()) {
target->addRunConfiguration(new ProjectExplorer::CustomExecutableRunConfiguration(target));
m_isApplication = false;
}