From: Guillaume Munch Date: Sat, 18 Mar 2017 23:06:40 +0000 (+0100) Subject: Ressurect old FileMonitor à la Frankenstein X-Git-Tag: 2.3.0alpha1~199 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=9926927fb1a38f15ec4fa1334075720925a3295e;p=features.git Ressurect old FileMonitor à la Frankenstein ActiveFileMonitor combines QFileSystemWatcher with the previous checksum approach. --- diff --git a/src/support/FileMonitor.cpp b/src/support/FileMonitor.cpp index ced1188667..50337cb288 100644 --- a/src/support/FileMonitor.cpp +++ b/src/support/FileMonitor.cpp @@ -3,6 +3,7 @@ * This file is part of LyX, the document processor. * Licence details can be found in the file COPYING. * + * \author Angus Leeming * \author Guillaume Munch * * Full author contact details are available in file CREDITS. @@ -42,17 +43,32 @@ FileSystemWatcher::FileSystemWatcher() {} -//static -FileMonitorPtr FileSystemWatcher::monitor(FileName const & file_with_path) +shared_ptr +FileSystemWatcher::getGuard(FileName const & filename) { - FileSystemWatcher & f = instance(); - string const filename = file_with_path.absFileName(); - weak_ptr & wptr = f.store_[filename]; + string const absfilename = filename.absFileName(); + weak_ptr & wptr = store_[absfilename]; if (shared_ptr mon = wptr.lock()) - return make_unique(mon); - auto mon = make_shared(filename, f.qwatcher_.get()); + return mon; + auto mon = make_shared(absfilename, qwatcher_.get()); wptr = mon; - return make_unique(mon); + return mon; +} + + +//static +FileMonitorPtr FileSystemWatcher::monitor(FileName const & filename) +{ + return make_unique(instance().getGuard(filename)); +} + + +//static +ActiveFileMonitorPtr FileSystemWatcher::activeMonitor(FileName const & filename, + int interval) +{ + return make_unique(instance().getGuard(filename), + filename, interval); } @@ -211,6 +227,59 @@ FileMonitorBlockerGuard::~FileMonitorBlockerGuard() QTimer::singleShot(delay_, monitor_, SLOT(reconnectToFileMonitorGuard())); } + +ActiveFileMonitor::ActiveFileMonitor(std::shared_ptr monitor, + FileName const & filename, int interval) + : FileMonitor(monitor), filename_(filename), interval_(interval), + timestamp_(0), checksum_(0), cooldown_(true) +{ + QObject::connect(this, SIGNAL(fileChanged()), this, SLOT(setCooldown())); + QTimer::singleShot(interval_, this, SLOT(clearCooldown())); + if (!filename_.exists()) + return; + timestamp_ = filename_.lastModified(); + checksum_ = filename_.checksum(); +} + + +void ActiveFileMonitor::checkModified() +{ + if (cooldown_) + return; + + cooldown_ = true; + bool changed = false; + if (!filename_.exists()) { + changed = timestamp_ || checksum_; + timestamp_ = 0; + checksum_ = 0; + } else { + time_t const new_timestamp = filename_.lastModified(); + + if (new_timestamp != timestamp_) { + timestamp_ = new_timestamp; + + unsigned long const new_checksum = filename_.checksum(); + if (new_checksum != checksum_) { + checksum_ = new_checksum; + changed = true; + } + } + } + if (changed) + FileMonitor::changed(); + QTimer::singleShot(interval_, this, SLOT(clearCooldown())); +} + + +void ActiveFileMonitor::checkModifiedAsync() +{ + if (!cooldown_) + QTimer::singleShot(0, this, SLOT(checkModified())); +} + + + } // namespace support } // namespace lyx diff --git a/src/support/FileMonitor.h b/src/support/FileMonitor.h index 51dbd7c72d..e2bbb1b1fe 100644 --- a/src/support/FileMonitor.h +++ b/src/support/FileMonitor.h @@ -4,6 +4,7 @@ * This file is part of LyX, the document processor. * Licence details can be found in the file COPYING. * + * \author Angus Leeming * \author Guillaume Munch * * Full author contact details are available in file CREDITS. @@ -15,6 +16,8 @@ #ifndef FILEMONITOR_H #define FILEMONITOR_H +#include "support/FileName.h" + #include #include @@ -27,15 +30,15 @@ namespace lyx { namespace support { -class FileName; - /// /// FileMonitor, a file monitor based on QFileSystemWatcher /// class FileMonitor; +class ActiveFileMonitor; class FileMonitorGuard; typedef std::unique_ptr FileMonitorPtr; +typedef std::unique_ptr ActiveFileMonitorPtr; /// /// Watch a file: @@ -72,14 +75,19 @@ class FileSystemWatcher { public: // as described above - static FileMonitorPtr monitor(FileName const & file_with_path); + static FileMonitorPtr monitor(FileName const & filename); + /// same but with an ActiveFileMonitor + static ActiveFileMonitorPtr activeMonitor(FileName const & filename, + int interval = 10000); // Output whether the paths tracked by qwatcher_ and the active // FileMonitorGuards are in correspondence. static void debug(); private: FileSystemWatcher(); - // A global instance is created automatically on first call to monitor + /// A global instance is created automatically on first call static FileSystemWatcher & instance(); + /// + std::shared_ptr getGuard(FileName const & filename); // Caches the monitor guards but allow them to be destroyed std::map> store_; // This class is a wrapper for QFileSystemWatcher @@ -87,8 +95,8 @@ private: }; -// Must be unique per path -// Ends the watch when deleted +/// Must be unique per path +/// Ends the watch when deleted class FileMonitorGuard : public QObject { Q_OBJECT @@ -174,7 +182,7 @@ Q_SIGNALS: /// Connect to this to be notified when the file changes void fileChanged() const; -private Q_SLOTS: +protected Q_SLOTS: /// Receive notifications from the FileMonitorGuard void changed(); /// @@ -190,6 +198,39 @@ private: }; +/// When a more active monitoring style is needed. +/// For instance because QFileSystemWatcher does not work for remote file +/// systems. +class ActiveFileMonitor : public FileMonitor +{ + Q_OBJECT +public: + ActiveFileMonitor(std::shared_ptr monitor, + FileName const & filename, int interval); + /// call checkModified asynchronously + void checkModifiedAsync(); + +public Q_SLOTS: + /// Check explicitly for a modification, but not more than once every + /// interval ms. + void checkModified(); + +private Q_SLOTS: + void setCooldown() { cooldown_ = true; } + void clearCooldown() { cooldown_ = false; } + +private: + FileName const filename_; + /// + int const interval_; + /// + time_t timestamp_; + /// + unsigned long checksum_; + /// + bool cooldown_; +}; + } // namespace support } // namespace lyx