diff --git a/src/Lib/AbstractDocument.hh b/src/Lib/AbstractDocument.hh new file mode 100644 index 0000000000000000000000000000000000000000..495f6c172abc1e233dde8494dfc1d3b72b5532d8 --- /dev/null +++ b/src/Lib/AbstractDocument.hh @@ -0,0 +1,55 @@ +#ifndef VIVY_ABSTRACT_DOCUMENT_H +#define VIVY_ABSTRACT_DOCUMENT_H + +#ifndef __cplusplus +#error "This is a C++ header" +#endif + +#include "Utils.hh" +#include "Uuid.hh" +#include <QFileInfo> +#include <QDir> + +namespace Vivy +{ +class AbstractDocument : public QObject { + Q_OBJECT + VIVY_UNMOVABLE_OBJECT(AbstractDocument) + +protected: + AbstractDocument() = default; + + // Automate a part of the rename process, just need to provide a "success" + // callback and the new file info. + bool renameWith(const QFileInfo &newFile, auto success) noexcept + { + const QFileInfo oldFile(getName()); + + // Create folder if needed + QDir dirOp; + const QString newAbsDirPath = newFile.dir().absolutePath(); + if (!dirOp.exists(newAbsDirPath)) { + qInfo() << "Create folder " << newAbsDirPath; + dirOp.mkpath(newAbsDirPath); + } + + if (dirOp.rename(oldFile.absoluteFilePath(), newFile.absoluteFilePath())) { + success(); + return true; + } + + qCritical() << "Failed to rename" << oldFile << "to" << newFile; + return false; + } + +public: + virtual bool rename(const QString &) noexcept = 0; + virtual QString getName() const noexcept = 0; + virtual Uuid getUuid() const noexcept = 0; + +signals: + void documentChanged(); +}; +} + +#endif // VIVY_ABSTRACT_DOCUMENT_H diff --git a/src/Lib/CRTPStore.hh b/src/Lib/CRTPStore.hh new file mode 100644 index 0000000000000000000000000000000000000000..d75be68098041fe270faaf295d579e2e1b0b6996 --- /dev/null +++ b/src/Lib/CRTPStore.hh @@ -0,0 +1,72 @@ +#pragma once + +#ifndef __cplusplus +#error "This is a C++ header" +#endif + +#include "Utils.hh" +#include "Uuid.hh" +#include <QString> +#include <QMap> +#include <memory> + +#define VIVY_STORAGE_CLASS(theClassName, theDocumentName) \ + VIVY_UNMOVABLE_OBJECT(theClassName) \ + friend CRTPStore<theClassName, theDocumentName>; + +namespace Vivy +{ +// For example: +// VivyDocumentStore final : public +// CRTPStore<VivyDocumentStore, <- Child class +// VivyDocument> <- Document type to hold +template <class Store, class Document> class CRTPStore { + VIVY_UNMOVABLE_OBJECT(CRTPStore) + +protected: + QMap<Uuid, std::shared_ptr<Document>> documents{}; + uint newDocumentNumber{ 1 }; + static inline const QString newDocumentBaseName = QStringLiteral("Untitled "); + +protected: + explicit CRTPStore() noexcept = default; + +public: + // Load a document by its name + std::shared_ptr<Document> loadDocument(const QString &file) + { + auto ret = std::make_shared<Document>(file); + const Uuid id = ret->getUuid(); + documents[id] = ret; + return ret; + } + + // Close a document, please be sure to not used any of the dangling + // references to the closed document... + void closeDocument(const Uuid &uuid) noexcept + { + auto *self = static_cast<Store *>(this); + self->documents.remove(uuid); + } + + // Get stored documents + std::shared_ptr<Document> getDocument(const Uuid &uuid) const + { + auto *self = static_cast<Store *>(this); + + if (!self->documents.contains(uuid)) { + qCritical() << "Couldn't find the document " << uuid; + throw std::runtime_error("Can't find the document"); + } + + return self->documents.value(uuid); + } + + // Get to see if a document is already present or not + [[nodiscard("handle-it")]] bool isDocumentPresent(const Uuid &uuid) noexcept + { + auto *self = static_cast<Store *>(this); + return self->documents.count(uuid) >= 1; + } +}; +} diff --git a/src/Lib/Document/AbstractDocument.hh b/src/Lib/Document/AbstractDocument.hh deleted file mode 100644 index 823a1a83a152f34ce73e4b96ceacdaccd9dc9b8c..0000000000000000000000000000000000000000 --- a/src/Lib/Document/AbstractDocument.hh +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef VIVY_ABSTRACT_DOCUMENT_H -#define VIVY_ABSTRACT_DOCUMENT_H - -#ifndef __cplusplus -#error "This is a C++ header" -#endif - -#include "../Utils.hh" - -namespace Vivy -{ -class AbstractDocument : public QObject { - Q_OBJECT - VIVY_UNMOVABLE_OBJECT(AbstractDocument) - -protected: - AbstractDocument() = default; - virtual ~AbstractDocument() noexcept = default; - -public: - virtual bool rename(const QString &) noexcept = 0; - virtual QString getName() const noexcept = 0; - -signals: - void documentChanged(); -}; -} - -#endif // VIVY_ABSTRACT_DOCUMENT_H diff --git a/src/Lib/Document/VivyDocument.cc b/src/Lib/Document/VivyDocument.cc index ed8fbfc66a7cfeb545919b2f8ded803a823135d6..be9bc9fbbf57c6cf2c35d33a9e315ca40fd429ba 100644 --- a/src/Lib/Document/VivyDocument.cc +++ b/src/Lib/Document/VivyDocument.cc @@ -109,26 +109,12 @@ VivyDocument::rename(const QString &name) noexcept /* Compute new paths */ const QString newNameWithExtension = name.right(filePrefix.size()) == filePrefix ? name : name + "." + filePrefix; - QFileInfo oldPath(documentLocation, documentName + "." + filePrefix); - QFileInfo newPath(documentLocation, newNameWithExtension); - - /* Create folder if needed */ - QDir dirOp; - const QString newAbsDirPath = newPath.dir().absolutePath(); - if (!dirOp.exists(newAbsDirPath)) { - qInfo() << "Create folder " << newAbsDirPath; - dirOp.mkpath(newAbsDirPath); - } + const QFileInfo newPath(documentLocation, newNameWithExtension); - if (dirOp.rename(oldPath.absoluteFilePath(), newPath.absoluteFilePath())) { + return renameWith(newPath, [=, this]() noexcept -> void { documentLocation = newPath.dir(); documentName = newPath.baseName(); - qDebug() << "Rename " << oldPath << " to " << newPath; - return true; - } - - qCritical() << "Failed to rename " << oldPath << " to " << newPath; - return false; + }); } std::shared_ptr<AudioSubDocument> @@ -155,7 +141,7 @@ VivyDocument::getName() const noexcept return documentName; } -VivyDocument::Uuid +Uuid VivyDocument::getUuid() const noexcept { return uuid; diff --git a/src/Lib/Document/VivyDocument.hh b/src/Lib/Document/VivyDocument.hh index 9ecfbaa56c186cd73c677fb5ed0eb2e075a77495..eefaa11daa5eb8363c42a08bcaa1ce5c4d051f13 100644 --- a/src/Lib/Document/VivyDocument.hh +++ b/src/Lib/Document/VivyDocument.hh @@ -6,13 +6,13 @@ #endif #include "../Utils.hh" +#include "../AbstractDocument.hh" +#include "../Uuid.hh" #include "CRTPSubDocument.hh" -#include "AbstractDocument.hh" #include <memory> #include <QString> #include <QDir> -#include <QUuid> #include <QJsonDocument> namespace Vivy @@ -33,19 +33,6 @@ public: UntouchedByDefault = (1 << 1), }; - class Uuid : public QUuid { - public: - explicit Uuid() - : QUuid(QUuid::createUuid()) - { - } - - QString toString() const noexcept - { - return QUuid::toString(Uuid::WithoutBraces); - }; - }; - static inline const QString filePrefix{ "vivy" }; static inline constexpr Utils::DocumentType type = Utils::DocumentType::Vivy; @@ -71,7 +58,6 @@ private: public: // Create an empty document explicit VivyDocument(const QString &name, Options opt = NoOption); - ~VivyDocument() noexcept = default; bool rename(const QString &) noexcept override; bool loadSubDocument(const QString &) noexcept; @@ -83,8 +69,8 @@ public: std::shared_ptr<AssSubDocument> getAssSubDocument() const noexcept; QString getName() const noexcept override; - Uuid getUuid() const noexcept; QString getDocumentCapabilitiesString() const noexcept; + Uuid getUuid() const noexcept override; bool checkDocumentCapabilities(Capabilities) const noexcept; bool checkDocumentOption(Options) const noexcept; diff --git a/src/Lib/Document/VivyDocumentStore.cc b/src/Lib/Document/VivyDocumentStore.cc index bdf6674dfa590094e5c260b29c22b231045db2c3..5e2ca6fb98915c88d3c89d10dd0eeee6c57649f0 100644 --- a/src/Lib/Document/VivyDocumentStore.cc +++ b/src/Lib/Document/VivyDocumentStore.cc @@ -5,37 +5,15 @@ using namespace Vivy; -std::shared_ptr<VivyDocument> -VivyDocumentStore::loadDocument(const QString &file) -{ - QFileInfo fileinfo(file); - QString baseName = fileinfo.baseName(); - - if (VivyDocument *ret = new VivyDocument(file)) { - qDebug() << "Register document " << baseName << ret->getDocumentCapabilitiesString(); - VivyDocument::Uuid uuid = ret->getUuid(); - documents[uuid] = std::shared_ptr<VivyDocument>(ret); - return documents[uuid]; - } else { - qDebug() << "Failed to create document from " << file; - throw std::runtime_error("Failed to create the document"); - } -} - -bool -VivyDocumentStore::isDocumentPresent(const VivyDocument::Uuid &uuid) noexcept -{ - return documents.count(uuid) >= 1; -} - std::shared_ptr<VivyDocument> VivyDocumentStore::newDocument(VivyDocument::Options opt) { - QString newDocName = newDocumentBaseName + QString::number(newDocumentNumber++); + const QString newDocName = newDocumentBaseName + QString::number(newDocumentNumber++); + auto ret = std::make_shared<VivyDocument>(newDocName, opt); - if (auto ret = std::make_shared<VivyDocument>(newDocName, opt)) { - VivyDocument::Uuid uuid = ret->getUuid(); - documents[uuid] = ret; + if (ret) { + const Uuid uuid = ret->getUuid(); + documents[uuid] = ret; qDebug() << "Create new document " << newDocName << "with uuid" << uuid; return ret; } else { @@ -43,20 +21,3 @@ VivyDocumentStore::newDocument(VivyDocument::Options opt) throw std::runtime_error("Failed to create the document"); } } - -void -VivyDocumentStore::closeDocument(const VivyDocument::Uuid &uuid) noexcept -{ - qDebug() << "Store is closing the document " << uuid; - documents.remove(uuid); -} - -std::shared_ptr<VivyDocument> -VivyDocumentStore::getDocument(const VivyDocument::Uuid &uuid) const -{ - if (!documents.contains(uuid)) { - qCritical() << "Couldn't find the document " << uuid; - throw std::runtime_error("Can't find the document"); - } - return documents.value(uuid); -} diff --git a/src/Lib/Document/VivyDocumentStore.hh b/src/Lib/Document/VivyDocumentStore.hh index f25fd3f7d374840596fa81ee0df07a38ddc4db66..c2ac6b8e729a8befca9c085aeac25af81141a42b 100644 --- a/src/Lib/Document/VivyDocumentStore.hh +++ b/src/Lib/Document/VivyDocumentStore.hh @@ -1,42 +1,23 @@ -#ifndef VIVY_DOCUMENTSTORE_H -#define VIVY_DOCUMENTSTORE_H +#pragma once + +#ifndef __cplusplus +#error "This is a C++ header" +#endif #include "VivyDocument.hh" #include "../Utils.hh" - -#include <QMap> -#include <QString> -#include <memory> +#include "../CRTPStore.hh" namespace Vivy { -class VivyDocumentStore final { - VIVY_UNMOVABLE_OBJECT(VivyDocumentStore) +class VivyDocumentStore final : public CRTPStore<VivyDocumentStore, VivyDocument> { + VIVY_STORAGE_CLASS(VivyDocumentStore, VivyDocument) public: explicit VivyDocumentStore() noexcept = default; - ~VivyDocumentStore() noexcept = default; - /* Create/load documents */ - std::shared_ptr<VivyDocument> loadDocument(const QString &file); + // Create a new empty document with no backing file for the moment std::shared_ptr<VivyDocument> newDocument(VivyDocument::Options opt = VivyDocument::NoOption); - - /* Get to see if a document is already present or not */ - [[nodiscard("handle-it")]] bool isDocumentPresent(const VivyDocument::Uuid &) noexcept; - - /* Close a document, please be sure to not used any of the dangling - * references to the closed document... */ - void closeDocument(const VivyDocument::Uuid &uuid) noexcept; - - /* Get stored documents */ - std::shared_ptr<VivyDocument> getDocument(const VivyDocument::Uuid &uuid) const; - -private: - QMap<VivyDocument::Uuid, std::shared_ptr<VivyDocument>> documents; - uint newDocumentNumber{ 1 }; - static inline const QString newDocumentBaseName = "Untitled "; }; } - -#endif // VIVY_DOCUMENTSTORE_H diff --git a/src/Lib/Script/ScriptDocument.cc b/src/Lib/Script/ScriptDocument.cc new file mode 100644 index 0000000000000000000000000000000000000000..a74328f060f267012815b587bf335580eacc31eb --- /dev/null +++ b/src/Lib/Script/ScriptDocument.cc @@ -0,0 +1,33 @@ +#include "ScriptDocument.hh" + +#include <QFileInfo> + +using namespace Vivy::Script; + +ScriptDocument::ScriptDocument(const QString &path) +{ + const QFileInfo file(path); + if (!file.exists()) + throw std::runtime_error("File don't exists, don't create ScriptDocument"); + name = file.absoluteFilePath(); +} + +bool +ScriptDocument::rename(const QString &newName) noexcept +{ + /* Compute new paths */ + const QFileInfo newPath(newName); + return renameWith(newPath, [=, this]() noexcept { name = newName; }); +} + +QString +ScriptDocument::getName() const noexcept +{ + return name; +} + +Vivy::Uuid +ScriptDocument::getUuid() const noexcept +{ + return uuid; +} diff --git a/src/Lib/Script/ScriptDocument.hh b/src/Lib/Script/ScriptDocument.hh new file mode 100644 index 0000000000000000000000000000000000000000..f5394514e48a5235d64c7c2e4c7f4c71c66c2ed6 --- /dev/null +++ b/src/Lib/Script/ScriptDocument.hh @@ -0,0 +1,24 @@ +#pragma once + +#ifndef __cplusplus +#error "This is a C++ header" +#endif + +#include "../AbstractDocument.hh" +#include "../Uuid.hh" + +namespace Vivy::Script +{ +class ScriptDocument final : public AbstractDocument { +public: + explicit ScriptDocument(const QString &name); + + bool rename(const QString &) noexcept override; + QString getName() const noexcept override; + Uuid getUuid() const noexcept override; + +private: + QString name{}; + const Uuid uuid{}; +}; +} diff --git a/src/Lib/Script/ScriptStore.cc b/src/Lib/Script/ScriptStore.cc new file mode 100644 index 0000000000000000000000000000000000000000..deb8b89ec8427d0f5170498d48d2a5e01505889e --- /dev/null +++ b/src/Lib/Script/ScriptStore.cc @@ -0,0 +1,4 @@ +#include "ScriptStore.hh" +#include "../Uuid.hh" + +using namespace Vivy::Script; diff --git a/src/Lib/Script/ScriptStore.hh b/src/Lib/Script/ScriptStore.hh new file mode 100644 index 0000000000000000000000000000000000000000..8cddd1ebb2e84783d9e5926c479d8d17c9caea3b --- /dev/null +++ b/src/Lib/Script/ScriptStore.hh @@ -0,0 +1,14 @@ +#pragma once + +#include "../CRTPStore.hh" +#include "ScriptDocument.hh" + +namespace Vivy::Script +{ +class ScriptStore final : public CRTPStore<ScriptStore, ScriptDocument> { + VIVY_STORAGE_CLASS(ScriptStore, ScriptDocument) + +public: + explicit ScriptStore() noexcept = default; +}; +} diff --git a/src/Lib/Uuid.hh b/src/Lib/Uuid.hh new file mode 100644 index 0000000000000000000000000000000000000000..02e0801b19eecf10adc8144280aa61d1c98cc30d --- /dev/null +++ b/src/Lib/Uuid.hh @@ -0,0 +1,19 @@ +#pragma once + +#include <QUuid> + +namespace Vivy +{ +class Uuid : public QUuid { +public: + explicit Uuid() + : QUuid(QUuid::createUuid()) + { + } + + QString toString() const noexcept + { + return QUuid::toString(Uuid::WithoutBraces); + } +}; +} diff --git a/src/UI/AbstractDocumentView.hh b/src/UI/AbstractDocumentView.hh index e73814ba43fd51bd424095a6378e1d57265dd027..43dc02e99877050426f3f9a227f4b57ce3e84692 100644 --- a/src/UI/AbstractDocumentView.hh +++ b/src/UI/AbstractDocumentView.hh @@ -5,7 +5,7 @@ #endif #include "../Lib/Utils.hh" -#include "../Lib/Document/AbstractDocument.hh" +#include "../Lib/AbstractDocument.hh" #include <QMainWindow> #include <QDockWidget> #include <QAction> @@ -27,7 +27,6 @@ public: public: explicit AbstractDocumentView(Type, QWidget *parent = nullptr) noexcept; - virtual ~AbstractDocumentView() noexcept = default; virtual void closeDocument() noexcept = 0; virtual void openProperties() noexcept = 0; diff --git a/src/UI/MainWindow.hh b/src/UI/MainWindow.hh index 24f65893017c58c00b52f56077dbadbe87c7cfbd..0da5f538c52619e3fd2298b675c060315b316520 100644 --- a/src/UI/MainWindow.hh +++ b/src/UI/MainWindow.hh @@ -5,7 +5,7 @@ #endif #include "../Lib/Utils.hh" -#include "../Lib/Document/AbstractDocument.hh" +#include "../Lib/AbstractDocument.hh" #include "../Lib/Document/VivyDocumentStore.hh" #include "DocumentViews/AudioVisualizer.hh" #include "VivyDocumentView.hh"