improve file change notification suppression in saveFile()

for one, entirely stop monitoring the own IFile.
second, expect changes on the filename - in case other IFiles use it as
well.
these two ensure that nothing weird happens, especially if we show a dialog
and thus enter an event loop.
This commit is contained in:
Oswald Buddenhagen
2011-04-15 21:23:21 +02:00
parent 2dd1f0d83d
commit 9e6448d38d
2 changed files with 17 additions and 39 deletions

View File

@@ -279,24 +279,6 @@ void FileManager::addFileInfo(const QString &fileName, IFile *file, bool isLink)
d->m_filesWithWatch[file].append(fileName); // inserts a new QStringList if not already there d->m_filesWithWatch[file].append(fileName); // inserts a new QStringList if not already there
} }
/* Updates the time stamp and permission information of the files
registered for this IFile (in m_filesWithWatch; can be the IFile's file + final link target) */
void FileManager::updateFileInfo(IFile *file)
{
foreach (const QString &fileName, d->m_filesWithWatch.value(file)) {
// If the filename is empty there's nothing to do
if (fileName.isEmpty())
continue;
const QFileInfo fi(fileName);
Internal::FileStateItem item;
item.modified = fi.lastModified();
item.permissions = fi.permissions();
QTC_ASSERT(d->m_states.contains(fileName), continue);
QTC_ASSERT(d->m_states.value(fileName).lastUpdatedState.contains(file), continue);
d->m_states[fileName].lastUpdatedState.insert(file, item);
}
}
/// Dumps the state of the file manager's map /// Dumps the state of the file manager's map
/// For debugging purposes /// For debugging purposes
void FileManager::dump() void FileManager::dump()
@@ -410,18 +392,21 @@ void FileManager::fileDestroyed(QObject *obj)
Removes a IFile object from the collection. Removes a IFile object from the collection.
Returns true if the file specified by \a file has been part of the file list. Returns true if the file specified by \a file had the addWatcher argument to addFile() set.
*/ */
void FileManager::removeFile(IFile *file) bool FileManager::removeFile(IFile *file)
{ {
QTC_ASSERT(file, return); QTC_ASSERT(file, return false);
bool addWatcher = false;
// Special casing unwatched files // Special casing unwatched files
if (!d->m_filesWithoutWatch.removeOne(file)) { if (!d->m_filesWithoutWatch.removeOne(file)) {
addWatcher = true;
removeFileInfo(file); removeFileInfo(file);
disconnect(file, SIGNAL(changed()), this, SLOT(checkForNewFileName())); disconnect(file, SIGNAL(changed()), this, SLOT(checkForNewFileName()));
} }
disconnect(file, SIGNAL(destroyed(QObject *)), this, SLOT(fileDestroyed(QObject *))); disconnect(file, SIGNAL(destroyed(QObject *)), this, SLOT(fileDestroyed(QObject *)));
return addWatcher;
} }
/* Slot reacting on IFile::changed. We need to check if the signal was sent /* Slot reacting on IFile::changed. We need to check if the signal was sent
@@ -633,7 +618,11 @@ QList<IFile *> FileManager::saveModifiedFiles(const QList<IFile *> &files,
bool FileManager::saveFile(IFile *file, const QString &fileName, bool *isReadOnly) bool FileManager::saveFile(IFile *file, const QString &fileName, bool *isReadOnly)
{ {
bool ret = true;
QString effName = fileName.isEmpty() ? file->fileName() : fileName; QString effName = fileName.isEmpty() ? file->fileName() : fileName;
expectFileChange(effName); // This only matters to other IFiles which refer to this file
bool addWatcher = removeFile(file); // So that our own IFile gets no notification at all
QString errorString; QString errorString;
if (!file->save(&errorString, fileName)) { if (!file->save(&errorString, fileName)) {
if (isReadOnly) { if (isReadOnly) {
@@ -642,28 +631,18 @@ bool FileManager::saveFile(IFile *file, const QString &fileName, bool *isReadOnl
if (ofi.exists() && !ofi.open(QIODevice::ReadWrite) if (ofi.exists() && !ofi.open(QIODevice::ReadWrite)
&& ofi.error() == QFile::PermissionsError) { && ofi.error() == QFile::PermissionsError) {
*isReadOnly = true; *isReadOnly = true;
return false; goto out;
} }
*isReadOnly = false; *isReadOnly = false;
} }
QMessageBox::critical(d->m_mainWindow, tr("File Error"), errorString); QMessageBox::critical(d->m_mainWindow, tr("File Error"), errorString);
return false; out:
ret = false;
} }
// We are updating the lastUpdated time to the current modification time addFile(file, addWatcher);
// in changedFile we'll compare the modification time with the last updated unexpectFileChange(effName);
// time, and if they are the same, then we don't deliver that notification return ret;
// 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);
foreach (const QString &fileName, d->m_filesWithWatch.value(file))
updateExpectedState(fileName);
return true;
} }
QString FileManager::getSaveFileName(const QString &title, const QString &pathIn, QString FileManager::getSaveFileName(const QString &title, const QString &pathIn,

View File

@@ -74,7 +74,7 @@ public:
// file pool to monitor // file pool to monitor
void addFiles(const QList<IFile *> &files, bool addWatcher = true); void addFiles(const QList<IFile *> &files, bool addWatcher = true);
void addFile(IFile *file, bool addWatcher = true); void addFile(IFile *file, bool addWatcher = true);
void removeFile(IFile *file); bool removeFile(IFile *file);
QList<IFile *> modifiedFiles() const; QList<IFile *> modifiedFiles() const;
void renamedFile(const QString &from, const QString &to); void renamedFile(const QString &from, const QString &to);
@@ -159,7 +159,6 @@ private:
void addFileInfo(const QString &fileName, IFile *file, bool isLink); void addFileInfo(const QString &fileName, IFile *file, bool isLink);
void removeFileInfo(IFile *file); void removeFileInfo(IFile *file);
void updateFileInfo(IFile *file);
void updateExpectedState(const QString &fileName); void updateExpectedState(const QString &fileName);
QList<IFile *> saveModifiedFiles(const QList<IFile *> &files, QList<IFile *> saveModifiedFiles(const QList<IFile *> &files,