From bd827512bb5565c5b16376244b3f35f77b4affc0 Mon Sep 17 00:00:00 2001 From: dt Date: Tue, 2 Dec 2008 18:14:06 +0100 Subject: [PATCH] Fixes: Mem leak in the pro file parser. Details: ProFileCache be gone, as is ManagedProFile, not to be missed. Drastically simplified how ownership works. --- shared/proparser/profileevaluator.cpp | 9 +- .../qt4projectmanager/profilecache.cpp | 363 ------------------ src/plugins/qt4projectmanager/profilecache.h | 98 ----- .../qt4projectmanager/profileeditor.cpp | 6 +- .../qt4projectmanager/profilereader.cpp | 17 +- src/plugins/qt4projectmanager/profilereader.h | 9 +- src/plugins/qt4projectmanager/qt4nodes.cpp | 80 ++-- src/plugins/qt4projectmanager/qt4nodes.h | 6 +- src/plugins/qt4projectmanager/qt4project.cpp | 65 +++- src/plugins/qt4projectmanager/qt4project.h | 6 +- .../qt4projectmanager/qt4projectmanager.cpp | 22 +- .../qt4projectmanager/qt4projectmanager.h | 8 +- .../qt4projectmanager/qt4projectmanager.pro | 2 - .../qt4projectmanagerplugin.cpp | 1 - 14 files changed, 141 insertions(+), 551 deletions(-) delete mode 100644 src/plugins/qt4projectmanager/profilecache.cpp delete mode 100644 src/plugins/qt4projectmanager/profilecache.h diff --git a/shared/proparser/profileevaluator.cpp b/shared/proparser/profileevaluator.cpp index 85966c1f918..c50de16feca 100644 --- a/shared/proparser/profileevaluator.cpp +++ b/shared/proparser/profileevaluator.cpp @@ -1519,12 +1519,9 @@ bool ProFileEvaluator::Private::evaluateFile(const QString &fileName, bool *resu if (pro) { m_profileStack.push(pro); ok = (currentProFile() ? pro->Accept(this) : false); - if (ok) { - if (m_profileStack.count() > 0) { - ProFile *pro = m_profileStack.pop(); - q->releaseParsedProFile(pro); - } - } + m_profileStack.pop(); + q->releaseParsedProFile(pro); + if (result) *result = true; } else { diff --git a/src/plugins/qt4projectmanager/profilecache.cpp b/src/plugins/qt4projectmanager/profilecache.cpp deleted file mode 100644 index e359c2c17dc..00000000000 --- a/src/plugins/qt4projectmanager/profilecache.cpp +++ /dev/null @@ -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 -#include - -#include -#include -#include -#include - -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() << 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() << 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 pros = m_projects.values(profile->fileName()); - for (int i=0; iupdate(); - } -} - -void ProFileCache::notifyChanged(const QSet &profiles, bool external) -{ - QList notifyProjects; - - foreach (ProFile *profile, profiles) { - QList pros = m_projects.values(profile->fileName()); - - if (external) { - ManagedProjectFile *file = m_profiles.value(profile->fileName()); - if (file) - file->setOutOfSync(true); - } - - QList::const_iterator i = pros.constBegin(); - for (; i != pros.constEnd(); ++i) { - if (!notifyProjects.contains(*i)) - notifyProjects << *i; - } - } - - QList::const_iterator i = notifyProjects.constBegin(); - while (i != notifyProjects.constEnd()) { - (*i)->update(); - ++i; - } -} - -void ProFileCache::updateDependencies(const QSet &files, Qt4ProFileNode *project) -{ - // just remove and add files that have changed - const QSet &oldFiles = m_projects.keys(project).toSet(); - QSet newFiles; - - QList 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 profiles = proFiles(QStringList(file)); - if (profiles.isEmpty()) - return 0; - return profiles.toList().first(); -} - -QSet ProFileCache::proFiles(const QStringList &files) const -{ - QSet results; - foreach (const QString &file, files) { - ManagedProjectFile *managedFile = m_profiles.value(file, 0); - if (managedFile && !managedFile->isOutOfSync()) { - results << managedFile->profile(); - } - } - return results; -} - -QSet 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 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(obj); - QStringList files = m_projects.keys(proj); - foreach (const QString &file, files) { - removeFile(file, proj); - } -} diff --git a/src/plugins/qt4projectmanager/profilecache.h b/src/plugins/qt4projectmanager/profilecache.h deleted file mode 100644 index 993ae6a489e..00000000000 --- a/src/plugins/qt4projectmanager/profilecache.h +++ /dev/null @@ -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 -#include -#include -#include - -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 &profiles, bool external = false); - - void updateDependencies(const QSet &files, Qt4ProFileNode *projectNode); - QStringList dependencies(Qt4ProFileNode *projectNode) const; - - ProFile *proFile(const QString &filename) const; - QSet proFiles(const QStringList &files) const; - QSet 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 m_projects; - QMap m_profiles; -}; - -} // namespace Internal -} // namespace Qt4ProjectManager - -#endif // PROFILECACHE_H diff --git a/src/plugins/qt4projectmanager/profileeditor.cpp b/src/plugins/qt4projectmanager/profileeditor.cpp index 79638d74fc0..0542f4a091e 100644 --- a/src/plugins/qt4projectmanager/profileeditor.cpp +++ b/src/plugins/qt4projectmanager/profileeditor.cpp @@ -36,7 +36,6 @@ #include "profilehighlighter.h" #include "qt4projectmanager.h" #include "qt4projectmanagerconstants.h" -#include "profilecache.h" #include "profileeditorfactory.h" #include "proeditormodel.h" #include "procommandmanager.h" @@ -51,6 +50,7 @@ #include #include #include +#include using namespace ExtensionSystem; using namespace Core; @@ -150,9 +150,7 @@ ProFileDocument::ProFileDocument(Qt4Manager *manager) bool ProFileDocument::save(const QString &name) { if (BaseTextDocument::save(name)) { - ProFile *profile = m_manager->proFileCache()->proFile(name); - if (profile) - m_manager->proFileCache()->notifyChanged(QSet() << profile, true); + m_manager->notifyChanged(name); return true; } return false; diff --git a/src/plugins/qt4projectmanager/profilereader.cpp b/src/plugins/qt4projectmanager/profilereader.cpp index 4c81c0aeec0..0618fe6c730 100644 --- a/src/plugins/qt4projectmanager/profilereader.cpp +++ b/src/plugins/qt4projectmanager/profilereader.cpp @@ -32,7 +32,6 @@ ***************************************************************************/ #include "profilereader.h" -#include "profilecache.h" #include #include @@ -40,11 +39,16 @@ using namespace Qt4ProjectManager; using namespace Qt4ProjectManager::Internal; -ProFileReader::ProFileReader(ProFileCache *cache) - : m_cache(cache) +ProFileReader::ProFileReader() { } +ProFileReader::~ProFileReader() +{ + foreach(ProFile *pf, m_proFiles) + delete pf; +} + void ProFileReader::setQtVersion(QtVersion *qtVersion) { QHash additionalVariables; additionalVariables.insert(QString("QT_BUILD_TREE"), QStringList() << qtVersion->path()); @@ -72,6 +76,7 @@ bool ProFileReader::readProFile(const QString &fileName) return false; } m_includeFiles.insert(fn, pro); + m_proFiles.append(pro); return accept(pro); } @@ -84,23 +89,23 @@ ProFile *ProFileReader::parsedProFile(const QString &fileName) ProFile *pro = ProFileEvaluator::parsedProFile(fn); if (pro) { m_includeFiles.insert(fn, pro); + m_proFiles.append(pro); } return pro; } -void ProFileReader::releaseParsedProFile(ProFile */*proFile*/) +void ProFileReader::releaseParsedProFile(ProFile *) { return; } ProFile *ProFileReader::proFileFromCache(const QString &fileName) const { + QString fn = QFileInfo(fileName).filePath(); ProFile *pro = 0; if (m_includeFiles.contains(fn)) pro = m_includeFiles.value(fn); - else - pro = m_cache->proFile(fn); // this can expand to null return pro; } diff --git a/src/plugins/qt4projectmanager/profilereader.h b/src/plugins/qt4projectmanager/profilereader.h index 50e2077c554..46e1f600386 100644 --- a/src/plugins/qt4projectmanager/profilereader.h +++ b/src/plugins/qt4projectmanager/profilereader.h @@ -43,14 +43,14 @@ namespace Qt4ProjectManager { namespace Internal { -class ProFileCache; class ProFileReader : public QObject, public ProFileEvaluator { Q_OBJECT public: - ProFileReader(ProFileCache *cache); + ProFileReader(); + ~ProFileReader(); void setQtVersion(QtVersion *qtVersion); bool readProFile(const QString &fileName); @@ -63,7 +63,7 @@ public: const QString &baseDirectory, PathValuesMode mode, const ProFile *pro = 0) const; - + ProFile *proFileFromCache(const QString &fileName) const; signals: void errorFound(const QString &error); @@ -75,9 +75,8 @@ private: virtual void errorMessage(const QString &msg); private: - ProFile *proFileFromCache(const QString &fileName) const; - ProFileCache *m_cache; QMap m_includeFiles; + QList m_proFiles; }; } // namespace Internal diff --git a/src/plugins/qt4projectmanager/qt4nodes.cpp b/src/plugins/qt4projectmanager/qt4nodes.cpp index f802738f65f..8d0c11fe139 100644 --- a/src/plugins/qt4projectmanager/qt4nodes.cpp +++ b/src/plugins/qt4projectmanager/qt4nodes.cpp @@ -87,7 +87,8 @@ Qt4PriFileNode::Qt4PriFileNode(Qt4Project *project, m_projectFilePath(filePath), m_projectDir(QFileInfo(filePath).absolutePath()), m_includeFile(0), - m_saveTimer(new QTimer(this)) + m_saveTimer(new QTimer(this)), + m_reader(0) { Q_ASSERT(project); setFolderName(QFileInfo(filePath).baseName()); @@ -104,6 +105,7 @@ void Qt4PriFileNode::update(ProFile *includeFile, ProFileReader *reader) { Q_ASSERT(includeFile); Q_ASSERT(reader); + m_reader = reader; m_includeFile = includeFile; @@ -363,10 +365,6 @@ void Qt4PriFileNode::changeFiles(const FileType fileType, return; // Check if file is readonly - ProFileCache *cache = m_project->qt4ProjectManager()->proFileCache(); - if (cache->fileInterface(m_projectFilePath)->isReadOnly() && !priFileWritable(m_projectFilePath)) - return; - ProEditorModel proModel; proModel.setProFiles(QList() << m_includeFile); @@ -449,22 +447,26 @@ void Qt4PriFileNode::changeFiles(const FileType fileType, void Qt4PriFileNode::save() { - // Prevent any reload questions; just reload Core::FileManager *fileManager = m_core->fileManager(); - ProFileCache *cache = m_project->qt4ProjectManager()->proFileCache(); - QList 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); - modifiedFileHandle->save(); - fileManager->unblockFileChange(modifiedFileHandle); + if (modifiedFileHandle) + fileManager->blockFileChange(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::ReloadAll; - foreach (Core::IFile *file, allFileHandles) { + foreach (Core::IFile *file, allFileHandles) file->modified(&tempBehavior); - } } /* @@ -516,8 +518,8 @@ Qt4ProFileNode::Qt4ProFileNode(Qt4Project *project, // own stuff m_projectType(InvalidProject), m_isQBuildProject(false), - m_cache(project->qt4ProjectManager()->proFileCache()), - m_dirWatcher(new DirectoryWatcher(this)) + m_dirWatcher(new DirectoryWatcher(this)), + m_reader(0) { if (parent) setParent(parent); @@ -530,6 +532,11 @@ Qt4ProFileNode::Qt4ProFileNode(Qt4Project *project, this, SLOT(update())); } +Qt4ProFileNode::~Qt4ProFileNode() +{ + delete m_reader; +} + bool Qt4ProFileNode::hasTargets() const { return (projectType() == ApplicationTemplate) || (projectType() == LibraryTemplate); @@ -547,10 +554,11 @@ QStringList Qt4ProFileNode::variableValue(const Qt4Variable var) const void Qt4ProFileNode::update() { - ProFileReader *reader = createProFileReader(); - if (!reader->readProFile(m_projectFilePath)) { + delete m_reader; + m_reader = createProFileReader(); + if (!m_reader->readProFile(m_projectFilePath)) { m_project->proFileParseError(tr("Error while parsing file %1. Giving up.").arg(m_projectFilePath)); - delete reader; + delete m_reader; invalidate(); return; } @@ -565,7 +573,7 @@ void Qt4ProFileNode::update() #endif Qt4ProjectType projectType = InvalidProject; - switch (reader->templateType()) { + switch (m_reader->templateType()) { case ProFileEvaluator::TT_Unknown: case ProFileEvaluator::TT_Application: { projectType = ApplicationTemplate; @@ -604,11 +612,11 @@ void Qt4ProFileNode::update() ProFile *fileForCurrentProject = 0; { if (projectType == SubDirsTemplate) { - foreach (const QString &subDirProject, subDirsPaths(reader)) + foreach (const QString &subDirProject, subDirsPaths(m_reader)) newProjectFiles << subDirProject; } - foreach (ProFile *includeFile, reader->includeFiles()) { + foreach (ProFile *includeFile, m_reader->includeFiles()) { if (includeFile->fileName() == m_projectFilePath) { // this file fileForCurrentProject = includeFile; } else { @@ -637,7 +645,7 @@ void Qt4ProFileNode::update() Qt4PriFileNode *priFileNode = new Qt4PriFileNode(m_project, *newProjectFileIter); - priFileNode->update(file, reader); + priFileNode->update(file, m_reader); toAdd << priFileNode; } else { toAdd << createSubProFileNode(*newProjectFileIter); @@ -646,7 +654,7 @@ void Qt4ProFileNode::update() } else { // *existingNodeIter->path() == *newProjectFileIter if (ProFile *file = includeFiles.value(*newProjectFileIter)) { Qt4PriFileNode *priFileNode = static_cast(*existingNodeIter); - priFileNode->update(file, reader); + priFileNode->update(file, m_reader); } ++existingNodeIter; @@ -662,7 +670,7 @@ void Qt4ProFileNode::update() Qt4PriFileNode *priFileNode = new Qt4PriFileNode(m_project, *newProjectFileIter); - priFileNode->update(file, reader); + priFileNode->update(file, m_reader); toAdd << priFileNode; } else { toAdd << createSubProFileNode(*newProjectFileIter); @@ -675,15 +683,15 @@ void Qt4ProFileNode::update() if (!toAdd.isEmpty()) addProjectNodes(toAdd); - Qt4PriFileNode::update(fileForCurrentProject, reader); + Qt4PriFileNode::update(fileForCurrentProject, m_reader); // update other variables QHash newVarValues; - newVarValues[CxxCompilerVar] << reader->value(QLatin1String("QMAKE_CXX")); - newVarValues[DefinesVar] = reader->values(QLatin1String("DEFINES")); - newVarValues[IncludePathVar] = includePaths(reader); - newVarValues[UiDirVar] = uiDirPaths(reader); - newVarValues[MocDirVar] = mocDirPaths(reader); + newVarValues[CxxCompilerVar] << m_reader->value(QLatin1String("QMAKE_CXX")); + newVarValues[DefinesVar] = m_reader->values(QLatin1String("DEFINES")); + newVarValues[IncludePathVar] = includePaths(m_reader); + newVarValues[UiDirVar] = uiDirPaths(m_reader); + newVarValues[MocDirVar] = mocDirPaths(m_reader); if (m_varValues != newVarValues) { m_varValues = newVarValues; @@ -693,9 +701,7 @@ void Qt4ProFileNode::update() } updateGeneratedFiles(); - m_project->qt4ProjectManager()->proFileCache()->updateDependencies(reader->includeFiles().toSet(), this); - delete reader; foreach (NodesWatcher *watcher, watchers()) if (Qt4NodesWatcher *qt4Watcher = qobject_cast(watcher)) emit qt4Watcher->proFileUpdated(this); @@ -812,7 +818,7 @@ void Qt4ProFileNode::updateGeneratedFiles() ProFileReader *Qt4ProFileNode::createProFileReader() const { - ProFileReader *reader = new ProFileReader(m_cache); + ProFileReader *reader = new ProFileReader(); connect(reader, SIGNAL(errorFound(const QString &)), m_project, SLOT(proFileParseError(const QString &))); @@ -971,6 +977,12 @@ void Qt4ProFileNode::invalidate() emit qt4Watcher->projectTypeChanged(this, oldType, InvalidProject); } + +ProFile *Qt4ProFileNode::proFileFromCache(const QString &fileName) +{ + return m_reader->proFileFromCache(fileName); +} + Qt4NodesWatcher::Qt4NodesWatcher(QObject *parent) : NodesWatcher(parent) { diff --git a/src/plugins/qt4projectmanager/qt4nodes.h b/src/plugins/qt4projectmanager/qt4nodes.h index 87cbdff28ac..f4d7c9bd17f 100644 --- a/src/plugins/qt4projectmanager/qt4nodes.h +++ b/src/plugins/qt4projectmanager/qt4nodes.h @@ -73,7 +73,6 @@ namespace Internal { using ProjectExplorer::FileType; -class ProFileCache; class ProFileReader; class DirectoryWatcher; @@ -154,6 +153,7 @@ private: QString m_projectDir; ProFile *m_includeFile; QTimer *m_saveTimer; + ProFileReader *m_reader; // managed by Qt4ProFileNode friend class Qt4ProFileNode; @@ -167,12 +167,14 @@ public: Qt4ProFileNode(Qt4Project *project, const QString &filePath, QObject *parent = 0); + ~Qt4ProFileNode(); bool hasTargets() const; Qt4ProjectType projectType() const; QStringList variableValue(const Qt4Variable var) const; + ProFile *proFileFromCache(const QString &fileName); public slots: void update(); @@ -200,8 +202,8 @@ private: QHash m_varValues; bool m_isQBuildProject; - ProFileCache *m_cache; DirectoryWatcher *m_dirWatcher; + ProFileReader *m_reader; friend class Qt4NodeHierarchy; }; diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp index 8ec4ea7f4be..b07900f9103 100644 --- a/src/plugins/qt4projectmanager/qt4project.cpp +++ b/src/plugins/qt4projectmanager/qt4project.cpp @@ -34,8 +34,8 @@ #include "qt4project.h" #include "qt4projectmanager.h" -#include "profilecache.h" #include "profilereader.h" +#include "prowriter.h" #include "makestep.h" #include "qmakestep.h" #include "deployhelper.h" @@ -179,8 +179,12 @@ Qt4ProjectFile::Qt4ProjectFile(Qt4Project *project, const QString &filePath, QOb bool Qt4ProjectFile::save(const QString &) { - Core::IFile *file = fileFromCache(); - return file && file->save(); + ProFile *file = m_project->proFileFromCache(m_filePath); + ProWriter pw; + bool ok = pw.write(file, file->fileName()); + file->setModified(false); + m_project->qt4ProjectManager()->notifyChanged(file->fileName()); + return ok; } QString Qt4ProjectFile::fileName() const @@ -205,14 +209,13 @@ QString Qt4ProjectFile::mimeType() const bool Qt4ProjectFile::isModified() const { - Core::IFile *file = fileFromCache(); - return file && fileFromCache()->isModified(); + return m_project->proFileFromCache(m_filePath)->isModified(); } bool Qt4ProjectFile::isReadOnly() const { - Core::IFile *file = fileFromCache(); - return file && fileFromCache()->isReadOnly(); + QFileInfo fi(m_filePath); + return !fi.isWritable(); } 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 @@ -247,6 +241,7 @@ Qt4Project::Qt4Project(Qt4Manager *manager, const QString& fileName) : m_isApplication(true), m_projectFiles(new Qt4ProjectFiles) { + m_manager->registerProject(this); m_rootProjectNode->registerWatcher(m_nodesWatcher); connect(m_nodesWatcher, SIGNAL(foldersAdded()), this, SLOT(updateFileList())); connect(m_nodesWatcher, SIGNAL(foldersRemoved()), this, SLOT(updateFileList())); @@ -267,6 +262,7 @@ Qt4Project::Qt4Project(Qt4Manager *manager, const QString& fileName) : Qt4Project::~Qt4Project() { + m_manager->unregisterProject(this); delete m_projectFiles; } @@ -520,7 +516,7 @@ void Qt4Project::update() ProFileReader *Qt4Project::createProFileReader() const { - ProFileReader *reader = new ProFileReader(m_manager->proFileCache()); + ProFileReader *reader = new ProFileReader(); connect(reader, SIGNAL(errorFound(const QString&)), this, SLOT(proFileParseError(const QString&))); QtVersion *version = qtVersion(activeBuildConfiguration()); @@ -578,10 +574,11 @@ QStringList Qt4Project::files(FilesMode fileMode) const QList Qt4Project::dependencies() { QList result; - ProFileCache *cache = m_manager->proFileCache(); - foreach (const QString &file, cache->dependencies(m_rootProjectNode)) { - result << cache->fileInterface(file); - } + // TODO profile cache is no longer +// ProFileCache *cache = m_manager->proFileCache(); +// foreach (const QString &file, cache->dependencies(m_rootProjectNode)) { +// result << cache->fileInterface(file); +// } return result; } @@ -897,3 +894,29 @@ MakeStep *Qt4Project::makeStep() const return qs; return 0; } + +ProFile *Qt4Project::proFileFromCache(const QString &fileName) +{ + return rootProjectNode()->proFileFromCache(fileName); +} + +void Qt4Project::findProFile(const QString& fileName, Qt4ProFileNode *root, QList &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(fn)) + findProFile(fileName, qt4proFileNode, list); +} + +void Qt4Project::notifyChanged(const QString &name) +{ + QList list; + findProFile(name, rootProjectNode(), list); + foreach(Qt4ProFileNode *node, list) + node->update(); + +} diff --git a/src/plugins/qt4projectmanager/qt4project.h b/src/plugins/qt4projectmanager/qt4project.h index 5284646ae49..18a7bf7f4f5 100644 --- a/src/plugins/qt4projectmanager/qt4project.h +++ b/src/plugins/qt4projectmanager/qt4project.h @@ -107,8 +107,6 @@ public: void modified(Core::IFile::ReloadBehavior *behavior); private: - Core::IFile *fileFromCache() const; - const QString m_mimeType; Qt4Project *m_project; QString m_filePath; @@ -182,6 +180,9 @@ public: QMakeStep *qmakeStep() const; MakeStep *makeStep() const; + ProFile *proFileFromCache(const QString &fileName); + void notifyChanged(const QString &name); + public slots: void update(); void proFileParseError(const QString &errorMessage); @@ -207,6 +208,7 @@ protected: private: static void collectApplicationProFiles(QList &list, Internal::Qt4ProFileNode *node); + static void findProFile(const QString& fileName, Internal::Qt4ProFileNode *root, QList &list); QList m_applicationProFileChange; ProjectExplorer::ProjectExplorerPlugin *projectExplorer() const; diff --git a/src/plugins/qt4projectmanager/qt4projectmanager.cpp b/src/plugins/qt4projectmanager/qt4projectmanager.cpp index 7e19f36450d..8ff73970d53 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanager.cpp +++ b/src/plugins/qt4projectmanager/qt4projectmanager.cpp @@ -37,7 +37,6 @@ #include "qt4projectmanagerplugin.h" #include "qt4nodes.h" #include "qt4project.h" -#include "profilecache.h" #include "profilereader.h" #include "qtversionmanager.h" #include "qmakestep.h" @@ -81,18 +80,33 @@ Qt4Manager::Qt4Manager(Qt4ProjectManagerPlugin *plugin, Core::ICore *core) : m_core(core), m_projectExplorer(0), m_contextProject(0), - m_languageID(0), - m_proFileCache(0) + m_languageID(0) { m_languageID = m_core->uniqueIDManager()-> uniqueIdentifier(ProjectExplorer::Constants::LANG_CXX); - m_proFileCache = new ProFileCache(this); } 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() { m_projectExplorer = m_core->pluginManager()->getObject(); diff --git a/src/plugins/qt4projectmanager/qt4projectmanager.h b/src/plugins/qt4projectmanager/qt4projectmanager.h index 3ef99a694fc..de33def6e67 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanager.h +++ b/src/plugins/qt4projectmanager/qt4projectmanager.h @@ -57,7 +57,6 @@ namespace Qt4ProjectManager { namespace Internal { class Qt4Builder; -class ProFileCache; class ProFileEditor; class Qt4ProjectManagerPlugin; class QtVersionManager; @@ -75,7 +74,10 @@ public: ~Qt4Manager(); 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; ExtensionSystem::PluginManager *pluginManager() const; @@ -104,6 +106,7 @@ public slots: void runQMakeContextMenu(); private: + QList m_projects; void runQMake(ProjectExplorer::Project *p); const QString m_mimeType; @@ -116,7 +119,6 @@ private: int m_languageID; - Internal::ProFileCache *m_proFileCache; }; } // namespace Qt4ProjectManager diff --git a/src/plugins/qt4projectmanager/qt4projectmanager.pro b/src/plugins/qt4projectmanager/qt4projectmanager.pro index 0118cf967c6..806e020e31c 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanager.pro +++ b/src/plugins/qt4projectmanager/qt4projectmanager.pro @@ -13,7 +13,6 @@ HEADERS = qt4projectmanagerplugin.h \ profilehighlighter.h \ profileeditorfactory.h \ profilereader.h \ - profilecache.h \ wizards/qtprojectparameters.h \ wizards/guiappwizard.h \ wizards/consoleappwizard.h \ @@ -55,7 +54,6 @@ SOURCES = qt4projectmanagerplugin.cpp \ profilehighlighter.cpp \ profileeditorfactory.cpp \ profilereader.cpp \ - profilecache.cpp \ wizards/qtprojectparameters.cpp \ wizards/guiappwizard.cpp \ wizards/consoleappwizard.cpp \ diff --git a/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp b/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp index 469df69dd38..14affc5f078 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp +++ b/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp @@ -40,7 +40,6 @@ #include "profileeditorfactory.h" #include "qt4projectmanagerconstants.h" #include "qt4project.h" -#include "profilecache.h" #include "qmakebuildstepfactory.h" #include "buildparserfactory.h" #include "qtversionmanager.h"