ProjectStore.h header
#include <ew/app/ProjectStore.h>
Namespace ew::app
ProjectStore class
class ew::app::ProjectStore
Where a project's content is read from and written to. An interface so everything above it – Workspace, the mounted-library loader, autosave – depends on the abstraction and tests drive a full open/edit/save/reload cycle against a double (CODING_STANDARDS section 7: seams are interfaces). FolderProjectStore, the implementation the product ships, is the only place the filesystem is named.
A location is opaque to callers: whatever the implementation addresses a project by. For the folder store it is a filesystem directory, which is why that store names the parameter directory.
Recoverable IO/parse failures come back as an Error inside the Result, never thrown – a project that will not load is an ordinary outcome the UI reports, not an exceptional one.
Members
ew::app::persistence::ProjectStore::ProjectStore()=default
Defaulted.
virtual ew::app::persistence::ProjectStore::~ProjectStore()=default
Defaulted.
ew::app::persistence::ProjectStore::ProjectStore(const ProjectStore &)=delete
Interface type: non-copyable and non-movable (held via pointer/reference).
ew::app::persistence::ProjectStore::ProjectStore(ProjectStore &&)=delete
Not movable.
ProjectStore & ew::app::persistence::ProjectStore::operator=(const ProjectStore &)=delete
Not copyable.
ProjectStore & ew::app::persistence::ProjectStore::operator=(ProjectStore &&)=delete
Not movable.
virtual ew::core::foundation::Result< void > ew::app::persistence::ProjectStore::save(const ew::core::project::Project &project, const QString &location)=0
Writes project to location in full, replacing the project content already there.
virtual ew::core::foundation::Result< std::unique_ptr< ew::core::project::Project > > ew::app::persistence::ProjectStore::load(const QString &location, const ew::core::foundation::OperationContext &operation)=0
Loads the project at location. A location holding no content loads as an EMPTY project rather than an error – ask exists first when the difference matters.
operation reports progress and is polled for cancellation. A cancelled load returns an Error, not a half-built project: a partially loaded project would look like data loss to everything downstream, which is the opposite of the batch runner's partial-results contract and deliberately so.
Measured, which is why it takes a context at all: a folder project loads in ~3 s cold for a typical novel (422 files) and ~25 s for a worldbuilding-heavy one (4 802 files), release build, linear at roughly 5 ms/file. The cost is COLD FILE I/O – warm, the same large project loads in under a second – so it is the first open after boot, or from an external, network or synced drive, that a writer waits through.
Required rather than defaulted, because a default argument on a virtual function is bound to the STATIC type: an override could silently supply a different one. Callers that do not watch the load pass {}.
virtual ew::core::foundation::Result< void > ew::app::persistence::ProjectStore::saveSubset(const ew::core::project::Project &project, const std::vector< ew::core::foundation::ContentId > &objectIds, const std::vector< ew::core::foundation::CategoryId > &categoryIds, const QString &location)=0
Writes only the objects with ids in objectIds and the taxonomy categories with ids in categoryIds from project to location, for authoring a content pack from a selected subset (DESIGN 4.20). No project-level metadata (pins, mounts, goals, ...) is written; ids not present in project are skipped.
virtual bool ew::app::persistence::ProjectStore::exists(const QString &location) const =0
Whether location holds a project at all.
Every implementation must distinguish this from "holds a project with nothing in it", and the distinction is load-bearing: load() succeeds for a location with no content, so a mounted library whose folder has moved would otherwise load as a perfectly healthy EMPTY library – listed as mounted, resolving nothing, every reference into it dangling, and no signal anywhere that the path is wrong. It is stated here because it is exactly the kind of difference a test double drifts on silently.