3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Angus Leeming
8 * Full author contact details are available in file CREDITS.
13 #include "support/FileMonitor.h"
14 #include "support/filename.h"
15 #include "support/lyxlib.h"
17 // FIXME Interface violation
18 #include "frontends/Timeout.h"
20 #include <boost/bind.hpp>
21 #include <boost/filesystem/operations.hpp>
22 #include <boost/signals/trackable.hpp>
27 namespace fs = boost::filesystem;
32 class FileMonitor::Impl : public boost::signals::trackable {
36 Impl(FileName const & file_with_path, int interval);
47 /// This signal is emitted if the file is modified (has a new checksum).
48 FileMonitor::FileChangedSig fileChanged_;
50 /** We use these to ascertain whether a file (once loaded successfully)
55 unsigned long checksum_;
59 FileMonitor::FileMonitor(FileName const & file_with_path, int interval)
60 : pimpl_(new Impl(file_with_path, interval))
64 FileMonitor::~FileMonitor()
68 void FileMonitor::reset(FileName const & file_with_path) const
70 if (pimpl_->filename_ == file_with_path)
73 bool const monitor = pimpl_->timer_.running();
77 pimpl_->filename_ = file_with_path;
84 FileName const & FileMonitor::filename() const
86 return pimpl_->filename_;
90 void FileMonitor::start() const
95 if (!fs::exists(pimpl_->filename_.toFilesystemEncoding()))
98 pimpl_->timestamp_ = fs::last_write_time(pimpl_->filename_.toFilesystemEncoding());
99 pimpl_->checksum_ = sum(pimpl_->filename_);
101 if (pimpl_->timestamp_ && pimpl_->checksum_) {
102 pimpl_->timer_.start();
104 pimpl_->timestamp_ = 0;
105 pimpl_->checksum_ = 0;
110 void FileMonitor::stop() const
112 pimpl_->timestamp_ = 0;
113 pimpl_->checksum_ = 0;
114 pimpl_->timer_.stop();
118 bool FileMonitor::monitoring() const
120 return pimpl_->timer_.running();
124 unsigned long FileMonitor::checksum() const
126 // If we aren't actively monitoring the file, then recompute the
127 // checksum explicitly.
128 if (!pimpl_->timer_.running() && !pimpl_->filename_.empty())
129 return sum(pimpl_->filename_);
131 return pimpl_->checksum_;
135 boost::signals::connection FileMonitor::connect(slot_type const & slot) const
137 return pimpl_->fileChanged_.connect(slot);
141 //------------------------------
142 // Implementation details follow
143 //------------------------------
146 FileMonitor::Impl::Impl(FileName const & file_with_path, int interval)
147 : filename_(file_with_path),
148 timer_(interval, Timeout::ONETIME),
152 timer_.timeout.connect(boost::bind(&Impl::monitorFile, this));
156 void FileMonitor::Impl::monitorFile()
158 bool changed = false;
160 if (!fs::exists(filename_.toFilesystemEncoding())) {
161 changed = timestamp_ || checksum_;
166 time_t const new_timestamp = fs::last_write_time(filename_.toFilesystemEncoding());
168 if (new_timestamp != timestamp_) {
169 timestamp_ = new_timestamp;
171 unsigned long const new_checksum = sum(filename_);
172 if (new_checksum != checksum_) {
173 checksum_ = new_checksum;
184 } // namespace support