]> git.lyx.org Git - lyx.git/commitdiff
Remove legacy FileMonitor
authorGuillaume Munch <gm@lyx.org>
Fri, 10 Mar 2017 21:41:48 +0000 (22:41 +0100)
committerGuillaume Munch <gm@lyx.org>
Fri, 10 Mar 2017 23:50:57 +0000 (00:50 +0100)
src/support/FileMonitor.cpp
src/support/FileMonitor.h
src/support/FileMonitor2.cpp [deleted file]
src/support/FileMonitor2.h [deleted file]
src/support/Makefile.am

index bdd6444ff677e6aa0f0f2759e7240e3d94e692d3..a55fd2396baf240e750e71b1d00394d03136e3cd 100644 (file)
@@ -3,7 +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.
  */
 
 #include "support/FileMonitor.h"
 
+#include "support/debug.h"
 #include "support/FileName.h"
-#include "support/Timeout.h"
+#include "support/qstring_helpers.h"
+#include "support/unique_ptr.h"
 
-#include "support/bind.h"
-#include <boost/signals2/trackable.hpp>
+#include <QFile>
+#include <QTimer>
+
+#include <algorithm>
 
 using namespace std;
 
 namespace lyx {
 namespace support {
 
-class FileMonitor::Impl : public boost::signals2::trackable {
-public:
-
-       ///
-       Impl(FileName const & file_with_path, int interval);
-
-       ///
-       void monitorFile();
-
-       ///
-       FileName filename_;
 
-       ///
-       Timeout timer_;
-
-       /// This signal is emitted if the file is modified (has a new checksum).
-       FileMonitor::FileChangedSig fileChanged_;
-
-       /** We use these to ascertain whether a file (once loaded successfully)
-        *  has changed.
-        */
-       time_t timestamp_;
-       ///
-       unsigned long checksum_;
-};
+FileSystemWatcher & FileSystemWatcher::instance()
+{
+       // This thread-safe because QFileSystemWatcher is thread-safe.
+       static FileSystemWatcher f;
+       return f;
+}
 
 
-FileMonitor::FileMonitor(FileName const & file_with_path, int interval)
-       : pimpl_(new Impl(file_with_path, interval))
+FileSystemWatcher::FileSystemWatcher()
+       : qwatcher_(make_unique<QFileSystemWatcher>())
 {}
 
 
-FileMonitor::~FileMonitor()
+//static
+FileMonitorPtr FileSystemWatcher::monitor(FileName const & file_with_path)
 {
-       delete pimpl_;
+       FileSystemWatcher & f = instance();
+       string const filename = file_with_path.absFileName();
+       weak_ptr<FileMonitorGuard> & wptr = f.store_[filename];
+       if (shared_ptr<FileMonitorGuard> mon = wptr.lock())
+               return make_unique<FileMonitor>(mon);
+       auto mon = make_shared<FileMonitorGuard>(filename, f.qwatcher_.get());
+       wptr = mon;
+       return make_unique<FileMonitor>(mon);
 }
 
 
-void FileMonitor::reset(FileName const & file_with_path) const
+//static
+void FileSystemWatcher::debug()
 {
-       if (pimpl_->filename_ == file_with_path)
-               return;
-
-       bool const monitor = pimpl_->timer_.running();
-       if (monitor)
-               stop();
+       FileSystemWatcher & f = instance();
+       QStringList q_files = f.qwatcher_->files();
+       for (pair<string, weak_ptr<FileMonitorGuard>> pair : f.store_) {
+               string const & name = pair.first;
+               if (!pair.second.expired()) {
+                       if (!q_files.contains(toqstr(name)))
+                               LYXERR0("Monitored but not QFileSystemWatched (bad): " << name);
+                       else {
+                               //LYXERR0("Monitored and QFileSystemWatched (good): " << name);
+                       }
+               }
+       }
+       for (QString const & qname : q_files) {
+               string const name = fromqstr(qname);
+               weak_ptr<FileMonitorGuard> & wptr = f.store_[name];
+               if (wptr.expired())
+                       LYXERR0("QFileSystemWatched but not monitored (bad): " << name);
+       }
+}
 
-       pimpl_->filename_ = file_with_path;
 
-       if (monitor)
-               start();
+FileMonitorGuard::FileMonitorGuard(string const & filename,
+                                   QFileSystemWatcher * qwatcher)
+       : filename_(filename), qwatcher_(qwatcher)
+{
+       QObject::connect(qwatcher, SIGNAL(fileChanged(QString const &)),
+                        this, SLOT(notifyChange(QString const &)));
+       if (qwatcher_->files().contains(toqstr(filename)))
+               LYXERR0("This file is already being QFileSystemWatched: " << filename
+                       << ". This should not happen.");
+       refresh();
 }
 
 
-FileName const & FileMonitor::filename() const
+FileMonitorGuard::~FileMonitorGuard()
 {
-       return pimpl_->filename_;
+       qwatcher_->removePath(toqstr(filename_));
 }
 
 
-void FileMonitor::start() const
+void FileMonitorGuard::refresh(bool new_file)
 {
-       if (monitoring())
-               return;
-
-       if (!pimpl_->filename_.exists())
-               return;
+       QString const qfilename = toqstr(filename_);
+       if(!qwatcher_->files().contains(qfilename)) {
+               bool exists = QFile(qfilename).exists();
+               if (!exists || !qwatcher_->addPath(qfilename)) {
+                       if (exists)
+                               LYXERR(Debug::FILES,
+                                      "Could not add path to QFileSystemWatcher: "
+                                      << filename_);
+                       QTimer::singleShot(1000, this, [=](){
+                                       refresh(new_file || !exists);
+                               });
+               } else if (exists && new_file)
+                       Q_EMIT fileChanged();
+       }
+}
 
-       pimpl_->timestamp_ = pimpl_->filename_.lastModified();
-       pimpl_->checksum_ = pimpl_->filename_.checksum();
 
-       if (pimpl_->timestamp_ && pimpl_->checksum_) {
-               pimpl_->timer_.start();
-       } else {
-               pimpl_->timestamp_ = 0;
-               pimpl_->checksum_ = 0;
+void FileMonitorGuard::notifyChange(QString const & path)
+{
+       if (path == toqstr(filename_)) {
+               Q_EMIT fileChanged();
+               // If the file has been modified by delete-move, we are notified of the
+               // deletion but we no longer track the file. See
+               // <https://bugreports.qt.io/browse/QTBUG-46483> (not a bug).
+               refresh();
        }
 }
 
 
-void FileMonitor::stop() const
+FileMonitor::FileMonitor(std::shared_ptr<FileMonitorGuard> monitor)
+       : monitor_(monitor)
 {
-       pimpl_->timestamp_ = 0;
-       pimpl_->checksum_ = 0;
-       pimpl_->timer_.stop();
+       connectToFileMonitorGuard();
+       refresh();
 }
 
 
-bool FileMonitor::monitoring() const
+void FileMonitor::connectToFileMonitorGuard()
 {
-       return pimpl_->timer_.running();
+       QObject::connect(monitor_.get(), SIGNAL(fileChanged()),
+                        this, SLOT(changed()));
 }
 
 
-unsigned long FileMonitor::checksum() const
+boost::signals2::connection
+FileMonitor::connect(sig::slot_type const & slot)
 {
-       // If we aren't actively monitoring the file, then recompute the
-       // checksum explicitly.
-       if (!pimpl_->timer_.running() && !pimpl_->filename_.empty())
-               return pimpl_->filename_.checksum();
-
-       return pimpl_->checksum_;
+       return fileChanged_.connect(slot);
 }
 
 
-boost::signals2::connection FileMonitor::connect(slot_type const & slot) const
+void FileMonitor::disconnect()
 {
-       return pimpl_->fileChanged_.connect(slot);
+       fileChanged_.disconnect_all_slots();
+       QObject::disconnect(this, SIGNAL(fileChanged()));
 }
 
 
-//------------------------------
-// Implementation details follow
-//------------------------------
+void FileMonitor::changed()
+{
+       // emit boost signal
+       fileChanged_();
+       Q_EMIT fileChanged();
+}
 
 
-FileMonitor::Impl::Impl(FileName const & file_with_path, int interval)
-       : filename_(file_with_path),
-         timer_(interval, Timeout::ONETIME),
-         timestamp_(0),
-         checksum_(0)
+FileMonitorBlocker FileMonitor::block(int delay)
 {
-       timer_.timeout.connect(bind(&Impl::monitorFile, this));
+       FileMonitorBlocker blocker = blocker_.lock();
+       if (!blocker)
+               blocker_ = blocker = make_shared<FileMonitorBlockerGuard>(this);
+       blocker->setDelay(delay);
+       return blocker;
 }
 
 
-void FileMonitor::Impl::monitorFile()
+FileMonitorBlockerGuard::FileMonitorBlockerGuard(FileMonitor * parent)
+       : QObject(parent), parent_(parent), delay_(0)
 {
-       bool changed = false;
-
-       if (!filename_.exists()) {
-               changed = timestamp_ || checksum_;
-               timestamp_ = 0;
-               checksum_ = 0;
+       QObject::disconnect(parent_->monitor_.get(), SIGNAL(fileChanged()),
+                           parent_, SLOT(changed()));
+}
 
-       } else {
-               time_t const new_timestamp = filename_.lastModified();
 
-               if (new_timestamp != timestamp_) {
-                       timestamp_ = new_timestamp;
+void FileMonitorBlockerGuard::setDelay(int delay)
+{
+       delay_ = max(delay_, delay);
+}
 
-                       unsigned long const new_checksum = filename_.checksum();
-                       if (new_checksum != checksum_) {
-                               checksum_ = new_checksum;
-                               changed = true;
-                       }
-               }
-       }
 
-       timer_.start();
-       if (changed)
-               fileChanged_();
+FileMonitorBlockerGuard::~FileMonitorBlockerGuard()
+{
+       // closures can only copy local copies
+       FileMonitor * parent = parent_;
+       // parent is also our QObject::parent() so we are deleted before parent.
+       // Even if delay_ is 0, the QTimer is necessary. Indeed, the notifications
+       // from QFileSystemWatcher that we meant to ignore are not going to be
+       // treated immediately, so we must yield to give us the opportunity to
+       // ignore them.
+       QTimer::singleShot(delay_, parent, [parent]() {
+                       parent->connectToFileMonitorGuard();
+               });
 }
 
 } // namespace support
 } // namespace lyx
+
+#include "moc_FileMonitor.cpp"
index efc8102ed578716c8d7f0a66114aa989e6ec8b7b..09d85e81a11eb2ac3b2ab279c8ec550f340f791f 100644 (file)
@@ -4,7 +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.
  *
 #ifndef FILEMONITOR_H
 #define FILEMONITOR_H
 
-// TODO: Remove FileMonitor
-#include "support/FileMonitor2.h"
+#include <memory>
+
+#include <QFileSystemWatcher>
+#include <QObject>
 
 #include <boost/signals2.hpp>
 
+
 namespace lyx {
 namespace support {
 
 class FileName;
 
-class FileMonitor
+///
+///  FileMonitor, a file monitor based on QFileSystemWatcher
+///
+
+class FileMonitor;
+class FileMonitorGuard;
+using FileMonitorPtr = std::unique_ptr<FileMonitor>;
+
+///
+/// Watch a file:
+///   FileMonitorPtr monitor = FileSystemWatcher::monitor(file_with_path);
+///   monitor.connect(...); //(using boost::signals2), or:
+///   connect(monitor, SIGNAL(fileChanged()),...); // (using Qt)
+///
+/// Remember that a unique_ptr is automatically deleted at the end of a scope if
+/// it has not been moved, or when assigned. When that happens, the signal
+/// object is deleted and therefore all the connections are closed. The file
+/// ceases being tracked when all the monitors for a file have been deleted.
+///
+/// Stop watching:
+///   * as determined statically by the scope, or
+///   * dynamically, using:
+///       monitor = nullptr;
+///
+/// Watch a different file:
+///   monitor = FileSystemWatcher::monitor(file_with_path2);
+///   monitor.connect(...);
+/// (stops watching the first)
+///
+/// Block notifications for the duration of a scope:
+///   {
+///       FileMonitorBlocker block = monitor.block();
+///       ...
+///   }
+///
+/// Reset connections:
+///   monitor.disconnect();
+///   or the disconnect method of the connection object for the boost signal.
+///
+class FileSystemWatcher
+{
+public:
+       // as described above
+       static FileMonitorPtr monitor(FileName const & file_with_path);
+       // 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
+       static FileSystemWatcher & instance();
+       // 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
+       std::unique_ptr<QFileSystemWatcher> const qwatcher_;
+};
+
+
+// Must be unique per path
+// Ends the watch when deleted
+class FileMonitorGuard : public QObject
 {
+       Q_OBJECT
+
 public:
-       /** Once monitoring begins, the file will be monitored every
-        *  interval ms.
-        *
-        * This is now obsoleted by FileMonitor2 based on QFileSystemWatcher.
-        * FIXME: Remove FileMonitor
-        */
-       FileMonitor(FileName const & file_with_path, int interval);
-
-       /// Destructor
-       ~FileMonitor();
-
-       ///
-       void reset(FileName const & file_with_path) const;
-
-       ///
-       FileName const & filename() const;
-
-       /// Begin monitoring the file
-       void start() const;
-       ///
-       void stop() const;
-       ///
-       bool monitoring() const;
-
-       /** The checksum is recomputed whenever the file is modified.
-        *  If the file is not being monitored, then the checksum will be
-        *  recomputed each time this function is called.
-        */
-       unsigned long checksum() const;
+       /// Start the watch
+       FileMonitorGuard(std::string const & filename,
+                        QFileSystemWatcher * qwatcher);
+       /// End the watch
+       ~FileMonitorGuard();
+       /// absolute path being tracked
+       std::string const & filename() { return filename_; }
+       /// Make sure it is being monitored, after e.g. a deletion. See
+       /// <https://bugreports.qt.io/browse/QTBUG-46483>. This is called
+       /// automatically.
+       /// \param new_file  If true, emit fileChanged if the file exists and was
+       /// successfully added.
+       void refresh(bool new_file = false);
+
+Q_SIGNALS:
+       /// Connect to this to be notified when the file changes
+       void fileChanged() const;
+
+private Q_SLOTS:
+       /// Receive notifications from the QFileSystemWatcher
+       void notifyChange(QString const & path);
 
+private:
+       std::string const filename_;
+       QFileSystemWatcher * qwatcher_;
+};
+
+
+class FileMonitorBlockerGuard : public QObject
+{
+       Q_OBJECT
+       FileMonitor * parent_;
+       int delay_;
+
+public:
+       FileMonitorBlockerGuard(FileMonitor * parent);
+       ~FileMonitorBlockerGuard();
+       void setDelay(int delay);
+};
+
+
+using FileMonitorBlocker = std::shared_ptr<FileMonitorBlockerGuard>;
+
+
+/// Main class
+class FileMonitor : public QObject
+{
+       Q_OBJECT
+       friend class FileMonitorBlockerGuard;
+
+public:
+       FileMonitor(std::shared_ptr<FileMonitorGuard> monitor);
+
+       using sig = boost::signals2::signal<void()>;
        /// Connect and you'll be informed when the file has changed.
-       typedef boost::signals2::signal<void()> FileChangedSig;
-       typedef FileChangedSig::slot_type slot_type;
-       ///
-       boost::signals2::connection connect(slot_type const &) const;
+       boost::signals2::connection connect(sig::slot_type const &);
+       /// disconnect all slots connected to the boost signal fileChanged_ or to
+       /// the qt signal fileChanged()
+       void disconnect();
+       /// absolute path being tracked
+       std::string const & filename() { return monitor_->filename(); }
+       /// Creates a guard that blocks notifications. Copyable. Notifications from
+       /// this monitor are blocked as long as there are copies around.
+       /// \param delay is the amount waited in ms after expiration of the guard
+       /// before reconnecting. This delay thing is to deal with asynchronous
+       /// notifications in a not so elegant fashion. But it can also be used to
+       /// slow down incoming events.
+       FileMonitorBlocker block(int delay = 0);
+       /// Make sure the good file is being monitored, after e.g. a move or a
+       /// deletion. See <https://bugreports.qt.io/browse/QTBUG-46483>. This is
+       /// called automatically.
+       void refresh() { return monitor_->refresh(); }
+
+Q_SIGNALS:
+       /// Connect to this to be notified when the file changes
+       void fileChanged() const;
+
+private Q_SLOTS:
+       /// Receive notifications from the FileMonitorGuard
+       void changed();
 
 private:
-       /// noncopyable
-       FileMonitor(FileMonitor const &);
-       void operator=(FileMonitor const &);
-
-       /// Use the Pimpl idiom to hide the internals.
-       class Impl;
-       /// The pointer never changes although *pimpl_'s contents may.
-       Impl * const pimpl_;
+       void connectToFileMonitorGuard();
+       // boost signal
+       sig fileChanged_;
+       // the unique watch for our file
+       std::shared_ptr<FileMonitorGuard> const monitor_;
+       //
+       std::weak_ptr<FileMonitorBlockerGuard> blocker_;
 };
 
+
+
 } // namespace support
 } // namespace lyx
 
diff --git a/src/support/FileMonitor2.cpp b/src/support/FileMonitor2.cpp
deleted file mode 100644 (file)
index 2cf8cb9..0000000
+++ /dev/null
@@ -1,211 +0,0 @@
-/**
- * \file FileMonitor.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Guillaume Munch
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "support/FileMonitor2.h"
-
-#include "support/debug.h"
-#include "support/FileName.h"
-#include "support/qstring_helpers.h"
-#include "support/unique_ptr.h"
-
-#include <QFile>
-#include <QSignalBlocker>
-#include <QTimer>
-
-#include <algorithm>
-
-using namespace std;
-
-namespace lyx {
-namespace support {
-
-
-FileSystemWatcher & FileSystemWatcher::instance()
-{
-       // This thread-safe because QFileSystemWatcher is thread-safe.
-       static FileSystemWatcher f;
-       return f;
-}
-
-
-FileSystemWatcher::FileSystemWatcher()
-       : qwatcher_(make_unique<QFileSystemWatcher>())
-{}
-
-
-//static
-FileMonitorPtr FileSystemWatcher::monitor(FileName const & file_with_path)
-{
-       FileSystemWatcher & f = instance();
-       string const filename = file_with_path.absFileName();
-       weak_ptr<FileMonitorGuard> & wptr = f.store_[filename];
-       if (shared_ptr<FileMonitorGuard> mon = wptr.lock())
-               return make_unique<FileMonitor2>(mon);
-       auto mon = make_shared<FileMonitorGuard>(filename, f.qwatcher_.get());
-       wptr = mon;
-       return make_unique<FileMonitor2>(mon);
-}
-
-
-//static
-void FileSystemWatcher::debug()
-{
-       FileSystemWatcher & f = instance();
-       QStringList q_files = f.qwatcher_->files();
-       for (pair<string, weak_ptr<FileMonitorGuard>> pair : f.store_) {
-               string const & name = pair.first;
-               if (!pair.second.expired()) {
-                       if (!q_files.contains(toqstr(name)))
-                               LYXERR0("Monitored but not QFileSystemWatched (bad): " << name);
-                       else {
-                               //LYXERR0("Monitored and QFileSystemWatched (good): " << name);
-                       }
-               }
-       }
-       for (QString const & qname : q_files) {
-               string const name = fromqstr(qname);
-               weak_ptr<FileMonitorGuard> & wptr = f.store_[name];
-               if (wptr.expired())
-                       LYXERR0("QFileSystemWatched but not monitored (bad): " << name);
-       }
-}
-
-
-FileMonitorGuard::FileMonitorGuard(string const & filename,
-                                   QFileSystemWatcher * qwatcher)
-       : filename_(filename), qwatcher_(qwatcher)
-{
-       QObject::connect(qwatcher, SIGNAL(fileChanged(QString const &)),
-                        this, SLOT(notifyChange(QString const &)));
-       if (qwatcher_->files().contains(toqstr(filename)))
-               LYXERR0("This file is already being QFileSystemWatched: " << filename
-                       << ". This should not happen.");
-       refresh();
-}
-
-
-FileMonitorGuard::~FileMonitorGuard()
-{
-       qwatcher_->removePath(toqstr(filename_));
-}
-
-
-void FileMonitorGuard::refresh(bool new_file)
-{
-       QString const qfilename = toqstr(filename_);
-       if(!qwatcher_->files().contains(qfilename)) {
-               bool exists = QFile(qfilename).exists();
-               if (!exists || !qwatcher_->addPath(qfilename)) {
-                       if (exists)
-                               LYXERR(Debug::FILES,
-                                      "Could not add path to QFileSystemWatcher: "
-                                      << filename_);
-                       QTimer::singleShot(1000, this, [=](){
-                                       refresh(new_file || !exists);
-                               });
-               } else if (exists && new_file)
-                       Q_EMIT fileChanged();
-       }
-}
-
-
-void FileMonitorGuard::notifyChange(QString const & path)
-{
-       if (path == toqstr(filename_)) {
-               Q_EMIT fileChanged();
-               // If the file has been modified by delete-move, we are notified of the
-               // deletion but we no longer track the file. See
-               // <https://bugreports.qt.io/browse/QTBUG-46483> (not a bug).
-               refresh();
-       }
-}
-
-
-FileMonitor2::FileMonitor2(std::shared_ptr<FileMonitorGuard> monitor)
-       : monitor_(monitor)
-{
-       connectToFileMonitorGuard();
-       refresh();
-}
-
-
-void FileMonitor2::connectToFileMonitorGuard()
-{
-       QObject::connect(monitor_.get(), SIGNAL(fileChanged()),
-                        this, SLOT(changed()));
-}
-
-
-boost::signals2::connection
-FileMonitor2::connect(sig::slot_type const & slot)
-{
-       return fileChanged_.connect(slot);
-}
-
-
-void FileMonitor2::disconnect()
-{
-       fileChanged_.disconnect_all_slots();
-       QObject::disconnect(this, SIGNAL(fileChanged()));
-}
-
-
-void FileMonitor2::changed()
-{
-       // emit boost signal
-       fileChanged_();
-       Q_EMIT fileChanged();
-}
-
-
-FileMonitorBlocker FileMonitor2::block(int delay)
-{
-       FileMonitorBlocker blocker = blocker_.lock();
-       if (!blocker)
-               blocker_ = blocker = make_shared<FileMonitorBlockerGuard>(this);
-       blocker->setDelay(delay);
-       return blocker;
-}
-
-
-FileMonitorBlockerGuard::FileMonitorBlockerGuard(FileMonitor2 * parent)
-       : QObject(parent), parent_(parent), delay_(0)
-{
-       QObject::disconnect(parent_->monitor_.get(), SIGNAL(fileChanged()),
-                           parent_, SLOT(changed()));
-}
-
-
-void FileMonitorBlockerGuard::setDelay(int delay)
-{
-       delay_ = max(delay_, delay);
-}
-
-
-FileMonitorBlockerGuard::~FileMonitorBlockerGuard()
-{
-       // closures can only copy local copies
-       FileMonitor2 * parent = parent_;
-       // parent is also our QObject::parent() so we are deleted before parent.
-       // Even if delay_ is 0, the QTimer is necessary. Indeed, the notifications
-       // from QFileSystemWatcher that we meant to ignore are not going to be
-       // treated immediately, so we must yield to give us the opportunity to
-       // ignore them.
-       QTimer::singleShot(delay_, parent, [parent]() {
-                       parent->connectToFileMonitorGuard();
-               });
-}
-
-} // namespace support
-} // namespace lyx
-
-#include "moc_FileMonitor2.cpp"
diff --git a/src/support/FileMonitor2.h b/src/support/FileMonitor2.h
deleted file mode 100644 (file)
index eb59fa5..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-// -*- C++ -*-
-/**
- * \file FileMonitor2.h
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Guillaume Munch
- *
- * Full author contact details are available in file CREDITS.
- *
- * FileMonitor monitors a file and informs a listener when that file has
- * changed.
- */
-
-#ifndef FILEMONITOR2_H
-#define FILEMONITOR2_H
-
-#include <memory>
-
-#include <QFileSystemWatcher>
-#include <QObject>
-
-#include <boost/signals2.hpp>
-
-
-namespace lyx {
-namespace support {
-
-class FileName;
-
-///
-///  FileMonitor2, a file monitor based on QFileSystemWatcher
-///
-
-class FileMonitor2;
-class FileMonitorGuard;
-using FileMonitorPtr = std::unique_ptr<FileMonitor2>;
-
-///
-/// Watch a file:
-///   FileMonitorPtr monitor = FileSystemWatcher::monitor(file_with_path);
-///   monitor.connect(...); //(using boost::signals2), or:
-///   connect(monitor, SIGNAL(fileChanged()),...); // (using Qt)
-///
-/// Remember that a unique_ptr is automatically deleted at the end of a scope if
-/// it has not been moved, or when assigned. When that happens, the signal
-/// object is deleted and therefore all the connections are closed. The file
-/// ceases being tracked when all the monitors for a file have been deleted.
-///
-/// Stop watching:
-///   * as determined statically by the scope, or
-///   * dynamically, using:
-///       monitor = nullptr;
-///
-/// Watch a different file:
-///   monitor = FileSystemWatcher::monitor(file_with_path2);
-///   monitor.connect(...);
-/// (stops watching the first)
-///
-/// Block notifications for the duration of a scope:
-///   {
-///       FileMonitorBlocker block = monitor.block();
-///       ...
-///   }
-///
-/// Reset connections:
-///   monitor.disconnect();
-///   or the disconnect method of the connection object for the boost signal.
-///
-class FileSystemWatcher
-{
-public:
-       // as described above
-       static FileMonitorPtr monitor(FileName const & file_with_path);
-       // 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
-       static FileSystemWatcher & instance();
-       // 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
-       std::unique_ptr<QFileSystemWatcher> const qwatcher_;
-};
-
-
-// Must be unique per path
-// Ends the watch when deleted
-class FileMonitorGuard : public QObject
-{
-       Q_OBJECT
-
-public:
-       /// Start the watch
-       FileMonitorGuard(std::string const & filename,
-                        QFileSystemWatcher * qwatcher);
-       /// End the watch
-       ~FileMonitorGuard();
-       /// absolute path being tracked
-       std::string const & filename() { return filename_; }
-       /// Make sure it is being monitored, after e.g. a deletion. See
-       /// <https://bugreports.qt.io/browse/QTBUG-46483>. This is called
-       /// automatically.
-       /// \param new_file  If true, emit fileChanged if the file exists and was
-       /// successfully added.
-       void refresh(bool new_file = false);
-
-Q_SIGNALS:
-       /// Connect to this to be notified when the file changes
-       void fileChanged() const;
-
-private Q_SLOTS:
-       /// Receive notifications from the QFileSystemWatcher
-       void notifyChange(QString const & path);
-
-private:
-       std::string const filename_;
-       QFileSystemWatcher * qwatcher_;
-};
-
-
-class FileMonitorBlockerGuard : public QObject
-{
-       Q_OBJECT
-       FileMonitor2 * parent_;
-       int delay_;
-
-public:
-       FileMonitorBlockerGuard(FileMonitor2 * parent);
-       ~FileMonitorBlockerGuard();
-       void setDelay(int delay);
-};
-
-
-using FileMonitorBlocker = std::shared_ptr<FileMonitorBlockerGuard>;
-
-
-/// Main class
-class FileMonitor2 : public QObject
-{
-       Q_OBJECT
-       friend class FileMonitorBlockerGuard;
-
-public:
-       FileMonitor2(std::shared_ptr<FileMonitorGuard> monitor);
-
-       using sig = boost::signals2::signal<void()>;
-       /// Connect and you'll be informed when the file has changed.
-       boost::signals2::connection connect(sig::slot_type const &);
-       /// disconnect all slots connected to the boost signal fileChanged_ or to
-       /// the qt signal fileChanged()
-       void disconnect();
-       /// absolute path being tracked
-       std::string const & filename() { return monitor_->filename(); }
-       /// Creates a guard that blocks notifications. Copyable. Notifications from
-       /// this monitor are blocked as long as there are copies around.
-       /// \param delay is the amount waited in ms after expiration of the guard
-       /// before reconnecting. This delay thing is to deal with asynchronous
-       /// notifications in a not so elegant fashion. But it can also be used to
-       /// slow down incoming events.
-       FileMonitorBlocker block(int delay = 0);
-       /// Make sure the good file is being monitored, after e.g. a move or a
-       /// deletion. See <https://bugreports.qt.io/browse/QTBUG-46483>. This is
-       /// called automatically.
-       void refresh() { return monitor_->refresh(); }
-
-Q_SIGNALS:
-       /// Connect to this to be notified when the file changes
-       void fileChanged() const;
-
-private Q_SLOTS:
-       /// Receive notifications from the FileMonitorGuard
-       void changed();
-
-private:
-       void connectToFileMonitorGuard();
-       // boost signal
-       sig fileChanged_;
-       // the unique watch for our file
-       std::shared_ptr<FileMonitorGuard> const monitor_;
-       //
-       std::weak_ptr<FileMonitorBlockerGuard> blocker_;
-};
-
-
-
-} // namespace support
-} // namespace lyx
-
-#endif // FILEMONITOR2_H
index e816c6fda911d541d5c89b110b068b0903fd437a..fe8eb947611be8adac0d663ecfa48ad34c65e403 100644 (file)
@@ -11,7 +11,7 @@ noinst_LIBRARIES = liblyxsupport.a
 
 MOCHEADER = \
        ConsoleApplicationPrivate.h \
-       FileMonitor2.h \
+       FileMonitor.h \
        SystemcallPrivate.h
 
 MOCEDFILES = $(MOCHEADER:%.h=moc_%.cpp)
@@ -34,8 +34,6 @@ AM_CPPFLAGS += -I$(srcdir)/.. \
 liblyxsupport_a_SOURCES = \
        FileMonitor.h \
        FileMonitor.cpp \
-       FileMonitor2.h \
-       FileMonitor2.cpp \
        RandomAccessList.h \
        bind.h \
        Cache.h \