Skip to content

Commit

Permalink
App: fix monitoring of Document files
Browse files Browse the repository at this point in the history
Relates to GitHub #279
  • Loading branch information
HuguesDelorme committed Jul 30, 2024
1 parent 97627a0 commit eabb97f
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 31 deletions.
30 changes: 17 additions & 13 deletions src/app/document_files_watcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@
#include "document_files_watcher.h"

#include "../base/application.h"
#include "../base/unit_system.h"
#include "../qtcommon/filepath_conv.h"

#include <QtCore/QFileSystemWatcher>

#include <QtCore/QDebug>

namespace Mayo {

DocumentFilesWatcher::DocumentFilesWatcher(const ApplicationPtr& app, QObject* parent)
Expand All @@ -20,6 +23,7 @@ DocumentFilesWatcher::DocumentFilesWatcher(const ApplicationPtr& app, QObject* p
app->signalDocumentAdded.connectSlot(&DocumentFilesWatcher::onDocumentAdded, this);
app->signalDocumentAboutToClose.connectSlot(&DocumentFilesWatcher::onDocumentAboutToClose, this);
app->signalDocumentFilePathChanged.connectSlot(&DocumentFilesWatcher::onDocumentFilePathChanged, this);
m_timer.start();
}

void DocumentFilesWatcher::enable(bool on)
Expand All @@ -38,7 +42,7 @@ void DocumentFilesWatcher::enable(bool on)
}
else {
this->destroyFileSystemWatcher();
m_vecNonAckDocumentChanged.clear();
m_mapDocLastChangeTime.clear();
}
}

Expand All @@ -47,11 +51,10 @@ bool DocumentFilesWatcher::isEnabled() const
return m_isEnabled;
}

void DocumentFilesWatcher::acknowledgeDocumentFileChange(const DocumentPtr& doc)
QuantityTime DocumentFilesWatcher::minimumDelayBetweenTwoDistinctFileChanges()
{
auto it = std::find(m_vecNonAckDocumentChanged.begin(), m_vecNonAckDocumentChanged.end(), doc);
if (it != m_vecNonAckDocumentChanged.end())
m_vecNonAckDocumentChanged.erase(it);
constexpr QuantityTime minDelay = 50 * Quantity_Millisecond;
return minDelay;
}

QFileSystemWatcher* DocumentFilesWatcher::fileSystemWatcher()
Expand All @@ -78,19 +81,20 @@ void DocumentFilesWatcher::onFileChanged(const QString& strFilePath)
if (m_isEnabled) {
const FilePath docFilePath = filepathFrom(strFilePath);
DocumentPtr doc = m_app->findDocumentByLocation(docFilePath);
if (this->isDocumentChangeAcknowledged(doc)) {
m_vecNonAckDocumentChanged.push_back(doc);
auto itLastChangeTime = m_mapDocLastChangeTime.find(doc);
int64_t timeDiff = -1;
if (itLastChangeTime != m_mapDocLastChangeTime.cend())
timeDiff = m_timer.elapsed() - itLastChangeTime->second;

const double minDelay = UnitSystem::milliseconds(minimumDelayBetweenTwoDistinctFileChanges());
//qDebug() << "onFileChanged()" << " timeDiff=" << timeDiff << " minDelay=" << minDelay;
if (timeDiff < 0 || timeDiff > minDelay) {
m_mapDocLastChangeTime.insert_or_assign(doc, m_timer.elapsed());
this->signalDocumentFileChanged.send(doc);
}
}
}

bool DocumentFilesWatcher::isDocumentChangeAcknowledged(const DocumentPtr& doc) const
{
auto it = std::find(m_vecNonAckDocumentChanged.cbegin(), m_vecNonAckDocumentChanged.cend(), doc);
return it == m_vecNonAckDocumentChanged.cend();
}

