From e1d3fe0d6bba40466ada300151c30deb0c96125b Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Thu, 19 Mar 2020 01:52:31 -0500 Subject: [PATCH] [nostalgia/studio] Add ability to subscribe to updates to files --- src/nostalgia/studio/lib/context.hpp | 11 +++--- src/nostalgia/studio/lib/project.cpp | 32 ++++++++++++++--- src/nostalgia/studio/lib/project.hpp | 54 ++++++++++++++++++++++++++-- src/nostalgia/studio/mainwindow.cpp | 10 ++++-- 4 files changed, 92 insertions(+), 15 deletions(-) diff --git a/src/nostalgia/studio/lib/context.hpp b/src/nostalgia/studio/lib/context.hpp index 6420e9a4..33343a20 100644 --- a/src/nostalgia/studio/lib/context.hpp +++ b/src/nostalgia/studio/lib/context.hpp @@ -13,11 +13,12 @@ namespace nostalgia::studio { -struct Context { - QString appName; - QString orgName; - QWidget* tabParent = nullptr; - const class Project* project = nullptr; +class Context { + public: + QString appName; + QString orgName; + QWidget* tabParent = nullptr; + const class Project* project = nullptr; }; } diff --git a/src/nostalgia/studio/lib/project.cpp b/src/nostalgia/studio/lib/project.cpp index f3595deb..72b50122 100644 --- a/src/nostalgia/studio/lib/project.cpp +++ b/src/nostalgia/studio/lib/project.cpp @@ -8,13 +8,12 @@ #include #include +#include #include "project.hpp" namespace nostalgia::studio { -using namespace ox; - Project::Project(QString path): m_fs(path.toUtf8()) { qDebug() << "Project:" << path; m_path = path; @@ -27,13 +26,13 @@ void Project::create() { QDir().mkpath(m_path); } -PassThroughFS *Project::romFs() { +ox::PassThroughFS *Project::romFs() { return &m_fs; } void Project::mkdir(QString path) const { oxThrowError(m_fs.mkdir(path.toUtf8().data(), true)); - emit updated(path); + emit fileUpdated(path); } ox::FileStat Project::stat(QString path) const { @@ -48,7 +47,7 @@ bool Project::exists(QString path) const { void Project::writeBuff(QString path, uint8_t *buff, size_t buffLen) const { oxThrowError(m_fs.write(path.toUtf8().data(), buff, buffLen)); - emit updated(path); + emit fileUpdated(path); } std::vector Project::loadBuff(QString path) const { @@ -58,4 +57,27 @@ std::vector Project::loadBuff(QString path) const { return buff; } +void Project::procDir(QStringList &paths, QString path) const { + oxThrowError(m_fs.ls(path.toUtf8(), [&](QString name, ox::InodeId_t) { + auto fullPath = path + "/" + name; + auto [stat, err] = m_fs.stat(fullPath.toUtf8().data()); + oxReturnError(err); + switch (stat.fileType) { + case ox::FileType_NormalFile: + paths.push_back(fullPath); + break; + case ox::FileType_Directory: + procDir(paths, fullPath); + break; + } + return OxError(0); + })); +} + +QStringList Project::listFiles(QString path) const { + QStringList paths; + procDir(paths, path); + return paths; +} + } diff --git a/src/nostalgia/studio/lib/project.hpp b/src/nostalgia/studio/lib/project.hpp index 04600d03..4d4235c7 100644 --- a/src/nostalgia/studio/lib/project.hpp +++ b/src/nostalgia/studio/lib/project.hpp @@ -14,11 +14,22 @@ #include #include +#include #include "nostalgiastudio_export.h" +#include "ox/fs/filesystem/passthroughfs.hpp" namespace nostalgia::studio { +enum class ProjectEvent { + FileAdded, + // FileRecognized is triggered for all matching files upon a new + // subscription to a section of the project and upon the addition of a file. + FileRecognized, + FileDeleted, + FileUpdated, +}; + class NOSTALGIASTUDIO_EXPORT Project: public QObject { Q_OBJECT @@ -50,13 +61,29 @@ class NOSTALGIASTUDIO_EXPORT Project: public QObject { bool exists(QString path) const; + void subscribe(ProjectEvent e, QObject *tgt, const char *slot) const; + + template + void subscribe(ProjectEvent e, QObject *tgt, Functor &&slot) const; + private: void writeBuff(QString path, uint8_t *buff, size_t buffLen) const; std::vector loadBuff(QString path) const; + void procDir(QStringList &paths, QString path) const; + + QStringList listFiles(QString path = "") const; + signals: - void updated(QString path) const; + void fileEvent(ProjectEvent, QString path) const; + void fileAdded(QString) const; + // FileRecognized is triggered for all matching files upon a new + // subscription to a section of the project and upon the addition of a + // file. + void fileRecognized(QString) const; + void fileDeleted(QString) const; + void fileUpdated(QString) const; }; @@ -68,7 +95,7 @@ void Project::writeObj(QString path, T *obj) const { oxThrowError(ox::writeMC(buff.data(), buff.size(), obj, &mcSize)); // write to FS writeBuff(path, buff.data(), mcSize); - emit updated(path); + emit fileUpdated(path); } template @@ -79,4 +106,27 @@ std::unique_ptr Project::loadObj(QString path) const { return obj; } +template +void Project::subscribe(ProjectEvent e, QObject *tgt, Functor &&slot) const { + switch (e) { + case ProjectEvent::FileAdded: + connect(this, &Project::fileAdded, tgt, (slot)); + break; + case ProjectEvent::FileRecognized: + { + for (auto f : listFiles()) { + slot(f); + } + connect(this, &Project::fileRecognized, tgt, (slot)); + break; + } + case ProjectEvent::FileDeleted: + connect(this, &Project::fileDeleted, tgt, (slot)); + break; + case ProjectEvent::FileUpdated: + connect(this, &Project::fileUpdated, tgt, (slot)); + break; + } +} + } diff --git a/src/nostalgia/studio/mainwindow.cpp b/src/nostalgia/studio/mainwindow.cpp index cf48d00f..cf36b385 100644 --- a/src/nostalgia/studio/mainwindow.cpp +++ b/src/nostalgia/studio/mainwindow.cpp @@ -297,7 +297,7 @@ void MainWindow::openProject(QString projectPath) { m_ctx.project = project; m_oxfsView = new OxFSModel(project->romFs()); m_projectExplorer->setModel(m_oxfsView); - connect(m_ctx.project, &Project::updated, m_oxfsView, &OxFSModel::updateFile); + connect(m_ctx.project, &Project::fileUpdated, m_oxfsView, &OxFSModel::updateFile); m_importAction->setEnabled(true); m_state.projectPath = projectPath; // reopen tabs @@ -306,7 +306,11 @@ void MainWindow::openProject(QString projectPath) { try { openFile(t, true); } catch (ox::Error err) { - oxTrace("nostalgia::studio::MainWindow::openProject") << "Error opening tab:" << err; + qInfo() << "Error opening tab:" << static_cast(err); + oxTrace("nostalgia::studio::MainWindow::openProject") << "Error opening tab:" << static_cast(err); + } catch (...) { + qInfo() << "Error opening tab"; + oxTrace("nostalgia::studio::MainWindow::openProject") << "Error opening tab"; } } qInfo() << "Open project:" << projectPath; @@ -322,7 +326,7 @@ void MainWindow::closeProject() { } if (m_ctx.project) { - disconnect(m_ctx.project, SIGNAL(updated(QString)), m_oxfsView, SLOT(updateFile(QString))); + disconnect(m_ctx.project, &Project::fileUpdated, m_oxfsView, &OxFSModel::updateFile); delete m_ctx.project; m_ctx.project = nullptr;