Save and open projects as JSON
A project is the whole setup as a small text file: the source paths, the effect chain with its params, the canvas and the seed. Reading and writing are driven by the effects' ParamSpecs rather than by whatever sits in a stage's values, so a new effect is saveable without touching this code, a key an effect does not declare is never written or read back, and an old project keeps the defaults for params that did not exist when it was saved. Paths under the project's own folder are written relative, so a folder of images and their project can be moved whole. src/core/project.cpp carries its own small JSON reader instead of a dependency, and names the line when a hand-edited file is wrong. The interface gets a header-bar menu: New, Open, Save, Save As, with Ctrl+N/O/S. The title shows the project name. Opening a project replaces the sources, discarding a decode still in flight rather than mixing it into the new project. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
#include "core/chain.hpp"
|
||||
#include "core/effect.hpp"
|
||||
#include "core/image.hpp"
|
||||
#include "core/project.hpp"
|
||||
|
||||
namespace effector {
|
||||
|
||||
@@ -54,6 +55,21 @@ private:
|
||||
void rebuildChainRows();
|
||||
void selectStage(int index);
|
||||
void onStageSelected();
|
||||
Gtk::Widget& buildMainMenu(); // the header menu: new, open, save project
|
||||
Project currentProject() const;
|
||||
void applyProject(const Project& project, const std::string& path);
|
||||
void clearSources();
|
||||
void onNewProject();
|
||||
void onOpenProject();
|
||||
void onProjectChosen(const Glib::RefPtr<Gio::AsyncResult>& result,
|
||||
const Glib::RefPtr<Gtk::FileDialog>& dialog);
|
||||
void onSaveProject(); // falls back to Save As while the project is untitled
|
||||
void onSaveProjectAs();
|
||||
void onSaveProjectChosen(const Glib::RefPtr<Gio::AsyncResult>& result,
|
||||
const Glib::RefPtr<Gtk::FileDialog>& dialog);
|
||||
void writeProject(const std::string& path);
|
||||
void updateTitle();
|
||||
|
||||
void onParamChanged();
|
||||
void onSeedEntered();
|
||||
void onRecreate();
|
||||
@@ -82,6 +98,7 @@ private:
|
||||
bool suspendStageSelect_ = false; // guards the rebuild of the chain rows
|
||||
Image result_;
|
||||
std::uint64_t seed_ = 0;
|
||||
std::string projectPath_; // empty until the project has been saved once
|
||||
bool suspendRender_ = true;
|
||||
|
||||
// Source loading. Decoding a batch of large photographs takes seconds, so
|
||||
@@ -98,6 +115,7 @@ private:
|
||||
std::vector<LoadFailure> loadFailures_;
|
||||
std::vector<std::string> loadQueue_; // chosen while another batch was loading
|
||||
bool loading_ = false;
|
||||
bool dropLoadedImages_ = false; // the batch in flight belongs to a replaced project
|
||||
sigc::connection loadWindowDelay_;
|
||||
|
||||
// Render job
|
||||
@@ -126,6 +144,7 @@ private:
|
||||
Gtk::Entry seedEntry_;
|
||||
Gtk::ListBox chainList_;
|
||||
Gtk::MenuButton addEffectButton_;
|
||||
Gtk::MenuButton menuButton_;
|
||||
Gtk::Button recreateButton_{"Recreate"};
|
||||
Gtk::Button saveButton_{"Save As…"};
|
||||
Gtk::Picture picture_;
|
||||
|
||||
Reference in New Issue
Block a user