diff options
-rw-r--r-- | src/core/FileWatcher.cpp | 56 | ||||
-rw-r--r-- | src/core/FileWatcher.h | 6 |
2 files changed, 34 insertions, 28 deletions
diff --git a/src/core/FileWatcher.cpp b/src/core/FileWatcher.cpp index 64e86c3fa..ae7878191 100644 --- a/src/core/FileWatcher.cpp +++ b/src/core/FileWatcher.cpp @@ -120,9 +120,9 @@ BulkFileWatcher::BulkFileWatcher(QObject* parent) { connect(&m_fileWatcher, SIGNAL(fileChanged(QString)), SLOT(handleFileChanged(QString))); connect(&m_fileWatcher, SIGNAL(directoryChanged(QString)), SLOT(handleDirectoryChanged(QString))); - connect(&m_fileWatchUnblockTimer, SIGNAL(timeout()), this, SLOT(observeFileChanges())); + connect(&m_watchedFilesIgnoreTimer, SIGNAL(timeout()), this, SLOT(observeFileChanges())); connect(&m_pendingSignalsTimer, SIGNAL(timeout()), this, SLOT(emitSignals())); - m_fileWatchUnblockTimer.setSingleShot(true); + m_watchedFilesIgnoreTimer.setSingleShot(true); m_pendingSignalsTimer.setSingleShot(true); } @@ -135,7 +135,7 @@ void BulkFileWatcher::clear() } m_watchedPaths.clear(); m_watchedFilesInDirectory.clear(); - m_ignoreFilesChangess.clear(); + m_watchedFilesIgnored.clear(); } void BulkFileWatcher::removePath(const QString& path) @@ -166,7 +166,7 @@ void BulkFileWatcher::addPath(const QString& path) const bool directorySuccess = m_fileWatcher.addPath(directoryPath); m_watchedPaths[directoryPath] = directorySuccess; } - m_watchedFilesInDirectory[directoryPath][filePath] = info.exists(); + m_watchedFilesInDirectory[directoryPath][filePath] = info.exists() ? info.lastModified().toMSecsSinceEpoch() : 0; } void BulkFileWatcher::handleFileChanged(const QString& path) @@ -174,13 +174,15 @@ void BulkFileWatcher::handleFileChanged(const QString& path) const QFileInfo info(path); const QString filePath = info.absoluteFilePath(); const QString directoryPath = info.absolutePath(); - const QMap<QString, bool>& watchedFiles = m_watchedFilesInDirectory[directoryPath]; - const bool created = !watchedFiles[filePath] && info.exists(); - const bool deleted = watchedFiles[filePath] && !info.exists(); - const bool changed = !created && !deleted; + const QMap<QString, qint64>& watchedFiles = m_watchedFilesInDirectory[directoryPath]; + const qint64 lastModificationTime = info.lastModified().toMSecsSinceEpoch(); + const bool created = watchedFiles[filePath] == 0 && info.exists(); + const bool deleted = watchedFiles[filePath] != 0 && !info.exists(); + const bool changed = !created && !deleted && lastModificationTime != watchedFiles[filePath]; + addPath(path); - if (m_ignoreFilesChangess[info.canonicalFilePath()] > Clock::currentDateTimeUtc()) { + if (m_watchedFilesIgnored[info.canonicalFilePath()] > Clock::currentDateTimeUtc()) { // changes are blocked return; } @@ -203,35 +205,36 @@ void BulkFileWatcher::handleDirectoryChanged(const QString& path) qDebug("Directory changed %s", qPrintable(path)); const QFileInfo directoryInfo(path); const QString directoryPath = directoryInfo.absoluteFilePath(); - QMap<QString, bool>& watchedFiles = m_watchedFilesInDirectory[directoryPath]; + QMap<QString, qint64>& watchedFiles = m_watchedFilesInDirectory[directoryPath]; for (const QString& filename : watchedFiles.keys()) { const QFileInfo fileInfo(filename); const QString filePath = fileInfo.absoluteFilePath(); - const bool existed = watchedFiles[filePath]; - if (!fileInfo.exists() && existed) { - qDebug("Remove watch file %s", qPrintable(filePath)); + const qint64 previousModificationTime = watchedFiles[filePath]; + const qint64 lastModificationTime = fileInfo.lastModified().toMSecsSinceEpoch(); + if (!fileInfo.exists() && previousModificationTime != 0) { + qDebug("Remove watch file %s", qPrintable(fileInfo.absoluteFilePath())); m_fileWatcher.removePath(filePath); m_watchedPaths.remove(filePath); watchedFiles.remove(filePath); scheduleSignal(Removed, filePath); } - if (!existed && fileInfo.exists()) { - qDebug("Add watch file %s", qPrintable(filePath)); + if (previousModificationTime == 0 && fileInfo.exists()) { + qDebug("Add watch file %s", qPrintable(fileInfo.absoluteFilePath())); if (!m_watchedPaths.value(filePath)) { const bool success = m_fileWatcher.addPath(filePath); m_watchedPaths[filePath] = success; - watchedFiles[filePath] = fileInfo.exists(); + watchedFiles[filePath] = lastModificationTime; } scheduleSignal(Created, filePath); } - if (existed && fileInfo.exists()) { + if (fileInfo.exists() && previousModificationTime != lastModificationTime) { // this case is handled using qDebug("Refresh watch file %s", qPrintable(fileInfo.absoluteFilePath())); m_fileWatcher.removePath(fileInfo.absolutePath()); m_fileWatcher.addPath(fileInfo.absolutePath()); scheduleSignal(Updated, filePath); } - m_watchedFilesInDirectory[directoryPath][filePath] = fileInfo.exists(); + m_watchedFilesInDirectory[directoryPath][filePath] = fileInfo.exists() ? lastModificationTime : 0; } } @@ -242,13 +245,16 @@ void BulkFileWatcher::emitSignals() for (const auto& path : queued.keys()) { const auto& signal = queued[path]; if (signal.last() == Removed) { + qDebug("Emit %s removed", qPrintable(path)); emit fileRemoved(path); continue; } if (signal.first() == Created) { + qDebug("Emit %s created", qPrintable(path)); emit fileCreated(path); continue; } + qDebug("Emit %s changed", qPrintable(path)); emit fileChanged(path); } } @@ -268,7 +274,7 @@ void BulkFileWatcher::scheduleSignal(Signal signal, const QString& path) void BulkFileWatcher::ignoreFileChanges(const QString& path) { const QFileInfo info(path); - m_ignoreFilesChangess[info.canonicalFilePath()] = Clock::currentDateTimeUtc().addMSecs(FileChangeDelay); + m_watchedFilesIgnored[info.canonicalFilePath()] = Clock::currentDateTimeUtc().addMSecs(FileChangeDelay); } void BulkFileWatcher::observeFileChanges(bool delayed) @@ -278,19 +284,19 @@ void BulkFileWatcher::observeFileChanges(bool delayed) timeout = TimerResolution; } else { const QDateTime current = Clock::currentDateTimeUtc(); - for (const QString& key : m_ignoreFilesChangess.keys()) { - if (m_ignoreFilesChangess[key] < current) { + for (const QString& key : m_watchedFilesIgnored.keys()) { + if (m_watchedFilesIgnored[key] < current) { // We assume that there was no concurrent change of the database // during our block - so no need to reimport qDebug("Remove block from %s", qPrintable(key)); - m_ignoreFilesChangess.remove(key); + m_watchedFilesIgnored.remove(key); continue; } qDebug("Keep block from %s", qPrintable(key)); - timeout = static_cast<int>(current.msecsTo(m_ignoreFilesChangess[key])); + timeout = qMin(timeout, static_cast<int>(current.msecsTo(m_watchedFilesIgnored[key]))); } } - if (timeout > 0 && !m_fileWatchUnblockTimer.isActive()) { - m_fileWatchUnblockTimer.start(timeout); + if (timeout > 0 && !m_watchedFilesIgnoreTimer.isActive()) { + m_watchedFilesIgnoreTimer.start(timeout); } } diff --git a/src/core/FileWatcher.h b/src/core/FileWatcher.h index 00d6a6c69..f6953cf80 100644 --- a/src/core/FileWatcher.h +++ b/src/core/FileWatcher.h @@ -93,11 +93,11 @@ private: private: QMap<QString, bool> m_watchedPaths; - QMap<QString, QDateTime> m_ignoreFilesChangess; + QMap<QString, QDateTime> m_watchedFilesIgnored; QFileSystemWatcher m_fileWatcher; - QMap<QString, QMap<QString, bool>> m_watchedFilesInDirectory; + QMap<QString, QMap<QString, qint64>> m_watchedFilesInDirectory; // needed for Import/Export-References to prevent update after self-write - QTimer m_fileWatchUnblockTimer; + QTimer m_watchedFilesIgnoreTimer; // needed to tolerate multiple signals for same event QTimer m_pendingSignalsTimer; QMap<QString, QList<Signal>> m_pendingSignals; |