Newer
Older
/**************************************************************************
** Copyright (c) 2009 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 <extensionsystem/pluginmanager.h>
#include <projectexplorer/nodesvisitor.h>
#include <projectexplorer/project.h>
#include <projectexplorer/customexecutablerunconfiguration.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_buildConfigurationFactory(new Qt4BuildConfigurationFactory(this)),
m_fileInfo(new Qt4ProjectFile(this, fileName, this)),
m_isApplication(true),
m_projectFiles(new Qt4ProjectFiles),
m_lastActiveQt4BuildConfiguration(0),
m_proFileOption(0)
m_updateCodeModelTimer.setSingleShot(true);
m_updateCodeModelTimer.setInterval(20);
connect(&m_updateCodeModelTimer, SIGNAL(timeout()), this, SLOT(updateCodeModel()));
}
Qt4Project::~Qt4Project()
{
Qt4BuildConfiguration *Qt4Project::activeQt4BuildConfiguration() const
{
return static_cast<Qt4BuildConfiguration *>(activeBuildConfiguration());
}
void Qt4Project::qtVersionChanged()
m_rootProjectNode->update();
}
void Qt4Project::updateFileList()
{
Qt4ProjectFiles newFiles;
ProjectFilesVisitor::findProjectFiles(m_rootProjectNode, &newFiles);
if (newFiles != *m_projectFiles) {
*m_projectFiles = newFiles;
emit fileListChanged();
if (debug)
qDebug() << Q_FUNC_INFO << *m_projectFiles;
}
}
bool Qt4Project::restoreSettingsImpl(PersistentSettingsReader &settingsReader)
if (buildConfigurations().isEmpty())
addDefaultBuild();
// Ensure that the qt version and tool chain in each build configuration is valid
foreach (BuildConfiguration *bc, buildConfigurations()) {
Qt4BuildConfiguration *qt4bc = static_cast<Qt4BuildConfiguration *>(bc);
qt4bc->qtVersionId();
qt4bc->toolChainType();
m_rootProjectNode = new Qt4ProFileNode(this, m_fileInfo->fileName(), this);
m_rootProjectNode->registerWatcher(m_nodesWatcher);
connect(m_nodesWatcher, SIGNAL(foldersAdded()), this, SLOT(updateFileList()));
connect(m_nodesWatcher, SIGNAL(foldersRemoved()), this, SLOT(updateFileList()));
connect(m_nodesWatcher, SIGNAL(filesAdded()), this, SLOT(updateFileList()));
connect(m_nodesWatcher, SIGNAL(filesRemoved()), this, SLOT(updateFileList()));
connect(m_nodesWatcher, SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *)),
this, SLOT(scheduleUpdateCodeModel(Qt4ProjectManager::Internal::Qt4ProFileNode *)));
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) {
RunConfiguration *rc(new Qt4RunConfiguration(this, node->path()));
addRunConfiguration(rc);
}
setActiveRunConfiguration(runConfigurations().first());
} else {
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, SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *)));
connect(this, SIGNAL(activeBuildConfigurationChanged()),
this, SLOT(slotActiveBuildConfigurationChanged()));
m_lastActiveQt4BuildConfiguration = activeQt4BuildConfiguration();
if (m_lastActiveQt4BuildConfiguration) {
connect(m_lastActiveQt4BuildConfiguration, SIGNAL(qtVersionChanged()),
this, SLOT(update()));
connect(m_lastActiveQt4BuildConfiguration, SIGNAL(targetInformationChanged()),
this, SIGNAL(targetInformationChanged()));
connect(m_lastActiveQt4BuildConfiguration, SIGNAL(environmentChanged()),
this, SIGNAL(environmentChanged()));
}
void Qt4Project::slotActiveBuildConfigurationChanged()
{
if (m_lastActiveQt4BuildConfiguration) {
disconnect(m_lastActiveQt4BuildConfiguration, SIGNAL(qtVersionChanged()),
this, SLOT(update()));
disconnect(m_lastActiveQt4BuildConfiguration, SIGNAL(targetInformationChanged()),
this, SIGNAL(targetInformationChanged()));
disconnect(m_lastActiveQt4BuildConfiguration, SIGNAL(environmentChanged()),
this, SIGNAL(environmentChanged()));
}
m_lastActiveQt4BuildConfiguration = activeQt4BuildConfiguration();
if (m_lastActiveQt4BuildConfiguration) {
connect(m_lastActiveQt4BuildConfiguration, SIGNAL(qtVersionChanged()),
this, SLOT(update()));
connect(m_lastActiveQt4BuildConfiguration, SIGNAL(targetInformationChanged()),
this, SIGNAL(targetInformationChanged()));
connect(m_lastActiveQt4BuildConfiguration, SIGNAL(environmentChanged()),
this, SIGNAL(environmentChanged()));
}
emit environmentChanged();
emit targetInformationChanged();
}
void Qt4Project::saveSettingsImpl(ProjectExplorer::PersistentSettingsWriter &writer)
{
Project::saveSettingsImpl(writer);
}
ProjectExplorer::IBuildConfigurationFactory *Qt4Project::buildConfigurationFactory() const
{
return m_buildConfigurationFactory;
}
Qt4BuildConfiguration *Qt4Project::addQt4BuildConfiguration(QString displayName, QtVersion *qtversion,
QtVersion::QmakeBuildConfigs qmakeBuildConfiguration,
QStringList additionalArguments)
{
bool debug = qmakeBuildConfiguration & QtVersion::DebugBuild;
// Add the buildconfiguration
Qt4BuildConfiguration *bc = new Qt4BuildConfiguration(this);
bc->setDisplayName(displayName);
bc->insertBuildStep(0, qmakeStep);
bc->insertBuildStep(1, makeStep);
cleanStep->setUserArguments(QStringList() << "clean");
bc->insertCleanStep(0, cleanStep);
if (!additionalArguments.isEmpty())
qmakeStep->setUserArguments(additionalArguments);
// set some options for qmake and make
if (qmakeBuildConfiguration & QtVersion::BuildAll) // debug_and_release => explicit targets
makeStep->setUserArguments(QStringList() << (debug ? "debug" : "release"));
bc->setQMakeBuildConfiguration(qmakeBuildConfiguration);
// Finally set the qt version
bool defaultQtVersion = (qtversion == 0);
if (defaultQtVersion)
bc->setQtVersion(qtversion->uniqueId());
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(Qt4ProjectManager::Internal::Qt4ProFileNode *pro)
m_proFilesForCodeModelUpdate.append(pro);
}
void Qt4Project::updateCodeModel()
{
if (debug)
qDebug()<<"Qt4Project::updateCodeModel()";
Qt4BuildConfiguration *activeBC = activeQt4BuildConfiguration();

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

hjk
committed
if (!modelmanager)
// Collect global headers/defines
QStringList predefinedIncludePaths;
QStringList predefinedFrameworkPaths;
QByteArray predefinedMacros;
QList<HeaderPath> allHeaderPaths;
if (tc) {
predefinedMacros = tc->predefinedMacros();
allHeaderPaths = tc->systemHeaderPaths();
//qDebug()<<"Predifined Macros";
//qDebug()<<tc->predefinedMacros();
//qDebug()<<"";
//qDebug()<<"System Header Paths";
//foreach(const HeaderPath &hp, tc->systemHeaderPaths())
// qDebug()<<hp.path();
foreach (HeaderPath headerPath, allHeaderPaths) {
if (headerPath.kind() == HeaderPath::FrameworkHeaderPath)
predefinedFrameworkPaths.append(headerPath.path());
predefinedIncludePaths.append(headerPath.path());
const QHash<QString, QString> versionInfo = activeBC->qtVersion()->versionInfo();
const QString newQtIncludePath = versionInfo.value(QLatin1String("QT_INSTALL_HEADERS"));
predefinedIncludePaths.append(newQtIncludePath);
QDir dir(newQtIncludePath);
foreach (QFileInfo info, dir.entryInfoList(QDir::Dirs)) {
const QString path = info.fileName();
if (path == QLatin1String("Qt"))
continue; // skip $QT_INSTALL_HEADERS/Qt. There's no need to include it.
else if (path.startsWith(QLatin1String("Qt")) || path == QLatin1String("phonon"))
predefinedIncludePaths.append(info.absoluteFilePath());
FindQt4ProFiles findQt4ProFiles;
QList<Qt4ProFileNode *> proFiles = findQt4ProFiles(rootProjectNode());
QByteArray definedMacros = predefinedMacros;
QStringList allIncludePaths = predefinedIncludePaths;
QStringList allFrameworkPaths = predefinedFrameworkPaths;
const QString newQtLibsPath = versionInfo.value(QLatin1String("QT_INSTALL_LIBS"));
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");
// Collect per .pro file information
m_codeModelInfo.clear();
Internal::CodeModelInfo info;
info.defines = predefinedMacros;
info.includes = predefinedIncludePaths;
info.frameworkPaths = predefinedFrameworkPaths;
// Add custom defines
foreach (const QString def, pro->variableValue(DefinesVar)) {
definedMacros += "#define ";
info.defines += "#define ";
const int index = def.indexOf(QLatin1Char('='));
if (index == -1) {
definedMacros += def.toLatin1();
definedMacros += " 1\n";
info.defines += def.toLatin1();
info.defines += " 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';
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);
#if 0
// Disable for now, we need better .pro parsing first
// Also the information gathered here isn't used
// by the codemodel yet
{ // 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.frameworkPaths = allFrameworkPaths;
#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 beeing 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());
// Dump things out
// This is debugging output...
// qDebug()<<"CodeModel stuff:";
// QMap<QString, CodeModelInfo>::const_iterator it, end;
// end = m_codeModelInfo.constEnd();
// for(it = m_codeModelInfo.constBegin(); it != end; ++it) {
// qDebug()<<"File: "<<it.key()<<"\nIncludes:"<<it.value().includes<<"\nDefines"<<it.value().defines<<"\n";
// }
// qDebug()<<"----------------------------";
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) {
if (pinfo.defines != predefinedMacros ||
pinfo.includePaths != allIncludePaths ||
pinfo.frameworkPaths != allFrameworkPaths) {
pinfo.sourceFiles.append(QLatin1String("<configuration>"));
}
pinfo.defines = predefinedMacros;
// pinfo.defines += definedMacros; // ### FIXME: me
pinfo.includePaths = allIncludePaths;
pinfo.frameworkPaths = allFrameworkPaths;
pinfo.sourceFiles = files;
modelmanager->updateProjectInfo(pinfo);
modelmanager->updateSourceFiles(pinfo.sourceFiles);
// TODO use this information
// These are the pro files that were actually changed
// if the list is empty we are at the initial stage
// TODO check that this also works if pro files get added
// and removed
m_proFilesForCodeModelUpdate.clear();
}
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
// */
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
void Qt4Project::update()
{
m_rootProjectNode->update();
//updateCodeModel();
}
/*!
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::displayName() 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];
}
return files;
}
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
// 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 (Qt4BuildConfiguration *qt4bc = activeQt4BuildConfiguration()) {
QtVersion *version = qt4bc->qtVersion();
if (version->isValid())
m_proFileOption->properties = version->versionInfo();
}
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;
}
}
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
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
Qt4TargetInformation Qt4Project::targetInformation(Qt4BuildConfiguration *buildConfiguration,
const QString &proFilePath)
{
Qt4TargetInformation info;
Qt4ProFileNode *proFileNode = rootProjectNode()->findProFileFor(proFilePath);
if (!proFileNode) {
info.error = Qt4TargetInformation::InvalidProjectError;
return info;
}
ProFileReader *reader = createProFileReader(proFileNode);
reader->setCumulative(false);
// Find out what flags we pass on to qmake
QStringList addedUserConfigArguments;
QStringList removedUserConfigArguments;
buildConfiguration->getConfigCommandLineArguments(&addedUserConfigArguments, &removedUserConfigArguments);
reader->setConfigCommandLineArguments(addedUserConfigArguments, removedUserConfigArguments);
if (!reader->readProFile(proFilePath)) {
destroyProFileReader(reader);
info.error = Qt4TargetInformation::ProParserError;
return info;
}
// Extract data
const QDir baseProjectDirectory = QFileInfo(file()->fileName()).absoluteDir();
const QString relSubDir = baseProjectDirectory.relativeFilePath(QFileInfo(proFilePath).path());
const QDir baseBuildDirectory = buildConfiguration->buildDirectory();
const QString baseDir = baseBuildDirectory.absoluteFilePath(relSubDir);
//qDebug()<<relSubDir<<baseDir;
// Working Directory
if (reader->contains("DESTDIR")) {
//qDebug() << "reader contains destdir:" << reader->value("DESTDIR");
info.workingDir = reader->value("DESTDIR");
if (QDir::isRelativePath(info.workingDir)) {
info.workingDir = baseDir + QLatin1Char('/') + info.workingDir;
//qDebug() << "was relative and expanded to" << info.workingDir;
}
} else {
//qDebug() << "reader didn't contain DESTDIR, setting to " << baseDir;
info.workingDir = baseDir;
}
info.target = reader->value("TARGET");
if (info.target.isEmpty())
info.target = QFileInfo(proFilePath).baseName();
#if defined (Q_OS_MAC)
if (reader->values("CONFIG").contains("app_bundle")) {
info.workingDir += QLatin1Char('/')
+ info.target
+ QLatin1String(".app/Contents/MacOS");
}
#endif
info.workingDir = QDir::cleanPath(info.workingDir);
QString wd = info.workingDir;
if (!reader->contains("DESTDIR")
&& reader->values("CONFIG").contains("debug_and_release")
&& reader->values("CONFIG").contains("debug_and_release_target")) {
// If we don't have a destdir and debug and release is set
// then the executable is in a debug/release folder
//qDebug() << "reader has debug_and_release_target";
QString qmakeBuildConfig = "release";
if (buildConfiguration->qmakeBuildConfiguration() & QtVersion::DebugBuild)
qmakeBuildConfig = "debug";
wd += QLatin1Char('/') + qmakeBuildConfig;
}
info.executable = QDir::cleanPath(wd + QLatin1Char('/') + info.target);
//qDebug() << "##### updateTarget sets:" << info.workingDir << info.executable;
#if defined (Q_OS_WIN)
info.executable += QLatin1String(".exe");
#endif
destroyProFileReader(reader);
info.error = Qt4TargetInformation::NoError;
return info;
}
Qt4ProFileNode *Qt4Project::rootProjectNode() const
{
return m_rootProjectNode;
}
return new Qt4ProjectConfigWidget(this);
QList<BuildConfigWidget*> Qt4Project::subConfigWidgets()
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
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::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 (RunConfiguration *rc, runConfigurations()) {
Qt4RunConfiguration *qtrc = qobject_cast<Qt4RunConfiguration *>(rc);
if (qtrc && qtrc->proFilePath() == qt4proFile->path()) {
found = true;
break;
}
}
if (!found) {
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<Qt4RunConfiguration *> removeList;
foreach (RunConfiguration *rc, runConfigurations()) {
if (Qt4RunConfiguration *qt4rc = qobject_cast<Qt4RunConfiguration *>(rc)) {
if (!paths.contains(qt4rc->proFilePath())) {
removeList.append(qt4rc);
// qDebug()<<"Removing runConfiguration for "<<qt4rc->proFilePath();
foreach (Qt4RunConfiguration *qt4rc, removeList) {