3 * Copyright 2002 the LyX Team
4 * Read the file COPYING
6 * \author Angus Leeming <leeming@lyx.org>
12 #pragma implementation
15 #include "FileMonitor.h"
17 #include "frontends/Timeout.h"
19 #include "support/FileInfo.h"
20 #include "support/lyxlib.h"
22 #include <boost/bind.hpp>
23 #include <boost/signals/trackable.hpp>
25 struct FileMonitor::Impl : public boost::signals::trackable {
28 Impl(string const & file_with_path, int interval);
39 /// This signal is emitted if the file is modified (has a new checksum).
40 boost::signal0<void> fileChanged_;
42 /** We use these to ascertain whether a file (once loaded successfully)
47 unsigned long checksum_;
51 FileMonitor::FileMonitor(string const & file_with_path, int interval)
52 : pimpl_(new Impl(file_with_path, interval))
56 FileMonitor::~FileMonitor()
60 void FileMonitor::reset(string const & file_with_path) const
62 if (pimpl_->filename_ == file_with_path)
65 bool const monitor = pimpl_->timer_.running();
69 pimpl_->filename_ = file_with_path;
76 string const & FileMonitor::filename() const
78 return pimpl_->filename_;
82 void FileMonitor::start() const
87 FileInfo finfo(pimpl_->filename_);
91 pimpl_->timestamp_ = finfo.getModificationTime();
92 pimpl_->checksum_ = lyx::sum(pimpl_->filename_);
94 if (pimpl_->timestamp_ && pimpl_->checksum_) {
95 pimpl_->timer_.start();
97 pimpl_->timestamp_ = 0;
98 pimpl_->checksum_ = 0;
103 void FileMonitor::stop() const
105 pimpl_->timestamp_ = 0;
106 pimpl_->checksum_ = 0;
107 pimpl_->timer_.stop();
111 bool FileMonitor::monitoring() const
113 return pimpl_->timer_.running();
117 unsigned long FileMonitor::checksum() const
119 // If we aren't actively monitoring the file, then recompute the
120 // checksum explicitly.
121 if (!pimpl_->timer_.running() && !pimpl_->filename_.empty())
122 return lyx::sum(pimpl_->filename_);
124 return pimpl_->checksum_;
128 boost::signals::connection FileMonitor::connect(slot_type const & slot) const
130 return pimpl_->fileChanged_.connect(slot);
134 //------------------------------
135 // Implementation details follow
136 //------------------------------
139 FileMonitor::Impl::Impl(string const & file_with_path, int interval)
140 : filename_(file_with_path),
141 timer_(interval, Timeout::ONETIME),
145 timer_.timeout.connect(boost::bind(&Impl::monitorFile, this));
149 void FileMonitor::Impl::monitorFile()
151 bool changed = false;
153 FileInfo finfo(filename_);
155 changed = timestamp_ || checksum_;
160 time_t const new_timestamp = finfo.getModificationTime();
162 if (new_timestamp != timestamp_) {
163 timestamp_ = new_timestamp;
165 unsigned long const new_checksum = lyx::sum(filename_);
166 if (new_checksum != checksum_) {
167 checksum_ = new_checksum;