4 * This file is part of LyX, the document processor.
5 * Licence details can be found in the file COPYING.
7 * \author Angus Leeming
8 * \author Guillaume Munch
10 * Full author contact details are available in file CREDITS.
12 * FileMonitor monitors a file and informs a listener when that file has
19 #include "support/FileName.h"
20 #include "support/signals.h"
25 #include <QFileSystemWatcher>
34 /// FileMonitor, a file monitor based on QFileSystemWatcher
38 class ActiveFileMonitor;
39 class FileMonitorGuard;
40 typedef std::unique_ptr<FileMonitor> FileMonitorPtr;
41 typedef std::unique_ptr<ActiveFileMonitor> ActiveFileMonitorPtr;
45 /// FileMonitorPtr monitor = FileSystemWatcher::monitor(file_with_path);
46 /// monitor.connect(...); //(using boost::signals2), or:
47 /// connect(monitor, SIGNAL(fileChanged()),...); // (using Qt)
49 /// Remember that a unique_ptr is automatically deleted at the end of a scope if
50 /// it has not been moved, or when assigned. When that happens, the signal
51 /// object is deleted and therefore all the connections are closed. The file
52 /// ceases being tracked when all the monitors for a file have been deleted.
55 /// * as determined statically by the scope, or
56 /// * dynamically, using:
57 /// monitor = nullptr;
59 /// Watch a different file:
60 /// monitor = FileSystemWatcher::monitor(file_with_path2);
61 /// monitor.connect(...);
62 /// (stops watching the first)
64 class FileSystemWatcher
67 /// as described above
68 static FileMonitorPtr monitor(FileName const & filename);
69 /// same but with an ActiveFileMonitor
70 static ActiveFileMonitorPtr activeMonitor(FileName const & filename,
71 int interval = 10000);
72 /// Output whether the paths tracked by qwatcher_ and the active
73 /// FileMonitorGuards are in correspondence.
77 /// A global instance is created automatically on first call
78 static FileSystemWatcher & instance();
80 std::shared_ptr<FileMonitorGuard> getGuard(FileName const & filename);
81 /// Caches the monitor guards but allow them to be destroyed
82 std::map<std::string, std::weak_ptr<FileMonitorGuard>> store_;
83 /// This class is a wrapper for QFileSystemWatcher
84 std::unique_ptr<QFileSystemWatcher> const qwatcher_;
88 /// Must be unique per path
89 /// Ends the watch when deleted
90 class FileMonitorGuard : public QObject
96 FileMonitorGuard(std::string const & filename,
97 QFileSystemWatcher * qwatcher);
100 /// absolute path being tracked
101 std::string const & filename() { return filename_; }
104 /// Make sure it is being monitored, after e.g. a deletion. See
105 /// <https://bugreports.qt.io/browse/QTBUG-46483>. This is called
107 void refresh(bool emit = true);
110 /// Connect to this to be notified when the file changes
111 void fileChanged(bool exists) const;
114 /// Receive notifications from the QFileSystemWatcher
115 void notifyChange(QString const & path);
118 std::string const filename_;
119 QFileSystemWatcher * qwatcher_;
120 /// for emitting fileChanged() when the file is created or deleted
126 class FileMonitor : public QObject
131 FileMonitor(std::shared_ptr<FileMonitorGuard> monitor);
133 typedef signal<void(bool)> sig;
134 typedef sig::slot_type slot;
135 /// Connect and you'll be informed when the file has changed.
136 connection connect(slot const &);
137 /// absolute path being tracked
138 std::string const & filename() { return monitor_->filename(); }
139 /// Make sure the good file is being monitored, after e.g. a move or a
140 /// deletion. See <https://bugreports.qt.io/browse/QTBUG-46483>. This is
141 /// called automatically.
142 void refresh() { monitor_->refresh(); }
145 /// Connect to this to be notified when the file changes
146 void fileChanged(bool exists) const;
149 /// Receive notifications from the FileMonitorGuard
150 void changed(bool exists);
152 void connectToFileMonitorGuard();
157 /// the unique watch for our file
158 std::shared_ptr<FileMonitorGuard> const monitor_;
162 /// When a more active monitoring style is needed.
163 /// For instance because QFileSystemWatcher does not work for remote file
165 class ActiveFileMonitor : public FileMonitor
169 ActiveFileMonitor(std::shared_ptr<FileMonitorGuard> monitor,
170 FileName const & filename, int interval);
171 /// call checkModified asynchronously
172 void checkModifiedAsync();
175 /// Check explicitly for a modification, but not more than once every
177 void checkModified();
180 void setCooldown() { cooldown_ = true; }
181 void clearCooldown() { cooldown_ = false; }
184 FileName const filename_;
190 unsigned long checksum_;
196 } // namespace support
199 #endif // FILEMONITOR_H