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"
24 #include <QFileSystemWatcher>
33 /// FileMonitor, a file monitor based on QFileSystemWatcher
37 class ActiveFileMonitor;
38 class FileMonitorGuard;
39 typedef std::unique_ptr<FileMonitor> FileMonitorPtr;
40 typedef std::unique_ptr<ActiveFileMonitor> ActiveFileMonitorPtr;
44 /// FileMonitorPtr monitor = FileSystemWatcher::monitor(file_with_path);
45 /// monitor.connect(...); //(using boost::signals2), or:
46 /// connect(monitor, SIGNAL(fileChanged()),...); // (using Qt)
48 /// Remember that a unique_ptr is automatically deleted at the end of a scope if
49 /// it has not been moved, or when assigned. When that happens, the signal
50 /// object is deleted and therefore all the connections are closed. The file
51 /// ceases being tracked when all the monitors for a file have been deleted.
54 /// * as determined statically by the scope, or
55 /// * dynamically, using:
56 /// monitor = nullptr;
58 /// Watch a different file:
59 /// monitor = FileSystemWatcher::monitor(file_with_path2);
60 /// monitor.connect(...);
61 /// (stops watching the first)
63 /// Reset connections:
64 /// monitor.disconnect();
65 /// or the disconnect method of the connection object for the boost signal.
67 class FileSystemWatcher
70 /// as described above
71 static FileMonitorPtr monitor(FileName const & filename);
72 /// same but with an ActiveFileMonitor
73 static ActiveFileMonitorPtr activeMonitor(FileName const & filename,
74 int interval = 10000);
75 /// Output whether the paths tracked by qwatcher_ and the active
76 /// FileMonitorGuards are in correspondence.
80 /// A global instance is created automatically on first call
81 static FileSystemWatcher & instance();
83 std::shared_ptr<FileMonitorGuard> getGuard(FileName const & filename);
84 /// Caches the monitor guards but allow them to be destroyed
85 std::map<std::string, std::weak_ptr<FileMonitorGuard>> store_;
86 /// This class is a wrapper for QFileSystemWatcher
87 std::unique_ptr<QFileSystemWatcher> const qwatcher_;
91 /// Must be unique per path
92 /// Ends the watch when deleted
93 class FileMonitorGuard : public QObject
99 FileMonitorGuard(std::string const & filename,
100 QFileSystemWatcher * qwatcher);
103 /// absolute path being tracked
104 std::string const & filename() { return filename_; }
107 /// Make sure it is being monitored, after e.g. a deletion. See
108 /// <https://bugreports.qt.io/browse/QTBUG-46483>. This is called
110 void refresh(bool emit = true);
113 /// Connect to this to be notified when the file changes
114 void fileChanged(bool exists) const;
117 /// Receive notifications from the QFileSystemWatcher
118 void notifyChange(QString const & path);
121 std::string const filename_;
122 QFileSystemWatcher * qwatcher_;
123 /// for emitting fileChanged() when the file is created or deleted
129 class FileMonitor : public QObject
134 FileMonitor(std::shared_ptr<FileMonitorGuard> monitor);
136 typedef signals2::signal<void(bool)> sig;
137 typedef sig::slot_type slot;
138 /// Connect and you'll be informed when the file has changed.
139 signals2::connection connect(slot const &);
140 /// disconnect all slots connected to the boost signal fileChanged_ or to
141 /// the qt signal fileChanged()
143 /// absolute path being tracked
144 std::string const & filename() { return monitor_->filename(); }
145 /// Make sure the good file is being monitored, after e.g. a move or a
146 /// deletion. See <https://bugreports.qt.io/browse/QTBUG-46483>. This is
147 /// called automatically.
148 void refresh() { monitor_->refresh(); }
151 /// Connect to this to be notified when the file changes
152 void fileChanged(bool exists) const;
155 /// Receive notifications from the FileMonitorGuard
156 void changed(bool exists);
158 void connectToFileMonitorGuard();
163 /// the unique watch for our file
164 std::shared_ptr<FileMonitorGuard> const monitor_;
168 /// When a more active monitoring style is needed.
169 /// For instance because QFileSystemWatcher does not work for remote file
171 class ActiveFileMonitor : public FileMonitor
175 ActiveFileMonitor(std::shared_ptr<FileMonitorGuard> monitor,
176 FileName const & filename, int interval);
177 /// call checkModified asynchronously
178 void checkModifiedAsync();
181 /// Check explicitly for a modification, but not more than once every
183 void checkModified();
186 void setCooldown() { cooldown_ = true; }
187 void clearCooldown() { cooldown_ = false; }
190 FileName const filename_;
196 unsigned long checksum_;
202 } // namespace support
205 #endif // FILEMONITOR_H