From bb57884cac0f8268684804c94e9192c10a4b4ea5 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 12 Jan 2020 18:36:31 +1100 Subject: [PATCH] added save functions to various classes Each class is responsible for its own saving and loading from the XML data in order to reduce the complexity of the save code. --- app/common/rational.cpp | 5 +++ app/common/rational.h | 2 + app/node/graph.cpp | 4 +- app/node/graph.h | 4 +- app/node/input.cpp | 52 ++++++++++++++++++++++++ app/node/input.h | 5 +++ app/node/inputarray.cpp | 11 +++++ app/node/inputarray.h | 3 ++ app/node/node.cpp | 13 ++++++ app/node/node.h | 6 +++ app/node/output.cpp | 13 ++++++ app/node/output.h | 2 + app/node/param.cpp | 20 +++++++++ app/node/param.h | 8 ++++ app/project/item/folder/folder.cpp | 13 ++++++ app/project/item/folder/folder.h | 2 + app/project/item/footage/footage.cpp | 21 +++++++++- app/project/item/footage/footage.h | 7 +++- app/project/item/footage/imagestream.cpp | 5 +++ app/project/item/footage/imagestream.h | 2 + app/project/item/footage/stream.cpp | 19 +++++++++ app/project/item/footage/stream.h | 7 +++- app/project/item/item.cpp | 5 +++ app/project/item/item.h | 23 +++-------- app/project/item/sequence/sequence.cpp | 14 ++++++- app/project/item/sequence/sequence.h | 5 +++ app/project/project.cpp | 13 ++++++ app/project/project.h | 2 + app/project/projectsavemanager.cpp | 23 +++++++---- app/project/projectsavemanager.h | 1 + 30 files changed, 275 insertions(+), 35 deletions(-) diff --git a/app/common/rational.cpp b/app/common/rational.cpp index 677ff9e89..a8b4ba49f 100644 --- a/app/common/rational.cpp +++ b/app/common/rational.cpp @@ -117,6 +117,11 @@ const intType &rational::denominator() const return denom; } +QString rational::toString() const +{ + return QStringLiteral("%1/%2").arg(QString::number(numer), QString::number(denom)); +} + //Assignment Operators const rational& rational::operator=(const rational &rhs) diff --git a/app/common/rational.h b/app/common/rational.h index ba35f45aa..a037e7c0e 100644 --- a/app/common/rational.h +++ b/app/common/rational.h @@ -108,6 +108,8 @@ public: const intType& numerator() const; const intType& denominator() const; + QString toString() const; + private: //numerator and denominator intType numer; diff --git a/app/node/graph.cpp b/app/node/graph.cpp index 1023f2619..4e467671f 100644 --- a/app/node/graph.cpp +++ b/app/node/graph.cpp @@ -72,12 +72,12 @@ void NodeGraph::TakeNode(Node *node, QObject* new_parent) emit NodeRemoved(node); } -const QList &NodeGraph::nodes() +const QList &NodeGraph::nodes() const { return node_children_; } -bool NodeGraph::ContainsNode(Node *n) +bool NodeGraph::ContainsNode(Node *n) const { return (n->parent() == this); } diff --git a/app/node/graph.h b/app/node/graph.h index c006f0508..8394760d7 100644 --- a/app/node/graph.h +++ b/app/node/graph.h @@ -58,12 +58,12 @@ public: /** * @brief Retrieve a complete list of the nodes belonging to this graph */ - const QList& nodes(); + const QList& nodes() const; /** * @brief Returns whether a certain Node is in the graph or not */ - bool ContainsNode(Node* n); + bool ContainsNode(Node* n) const; signals: /** diff --git a/app/node/input.cpp b/app/node/input.cpp index 6449a4ea0..8dcd5e2f2 100644 --- a/app/node/input.cpp +++ b/app/node/input.cpp @@ -84,11 +84,63 @@ QString NodeInput::name() return NodeParam::name(); } +void NodeInput::Save(QXmlStreamWriter *writer) const +{ + writer->writeStartElement("input"); + + writer->writeAttribute("id", id()); + + writer->writeAttribute("ptr", QString::number(reinterpret_cast(this))); + + writer->writeAttribute("keyframing", QString::number(keyframing_)); + + // Write standard value + writer->writeStartElement("standard"); + + foreach (const QVariant& v, standard_value_) { + writer->writeTextElement("value", v.toString()); + } + + writer->writeEndElement(); // standard + + // Write keyframes + writer->writeStartElement("keyframes"); + + foreach (const KeyframeTrack& track, keyframe_tracks()) { + writer->writeStartElement("track"); + + foreach (NodeKeyframePtr key, track) { + writer->writeStartElement("key"); + + writer->writeAttribute("time", key->time().toString()); + writer->writeAttribute("type", QString::number(key->type())); + + writer->writeCharacters(key->value().toString()); + + writer->writeEndElement(); // key + } + + writer->writeEndElement(); // track + } + + writer->writeEndElement(); // keyframes + + SaveConnections(writer); + + SaveInternal(writer); + + writer->writeEndElement(); // input +} + const NodeParam::DataType &NodeInput::data_type() const { return data_type_; } +void NodeInput::SaveInternal(QXmlStreamWriter *writer) const +{ +} + NodeOutput *NodeInput::get_connected_output() const { if (!edges_.isEmpty()) { diff --git a/app/node/input.h b/app/node/input.h index 3f14e99e8..9e2802724 100644 --- a/app/node/input.h +++ b/app/node/input.h @@ -54,6 +54,8 @@ public: virtual QString name() override; + virtual void Save(QXmlStreamWriter* writer) const override; + /** * @brief The data type this parameter outputs * @@ -238,6 +240,9 @@ signals: void KeyframeRemoved(NodeKeyframePtr key); +protected: + virtual void SaveInternal(QXmlStreamWriter* writer) const; + private: /** * @brief Returns whether a data type can be interpolated or not diff --git a/app/node/inputarray.cpp b/app/node/inputarray.cpp index 719874732..9fcfbc934 100644 --- a/app/node/inputarray.cpp +++ b/app/node/inputarray.cpp @@ -166,3 +166,14 @@ void NodeInputArray::RemoveAt(int index) RemoveLast(); } + +void NodeInputArray::SaveInternal(QXmlStreamWriter *writer) const +{ + writer->writeStartElement("subparameters"); + + foreach (NodeInput* sub, sub_params_) { + sub->Save(writer); + } + + writer->writeEndElement(); // subparameters +} diff --git a/app/node/inputarray.h b/app/node/inputarray.h index ebc33df86..4f2df806e 100644 --- a/app/node/inputarray.h +++ b/app/node/inputarray.h @@ -32,6 +32,9 @@ public: signals: void SizeChanged(int size); +protected: + virtual void SaveInternal(QXmlStreamWriter* writer) const override; + private: QVector sub_params_; diff --git a/app/node/node.cpp b/app/node/node.cpp index 695a58ca2..2fef04065 100644 --- a/app/node/node.cpp +++ b/app/node/node.cpp @@ -47,6 +47,19 @@ Node::~Node() } } +void Node::Save(QXmlStreamWriter *writer) const +{ + writer->writeStartElement("node"); + + writer->writeAttribute("id", id()); + + foreach (NodeParam* param, parameters()) { + param->Save(writer); + } + + writer->writeEndElement(); // node +} + QString Node::Category() const { // Return an empty category for any nodes that don't use one diff --git a/app/node/node.h b/app/node/node.h index 3c7afebb1..b49768cc9 100644 --- a/app/node/node.h +++ b/app/node/node.h @@ -25,6 +25,7 @@ #include #include #include +#include #include "common/rational.h" #include "node/dependency.h" @@ -64,6 +65,11 @@ public: */ virtual Node* copy() const = 0; + /** + * @brief Save this node into a text/XML format + */ + void Save(QXmlStreamWriter* writer) const; + /** * @brief Return the name of the node * diff --git a/app/node/output.cpp b/app/node/output.cpp index c70fae381..4f4b2bbfd 100644 --- a/app/node/output.cpp +++ b/app/node/output.cpp @@ -40,3 +40,16 @@ QString NodeOutput::name() return NodeParam::name(); } + +void NodeOutput::Save(QXmlStreamWriter *writer) const +{ + writer->writeStartElement("output"); + + writer->writeAttribute("id", id()); + + writer->writeAttribute("ptr", QString::number(reinterpret_cast(this))); + + SaveConnections(writer); + + writer->writeEndElement(); // output +} diff --git a/app/node/output.h b/app/node/output.h index f7d86989f..1b6e66941 100644 --- a/app/node/output.h +++ b/app/node/output.h @@ -42,6 +42,8 @@ public: virtual QString name() override; + virtual void Save(QXmlStreamWriter* writer) const override; + private: }; diff --git a/app/node/param.cpp b/app/node/param.cpp index d2cbd8b68..d9a65fef0 100644 --- a/app/node/param.cpp +++ b/app/node/param.cpp @@ -282,3 +282,23 @@ QByteArray NodeParam::ValueToBytesInternal(const QVariant &v) return bytes; } + +void NodeParam::SaveConnections(QXmlStreamWriter *writer) const +{ + writer->writeStartElement("connections"); + + foreach (NodeEdgePtr edge, edges_) { + NodeParam* other; + + if (edge->input() == this) { + other = edge->output(); + } else { + other = edge->input(); + } + + writer->writeTextElement("connection", + QString::number(reinterpret_cast(other))); + } + + writer->writeEndElement(); // connections +} diff --git a/app/node/param.h b/app/node/param.h index e6057f2b8..55d0a8d4b 100644 --- a/app/node/param.h +++ b/app/node/param.h @@ -25,6 +25,7 @@ #include #include #include +#include #include "common/rational.h" #include "node/edge.h" @@ -229,6 +230,11 @@ public: virtual ~NodeParam() override; + /** + * @brief Save function + */ + virtual void Save(QXmlStreamWriter* writer) const = 0; + /** * @brief Return ID of this parameter */ @@ -368,6 +374,8 @@ signals: void EdgeRemoved(NodeEdgePtr edge); protected: + void SaveConnections(QXmlStreamWriter* writer) const; + /** * @brief Internal list of edges */ diff --git a/app/project/item/folder/folder.cpp b/app/project/item/folder/folder.cpp index 0493e3426..c3f1b6cf2 100644 --- a/app/project/item/folder/folder.cpp +++ b/app/project/item/folder/folder.cpp @@ -40,3 +40,16 @@ QIcon Folder::icon() { return icon::Folder; } + +void Folder::Save(QXmlStreamWriter *writer) const +{ + writer->writeStartElement("folder"); + + writer->writeAttribute("name", name()); + + foreach (ItemPtr child, children()) { + child->Save(writer); + } + + writer->writeEndElement(); // folder +} diff --git a/app/project/item/folder/folder.h b/app/project/item/folder/folder.h index cbbba9d36..340228188 100644 --- a/app/project/item/folder/folder.h +++ b/app/project/item/folder/folder.h @@ -40,6 +40,8 @@ public: virtual QIcon icon() override; + virtual void Save(QXmlStreamWriter* writer) const override; + private: }; diff --git a/app/project/item/footage/footage.cpp b/app/project/item/footage/footage.cpp index 4f2745c86..941e87e5e 100644 --- a/app/project/item/footage/footage.cpp +++ b/app/project/item/footage/footage.cpp @@ -35,6 +35,21 @@ Footage::~Footage() ClearStreams(); } +void Footage::Save(QXmlStreamWriter *writer) const +{ + writer->writeStartElement("footage"); + + writer->writeAttribute("name", name()); + writer->writeAttribute("filename", filename()); + writer->writeAttribute("ptr", FootageToString(this)); + + foreach (StreamPtr stream, streams_) { + stream->Save(writer); + } + + writer->writeEndElement(); // footage +} + const Footage::Status& Footage::status() const { return status_; @@ -147,7 +162,6 @@ QIcon Footage::icon() return QIcon(); } -#include QString Footage::duration() { if (streams_.isEmpty()) { @@ -283,3 +297,8 @@ void Footage::UpdateTooltip() break; } } + +QString FootageToString(const Footage *footage) +{ + return QString::number(reinterpret_cast(footage)); +} diff --git a/app/project/item/footage/footage.h b/app/project/item/footage/footage.h index 2059e0544..6630a7193 100644 --- a/app/project/item/footage/footage.h +++ b/app/project/item/footage/footage.h @@ -60,7 +60,10 @@ public: */ virtual ~Footage() override; - DISABLE_COPY_MOVE(Footage) + /** + * @brief Save function + */ + virtual void Save(QXmlStreamWriter *writer) const override; /** * @brief Check the ready state of this Footage object @@ -252,6 +255,8 @@ private: }; +QString FootageToString(const Footage* footage); + using FootagePtr = std::shared_ptr; #endif // FOOTAGE_H diff --git a/app/project/item/footage/imagestream.cpp b/app/project/item/footage/imagestream.cpp index 1a81b0bff..99c16c3f7 100644 --- a/app/project/item/footage/imagestream.cpp +++ b/app/project/item/footage/imagestream.cpp @@ -36,6 +36,11 @@ void ImageStream::FootageSetEvent(Footage *f) connect(f->project()->color_manager(), SIGNAL(ConfigChanged()), this, SLOT(ColorConfigChanged()), Qt::DirectConnection); } +void ImageStream::SaveCustomParameters(QXmlStreamWriter *writer) const +{ + writer->writeTextElement("colorspace", colorspace_); +} + QString ImageStream::description() { return QCoreApplication::translate("Stream", "%1: Image - %2x%3").arg(QString::number(index()), diff --git a/app/project/item/footage/imagestream.h b/app/project/item/footage/imagestream.h index d7f170511..8ff140b90 100644 --- a/app/project/item/footage/imagestream.h +++ b/app/project/item/footage/imagestream.h @@ -52,6 +52,8 @@ signals: protected: virtual void FootageSetEvent(Footage*) override; + virtual void SaveCustomParameters(QXmlStreamWriter* writer) const override; + private: int width_; int height_; diff --git a/app/project/item/footage/stream.cpp b/app/project/item/footage/stream.cpp index 8a36dc689..0f30acd09 100644 --- a/app/project/item/footage/stream.cpp +++ b/app/project/item/footage/stream.cpp @@ -35,6 +35,17 @@ Stream::~Stream() { } +void Stream::Save(QXmlStreamWriter *writer) const +{ + writer->writeStartElement("stream"); + + writer->writeAttribute("index", QString::number(index_)); + + SaveCustomParameters(writer); + + writer->writeEndElement(); // stream +} + QString Stream::description() { return QCoreApplication::translate("Stream", "%1: Unknown").arg(index()); @@ -122,6 +133,14 @@ StreamID Stream::ToID() const return StreamID(footage_->filename(), index_); } +void Stream::FootageSetEvent(Footage *) +{ +} + +void Stream::SaveCustomParameters(QXmlStreamWriter *writer) const +{ +} + StreamID::StreamID(const QString &filename, const int &stream_index) : filename_(filename), stream_index_(stream_index) diff --git a/app/project/item/footage/stream.h b/app/project/item/footage/stream.h index ed08d811d..a80e4ac7f 100644 --- a/app/project/item/footage/stream.h +++ b/app/project/item/footage/stream.h @@ -25,6 +25,7 @@ #include #include #include +#include #include "common/rational.h" @@ -74,6 +75,8 @@ public: */ virtual ~Stream(); + void Save(QXmlStreamWriter *writer) const; + virtual QString description(); const Type& type(); @@ -101,7 +104,9 @@ public: QMutex index_lock_; protected: - virtual void FootageSetEvent(Footage*){} + virtual void FootageSetEvent(Footage*); + + virtual void SaveCustomParameters(QXmlStreamWriter* writer) const; private: Footage* footage_; diff --git a/app/project/item/item.cpp b/app/project/item/item.cpp index c5f3f7b00..985e7882c 100644 --- a/app/project/item/item.cpp +++ b/app/project/item/item.cpp @@ -71,6 +71,11 @@ Item *Item::child(int i) const return children_.at(i).get(); } +const QList &Item::children() const +{ + return children_; +} + ItemPtr Item::shared_ptr_from_raw(Item *item) { for (int i=0;i #include #include +#include +#include "common/constructors.h" #include "common/threadedobject.h" class Project; @@ -59,25 +61,9 @@ public: */ virtual ~Item(); - /** - * @brief Deleted copy constructor - */ - Item(const Item& other) = delete; + DISABLE_COPY_MOVE(Item) - /** - * @brief Deleted move constructor - */ - Item(Item&& other) = delete; - - /** - * @brief Deleted copy assignment - */ - Item& operator=(const Item& other) = delete; - - /** - * @brief Deleted move assignment - */ - Item& operator=(Item&& other) = delete; + virtual void Save(QXmlStreamWriter* writer) const = 0; virtual Type type() const = 0; @@ -85,6 +71,7 @@ public: void remove_child(Item* c); int child_count() const; Item* child(int i) const; + const QList& children() const; ItemPtr shared_ptr_from_raw(Item* item); diff --git a/app/project/item/sequence/sequence.cpp b/app/project/item/sequence/sequence.cpp index a8632bc5c..6384094b9 100644 --- a/app/project/item/sequence/sequence.cpp +++ b/app/project/item/sequence/sequence.cpp @@ -38,6 +38,19 @@ Sequence::Sequence() : { } +void Sequence::Save(QXmlStreamWriter *writer) const +{ + writer->writeStartElement("sequence"); + + writer->writeAttribute("name", name()); + + foreach (Node* node, nodes()) { + node->Save(writer); + } + + writer->writeEndElement(); // sequence +} + void Sequence::Open(Sequence* sequence) { // FIXME: This is fairly "hardcoded" behavior and doesn't support infinite panels @@ -62,7 +75,6 @@ void Sequence::add_default_nodes() Node* audio_track_output = viewer_output_->track_list(Timeline::kTrackTypeAudio)->AddTrack(); NodeParam::ConnectEdge(video_track_output->output(), viewer_output_->texture_input()); NodeParam::ConnectEdge(audio_track_output->output(), viewer_output_->samples_input()); - //timeline_output_->track_list(TrackType::kTrackTypeVideo)->AddTrack(); // Update the timebase on these nodes set_video_params(video_params_); diff --git a/app/project/item/sequence/sequence.h b/app/project/item/sequence/sequence.h index a1ae6c41e..71aa31f6e 100644 --- a/app/project/item/sequence/sequence.h +++ b/app/project/item/sequence/sequence.h @@ -38,6 +38,11 @@ class Sequence : public Item, public NodeGraph public: Sequence(); + /** + * @brief Save function + */ + virtual void Save(QXmlStreamWriter *writer) const override; + static void Open(Sequence *sequence); void add_default_nodes(); diff --git a/app/project/project.cpp b/app/project/project.cpp index 6f26ff194..bee92d4a0 100644 --- a/app/project/project.cpp +++ b/app/project/project.cpp @@ -27,6 +27,19 @@ Project::Project() root_.set_project(this); } +void Project::Save(QXmlStreamWriter *writer) const +{ + writer->writeStartElement("project"); + + writer->writeTextElement("url", filename_); + + root_.Save(writer); + + + + writer->writeEndElement(); // project +} + Folder *Project::root() { return &root_; diff --git a/app/project/project.h b/app/project/project.h index b6d993e2b..7f3b83d4c 100644 --- a/app/project/project.h +++ b/app/project/project.h @@ -44,6 +44,8 @@ class Project : public QObject public: Project(); + void Save(QXmlStreamWriter* writer) const; + Folder* root(); QString name() const; diff --git a/app/project/projectsavemanager.cpp b/app/project/projectsavemanager.cpp index 7b9c498e4..c53b8df9c 100644 --- a/app/project/projectsavemanager.cpp +++ b/app/project/projectsavemanager.cpp @@ -1,5 +1,7 @@ #include "projectsavemanager.h" +#include + ProjectSaveManager::ProjectSaveManager(Project *project) : project_(project), cancelled_(false) @@ -9,19 +11,22 @@ ProjectSaveManager::ProjectSaveManager(Project *project) : void ProjectSaveManager::Start() { - int prog = 0; + QFile project_file(project_->filename()); - do { - if (cancelled_) { - break; - } + if (project_file.open(QFile::WriteOnly | QFile::Text)) { + QXmlStreamWriter writer(&project_file); + writer.setAutoFormatting(true); - prog += 10; + writer.writeStartDocument(); - emit ProgressChanged(prog); + writer.writeTextElement("version", "0.2.0"); - Sleep(200); - } while (prog < 100); + project_->Save(&writer); + + writer.writeEndDocument(); + + project_file.close(); + } emit Finished(); } diff --git a/app/project/projectsavemanager.h b/app/project/projectsavemanager.h index 7308fe0af..b49788b6f 100644 --- a/app/project/projectsavemanager.h +++ b/app/project/projectsavemanager.h @@ -2,6 +2,7 @@ #define PROJECTSAVEMANAGER_H #include +#include #include "project.h"