* 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"
* 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
+++ /dev/null
-/**
- * \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"
+++ /dev/null
-// -*- 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
MOCHEADER = \
ConsoleApplicationPrivate.h \
- FileMonitor2.h \
+ FileMonitor.h \
SystemcallPrivate.h
MOCEDFILES = $(MOCHEADER:%.h=moc_%.cpp)
liblyxsupport_a_SOURCES = \
FileMonitor.h \
FileMonitor.cpp \
- FileMonitor2.h \
- FileMonitor2.cpp \
RandomAccessList.h \
bind.h \
Cache.h \