Fixes: Mem leak in the pro file parser.

Details:  ProFileCache be gone, as is ManagedProFile, not to be missed.
Drastically simplified how ownership works.
This commit is contained in:
dt
2008-12-02 18:14:06 +01:00
parent 4eaa9f5052
commit bd827512bb
14 changed files with 141 additions and 551 deletions

View File

@@ -1519,12 +1519,9 @@ bool ProFileEvaluator::Private::evaluateFile(const QString &fileName, bool *resu
if (pro) { if (pro) {
m_profileStack.push(pro); m_profileStack.push(pro);
ok = (currentProFile() ? pro->Accept(this) : false); ok = (currentProFile() ? pro->Accept(this) : false);
if (ok) { m_profileStack.pop();
if (m_profileStack.count() > 0) { q->releaseParsedProFile(pro);
ProFile *pro = m_profileStack.pop();
q->releaseParsedProFile(pro);
}
}
if (result) if (result)
*result = true; *result = true;
} else { } else {

View File

@@ -1,363 +0,0 @@
/***************************************************************************
**
** 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 "qt4nodes.h"
#include "qt4projectmanager.h"
#include "profilecache.h"
#include "proparser/prowriter.h"
#include "proitems.h"
#include "qt4projectmanagerconstants.h"
#include <coreplugin/filemanager.h>
#include <utils/reloadpromptutils.h>
#include <QtCore/QFileInfo>
#include <QtCore/QDebug>
#include <QtGui/QMainWindow>
#include <QtCore/QDir>
using namespace Qt4ProjectManager;
using namespace Qt4ProjectManager::Internal;
namespace {
bool debug = false;
}
namespace Qt4ProjectManager {
namespace Internal {
class ManagedProjectFile
: public Core::IFile
{
Q_OBJECT
public:
ManagedProjectFile(ProFileCache *parent, ProFile *profile);
virtual ~ManagedProjectFile();
ProFile *profile();
void setProfile(ProFile *profile);
bool isOutOfSync() { return m_outOfSync; }
void setOutOfSync(bool state) { m_outOfSync = state; }
// Core::IFile
bool save(const QString &fileName = QString());
QString fileName() const;
QString defaultPath() const;
QString suggestedFileName() const;
virtual QString mimeType() const;
bool isModified() const;
bool isReadOnly() const;
bool isSaveAsAllowed() const;
void modified(ReloadBehavior *behavior);
signals:
void changed();
private:
const QString m_mimeType;
ProFile *m_profile;
ProFileCache *m_cache;
bool m_outOfSync;
};
} // namespace Internal
} // namespace Qt4ProFileNodemanager
ManagedProjectFile::ManagedProjectFile(ProFileCache *parent, ProFile *profile) :
Core::IFile(parent),
m_mimeType(QLatin1String(Qt4ProjectManager::Constants::PROFILE_MIMETYPE)),
m_profile(profile),
m_cache(parent),
m_outOfSync(false)
{
}
ManagedProjectFile::~ManagedProjectFile()
{
delete m_profile;
}
ProFile *ManagedProjectFile::profile()
{
return m_profile;
}
void ManagedProjectFile::setProfile(ProFile *profile)
{
m_outOfSync = false;
if (profile == m_profile)
return;
delete m_profile;
m_profile = profile;
}
bool ManagedProjectFile::save(const QString &)
{
if (!m_profile)
return false;
ProWriter pw;
bool ok = pw.write(m_profile, m_profile->fileName());
m_profile->setModified(false);
m_cache->notifyModifiedChanged(m_profile);
return ok;
}
QString ManagedProjectFile::fileName() const
{
return QDir::cleanPath(m_profile->fileName());
}
QString ManagedProjectFile::defaultPath() const
{
QFileInfo fi(fileName());
return fi.absolutePath();
}
QString ManagedProjectFile::suggestedFileName() const
{
QFileInfo fi(fileName());
return fi.fileName();
}
bool ManagedProjectFile::isModified() const
{
return m_profile->isModified();
}
bool ManagedProjectFile::isReadOnly() const
{
QFileInfo fi(fileName());
return !fi.isWritable();
}
bool ManagedProjectFile::isSaveAsAllowed() const
{
return false;
}
void ManagedProjectFile::modified(ReloadBehavior *behavior)
{
switch (*behavior) {
case Core::IFile::ReloadNone:
case Core::IFile::ReloadPermissions:
return;
case Core::IFile::ReloadAll:
m_cache->notifyChanged(QSet<ProFile *>() << m_profile, true);
return;
case Core::IFile::AskForReload:
break;
}
const QString prompt = tr("The project file %1 has changed outside Qt Creator. Do you want to reload it?").arg(m_profile->fileName());
switch (const Core::Utils::ReloadPromptAnswer answer = Core::Utils::reloadPrompt(tr("File Changed"), prompt, m_cache->manager()->core()->mainWindow())) {
case Core::Utils::ReloadAll:
case Core::Utils::ReloadCurrent:
m_cache->notifyChanged(QSet<ProFile *>() << m_profile, true);
if (answer == Core::Utils::ReloadAll)
*behavior = Core::IFile::ReloadAll;
break;
case Core::Utils::ReloadSkipCurrent:
break;
case Core::Utils::ReloadNone:
*behavior = Core::IFile::ReloadNone;
break;
}
}
QString ManagedProjectFile::mimeType() const
{
return m_mimeType;
}
#include "profilecache.moc"
ProFileCache::ProFileCache(Qt4Manager *manager)
: QObject(manager)
{
m_manager = manager;
}
ProFileCache::~ProFileCache()
{
qDeleteAll(m_profiles.values());
m_profiles.clear();
m_projects.clear();
}
void ProFileCache::notifyModifiedChanged(ProFile *profile)
{
QList<Qt4ProFileNode *> pros = m_projects.values(profile->fileName());
for (int i=0; i<pros.count(); ++i) {
Qt4ProFileNode *pro = pros.at(i);
pro->update();
}
}
void ProFileCache::notifyChanged(const QSet<ProFile *> &profiles, bool external)
{
QList<Qt4ProFileNode *> notifyProjects;
foreach (ProFile *profile, profiles) {
QList<Qt4ProFileNode *> pros = m_projects.values(profile->fileName());
if (external) {
ManagedProjectFile *file = m_profiles.value(profile->fileName());
if (file)
file->setOutOfSync(true);
}
QList<Qt4ProFileNode *>::const_iterator i = pros.constBegin();
for (; i != pros.constEnd(); ++i) {
if (!notifyProjects.contains(*i))
notifyProjects << *i;
}
}
QList<Qt4ProFileNode *>::const_iterator i = notifyProjects.constBegin();
while (i != notifyProjects.constEnd()) {
(*i)->update();
++i;
}
}
void ProFileCache::updateDependencies(const QSet<ProFile *> &files, Qt4ProFileNode *project)
{
// just remove and add files that have changed
const QSet<QString> &oldFiles = m_projects.keys(project).toSet();
QSet<QString> newFiles;
QList<Core::IFile *> addedFiles;
foreach (ProFile *file, files) {
newFiles << file->fileName();
if (!m_profiles.contains(file->fileName())) {
ManagedProjectFile *profile = new ManagedProjectFile(this, file);
m_profiles.insert(file->fileName(), profile);
if (debug)
qDebug() << "ProFileCache - inserting file " << file->fileName();
addedFiles << profile;
} else {
ManagedProjectFile *profile = m_profiles.value(file->fileName());
profile->setProfile(file);
}
}
m_manager->core()->fileManager()->addFiles(addedFiles);
if (oldFiles.isEmpty()) {
connect(project, SIGNAL(destroyed(QObject *)),
this, SLOT(removeProject(QObject *)));
}
foreach (const QString &profile, (oldFiles - newFiles).toList()) {
removeFile(profile, project);
}
foreach (const QString &profile, (newFiles - oldFiles).toList()) {
m_projects.insertMulti(profile, project);
}
}
QStringList ProFileCache::dependencies(Qt4ProFileNode *project) const
{
return m_projects.keys(project);
}
ProFile *ProFileCache::proFile(const QString &file) const
{
QSet<ProFile *> profiles = proFiles(QStringList(file));
if (profiles.isEmpty())
return 0;
return profiles.toList().first();
}
QSet<ProFile *> ProFileCache::proFiles(const QStringList &files) const
{
QSet<ProFile *> results;
foreach (const QString &file, files) {
ManagedProjectFile *managedFile = m_profiles.value(file, 0);
if (managedFile && !managedFile->isOutOfSync()) {
results << managedFile->profile();
}
}
return results;
}
QSet<ProFile *> ProFileCache::proFiles(Qt4ProFileNode *project) const
{
return proFiles(m_projects.keys(project));
}
Core::IFile *ProFileCache::fileInterface(const QString &file)
{
return m_profiles.value(file);
}
void ProFileCache::removeFile(const QString &file, Qt4ProFileNode *proj)
{
QList<Qt4ProFileNode*> projects = m_projects.values(file);
m_projects.remove(file);
projects.removeAll(proj);
if (!projects.isEmpty()) {
foreach (Qt4ProFileNode *p, projects) {
m_projects.insert(file, p);
}
} else {
ManagedProjectFile *mp = m_profiles.value(file, 0);
if (debug)
qDebug() << "ProFileCache - removing file " << file;
m_manager->core()->fileManager()->removeFile(mp);
m_profiles.remove(file);
delete mp;
}
}
void ProFileCache::removeProject(QObject *obj)
{
// Cannot use qobject_cast here because
// it is triggered by destroyed signal
Qt4ProFileNode *proj = static_cast<Qt4ProFileNode*>(obj);
QStringList files = m_projects.keys(proj);
foreach (const QString &file, files) {
removeFile(file, proj);
}
}

View File

@@ -1,98 +0,0 @@
/***************************************************************************
**
** 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.
**
***************************************************************************/
#ifndef PROFILECACHE_H
#define PROFILECACHE_H
#include <QtCore/QObject>
#include <QtCore/QSet>
#include <QtCore/QStringList>
#include <QtCore/QMap>
QT_BEGIN_NAMESPACE
class ProFile;
QT_END_NAMESPACE
namespace Core {
class IFile;
}
namespace Qt4ProjectManager {
//class Qt4Project;
class Qt4Manager;
namespace Internal {
class Qt4ProFileNode;
class ManagedProjectFile;
class ProFileCache : public QObject
{
Q_OBJECT
public:
ProFileCache(Qt4Manager *manager);
~ProFileCache();
// does not result in a reparse or resolve
void notifyModifiedChanged(ProFile *profile);
// if external is true we need to reparse, it it's false we only resolve
void notifyChanged(const QSet<ProFile *> &profiles, bool external = false);
void updateDependencies(const QSet<ProFile *> &files, Qt4ProFileNode *projectNode);
QStringList dependencies(Qt4ProFileNode *projectNode) const;
ProFile *proFile(const QString &filename) const;
QSet<ProFile *> proFiles(const QStringList &files) const;
QSet<ProFile *> proFiles(Qt4ProFileNode *projectNode) const;
Core::IFile *fileInterface(const QString &filename);
inline Qt4Manager *manager() const { return m_manager; }
protected slots:
void removeProject(QObject *obj);
private:
void removeFile(const QString &profile, Qt4ProFileNode *projectNode);
Qt4Manager *m_manager;
QMultiMap<QString, Qt4ProFileNode *> m_projects;
QMap<QString, ManagedProjectFile *> m_profiles;
};
} // namespace Internal
} // namespace Qt4ProjectManager
#endif // PROFILECACHE_H

View File

@@ -36,7 +36,6 @@
#include "profilehighlighter.h" #include "profilehighlighter.h"
#include "qt4projectmanager.h" #include "qt4projectmanager.h"
#include "qt4projectmanagerconstants.h" #include "qt4projectmanagerconstants.h"
#include "profilecache.h"
#include "profileeditorfactory.h" #include "profileeditorfactory.h"
#include "proeditormodel.h" #include "proeditormodel.h"
#include "procommandmanager.h" #include "procommandmanager.h"
@@ -51,6 +50,7 @@
#include <QtCore/QFileInfo> #include <QtCore/QFileInfo>
#include <QtGui/QTextEdit> #include <QtGui/QTextEdit>
#include <QtGui/QHeaderView> #include <QtGui/QHeaderView>
#include <QtCore/QDebug>
using namespace ExtensionSystem; using namespace ExtensionSystem;
using namespace Core; using namespace Core;
@@ -150,9 +150,7 @@ ProFileDocument::ProFileDocument(Qt4Manager *manager)
bool ProFileDocument::save(const QString &name) bool ProFileDocument::save(const QString &name)
{ {
if (BaseTextDocument::save(name)) { if (BaseTextDocument::save(name)) {
ProFile *profile = m_manager->proFileCache()->proFile(name); m_manager->notifyChanged(name);
if (profile)
m_manager->proFileCache()->notifyChanged(QSet<ProFile*>() << profile, true);
return true; return true;
} }
return false; return false;

View File

@@ -32,7 +32,6 @@
***************************************************************************/ ***************************************************************************/
#include "profilereader.h" #include "profilereader.h"
#include "profilecache.h"
#include <QtCore/QDir> #include <QtCore/QDir>
#include <QtCore/QDebug> #include <QtCore/QDebug>
@@ -40,11 +39,16 @@
using namespace Qt4ProjectManager; using namespace Qt4ProjectManager;
using namespace Qt4ProjectManager::Internal; using namespace Qt4ProjectManager::Internal;
ProFileReader::ProFileReader(ProFileCache *cache) ProFileReader::ProFileReader()
: m_cache(cache)
{ {
} }
ProFileReader::~ProFileReader()
{
foreach(ProFile *pf, m_proFiles)
delete pf;
}
void ProFileReader::setQtVersion(QtVersion *qtVersion) { void ProFileReader::setQtVersion(QtVersion *qtVersion) {
QHash<QString, QStringList> additionalVariables; QHash<QString, QStringList> additionalVariables;
additionalVariables.insert(QString("QT_BUILD_TREE"), QStringList() << qtVersion->path()); additionalVariables.insert(QString("QT_BUILD_TREE"), QStringList() << qtVersion->path());
@@ -72,6 +76,7 @@ bool ProFileReader::readProFile(const QString &fileName)
return false; return false;
} }
m_includeFiles.insert(fn, pro); m_includeFiles.insert(fn, pro);
m_proFiles.append(pro);
return accept(pro); return accept(pro);
} }
@@ -84,23 +89,23 @@ ProFile *ProFileReader::parsedProFile(const QString &fileName)
ProFile *pro = ProFileEvaluator::parsedProFile(fn); ProFile *pro = ProFileEvaluator::parsedProFile(fn);
if (pro) { if (pro) {
m_includeFiles.insert(fn, pro); m_includeFiles.insert(fn, pro);
m_proFiles.append(pro);
} }
return pro; return pro;
} }
void ProFileReader::releaseParsedProFile(ProFile */*proFile*/) void ProFileReader::releaseParsedProFile(ProFile *)
{ {
return; return;
} }
ProFile *ProFileReader::proFileFromCache(const QString &fileName) const ProFile *ProFileReader::proFileFromCache(const QString &fileName) const
{ {
QString fn = QFileInfo(fileName).filePath(); QString fn = QFileInfo(fileName).filePath();
ProFile *pro = 0; ProFile *pro = 0;
if (m_includeFiles.contains(fn)) if (m_includeFiles.contains(fn))
pro = m_includeFiles.value(fn); pro = m_includeFiles.value(fn);
else
pro = m_cache->proFile(fn); // this can expand to null
return pro; return pro;
} }

View File

@@ -43,14 +43,14 @@
namespace Qt4ProjectManager { namespace Qt4ProjectManager {
namespace Internal { namespace Internal {
class ProFileCache;
class ProFileReader : public QObject, public ProFileEvaluator class ProFileReader : public QObject, public ProFileEvaluator
{ {
Q_OBJECT Q_OBJECT
public: public:
ProFileReader(ProFileCache *cache); ProFileReader();
~ProFileReader();
void setQtVersion(QtVersion *qtVersion); void setQtVersion(QtVersion *qtVersion);
bool readProFile(const QString &fileName); bool readProFile(const QString &fileName);
@@ -63,7 +63,7 @@ public:
const QString &baseDirectory, const QString &baseDirectory,
PathValuesMode mode, PathValuesMode mode,
const ProFile *pro = 0) const; const ProFile *pro = 0) const;
ProFile *proFileFromCache(const QString &fileName) const;
signals: signals:
void errorFound(const QString &error); void errorFound(const QString &error);
@@ -75,9 +75,8 @@ private:
virtual void errorMessage(const QString &msg); virtual void errorMessage(const QString &msg);
private: private:
ProFile *proFileFromCache(const QString &fileName) const;
ProFileCache *m_cache;
QMap<QString, ProFile *> m_includeFiles; QMap<QString, ProFile *> m_includeFiles;
QList<ProFile *> m_proFiles;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -87,7 +87,8 @@ Qt4PriFileNode::Qt4PriFileNode(Qt4Project *project,
m_projectFilePath(filePath), m_projectFilePath(filePath),
m_projectDir(QFileInfo(filePath).absolutePath()), m_projectDir(QFileInfo(filePath).absolutePath()),
m_includeFile(0), m_includeFile(0),
m_saveTimer(new QTimer(this)) m_saveTimer(new QTimer(this)),
m_reader(0)
{ {
Q_ASSERT(project); Q_ASSERT(project);
setFolderName(QFileInfo(filePath).baseName()); setFolderName(QFileInfo(filePath).baseName());
@@ -104,6 +105,7 @@ void Qt4PriFileNode::update(ProFile *includeFile, ProFileReader *reader)
{ {
Q_ASSERT(includeFile); Q_ASSERT(includeFile);
Q_ASSERT(reader); Q_ASSERT(reader);
m_reader = reader;
m_includeFile = includeFile; m_includeFile = includeFile;
@@ -363,10 +365,6 @@ void Qt4PriFileNode::changeFiles(const FileType fileType,
return; return;
// Check if file is readonly // Check if file is readonly
ProFileCache *cache = m_project->qt4ProjectManager()->proFileCache();
if (cache->fileInterface(m_projectFilePath)->isReadOnly() && !priFileWritable(m_projectFilePath))
return;
ProEditorModel proModel; ProEditorModel proModel;
proModel.setProFiles(QList<ProFile*>() << m_includeFile); proModel.setProFiles(QList<ProFile*>() << m_includeFile);
@@ -449,22 +447,26 @@ void Qt4PriFileNode::changeFiles(const FileType fileType,
void Qt4PriFileNode::save() void Qt4PriFileNode::save()
{ {
// Prevent any reload questions; just reload
Core::FileManager *fileManager = m_core->fileManager(); Core::FileManager *fileManager = m_core->fileManager();
ProFileCache *cache = m_project->qt4ProjectManager()->proFileCache();
QList<Core::IFile *> allFileHandles = fileManager->managedFiles(m_includeFile->fileName()); QList<Core::IFile *> allFileHandles = fileManager->managedFiles(m_includeFile->fileName());
Core::IFile *modifiedFileHandle = cache->fileInterface(m_includeFile->fileName()); Core::IFile *modifiedFileHandle = 0;
foreach(Core::IFile *file, allFileHandles)
if (file->fileName() == m_includeFile->fileName())
modifiedFileHandle = file;
fileManager->blockFileChange(modifiedFileHandle); if (modifiedFileHandle)
modifiedFileHandle->save(); fileManager->blockFileChange(modifiedFileHandle);
fileManager->unblockFileChange(modifiedFileHandle); ProWriter pw;
bool ok = pw.write(m_includeFile, m_includeFile->fileName());
m_includeFile->setModified(false);
m_project->qt4ProjectManager()->notifyChanged(m_includeFile->fileName());
if (modifiedFileHandle)
fileManager->unblockFileChange(modifiedFileHandle);
Core::IFile::ReloadBehavior tempBehavior = Core::IFile::ReloadBehavior tempBehavior =
Core::IFile::ReloadAll; Core::IFile::ReloadAll;
foreach (Core::IFile *file, allFileHandles) { foreach (Core::IFile *file, allFileHandles)
file->modified(&tempBehavior); file->modified(&tempBehavior);
}
} }
/* /*
@@ -516,8 +518,8 @@ Qt4ProFileNode::Qt4ProFileNode(Qt4Project *project,
// own stuff // own stuff
m_projectType(InvalidProject), m_projectType(InvalidProject),
m_isQBuildProject(false), m_isQBuildProject(false),
m_cache(project->qt4ProjectManager()->proFileCache()), m_dirWatcher(new DirectoryWatcher(this)),
m_dirWatcher(new DirectoryWatcher(this)) m_reader(0)
{ {
if (parent) if (parent)
setParent(parent); setParent(parent);
@@ -530,6 +532,11 @@ Qt4ProFileNode::Qt4ProFileNode(Qt4Project *project,
this, SLOT(update())); this, SLOT(update()));
} }
Qt4ProFileNode::~Qt4ProFileNode()
{
delete m_reader;
}
bool Qt4ProFileNode::hasTargets() const bool Qt4ProFileNode::hasTargets() const
{ {
return (projectType() == ApplicationTemplate) || (projectType() == LibraryTemplate); return (projectType() == ApplicationTemplate) || (projectType() == LibraryTemplate);
@@ -547,10 +554,11 @@ QStringList Qt4ProFileNode::variableValue(const Qt4Variable var) const
void Qt4ProFileNode::update() void Qt4ProFileNode::update()
{ {
ProFileReader *reader = createProFileReader(); delete m_reader;
if (!reader->readProFile(m_projectFilePath)) { m_reader = createProFileReader();
if (!m_reader->readProFile(m_projectFilePath)) {
m_project->proFileParseError(tr("Error while parsing file %1. Giving up.").arg(m_projectFilePath)); m_project->proFileParseError(tr("Error while parsing file %1. Giving up.").arg(m_projectFilePath));
delete reader; delete m_reader;
invalidate(); invalidate();
return; return;
} }
@@ -565,7 +573,7 @@ void Qt4ProFileNode::update()
#endif #endif
Qt4ProjectType projectType = InvalidProject; Qt4ProjectType projectType = InvalidProject;
switch (reader->templateType()) { switch (m_reader->templateType()) {
case ProFileEvaluator::TT_Unknown: case ProFileEvaluator::TT_Unknown:
case ProFileEvaluator::TT_Application: { case ProFileEvaluator::TT_Application: {
projectType = ApplicationTemplate; projectType = ApplicationTemplate;
@@ -604,11 +612,11 @@ void Qt4ProFileNode::update()
ProFile *fileForCurrentProject = 0; ProFile *fileForCurrentProject = 0;
{ {
if (projectType == SubDirsTemplate) { if (projectType == SubDirsTemplate) {
foreach (const QString &subDirProject, subDirsPaths(reader)) foreach (const QString &subDirProject, subDirsPaths(m_reader))
newProjectFiles << subDirProject; newProjectFiles << subDirProject;
} }
foreach (ProFile *includeFile, reader->includeFiles()) { foreach (ProFile *includeFile, m_reader->includeFiles()) {
if (includeFile->fileName() == m_projectFilePath) { // this file if (includeFile->fileName() == m_projectFilePath) { // this file
fileForCurrentProject = includeFile; fileForCurrentProject = includeFile;
} else { } else {
@@ -637,7 +645,7 @@ void Qt4ProFileNode::update()
Qt4PriFileNode *priFileNode Qt4PriFileNode *priFileNode
= new Qt4PriFileNode(m_project, = new Qt4PriFileNode(m_project,
*newProjectFileIter); *newProjectFileIter);
priFileNode->update(file, reader); priFileNode->update(file, m_reader);
toAdd << priFileNode; toAdd << priFileNode;
} else { } else {
toAdd << createSubProFileNode(*newProjectFileIter); toAdd << createSubProFileNode(*newProjectFileIter);
@@ -646,7 +654,7 @@ void Qt4ProFileNode::update()
} else { // *existingNodeIter->path() == *newProjectFileIter } else { // *existingNodeIter->path() == *newProjectFileIter
if (ProFile *file = includeFiles.value(*newProjectFileIter)) { if (ProFile *file = includeFiles.value(*newProjectFileIter)) {
Qt4PriFileNode *priFileNode = static_cast<Qt4PriFileNode*>(*existingNodeIter); Qt4PriFileNode *priFileNode = static_cast<Qt4PriFileNode*>(*existingNodeIter);
priFileNode->update(file, reader); priFileNode->update(file, m_reader);
} }
++existingNodeIter; ++existingNodeIter;
@@ -662,7 +670,7 @@ void Qt4ProFileNode::update()
Qt4PriFileNode *priFileNode Qt4PriFileNode *priFileNode
= new Qt4PriFileNode(m_project, = new Qt4PriFileNode(m_project,
*newProjectFileIter); *newProjectFileIter);
priFileNode->update(file, reader); priFileNode->update(file, m_reader);
toAdd << priFileNode; toAdd << priFileNode;
} else { } else {
toAdd << createSubProFileNode(*newProjectFileIter); toAdd << createSubProFileNode(*newProjectFileIter);
@@ -675,15 +683,15 @@ void Qt4ProFileNode::update()
if (!toAdd.isEmpty()) if (!toAdd.isEmpty())
addProjectNodes(toAdd); addProjectNodes(toAdd);
Qt4PriFileNode::update(fileForCurrentProject, reader); Qt4PriFileNode::update(fileForCurrentProject, m_reader);
// update other variables // update other variables
QHash<Qt4Variable, QStringList> newVarValues; QHash<Qt4Variable, QStringList> newVarValues;
newVarValues[CxxCompilerVar] << reader->value(QLatin1String("QMAKE_CXX")); newVarValues[CxxCompilerVar] << m_reader->value(QLatin1String("QMAKE_CXX"));
newVarValues[DefinesVar] = reader->values(QLatin1String("DEFINES")); newVarValues[DefinesVar] = m_reader->values(QLatin1String("DEFINES"));
newVarValues[IncludePathVar] = includePaths(reader); newVarValues[IncludePathVar] = includePaths(m_reader);
newVarValues[UiDirVar] = uiDirPaths(reader); newVarValues[UiDirVar] = uiDirPaths(m_reader);
newVarValues[MocDirVar] = mocDirPaths(reader); newVarValues[MocDirVar] = mocDirPaths(m_reader);
if (m_varValues != newVarValues) { if (m_varValues != newVarValues) {
m_varValues = newVarValues; m_varValues = newVarValues;
@@ -693,9 +701,7 @@ void Qt4ProFileNode::update()
} }
updateGeneratedFiles(); updateGeneratedFiles();
m_project->qt4ProjectManager()->proFileCache()->updateDependencies(reader->includeFiles().toSet(), this);
delete reader;
foreach (NodesWatcher *watcher, watchers()) foreach (NodesWatcher *watcher, watchers())
if (Qt4NodesWatcher *qt4Watcher = qobject_cast<Qt4NodesWatcher*>(watcher)) if (Qt4NodesWatcher *qt4Watcher = qobject_cast<Qt4NodesWatcher*>(watcher))
emit qt4Watcher->proFileUpdated(this); emit qt4Watcher->proFileUpdated(this);
@@ -812,7 +818,7 @@ void Qt4ProFileNode::updateGeneratedFiles()
ProFileReader *Qt4ProFileNode::createProFileReader() const ProFileReader *Qt4ProFileNode::createProFileReader() const
{ {
ProFileReader *reader = new ProFileReader(m_cache); ProFileReader *reader = new ProFileReader();
connect(reader, SIGNAL(errorFound(const QString &)), connect(reader, SIGNAL(errorFound(const QString &)),
m_project, SLOT(proFileParseError(const QString &))); m_project, SLOT(proFileParseError(const QString &)));
@@ -971,6 +977,12 @@ void Qt4ProFileNode::invalidate()
emit qt4Watcher->projectTypeChanged(this, oldType, InvalidProject); emit qt4Watcher->projectTypeChanged(this, oldType, InvalidProject);
} }
ProFile *Qt4ProFileNode::proFileFromCache(const QString &fileName)
{
return m_reader->proFileFromCache(fileName);
}
Qt4NodesWatcher::Qt4NodesWatcher(QObject *parent) Qt4NodesWatcher::Qt4NodesWatcher(QObject *parent)
: NodesWatcher(parent) : NodesWatcher(parent)
{ {

View File

@@ -73,7 +73,6 @@ namespace Internal {
using ProjectExplorer::FileType; using ProjectExplorer::FileType;
class ProFileCache;
class ProFileReader; class ProFileReader;
class DirectoryWatcher; class DirectoryWatcher;
@@ -154,6 +153,7 @@ private:
QString m_projectDir; QString m_projectDir;
ProFile *m_includeFile; ProFile *m_includeFile;
QTimer *m_saveTimer; QTimer *m_saveTimer;
ProFileReader *m_reader;
// managed by Qt4ProFileNode // managed by Qt4ProFileNode
friend class Qt4ProFileNode; friend class Qt4ProFileNode;
@@ -167,12 +167,14 @@ public:
Qt4ProFileNode(Qt4Project *project, Qt4ProFileNode(Qt4Project *project,
const QString &filePath, const QString &filePath,
QObject *parent = 0); QObject *parent = 0);
~Qt4ProFileNode();
bool hasTargets() const; bool hasTargets() const;
Qt4ProjectType projectType() const; Qt4ProjectType projectType() const;
QStringList variableValue(const Qt4Variable var) const; QStringList variableValue(const Qt4Variable var) const;
ProFile *proFileFromCache(const QString &fileName);
public slots: public slots:
void update(); void update();
@@ -200,8 +202,8 @@ private:
QHash<Qt4Variable, QStringList> m_varValues; QHash<Qt4Variable, QStringList> m_varValues;
bool m_isQBuildProject; bool m_isQBuildProject;
ProFileCache *m_cache;
DirectoryWatcher *m_dirWatcher; DirectoryWatcher *m_dirWatcher;
ProFileReader *m_reader;
friend class Qt4NodeHierarchy; friend class Qt4NodeHierarchy;
}; };

View File

@@ -34,8 +34,8 @@
#include "qt4project.h" #include "qt4project.h"
#include "qt4projectmanager.h" #include "qt4projectmanager.h"
#include "profilecache.h"
#include "profilereader.h" #include "profilereader.h"
#include "prowriter.h"
#include "makestep.h" #include "makestep.h"
#include "qmakestep.h" #include "qmakestep.h"
#include "deployhelper.h" #include "deployhelper.h"
@@ -179,8 +179,12 @@ Qt4ProjectFile::Qt4ProjectFile(Qt4Project *project, const QString &filePath, QOb
bool Qt4ProjectFile::save(const QString &) bool Qt4ProjectFile::save(const QString &)
{ {
Core::IFile *file = fileFromCache(); ProFile *file = m_project->proFileFromCache(m_filePath);
return file && file->save(); ProWriter pw;
bool ok = pw.write(file, file->fileName());
file->setModified(false);
m_project->qt4ProjectManager()->notifyChanged(file->fileName());
return ok;
} }
QString Qt4ProjectFile::fileName() const QString Qt4ProjectFile::fileName() const
@@ -205,14 +209,13 @@ QString Qt4ProjectFile::mimeType() const
bool Qt4ProjectFile::isModified() const bool Qt4ProjectFile::isModified() const
{ {
Core::IFile *file = fileFromCache(); return m_project->proFileFromCache(m_filePath)->isModified();
return file && fileFromCache()->isModified();
} }
bool Qt4ProjectFile::isReadOnly() const bool Qt4ProjectFile::isReadOnly() const
{ {
Core::IFile *file = fileFromCache(); QFileInfo fi(m_filePath);
return file && fileFromCache()->isReadOnly(); return !fi.isWritable();
} }
bool Qt4ProjectFile::isSaveAsAllowed() const bool Qt4ProjectFile::isSaveAsAllowed() const
@@ -224,15 +227,6 @@ 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 /class Qt4Project
@@ -247,6 +241,7 @@ Qt4Project::Qt4Project(Qt4Manager *manager, const QString& fileName) :
m_isApplication(true), m_isApplication(true),
m_projectFiles(new Qt4ProjectFiles) m_projectFiles(new Qt4ProjectFiles)
{ {
m_manager->registerProject(this);
m_rootProjectNode->registerWatcher(m_nodesWatcher); m_rootProjectNode->registerWatcher(m_nodesWatcher);
connect(m_nodesWatcher, SIGNAL(foldersAdded()), this, SLOT(updateFileList())); connect(m_nodesWatcher, SIGNAL(foldersAdded()), this, SLOT(updateFileList()));
connect(m_nodesWatcher, SIGNAL(foldersRemoved()), this, SLOT(updateFileList())); connect(m_nodesWatcher, SIGNAL(foldersRemoved()), this, SLOT(updateFileList()));
@@ -267,6 +262,7 @@ Qt4Project::Qt4Project(Qt4Manager *manager, const QString& fileName) :
Qt4Project::~Qt4Project() Qt4Project::~Qt4Project()
{ {
m_manager->unregisterProject(this);
delete m_projectFiles; delete m_projectFiles;
} }
@@ -520,7 +516,7 @@ void Qt4Project::update()
ProFileReader *Qt4Project::createProFileReader() const ProFileReader *Qt4Project::createProFileReader() const
{ {
ProFileReader *reader = new ProFileReader(m_manager->proFileCache()); ProFileReader *reader = new ProFileReader();
connect(reader, SIGNAL(errorFound(const QString&)), connect(reader, SIGNAL(errorFound(const QString&)),
this, SLOT(proFileParseError(const QString&))); this, SLOT(proFileParseError(const QString&)));
QtVersion *version = qtVersion(activeBuildConfiguration()); QtVersion *version = qtVersion(activeBuildConfiguration());
@@ -578,10 +574,11 @@ QStringList Qt4Project::files(FilesMode fileMode) const
QList<Core::IFile *> Qt4Project::dependencies() QList<Core::IFile *> Qt4Project::dependencies()
{ {
QList<Core::IFile *> result; QList<Core::IFile *> result;
ProFileCache *cache = m_manager->proFileCache(); // TODO profile cache is no longer
foreach (const QString &file, cache->dependencies(m_rootProjectNode)) { // ProFileCache *cache = m_manager->proFileCache();
result << cache->fileInterface(file); // foreach (const QString &file, cache->dependencies(m_rootProjectNode)) {
} // result << cache->fileInterface(file);
// }
return result; return result;
} }
@@ -897,3 +894,29 @@ MakeStep *Qt4Project::makeStep() const
return qs; return qs;
return 0; return 0;
} }
ProFile *Qt4Project::proFileFromCache(const QString &fileName)
{
return rootProjectNode()->proFileFromCache(fileName);
}
void Qt4Project::findProFile(const QString& fileName, Qt4ProFileNode *root, QList<Qt4ProFileNode *> &list)
{
if (root->path() == fileName)
list.append(root);
else if (root->proFileFromCache(fileName))
list.append(root);
foreach (FolderNode *fn, root->subFolderNodes())
if (Qt4ProFileNode *qt4proFileNode = qobject_cast<Qt4ProFileNode *>(fn))
findProFile(fileName, qt4proFileNode, list);
}
void Qt4Project::notifyChanged(const QString &name)
{
QList<Qt4ProFileNode *> list;
findProFile(name, rootProjectNode(), list);
foreach(Qt4ProFileNode *node, list)
node->update();
}

View File

@@ -107,8 +107,6 @@ public:
void modified(Core::IFile::ReloadBehavior *behavior); void modified(Core::IFile::ReloadBehavior *behavior);
private: private:
Core::IFile *fileFromCache() const;
const QString m_mimeType; const QString m_mimeType;
Qt4Project *m_project; Qt4Project *m_project;
QString m_filePath; QString m_filePath;
@@ -182,6 +180,9 @@ public:
QMakeStep *qmakeStep() const; QMakeStep *qmakeStep() const;
MakeStep *makeStep() const; MakeStep *makeStep() const;
ProFile *proFileFromCache(const QString &fileName);
void notifyChanged(const QString &name);
public slots: public slots:
void update(); void update();
void proFileParseError(const QString &errorMessage); void proFileParseError(const QString &errorMessage);
@@ -207,6 +208,7 @@ protected:
private: private:
static void collectApplicationProFiles(QList<Internal::Qt4ProFileNode *> &list, Internal::Qt4ProFileNode *node); static void collectApplicationProFiles(QList<Internal::Qt4ProFileNode *> &list, Internal::Qt4ProFileNode *node);
static void findProFile(const QString& fileName, Internal::Qt4ProFileNode *root, QList<Internal::Qt4ProFileNode *> &list);
QList<Internal::Qt4ProFileNode *> m_applicationProFileChange; QList<Internal::Qt4ProFileNode *> m_applicationProFileChange;
ProjectExplorer::ProjectExplorerPlugin *projectExplorer() const; ProjectExplorer::ProjectExplorerPlugin *projectExplorer() const;

View File

@@ -37,7 +37,6 @@
#include "qt4projectmanagerplugin.h" #include "qt4projectmanagerplugin.h"
#include "qt4nodes.h" #include "qt4nodes.h"
#include "qt4project.h" #include "qt4project.h"
#include "profilecache.h"
#include "profilereader.h" #include "profilereader.h"
#include "qtversionmanager.h" #include "qtversionmanager.h"
#include "qmakestep.h" #include "qmakestep.h"
@@ -81,18 +80,33 @@ Qt4Manager::Qt4Manager(Qt4ProjectManagerPlugin *plugin, Core::ICore *core) :
m_core(core), m_core(core),
m_projectExplorer(0), m_projectExplorer(0),
m_contextProject(0), m_contextProject(0),
m_languageID(0), m_languageID(0)
m_proFileCache(0)
{ {
m_languageID = m_core->uniqueIDManager()-> m_languageID = m_core->uniqueIDManager()->
uniqueIdentifier(ProjectExplorer::Constants::LANG_CXX); uniqueIdentifier(ProjectExplorer::Constants::LANG_CXX);
m_proFileCache = new ProFileCache(this);
} }
Qt4Manager::~Qt4Manager() Qt4Manager::~Qt4Manager()
{ {
} }
void Qt4Manager::registerProject(Qt4Project *project)
{
m_projects.append(project);
}
void Qt4Manager::unregisterProject(Qt4Project *project)
{
m_projects.removeOne(project);
}
void Qt4Manager::notifyChanged(const QString &name)
{
foreach(Qt4Project *pro, m_projects) {
pro->notifyChanged(name);
}
}
void Qt4Manager::init() void Qt4Manager::init()
{ {
m_projectExplorer = m_core->pluginManager()->getObject<ProjectExplorer::ProjectExplorerPlugin>(); m_projectExplorer = m_core->pluginManager()->getObject<ProjectExplorer::ProjectExplorerPlugin>();

View File

@@ -57,7 +57,6 @@ namespace Qt4ProjectManager {
namespace Internal { namespace Internal {
class Qt4Builder; class Qt4Builder;
class ProFileCache;
class ProFileEditor; class ProFileEditor;
class Qt4ProjectManagerPlugin; class Qt4ProjectManagerPlugin;
class QtVersionManager; class QtVersionManager;
@@ -75,7 +74,10 @@ public:
~Qt4Manager(); ~Qt4Manager();
void init(); void init();
inline Internal::ProFileCache *proFileCache() const { return m_proFileCache; }
void registerProject(Qt4Project *project);
void unregisterProject(Qt4Project *project);
void notifyChanged(const QString &name);
ProjectExplorer::ProjectExplorerPlugin *projectExplorer() const; ProjectExplorer::ProjectExplorerPlugin *projectExplorer() const;
ExtensionSystem::PluginManager *pluginManager() const; ExtensionSystem::PluginManager *pluginManager() const;
@@ -104,6 +106,7 @@ public slots:
void runQMakeContextMenu(); void runQMakeContextMenu();
private: private:
QList<Qt4Project *> m_projects;
void runQMake(ProjectExplorer::Project *p); void runQMake(ProjectExplorer::Project *p);
const QString m_mimeType; const QString m_mimeType;
@@ -116,7 +119,6 @@ private:
int m_languageID; int m_languageID;
Internal::ProFileCache *m_proFileCache;
}; };
} // namespace Qt4ProjectManager } // namespace Qt4ProjectManager

View File

@@ -13,7 +13,6 @@ HEADERS = qt4projectmanagerplugin.h \
profilehighlighter.h \ profilehighlighter.h \
profileeditorfactory.h \ profileeditorfactory.h \
profilereader.h \ profilereader.h \
profilecache.h \
wizards/qtprojectparameters.h \ wizards/qtprojectparameters.h \
wizards/guiappwizard.h \ wizards/guiappwizard.h \
wizards/consoleappwizard.h \ wizards/consoleappwizard.h \
@@ -55,7 +54,6 @@ SOURCES = qt4projectmanagerplugin.cpp \
profilehighlighter.cpp \ profilehighlighter.cpp \
profileeditorfactory.cpp \ profileeditorfactory.cpp \
profilereader.cpp \ profilereader.cpp \
profilecache.cpp \
wizards/qtprojectparameters.cpp \ wizards/qtprojectparameters.cpp \
wizards/guiappwizard.cpp \ wizards/guiappwizard.cpp \
wizards/consoleappwizard.cpp \ wizards/consoleappwizard.cpp \

View File

@@ -40,7 +40,6 @@
#include "profileeditorfactory.h" #include "profileeditorfactory.h"
#include "qt4projectmanagerconstants.h" #include "qt4projectmanagerconstants.h"
#include "qt4project.h" #include "qt4project.h"
#include "profilecache.h"
#include "qmakebuildstepfactory.h" #include "qmakebuildstepfactory.h"
#include "buildparserfactory.h" #include "buildparserfactory.h"
#include "qtversionmanager.h" #include "qtversionmanager.h"