]> git.lyx.org Git - features.git/commitdiff
Ressurect old FileMonitor à la Frankenstein
authorGuillaume Munch <gm@lyx.org>
Sat, 18 Mar 2017 23:06:40 +0000 (00:06 +0100)
committerGuillaume Munch <gm@lyx.org>
Sun, 19 Mar 2017 13:41:17 +0000 (14:41 +0100)
ActiveFileMonitor combines QFileSystemWatcher with the previous checksum
approach.

src/support/FileMonitor.cpp
src/support/FileMonitor.h

index ced1188667beae5ef6bb86b678375bbcaaa46605..50337cb288db871f4c0cec6745abb39d1027c887 100644 (file)
@@ -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<FileMonitorGuard>
+FileSystemWatcher::getGuard(FileName const & filename)
 {
-       FileSystemWatcher & f = instance();
-       string const filename = file_with_path.absFileName();
-       weak_ptr<FileMonitorGuard> & wptr = f.store_[filename];
+       string const absfilename = filename.absFileName();
+       weak_ptr<FileMonitorGuard> & wptr = store_[absfilename];
        if (shared_ptr<FileMonitorGuard> mon = wptr.lock())
-               return make_unique<FileMonitor>(mon);
-       auto mon = make_shared<FileMonitorGuard>(filename, f.qwatcher_.get());
+               return mon;
+       auto mon = make_shared<FileMonitorGuard>(absfilename, qwatcher_.get());
        wptr = mon;
-       return make_unique<FileMonitor>(mon);
+       return mon;
+}
+
+
+//static
+FileMonitorPtr FileSystemWatcher::monitor(FileName const & filename)
+{
+       return make_unique<FileMonitor>(instance().getGuard(filename));
+}
+
+
+//static
+ActiveFileMonitorPtr FileSystemWatcher::activeMonitor(FileName const & filename,
+                                                      int interval)
+{
+       return make_unique<ActiveFileMonitor>(instance().getGuard(filename),
+                                             filename, interval);
 }
 
 
@@ -211,6 +227,59 @@ FileMonitorBlockerGuard::~FileMonitorBlockerGuard()
        QTimer::singleShot(delay_, monitor_, SLOT(reconnectToFileMonitorGuard()));
 }
 
+
+ActiveFileMonitor::ActiveFileMonitor(std::shared_ptr<FileMonitorGuard> 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
 
index 51dbd7c72d8d1ecfd6458547653a0a2934792e2f..e2bbb1b1feba5310a321a9c5cbeeb7097c677376 100644 (file)
@@ -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 <memory>
 
 #include <QFileSystemWatcher>
 namespace lyx {
 namespace support {
 
-class FileName;
-
 ///
 ///  FileMonitor, a file monitor based on QFileSystemWatcher
 ///
 
 class FileMonitor;
+class ActiveFileMonitor;
 class FileMonitorGuard;
 typedef std::unique_ptr<FileMonitor> FileMonitorPtr;
+typedef std::unique_ptr<ActiveFileMonitor> 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<FileMonitorGuard> getGuard(FileName const & filename);
        // Caches the monitor guards but allow them to be destroyed
        std::map<std::string, std::weak_ptr<FileMonitorGuard>> 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<FileMonitorGuard> 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