From 75545a2bf0121af9f081b2e5e76879e42e490cc2 Mon Sep 17 00:00:00 2001 From: dt <qtc-committer@nokia.com> Date: Fri, 22 Jan 2010 16:49:57 +0100 Subject: [PATCH] Fix FileManager to correctly handle multiple IFile's for the same file And port the Qt4ProjectManager to use that API for synchronization between editors and the .pro file tree. Reviewed-By: con --- src/plugins/coreplugin/filemanager.cpp | 349 ++++++++++++------ src/plugins/coreplugin/filemanager.h | 14 +- .../scriptmanager/qworkbench_wrapper.cpp | 6 - .../scriptmanager/qworkbench_wrapper.h | 1 - src/plugins/cvs/cvsplugin.cpp | 1 - src/plugins/git/gitplugin.cpp | 1 - src/plugins/perforce/perforceplugin.cpp | 1 - .../qt4projectmanager/profileeditor.cpp | 16 +- src/plugins/qt4projectmanager/profileeditor.h | 6 +- src/plugins/qt4projectmanager/qt4nodes.cpp | 55 ++- src/plugins/qt4projectmanager/qt4nodes.h | 7 +- src/plugins/subversion/subversionplugin.cpp | 1 - 12 files changed, 264 insertions(+), 194 deletions(-) diff --git a/src/plugins/coreplugin/filemanager.cpp b/src/plugins/coreplugin/filemanager.cpp index 24e2178307a..a81002bcace 100644 --- a/src/plugins/coreplugin/filemanager.cpp +++ b/src/plugins/coreplugin/filemanager.cpp @@ -41,7 +41,6 @@ #include <utils/qtcassert.h> #include <utils/pathchooser.h> -#include <QtCore/QDebug> #include <QtCore/QSettings> #include <QtCore/QFileInfo> #include <QtCore/QFile> @@ -66,9 +65,13 @@ be asked to save all modified files. Different IFile objects in the set can point to the same file in the - filesystem. The monitoring of a file can be blocked by blockFileChange(), and + filesystem. The monitoring for a IFile can be blocked by blockFileChange(), and enabled again by unblockFileChange(). + The functions expectFileChange() and unexpectFileChange() mark a file change + as expected. On expected file changes all IFile objects are notified to reload + themselves. + The FileManager service also provides two convenience methods for saving files: saveModifiedFiles() and saveModifiedFilesSilently(). Both take a list of FileInterfaces as an argument, and return the list of files which were @@ -88,17 +91,24 @@ static const char useProjectDirectoryKeyC[] = "UseProjectsDirectory"; namespace Core { namespace Internal { -struct FileInfo +struct FileStateItem { - QString fileName; QDateTime modified; QFile::Permissions permissions; }; +struct FileState +{ + QMap<IFile *, FileStateItem> lastUpdatedState; + FileStateItem expected; +}; + + struct FileManagerPrivate { explicit FileManagerPrivate(QObject *q, QMainWindow *mw); - QMap<IFile*, FileInfo> m_managedFiles; + QMap<QString, FileState> m_states; + QStringList m_changedFiles; QStringList m_recentFiles; static const int m_maxRecentFiles = 7; @@ -107,7 +117,6 @@ struct FileManagerPrivate { QMainWindow *m_mainWindow; QFileSystemWatcher *m_fileWatcher; - QList<QPointer<IFile> > m_changedFiles; bool m_blockActivated; QString m_lastVisitedDirectory; QString m_projectsDirectory; @@ -178,17 +187,90 @@ bool FileManager::addFiles(const QList<IFile *> &files) { bool filesAdded = false; foreach (IFile *file, files) { - if (!file || d->m_managedFiles.contains(file)) + if (!file) + continue; + const QString &fixedFileName = fixFileName(file->fileName()); + if (d->m_states.value(fixedFileName).lastUpdatedState.contains(file)) continue; connect(file, SIGNAL(changed()), this, SLOT(checkForNewFileName())); connect(file, SIGNAL(destroyed(QObject *)), this, SLOT(fileDestroyed(QObject *))); filesAdded = true; - addWatch(fixFileName(file->fileName())); - updateFileInfo(file); + + addFileInfo(file); } return filesAdded; } +void FileManager::addFileInfo(IFile *file) +{ + // We do want to insert the IFile into d->m_states even if the filename is empty + // Such that m_states always contains all IFiles + + const QString fixedname = fixFileName(file->fileName()); + Internal::FileStateItem item; + if (!fixedname.isEmpty()) { + const QFileInfo fi(file->fileName()); + item.modified = fi.lastModified(); + item.permissions = fi.permissions(); + } + + if (!d->m_states.contains(fixedname)) { + d->m_states.insert(fixedname, Internal::FileState()); + if (!fixedname.isEmpty()) + d->m_fileWatcher->addPath(fixedname); + } + + d->m_states[fixedname].lastUpdatedState.insert(file, item); +} + +void FileManager::updateFileInfo(IFile *file) +{ + const QString fixedname = fixFileName(file->fileName()); + // If the filename is empty there's nothing to do + if (fixedname.isEmpty()) + return; + const QFileInfo fi(file->fileName()); + + Internal::FileStateItem item; + item.modified = fi.lastModified(); + item.permissions = fi.permissions(); + + d->m_states[fixedname].lastUpdatedState.insert(file, item); +} + +/// +/// Does not use file->fileName, as such is save to use +/// with renamed files and deleted files +void FileManager::removeFileInfo(IFile *file) +{ + QString fileName; + QMap<QString, Internal::FileState>::const_iterator it, end; + end = d->m_states.constEnd(); + for (it = d->m_states.constBegin(); it != end; ++it) { + if (it.value().lastUpdatedState.contains(file)) { + fileName = it.key(); + break; + } + } + + // The filename might be empty but not null + Q_ASSERT(fileName != QString::null); + + removeFileInfo(fileName, file); +} + +void FileManager::removeFileInfo(const QString &fileName, IFile *file) +{ + const QString &fixedName = fixFileName(fileName); + d->m_states[fixedName].lastUpdatedState.remove(file); + + if (d->m_states.value(fixedName).lastUpdatedState.isEmpty()) { + d->m_states.remove(fixedName); + if (!fixedName.isEmpty()) + d->m_fileWatcher->removePath(fixedName); + } +} + /*! \fn bool FileManager::addFile(IFile *files) @@ -203,11 +285,9 @@ bool FileManager::addFile(IFile *file) void FileManager::fileDestroyed(QObject *obj) { - // we can't use qobject_cast here, because meta data is already destroyed + // removeFileInfo works even if the file does not really exist anymore IFile *file = static_cast<IFile*>(obj); - const QString filename = d->m_managedFiles.value(file).fileName; - d->m_managedFiles.remove(file); - removeWatch(filename); + removeFileInfo(file); } /*! @@ -225,37 +305,29 @@ bool FileManager::removeFile(IFile *file) disconnect(file, SIGNAL(changed()), this, SLOT(checkForNewFileName())); disconnect(file, SIGNAL(destroyed(QObject *)), this, SLOT(fileDestroyed(QObject *))); - if (!d->m_managedFiles.contains(file)) - return false; - const Internal::FileInfo info = d->m_managedFiles.take(file); - const QString filename = info.fileName; - removeWatch(filename); + removeFileInfo(file->fileName(), file); return true; } -void FileManager::addWatch(const QString &filename) -{ - if (!filename.isEmpty() && managedFiles(filename).isEmpty()) - d->m_fileWatcher->addPath(filename); -} -void FileManager::removeWatch(const QString &filename) -{ - if (!filename.isEmpty() && managedFiles(filename).isEmpty()) - d->m_fileWatcher->removePath(filename); -} void FileManager::checkForNewFileName() { IFile *file = qobject_cast<IFile *>(sender()); QTC_ASSERT(file, return); - const QString newfilename = fixFileName(file->fileName()); - const QString oldfilename = d->m_managedFiles.value(file).fileName; - if (!newfilename.isEmpty() && newfilename != oldfilename) { - d->m_managedFiles[file].fileName = newfilename; - removeWatch(oldfilename); - addWatch(newfilename); + const QString &fileName = fixFileName(file->fileName()); + + // check if the IFile is in the map + if (d->m_states[fileName].lastUpdatedState.contains(file)) { + // Should checkForNewFileName also call updateFileInfo if the name didn't change? + updateFileInfo(file); + return; } + + // Probably the name has changed... + // This also updates the state to the on disk state + removeFileInfo(file); + addFileInfo(file); } // TODO Rename to nativeFileName @@ -280,7 +352,7 @@ bool FileManager::isFileManaged(const QString &fileName) const if (fileName.isEmpty()) return false; - return !managedFiles(fixFileName(fileName)).isEmpty(); + return !d->m_states.contains(fixFileName(fileName)); } /*! @@ -292,11 +364,15 @@ QList<IFile *> FileManager::modifiedFiles() const { QList<IFile *> modifiedFiles; - const QMap<IFile*, Internal::FileInfo>::const_iterator cend = d->m_managedFiles.constEnd(); - for (QMap<IFile*, Internal::FileInfo>::const_iterator i = d->m_managedFiles.constBegin(); i != cend; ++i) { - IFile *fi = i.key(); - if (fi->isModified()) - modifiedFiles << fi; + QMap<QString, Internal::FileState>::const_iterator it, end; + end = d->m_states.constEnd(); + for(it = d->m_states.constBegin(); it != end; ++it) { + QMap<IFile *, Internal::FileStateItem>::const_iterator jt, jend; + jt = it.value().lastUpdatedState.constBegin(); + jend = it.value().lastUpdatedState.constEnd(); + for( ; jt != jend; ++jt) + if (jt.key()->isModified()) + modifiedFiles << jt.key(); } return modifiedFiles; } @@ -308,8 +384,8 @@ QList<IFile *> FileManager::modifiedFiles() const */ void FileManager::blockFileChange(IFile *file) { - if (!file->fileName().isEmpty()) - d->m_fileWatcher->removePath(file->fileName()); + // Nothing to do + Q_UNUSED(file); } /*! @@ -319,21 +395,58 @@ void FileManager::blockFileChange(IFile *file) */ void FileManager::unblockFileChange(IFile *file) { - foreach (IFile *managedFile, managedFiles(file->fileName())) - updateFileInfo(managedFile); - if (!file->fileName().isEmpty()) - d->m_fileWatcher->addPath(file->fileName()); + // We are updating the lastUpdated time to the current modification time + // in changedFile we'll compare the modification time with the last updated + // time, and if they are the same, then we don't deliver that notification + // to corresponding IFile + // + // Also we are updating the expected time of the file + // in changedFile we'll check if the modification time + // is the same as the saved one here + // If so then it's a expected change + + updateFileInfo(file); + updateExpectedState(fixFileName(file->fileName())); } -void FileManager::updateFileInfo(IFile *file) +/*! + \fn void FileManager::expectFileChange(const QString &fileName) + + Any subsequent change to \a fileName is treated as a expected file change. + + \see FileManager::unexpectFileChange(const QString &fileName) +*/ +void FileManager::expectFileChange(const QString &fileName) { - const QString fixedname = fixFileName(file->fileName()); - const QFileInfo fi(file->fileName()); - Internal::FileInfo info; - info.fileName = fixedname; - info.modified = fi.lastModified(); - info.permissions = fi.permissions(); - d->m_managedFiles.insert(file, info); + // Nothing to do + Q_UNUSED(fileName); +} + +/*! + \fn void FileManager::unexpectFileChange(const QString &fileName) + + Any change to \a fileName are unexpected again. + + \see FileManager::expectFileChange(const QString &fileName) +*/ +void FileManager::unexpectFileChange(const QString &fileName) +{ + // We are updating the expected time of the file + // And in changedFile we'll check if the modification time + // is the same as the saved one here + // If so then it's a expected change + + updateExpectedState(fileName); +} + +void FileManager::updateExpectedState(const QString &fileName) +{ + const QString &fixedName = fixFileName(fileName); + if (fixedName.isEmpty()) + return; + QFileInfo fi(fixedName); + d->m_states[fixedName].expected.modified = fi.lastModified(); + d->m_states[fixedName].expected.permissions = fi.permissions(); } /*! @@ -543,11 +656,14 @@ QStringList FileManager::getOpenFileNames(const QString &filters, } -void FileManager::changedFile(const QString &file) +void FileManager::changedFile(const QString &fileName) { const bool wasempty = d->m_changedFiles.isEmpty(); - foreach (IFile *fileinterface, managedFiles(file)) - d->m_changedFiles << fileinterface; + + const QString &fixedName = fixFileName(fileName); + if (!d->m_changedFiles.contains(fixedName)) + d->m_changedFiles.append(fixedName); + if (wasempty && !d->m_changedFiles.isEmpty()) { QTimer::singleShot(200, this, SLOT(checkForReload())); } @@ -563,36 +679,61 @@ void FileManager::mainWindowActivated() void FileManager::checkForReload() { - if (QApplication::activeWindow() == d->m_mainWindow && - !d->m_blockActivated && !d->m_changedFiles.isEmpty()) { - d->m_blockActivated = true; - const QList<QPointer<IFile> > changed = d->m_changedFiles; - d->m_changedFiles.clear(); - IFile::ReloadBehavior behavior = EditorManager::instance()->reloadBehavior(); - foreach (IFile *f, changed) { - if (!f) - continue; - QFileInfo fi(f->fileName()); - Internal::FileInfo info = d->m_managedFiles.value(f); - if (info.modified != fi.lastModified() - || info.permissions != fi.permissions()) { - if (info.modified != fi.lastModified()) - f->modified(&behavior); - else { - IFile::ReloadBehavior tempBeh = - IFile::ReloadPermissions; - f->modified(&tempBeh); - } - updateFileInfo(f); + if (QApplication::activeWindow() != d->m_mainWindow) + return; - // the file system watchers loses inodes when a file is removed/renamed. Work around it. - d->m_fileWatcher->removePath(f->fileName()); - d->m_fileWatcher->addPath(f->fileName()); + if (d->m_blockActivated) + return; + + d->m_blockActivated = true; + + IFile::ReloadBehavior behavior = EditorManager::instance()->reloadBehavior(); + + foreach(const QString &fileName, d->m_changedFiles) { + // Get the information from the filesystem + QFileInfo fi(fileName); + bool expected = false; + if (fi.lastModified() == d->m_states.value(fileName).expected.modified + && fi.permissions() == d->m_states.value(fileName).expected.permissions) { + expected = true; + } + + const QMap<IFile *, Internal::FileStateItem> &lastUpdated = + d->m_states.value(fileName).lastUpdatedState; + QMap<IFile *, Internal::FileStateItem>::const_iterator it, end; + it = lastUpdated.constBegin(); + end = lastUpdated.constEnd(); + + for ( ; it != end; ++it) { + // Compare + if (it.value().modified == fi.lastModified() + && it.value().permissions == fi.permissions()) { + // Already up to date + } else { + // Update IFile + if (expected) { + IFile::ReloadBehavior tempBeh = IFile::ReloadUnmodified; + it.key()->modified(&tempBeh); + } else { + if (it.value().modified == fi.lastModified()) { + // Only permission change + IFile::ReloadBehavior tempBeh = IFile::ReloadPermissions; + it.key()->modified(&tempBeh); + } else { + it.key()->modified(&behavior); + } + } + updateFileInfo(it.key()); } + } - d->m_blockActivated = false; - checkForReload(); + + d->m_fileWatcher->removePath(fileName); + d->m_fileWatcher->addPath(fileName); } + + d->m_changedFiles.clear(); + d->m_blockActivated = false; } void FileManager::syncWithEditor(Core::IContext *context) @@ -671,25 +812,6 @@ QString FileManager::currentFile() const return d->m_currentFile; } -/*! - \fn QList<IFile*> FileManager::managedFiles(const QString &fileName) const - - Returns the list one IFile's in the set that point to \a fileName. -*/ -QList<IFile *> FileManager::managedFiles(const QString &fileName) const -{ - const QString fixedName = fixFileName(fileName); - QList<IFile *> result; - if (!fixedName.isEmpty()) { - const QMap<IFile*, Internal::FileInfo>::const_iterator cend = d->m_managedFiles.constEnd(); - for (QMap<IFile*, Internal::FileInfo>::const_iterator i = d->m_managedFiles.constBegin(); i != cend; ++i) { - if (i.value().fileName == fixedName) - result << i.key(); - } - } - return result; -} - /*! Returns the initial directory for a new file dialog. If there is @@ -789,33 +911,16 @@ void FileManager::notifyFilesChangedInternally(const QStringList &files) // -------------- FileChangeBlocker FileChangeBlocker::FileChangeBlocker(const QString &fileName) - : m_reload(false) + : m_fileName(fileName) { Core::FileManager *fm = Core::ICore::instance()->fileManager(); - m_files = fm->managedFiles(fileName); - foreach (Core::IFile *file, m_files) - fm->blockFileChange(file); + fm->expectFileChange(fileName); } FileChangeBlocker::~FileChangeBlocker() { - Core::IFile::ReloadBehavior tempBehavior = Core::IFile::ReloadAll; Core::FileManager *fm = Core::ICore::instance()->fileManager(); - foreach (Core::IFile *file, m_files) { - if (m_reload) - file->modified(&tempBehavior); - fm->unblockFileChange(file); - } -} - -void FileChangeBlocker::setModifiedReload(bool b) -{ - m_reload = b; -} - -bool FileChangeBlocker::modifiedReload() const -{ - return m_reload; + fm->unexpectFileChange(m_fileName); } } // namespace Core diff --git a/src/plugins/coreplugin/filemanager.h b/src/plugins/coreplugin/filemanager.h index 55dd392e409..8e9c830164a 100644 --- a/src/plugins/coreplugin/filemanager.h +++ b/src/plugins/coreplugin/filemanager.h @@ -61,12 +61,14 @@ public: bool addFile(IFile *file); bool removeFile(IFile *file); bool isFileManaged(const QString &fileName) const; - QList<IFile *> managedFiles(const QString &fileName) const; QList<IFile *> modifiedFiles() const; void blockFileChange(IFile *file); void unblockFileChange(IFile *file); + void expectFileChange(const QString &fileName); + void unexpectFileChange(const QString &fileName); + // recent files void addToRecentFiles(const QString &fileName); QStringList recentFiles() const; @@ -126,9 +128,14 @@ private slots: void syncWithEditor(Core::IContext *context); private: + void addFileInfo(IFile *file); + void removeFileInfo(IFile *file); + void removeFileInfo(const QString &fileName, IFile *file); + void addWatch(const QString &filename); void removeWatch(const QString &filename); void updateFileInfo(IFile *file); + void updateExpectedState(const QString &fileName); QList<IFile *> saveModifiedFiles(const QList<IFile *> &files, bool *cancelled, bool silently, @@ -150,11 +157,8 @@ class CORE_EXPORT FileChangeBlocker public: FileChangeBlocker(const QString &fileName); ~FileChangeBlocker(); - void setModifiedReload(bool reload); - bool modifiedReload() const; private: - QList<IFile *> m_files; - bool m_reload; + QString m_fileName; Q_DISABLE_COPY(FileChangeBlocker) }; diff --git a/src/plugins/coreplugin/scriptmanager/qworkbench_wrapper.cpp b/src/plugins/coreplugin/scriptmanager/qworkbench_wrapper.cpp index abd51592268..191e108437c 100644 --- a/src/plugins/coreplugin/scriptmanager/qworkbench_wrapper.cpp +++ b/src/plugins/coreplugin/scriptmanager/qworkbench_wrapper.cpp @@ -187,12 +187,6 @@ bool FileManagerPrototype::isFileManaged(const QString &fileName) const return callee()->isFileManaged(fileName); } -QList<Core::IFile *> -FileManagerPrototype::managedFiles(const QString &fileName) const -{ - return callee()->managedFiles(fileName); -} - void FileManagerPrototype::blockFileChange(Core::IFile *file) { callee()->blockFileChange(file); diff --git a/src/plugins/coreplugin/scriptmanager/qworkbench_wrapper.h b/src/plugins/coreplugin/scriptmanager/qworkbench_wrapper.h index 834a4e27c46..7028df13272 100644 --- a/src/plugins/coreplugin/scriptmanager/qworkbench_wrapper.h +++ b/src/plugins/coreplugin/scriptmanager/qworkbench_wrapper.h @@ -117,7 +117,6 @@ public slots: QString getSaveAsFileName(Core::IFile *file); bool isFileManaged(const QString &fileName) const; - QList<Core::IFile *> managedFiles(const QString &fileName) const; void blockFileChange(Core::IFile *file); void unblockFileChange(Core::IFile *file); diff --git a/src/plugins/cvs/cvsplugin.cpp b/src/plugins/cvs/cvsplugin.cpp index ddb06bf1b09..b7d268da541 100644 --- a/src/plugins/cvs/cvsplugin.cpp +++ b/src/plugins/cvs/cvsplugin.cpp @@ -599,7 +599,6 @@ void CVSPlugin::revertCurrentFile() args << QLatin1String("update") << QLatin1String("-C") << state.relativeCurrentFile(); const CVSResponse revertResponse = runCVS(state.currentFileTopLevel(), args, m_settings.timeOutMS(), true); if (revertResponse.result == CVSResponse::Ok) { - fcb.setModifiedReload(true); cvsVersionControl()->emitFilesChanged(QStringList(state.currentFile())); } } diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp index 1fe58493683..cdfd3a33879 100644 --- a/src/plugins/git/gitplugin.cpp +++ b/src/plugins/git/gitplugin.cpp @@ -490,7 +490,6 @@ void GitPlugin::undoFileChanges() const VCSBase::VCSBasePluginState state = currentState(); QTC_ASSERT(state.hasFile(), return) Core::FileChangeBlocker fcb(state.currentFile()); - fcb.setModifiedReload(true); m_gitClient->revert(QStringList(state.currentFile())); } diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp index 8bf910188a1..548e8553fc3 100644 --- a/src/plugins/perforce/perforceplugin.cpp +++ b/src/plugins/perforce/perforceplugin.cpp @@ -495,7 +495,6 @@ void PerforcePlugin::revertCurrentFile() return; Core::FileChangeBlocker fcb(state.currentFile()); - fcb.setModifiedReload(true); args.clear(); args << QLatin1String("revert") << state.relativeCurrentFile(); PerforceResponse result2 = runP4Cmd(state.currentFileTopLevel(), args, diff --git a/src/plugins/qt4projectmanager/profileeditor.cpp b/src/plugins/qt4projectmanager/profileeditor.cpp index 86a7f36bd7a..31d67295b0a 100644 --- a/src/plugins/qt4projectmanager/profileeditor.cpp +++ b/src/plugins/qt4projectmanager/profileeditor.cpp @@ -84,8 +84,7 @@ QString ProFileEditorEditable::id() const ProFileEditor::ProFileEditor(QWidget *parent, ProFileEditorFactory *factory, TextEditor::TextEditorActionHandler *ah) : BaseTextEditor(parent), m_factory(factory), m_ah(ah) { - Qt4Manager *manager = factory->qt4ProjectManager(); - ProFileDocument *doc = new ProFileDocument(manager); + ProFileDocument *doc = new ProFileDocument(); doc->setMimeType(QLatin1String(Qt4ProjectManager::Constants::PROFILE_MIMETYPE)); setBaseTextDocument(doc); @@ -126,20 +125,11 @@ void ProFileEditor::setFontSettings(const TextEditor::FontSettings &fs) // ProFileDocument // -ProFileDocument::ProFileDocument(Qt4Manager *manager) - : TextEditor::BaseTextDocument(), m_manager(manager) +ProFileDocument::ProFileDocument() + : TextEditor::BaseTextDocument() { } -bool ProFileDocument::save(const QString &name) -{ - if (BaseTextDocument::save(name)) { - m_manager->notifyChanged(name); - return true; - } - return false; -} - QString ProFileDocument::defaultPath() const { QFileInfo fi(fileName()); diff --git a/src/plugins/qt4projectmanager/profileeditor.h b/src/plugins/qt4projectmanager/profileeditor.h index 6756dc5b785..ee301fd13af 100644 --- a/src/plugins/qt4projectmanager/profileeditor.h +++ b/src/plugins/qt4projectmanager/profileeditor.h @@ -93,13 +93,9 @@ class ProFileDocument : public TextEditor::BaseTextDocument Q_OBJECT public: - ProFileDocument(Qt4Manager *manager); - bool save(const QString &name); + ProFileDocument(); QString defaultPath() const; QString suggestedFileName() const; - -private: - Qt4Manager *m_manager; }; } // namespace Internal diff --git a/src/plugins/qt4projectmanager/qt4nodes.cpp b/src/plugins/qt4projectmanager/qt4nodes.cpp index 95369b0fc28..ec7bc33b79a 100644 --- a/src/plugins/qt4projectmanager/qt4nodes.cpp +++ b/src/plugins/qt4projectmanager/qt4nodes.cpp @@ -226,8 +226,8 @@ Qt4PriFileNode::Qt4PriFileNode(Qt4Project *project, Qt4ProFileNode* qt4ProFileNo m_projectDir(QFileInfo(filePath).absolutePath()) { Q_ASSERT(project); - Qt4PriFile *qt4PriFile = new Qt4PriFile(this); - Core::ICore::instance()->fileManager()->addFile(qt4PriFile); + m_qt4PriFile = new Qt4PriFile(this); + Core::ICore::instance()->fileManager()->addFile(m_qt4PriFile); setFolderName(QFileInfo(filePath).completeBaseName()); @@ -608,18 +608,13 @@ bool Qt4PriFileNode::priFileWritable(const QString &path) return true; } -bool Qt4PriFileNode::saveModifiedEditors(const QString &path) +bool Qt4PriFileNode::saveModifiedEditors() { - QList<Core::IFile*> allFileHandles; QList<Core::IFile*> modifiedFileHandles; Core::ICore *core = Core::ICore::instance(); - foreach (Core::IFile *file, core->fileManager()->managedFiles(path)) { - allFileHandles << file; - } - - foreach (Core::IEditor *editor, core->editorManager()->editorsForFileName(path)) { + foreach (Core::IEditor *editor, core->editorManager()->editorsForFileName(m_projectFilePath)) { if (Core::IFile *editorFile = editor->file()) { if (editorFile->isModified()) modifiedFileHandles << editorFile; @@ -629,14 +624,12 @@ bool Qt4PriFileNode::saveModifiedEditors(const QString &path) if (!modifiedFileHandles.isEmpty()) { bool cancelled; core->fileManager()->saveModifiedFiles(modifiedFileHandles, &cancelled, - tr("There are unsaved changes for project file %1.").arg(path)); + tr("There are unsaved changes for project file %1.").arg(m_projectFilePath)); if (cancelled) return false; - // force instant reload - foreach (Core::IFile *fileHandle, allFileHandles) { - Core::IFile::ReloadBehavior reload = Core::IFile::ReloadAll; - fileHandle->modified(&reload); - } + // force instant reload of ourselves + ProFileCacheManager::instance()->discardFile(m_projectFilePath); + m_project->qt4ProjectManager()->notifyChanged(m_projectFilePath); } return true; } @@ -652,7 +645,7 @@ void Qt4PriFileNode::changeFiles(const FileType fileType, *notChanged = filePaths; // Check for modified editors - if (!saveModifiedEditors(m_projectFilePath)) + if (!saveModifiedEditors()) return; QStringList lines; @@ -692,21 +685,23 @@ void Qt4PriFileNode::changeFiles(const FileType fileType, // save file save(lines); + // This is a hack + // We are savign twice in a very short timeframe, once the editor and once the ProFile + // So the modification time might not change between those two saves + // We manually tell each editor to reload it's file + // (The .pro files are notified by the file system watcher) + foreach (Core::IEditor *editor, Core::ICore::instance()->editorManager()->editorsForFileName(m_projectFilePath)) { + if (Core::IFile *editorFile = editor->file()) { + Core::IFile::ReloadBehavior b = Core::IFile::ReloadUnmodified; + editorFile->modified(&b); + } + } + includeFile->deref(); } void Qt4PriFileNode::save(const QStringList &lines) { - Core::ICore *core = Core::ICore::instance(); - Core::FileManager *fileManager = core->fileManager(); - QList<Core::IFile *> allFileHandles = fileManager->managedFiles(m_projectFilePath); - Core::IFile *modifiedFileHandle = 0; - foreach (Core::IFile *file, allFileHandles) - if (file->fileName() == m_projectFilePath) - modifiedFileHandle = file; - - if (modifiedFileHandle) - fileManager->blockFileChange(modifiedFileHandle); QFile qfile(m_projectFilePath); if (qfile.open(QIODevice::WriteOnly | QIODevice::Text)) { foreach (const QString &str, lines) { @@ -715,14 +710,8 @@ void Qt4PriFileNode::save(const QStringList &lines) } qfile.close(); } - m_project->qt4ProjectManager()->notifyChanged(m_projectFilePath); - if (modifiedFileHandle) - fileManager->unblockFileChange(modifiedFileHandle); - Core::IFile::ReloadBehavior tempBehavior = - Core::IFile::ReloadAll; - foreach (Core::IFile *file, allFileHandles) - file->modified(&tempBehavior); + m_project->qt4ProjectManager()->notifyChanged(m_projectFilePath); } /* diff --git a/src/plugins/qt4projectmanager/qt4nodes.h b/src/plugins/qt4projectmanager/qt4nodes.h index 0f7cf2fb0b5..4b2d673e890 100644 --- a/src/plugins/qt4projectmanager/qt4nodes.h +++ b/src/plugins/qt4projectmanager/qt4nodes.h @@ -49,10 +49,6 @@ namespace Core { class ICore; } -namespace ProjectExplorer { -class FileWatcher; -} - namespace Designer { class FormWindowEditor; } @@ -176,7 +172,7 @@ private slots: private: void save(const QStringList &lines); bool priFileWritable(const QString &path); - bool saveModifiedEditors(const QString &path); + bool saveModifiedEditors(); Qt4Project *m_project; Qt4ProFileNode *m_qt4ProFileNode; @@ -184,6 +180,7 @@ private: QString m_projectDir; QMap<QString, Qt4UiCodeModelSupport *> m_uiCodeModelSupport; + Qt4PriFile *m_qt4PriFile; // managed by Qt4ProFileNode friend class Qt4ProFileNode; diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp index 6354a2013de..f0f200d443f 100644 --- a/src/plugins/subversion/subversionplugin.cpp +++ b/src/plugins/subversion/subversionplugin.cpp @@ -634,7 +634,6 @@ void SubversionPlugin::revertCurrentFile() const SubversionResponse revertResponse = runSvn(state.currentFileTopLevel(), args, m_settings.timeOutMS(), true); if (!revertResponse.error) { - fcb.setModifiedReload(true); subVersionControl()->emitFilesChanged(QStringList(state.currentFile())); } } -- GitLab