void DocumentFilesWatcher::onDocumentFilePathChanged(const DocumentPtr&, const FilePath& fp)
{
if (m_isEnabled) {
Expand Down
13 changes: 6 additions & 7 deletions src/app/document_files_watcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
#include "../base/application_ptr.h"
#include "../base/document_ptr.h"
#include "../base/filepath.h"
#include "../base/quantity.h"
#include "../base/signal.h"

#include <QtCore/QElapsedTimer>
#include <QtCore/QObject>

#include <vector>
#include <unordered_map>

class QFileSystemWatcher;

Expand All @@ -20,8 +22,6 @@ namespace Mayo {
// Monitors the file system for changes to Document files owned by Application object
// When a Document is opened then DocumentFilesWatcher automatically monitors the corresponding file
// for changes. When an Document is closed then monitoring for that file is terminated
// File changes need to be acknowledged with DocumentFilesWatcher:acknowledgeDocumentFileChange()
// otherwise there won't be further signal notification for the changed file
class DocumentFilesWatcher : public QObject {
public:
DocumentFilesWatcher(const ApplicationPtr& app, QObject* parent = nullptr);
Expand All @@ -31,23 +31,22 @@ class DocumentFilesWatcher : public QObject {
void enable(bool on);
bool isEnabled() const;

void acknowledgeDocumentFileChange(const DocumentPtr& doc);
static QuantityTime minimumDelayBetweenTwoDistinctFileChanges();

private:
QFileSystemWatcher* fileSystemWatcher();
void destroyFileSystemWatcher();
void onFileChanged(const QString& strFilePath);

bool isDocumentChangeAcknowledged(const DocumentPtr& doc) const;

void onDocumentFilePathChanged(const DocumentPtr& doc, const FilePath& fp);
void onDocumentAdded(const DocumentPtr& doc);
void onDocumentAboutToClose(const DocumentPtr& doc);

ApplicationPtr m_app;
QFileSystemWatcher* m_fileSystemWatcher = nullptr;
bool m_isEnabled = false;
std::vector<DocumentPtr> m_vecNonAckDocumentChanged;
std::unordered_map<DocumentPtr, int64_t/*ms*/> m_mapDocLastChangeTime;
QElapsedTimer m_timer;
};

} // namespace Mayo
5 changes: 1 addition & 4 deletions src/app/widget_main_control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,10 +340,8 @@ void WidgetMainControl::reloadDocumentAfterChange(const DocumentPtr& doc)
const auto& propActionOnDocumentFileChange = AppModule::get()->properties()->actionOnDocumentFileChange;

// Option: silent reloading
if (propActionOnDocumentFileChange == ActionOnDocumentFileChange::ReloadSilently) {
m_docFilesWatcher->acknowledgeDocumentFileChange(doc);
if (propActionOnDocumentFileChange == ActionOnDocumentFileChange::ReloadSilently)
fnReloadDoc(doc);
}

// Option: ask user to confirm reloading
if (propActionOnDocumentFileChange == ActionOnDocumentFileChange::ReloadIfUserConfirm) {
Expand All @@ -359,7 +357,6 @@ void WidgetMainControl::reloadDocumentAfterChange(const DocumentPtr& doc)
msgBox->setTextFormat(Qt::MarkdownText);
QtWidgetsUtils::asyncDialogExec(msgBox);
QObject::connect(msgBox, &QMessageBox::buttonClicked, this, [=](QAbstractButton* btn) {
m_docFilesWatcher->acknowledgeDocumentFileChange(doc);
if (btn == msgBox->button(QMessageBox::Yes))
fnReloadDoc(doc);
});
Expand Down
8 changes: 1 addition & 7 deletions tests/test_app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,9 @@ void TestApp::DocumentFilesWatcher_test()
QVERIFY(okWait);
QCOMPARE(changedDocId, doc->identifier());

// Check further file changes are not monitored until last one is acknowledged
changedDocId = -1;
fnCopyCadFile();
QTest::qWait(125/*ms*/);
QCOMPARE(changedDocId, -1);

// Check closing document unmonitors file in DocumentFilesWatcher
docFilesWatcher.acknowledgeDocumentFileChange(doc);
app->closeDocument(doc);
changedDocId = -1;
fnCopyCadFile();
QTest::qWait(125/*ms*/);
QCOMPARE(changedDocId, -1);
Expand Down

0 comments on commit eabb97f

Please sign in to comment.