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 Aug 1, 2024
1 parent 97627a0 commit 5c59821
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 11 deletions.
7 changes: 3 additions & 4 deletions src/app/commands_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,15 +248,14 @@ void FileCommandTools::importInDocument(
const QString taskTitle =
listFilePaths.size() > 1 ?
Command::tr("Import") :
filepathTo<QString>(listFilePaths.front().stem());
filepathTo<QString>(listFilePaths.front().stem())
;
context->taskMgr()->setTitle(taskId, to_stdString(taskTitle));
context->taskMgr()->run(taskId);
}

void FileCommandTools::importInDocument(
IAppContext* context,
const DocumentPtr& targetDoc,
const FilePath& filePath
IAppContext* context, const DocumentPtr& targetDoc, const FilePath& filePath
)
{
FileCommandTools::importInDocument(context, targetDoc, Span<const FilePath>(&filePath, 1));
Expand Down
45 changes: 40 additions & 5 deletions src/app/document_files_watcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@
#include "document_files_watcher.h"

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

#include <QtCore/QFileSystemWatcher>
#include <QtCore/QtDebug>
#include <QtCore/QTimer>

#include <cassert>

namespace Mayo {

Expand Down Expand Up @@ -38,6 +43,7 @@ void DocumentFilesWatcher::enable(bool on)
}
else {
this->destroyFileSystemWatcher();
m_setDocBeingChanged.clear();
m_vecNonAckDocumentChanged.clear();
}
}
Expand All @@ -54,6 +60,16 @@ void DocumentFilesWatcher::acknowledgeDocumentFileChange(const DocumentPtr& doc)
m_vecNonAckDocumentChanged.erase(it);
}

QuantityTime DocumentFilesWatcher::signalSendDelay() const
{
return m_signalSendDelay;
}

void DocumentFilesWatcher::setSignalSendDelay(QuantityTime delay)
{
m_signalSendDelay = delay;
}

QFileSystemWatcher* DocumentFilesWatcher::fileSystemWatcher()
{
if (!m_fileSystemWatcher) {
Expand All @@ -78,10 +94,28 @@ 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);
this->signalDocumentFileChanged.send(doc);

if (!this->isDocumentChangeAcknowledged(doc)) {
//qDebug() << "onFileChanged()" << strFilePath << " -- file change !ack: signal rejected";
return;
}

if (m_setDocBeingChanged.find(doc) != m_setDocBeingChanged.cend()) {
//qDebug() << "onFileChanged()" << strFilePath << " -- being modified: signal rejected";
return;
}

//qDebug() << "onFileChanged()" << strFilePath << " -- register callback: signal accepted";
m_setDocBeingChanged.insert(doc);
const int sendSignalDelay_ms = UnitSystem::milliseconds(m_signalSendDelay).value;
QTimer::singleShot(sendSignalDelay_ms, this, [=]{
if (m_setDocBeingChanged.find(doc) != m_setDocBeingChanged.cend()) {
//qDebug() << "onFileChanged()" << strFilePath << " -- timer callback: signal";
m_vecNonAckDocumentChanged.push_back(doc);
this->signalDocumentFileChanged.send(doc);
m_setDocBeingChanged.erase(doc);
}
});
}
}

Expand Down Expand Up @@ -109,9 +143,10 @@ void DocumentFilesWatcher::onDocumentAdded(const DocumentPtr& doc)

void DocumentFilesWatcher::onDocumentAboutToClose(const DocumentPtr& doc)
{
if (m_isEnabled)
if (m_isEnabled) {
this->fileSystemWatcher()->removePath(filepathTo<QString>(doc->filePath()));
m_setDocBeingChanged.erase(doc);
}
}


} // namespace Mayo
7 changes: 7 additions & 0 deletions src/app/document_files_watcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
#include "../base/application_ptr.h"
#include "../base/document_ptr.h"
#include "../base/filepath.h"
#include "../base/quantity.h"
#include "../base/signal.h"

#include <QtCore/QObject>

#include <unordered_set>
#include <vector>

class QFileSystemWatcher;
Expand All @@ -33,6 +35,9 @@ class DocumentFilesWatcher : public QObject {

void acknowledgeDocumentFileChange(const DocumentPtr& doc);

QuantityTime signalSendDelay() const;
void setSignalSendDelay(QuantityTime delay);

private:
QFileSystemWatcher* fileSystemWatcher();
void destroyFileSystemWatcher();
Expand All @@ -47,7 +52,9 @@ class DocumentFilesWatcher : public QObject {
ApplicationPtr m_app;
QFileSystemWatcher* m_fileSystemWatcher = nullptr;
bool m_isEnabled = false;
std::unordered_set<DocumentPtr> m_setDocBeingChanged;
std::vector<DocumentPtr> m_vecNonAckDocumentChanged;
QuantityTime m_signalSendDelay = 1 * Quantity_Second;
};

} // namespace Mayo
13 changes: 11 additions & 2 deletions tests/test_app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,14 @@ void TestApp::DocumentFilesWatcher_test()
auto app = makeOccHandle<Application>();

DocumentFilesWatcher docFilesWatcher(app);
const int signalSendDelay_ms = 250;
docFilesWatcher.setSignalSendDelay(signalSendDelay_ms * Quantity_Millisecond);
docFilesWatcher.enable(true);
Document::Identifier changedDocId = -1;
int signalCallCount = 0;
docFilesWatcher.signalDocumentFileChanged.connectSlot([&](DocumentPtr changedDoc) {
changedDocId = changedDoc->identifier();
++signalCallCount;
});

const FilePath cadFilePath = "tests/outputs/temp-cube.ply";
Expand All @@ -92,20 +96,25 @@ void TestApp::DocumentFilesWatcher_test()
fnCopyCadFile();
const bool okWait = QTest::qWaitFor([&]{ return changedDocId != -1; });
QVERIFY(okWait);
QCOMPARE(signalCallCount, 1);
QCOMPARE(changedDocId, doc->identifier());

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

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

void TestApp::FilePathConv_test()
Expand Down

0 comments on commit 5c59821

Please sign in to comment.