]> git.lyx.org Git - lyx.git/blobdiff - src/support/FileMonitor.cpp
Update shortcuts in fr.po
[lyx.git] / src / support / FileMonitor.cpp
index f1fefb8d18afb918cdc3dd676f0813b5b7a6a91e..a3b17ad012f3f9a86e6505790ee16a400532b446 100644 (file)
@@ -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
                // <https://bugreports.qt.io/browse/QTBUG-46483> (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<FileMonitorGuard> 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<FileMonitorBlockerGuard>(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<FileMonitorGuard> 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()));
 }