X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fsupport%2FFileMonitor.cpp;h=a3b17ad012f3f9a86e6505790ee16a400532b446;hb=41a8994da902031a743373c1c57d028b7c900797;hp=f1fefb8d18afb918cdc3dd676f0813b5b7a6a91e;hpb=db58111360d68f76c5797069a7b80967447d1379;p=lyx.git diff --git a/src/support/FileMonitor.cpp b/src/support/FileMonitor.cpp index f1fefb8d18..a3b17ad012 100644 --- a/src/support/FileMonitor.cpp +++ b/src/support/FileMonitor.cpp @@ -118,31 +118,37 @@ FileMonitorGuard::~FileMonitorGuard() } -void FileMonitorGuard::refresh() +void FileMonitorGuard::refresh(bool const emit) { if (filename_.empty()) return; QString const qfilename = toqstr(filename_); - if(!qwatcher_->files().contains(qfilename)) { - bool exists = QFile(qfilename).exists(); + if (!qwatcher_->files().contains(qfilename)) { + bool const existed = exists_; + exists_ = QFile(qfilename).exists(); #if (QT_VERSION >= 0x050000) - if (!exists || !qwatcher_->addPath(qfilename)) + if (exists_ && !qwatcher_->addPath(qfilename)) #else auto add_path = [&]() { qwatcher_->addPath(qfilename); return qwatcher_->files().contains(qfilename); }; - if (!exists || !add_path()) + if (exists_ && !add_path()) #endif { - if (exists) - LYXERR(Debug::FILES, - "Could not add path to QFileSystemWatcher: " - << filename_); - QTimer::singleShot(2000, this, SLOT(refresh())); - } else if (exists && !exists_) - Q_EMIT fileChanged(); - setExists(exists); + LYXERR(Debug::FILES, + "Could not add path to QFileSystemWatcher: " << filename_); + QTimer::singleShot(5000, this, SLOT(refresh())); + } else { + if (!exists_) + // The standard way to overwrite a file is to delete it and + // create a new file with the same name. Therefore if the file + // has just been deleted, it is smart to check not too long + // after whether it has been recreated. + QTimer::singleShot(existed ? 100 : 2000, this, SLOT(refresh())); + if (existed != exists_ && emit) + Q_EMIT fileChanged(exists_); + } } } @@ -150,11 +156,12 @@ void FileMonitorGuard::refresh() 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 // (not a bug). - refresh(); + // Therefore we must refresh. + refresh(false); + Q_EMIT fileChanged(exists_); } } @@ -162,17 +169,22 @@ void FileMonitorGuard::notifyChange(QString const & path) FileMonitor::FileMonitor(std::shared_ptr monitor) : monitor_(monitor) { - QObject::connect(monitor_.get(), SIGNAL(fileChanged()), - this, SLOT(changed())); + connectToFileMonitorGuard(); refresh(); } -void FileMonitor::reconnectToFileMonitorGuard() +void FileMonitor::connectToFileMonitorGuard() { - monitor_->setExists(true); - QObject::connect(monitor_.get(), SIGNAL(fileChanged()), - this, SLOT(changed())); + // Connections need to be asynchronous because the receiver can own this + // object and therefore is allowed to delete it. + // Qt signal: + QObject::connect(monitor_.get(), SIGNAL(fileChanged(bool)), + this, SIGNAL(fileChanged(bool)), + Qt::QueuedConnection); + // Boost signal: + QObject::connect(this, SIGNAL(fileChanged(bool)), + this, SLOT(changed(bool))); } @@ -182,54 +194,10 @@ signals2::connection FileMonitor::connect(slot const & slot) } -void FileMonitor::disconnect() -{ - fileChanged_.disconnect_all_slots(); - QObject::disconnect(this, SIGNAL(fileChanged())); -} - - -void FileMonitor::changed() +void FileMonitor::changed(bool const exists) { // emit boost signal - fileChanged_(); - Q_EMIT fileChanged(); -} - - -FileMonitorBlocker FileMonitor::block(int delay) -{ - FileMonitorBlocker blocker = blocker_.lock(); - if (!blocker) - blocker_ = blocker = make_shared(this); - blocker->setDelay(delay); - return blocker; -} - - -FileMonitorBlockerGuard::FileMonitorBlockerGuard(FileMonitor * monitor) - : monitor_(monitor), delay_(0) -{ - QObject::disconnect(monitor->monitor_.get(), SIGNAL(fileChanged()), - monitor, SLOT(changed())); -} - - -void FileMonitorBlockerGuard::setDelay(int delay) -{ - delay_ = max(delay_, delay); -} - - -FileMonitorBlockerGuard::~FileMonitorBlockerGuard() -{ - if (!monitor_) - return; - // 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_, monitor_, SLOT(reconnectToFileMonitorGuard())); + fileChanged_(exists); } @@ -238,8 +206,9 @@ ActiveFileMonitor::ActiveFileMonitor(std::shared_ptr monitor, : FileMonitor(monitor), filename_(filename), interval_(interval), timestamp_(0), checksum_(0), cooldown_(true) { - QObject::connect(this, SIGNAL(fileChanged()), this, SLOT(setCooldown())); + QObject::connect(this, SIGNAL(fileChanged(bool)), this, SLOT(setCooldown())); QTimer::singleShot(interval_, this, SLOT(clearCooldown())); + filename_.refresh(); if (!filename_.exists()) return; timestamp_ = filename_.lastModified(); @@ -254,7 +223,9 @@ void ActiveFileMonitor::checkModified() cooldown_ = true; bool changed = false; - if (!filename_.exists()) { + filename_.refresh(); + bool exists = filename_.exists(); + if (!exists) { changed = timestamp_ || checksum_; timestamp_ = 0; checksum_ = 0; @@ -272,7 +243,7 @@ void ActiveFileMonitor::checkModified() } } if (changed) - FileMonitor::changed(); + Q_EMIT FileMonitor::fileChanged(exists); QTimer::singleShot(interval_, this, SLOT(clearCooldown())); }