change: change code style to Linux style except indent.

This commit is contained in:
Mike Solar
2025-08-03 03:09:40 +08:00
parent 65ab76edc8
commit 74f73ab3be
789 changed files with 77113 additions and 68888 deletions
+89 -79
View File
@@ -26,7 +26,8 @@
#include "node/project/sequence/sequence.h"
#include "ui/icons/icons.h"
namespace olive {
namespace olive
{
#define super Node
@@ -34,143 +35,152 @@ const QString Folder::kChildInput = QStringLiteral("child_in");
Folder::Folder()
{
SetFlag(kIsItem);
SetFlag(kIsItem);
AddInput(kChildInput, NodeValue::kNone, InputFlags(kInputFlagArray | kInputFlagNotKeyframable));
AddInput(kChildInput, NodeValue::kNone,
InputFlags(kInputFlagArray | kInputFlagNotKeyframable));
}
QVariant Folder::data(const DataType &d) const
{
if (d == ICON) {
return icon::Folder;
}
if (d == ICON) {
return icon::Folder;
}
return super::data(d);
return super::data(d);
}
void Folder::Retranslate()
{
super::Retranslate();
super::Retranslate();
SetInputName(kChildInput, tr("Children"));
SetInputName(kChildInput, tr("Children"));
}
Node *GetChildWithNameInternal(const Folder* n, const QString& s)
Node *GetChildWithNameInternal(const Folder *n, const QString &s)
{
for (int i=0; i<n->item_child_count(); i++) {
Node* child = n->item_child(i);
for (int i = 0; i < n->item_child_count(); i++) {
Node *child = n->item_child(i);
if (child->GetLabel() == s) {
return child;
} else if (Folder* subfolder = dynamic_cast<Folder*>(child)) {
if (Node *n2 = GetChildWithNameInternal(subfolder, s)) {
return n2;
}
}
}
if (child->GetLabel() == s) {
return child;
} else if (Folder *subfolder = dynamic_cast<Folder *>(child)) {
if (Node *n2 = GetChildWithNameInternal(subfolder, s)) {
return n2;
}
}
}
return nullptr;
return nullptr;
}
Node *Folder::GetChildWithName(const QString &s) const
{
return GetChildWithNameInternal(this, s);
return GetChildWithNameInternal(this, s);
}
bool Folder::HasChildRecursive(Node *child) const
{
for (Node *i : item_children_) {
if (i == child) {
return true;
} else if (Folder *f = dynamic_cast<Folder*>(i)) {
if (f->HasChildRecursive(child)) {
return true;
}
}
}
for (Node *i : item_children_) {
if (i == child) {
return true;
} else if (Folder *f = dynamic_cast<Folder *>(i)) {
if (f->HasChildRecursive(child)) {
return true;
}
}
}
return false;
return false;
}
int Folder::index_of_child_in_array(Node *item) const
{
int index_of_item = item_children_.indexOf(item);
int index_of_item = item_children_.indexOf(item);
if (index_of_item == -1) {
return -1;
}
if (index_of_item == -1) {
return -1;
}
return item_element_index_.at(index_of_item);
return item_element_index_.at(index_of_item);
}
void Folder::InputConnectedEvent(const QString &input, int element, Node *output)
void Folder::InputConnectedEvent(const QString &input, int element,
Node *output)
{
if (input == kChildInput && element != -1) {
Node* item = output;
if (input == kChildInput && element != -1) {
Node *item = output;
// The insert index is always our "count" because we only support appending in our internal
// model. For sorting/organizing, a QSortFilterProxyModel is used instead.
emit BeginInsertItem(item, item_child_count());
item_children_.append(item);
item_element_index_.append(element);
item->SetFolder(this);
emit EndInsertItem();
}
// The insert index is always our "count" because we only support appending in our internal
// model. For sorting/organizing, a QSortFilterProxyModel is used instead.
emit BeginInsertItem(item, item_child_count());
item_children_.append(item);
item_element_index_.append(element);
item->SetFolder(this);
emit EndInsertItem();
}
}
void Folder::InputDisconnectedEvent(const QString &input, int element, Node *output)
void Folder::InputDisconnectedEvent(const QString &input, int element,
Node *output)
{
if (input == kChildInput && element != -1) {
Node* item = output;
if (input == kChildInput && element != -1) {
Node *item = output;
int child_index = item_children_.indexOf(item);
emit BeginRemoveItem(item, child_index);
item_children_.removeAt(child_index);
item_element_index_.removeAt(child_index);
item->SetFolder(nullptr);
emit EndRemoveItem();
}
int child_index = item_children_.indexOf(item);
emit BeginRemoveItem(item, child_index);
item_children_.removeAt(child_index);
item_element_index_.removeAt(child_index);
item->SetFolder(nullptr);
emit EndRemoveItem();
}
}
FolderAddChild::FolderAddChild(Folder *folder, Node *child) :
folder_(folder),
child_(child)
FolderAddChild::FolderAddChild(Folder *folder, Node *child)
: folder_(folder)
, child_(child)
{
}
Project *FolderAddChild::GetRelevantProject() const
{
return folder_->project();
return folder_->project();
}
void FolderAddChild::redo()
{
int array_index = folder_->InputArraySize(Folder::kChildInput);
folder_->InputArrayAppend(Folder::kChildInput);
Node::ConnectEdge(child_, NodeInput(folder_, Folder::kChildInput, array_index));
int array_index = folder_->InputArraySize(Folder::kChildInput);
folder_->InputArrayAppend(Folder::kChildInput);
Node::ConnectEdge(child_,
NodeInput(folder_, Folder::kChildInput, array_index));
}
void FolderAddChild::undo()
{
Node::DisconnectEdge(child_, NodeInput(folder_, Folder::kChildInput, folder_->InputArraySize(Folder::kChildInput)-1));
folder_->InputArrayRemoveLast(Folder::kChildInput);
Node::DisconnectEdge(
child_, NodeInput(folder_, Folder::kChildInput,
folder_->InputArraySize(Folder::kChildInput) - 1));
folder_->InputArrayRemoveLast(Folder::kChildInput);
}
void Folder::RemoveElementCommand::redo()
{
if (!subcommand_) {
remove_index_ = folder_->index_of_child_in_array(child_);
if (remove_index_ != -1) {
NodeInput connected_input(folder_, Folder::kChildInput, remove_index_);
subcommand_ = new MultiUndoCommand();
subcommand_->add_child(new NodeEdgeRemoveCommand(folder_->GetConnectedOutput(connected_input), connected_input));
subcommand_->add_child(new NodeArrayRemoveCommand(folder_, Folder::kChildInput, remove_index_));
}
}
if (!subcommand_) {
remove_index_ = folder_->index_of_child_in_array(child_);
if (remove_index_ != -1) {
NodeInput connected_input(folder_, Folder::kChildInput,
remove_index_);
subcommand_ = new MultiUndoCommand();
subcommand_->add_child(new NodeEdgeRemoveCommand(
folder_->GetConnectedOutput(connected_input), connected_input));
subcommand_->add_child(new NodeArrayRemoveCommand(
folder_, Folder::kChildInput, remove_index_));
}
}
if (subcommand_) {
subcommand_->redo_now();
}
if (subcommand_) {
subcommand_->redo_now();
}
}
}
+131 -134
View File
@@ -23,7 +23,8 @@
#include "node/node.h"
namespace olive {
namespace olive
{
/**
* @brief The Folder class representing a directory in a project structure
@@ -31,193 +32,189 @@ namespace olive {
* The Item base class already has support for children, but this functionality is disabled by default
* (see CanHaveChildren() override). The Folder is a specific type that enables this functionality.
*/
class Folder : public Node
{
Q_OBJECT
class Folder : public Node {
Q_OBJECT
public:
Folder();
Folder();
NODE_DEFAULT_FUNCTIONS(Folder)
NODE_DEFAULT_FUNCTIONS(Folder)
virtual QString Name() const override
{
return tr("Folder");
}
virtual QString Name() const override
{
return tr("Folder");
}
virtual QString id() const override
{
return QStringLiteral("org.olivevideoeditor.Olive.folder");
}
virtual QString id() const override
{
return QStringLiteral("org.olivevideoeditor.Olive.folder");
}
virtual QVector<CategoryID> Category() const override
{
return {kCategoryProject};
}
virtual QVector<CategoryID> Category() const override
{
return { kCategoryProject };
}
virtual QString Description() const override
{
return tr("Organize several items into a single collection.");
}
virtual QString Description() const override
{
return tr("Organize several items into a single collection.");
}
virtual QVariant data(const DataType &d) const override;
virtual QVariant data(const DataType &d) const override;
virtual void Retranslate() override;
virtual void Retranslate() override;
Node *GetChildWithName(const QString& s) const;
bool ChildExistsWithName(const QString& s) const
{
return GetChildWithName(s);
}
Node *GetChildWithName(const QString &s) const;
bool ChildExistsWithName(const QString &s) const
{
return GetChildWithName(s);
}
bool HasChildRecursive(Node *child) const;
bool HasChildRecursive(Node *child) const;
int item_child_count() const
{
return item_children_.size();
}
int item_child_count() const
{
return item_children_.size();
}
Node* item_child(int i) const
{
return item_children_.at(i);
}
Node *item_child(int i) const
{
return item_children_.at(i);
}
const QVector<Node*>& children() const
{
return item_children_;
}
const QVector<Node *> &children() const
{
return item_children_;
}
int index_of_child(Node* item) const
{
return item_children_.indexOf(item);
}
int index_of_child(Node *item) const
{
return item_children_.indexOf(item);
}
int index_of_child_in_array(Node* item) const;
int index_of_child_in_array(Node *item) const;
template <typename T>
QVector<T*> ListChildrenOfType() const
{
QVector<T*> list;
template <typename T> QVector<T *> ListChildrenOfType() const
{
QVector<T *> list;
foreach (Node* node, item_children_) {
T* cast_test = dynamic_cast<T*>(node);
if (cast_test) {
list.append(cast_test);
}
foreach (Node *node, item_children_) {
T *cast_test = dynamic_cast<T *>(node);
if (cast_test) {
list.append(cast_test);
}
Folder *folder_test = dynamic_cast<Folder*>(node);
if (folder_test) {
list.append(folder_test->ListChildrenOfType<T>());
}
}
Folder *folder_test = dynamic_cast<Folder *>(node);
if (folder_test) {
list.append(folder_test->ListChildrenOfType<T>());
}
}
return list;
}
return list;
}
static const QString kChildInput;
static const QString kChildInput;
class RemoveElementCommand : public UndoCommand
{
public:
RemoveElementCommand(Folder *folder, Node *child) :
folder_(folder),
child_(child),
subcommand_(nullptr)
{
}
class RemoveElementCommand : public UndoCommand {
public:
RemoveElementCommand(Folder *folder, Node *child)
: folder_(folder)
, child_(child)
, subcommand_(nullptr)
{
}
virtual ~RemoveElementCommand() override
{
delete subcommand_;
}
virtual ~RemoveElementCommand() override
{
delete subcommand_;
}
virtual Project *GetRelevantProject() const override
{
return folder_->project();
}
virtual Project *GetRelevantProject() const override
{
return folder_->project();
}
protected:
virtual void redo() override;
protected:
virtual void redo() override;
virtual void undo() override
{
if (subcommand_) {
subcommand_->undo_now();
}
}
virtual void undo() override
{
if (subcommand_) {
subcommand_->undo_now();
}
}
private:
Folder *folder_;
private:
Folder *folder_;
Node *child_;
Node *child_;
int remove_index_;
int remove_index_;
MultiUndoCommand *subcommand_;
};
MultiUndoCommand *subcommand_;
};
signals:
void BeginInsertItem(Node* n, int index);
void BeginInsertItem(Node *n, int index);
void EndInsertItem();
void EndInsertItem();
void BeginRemoveItem(Node* n, int index);
void BeginRemoveItem(Node *n, int index);
void EndRemoveItem();
void EndRemoveItem();
protected:
virtual void InputConnectedEvent(const QString& input, int element, Node *output) override;
virtual void InputConnectedEvent(const QString &input, int element,
Node *output) override;
virtual void InputDisconnectedEvent(const QString& input, int element, Node *output) override;
virtual void InputDisconnectedEvent(const QString &input, int element,
Node *output) override;
private:
template<typename T>
static void ListOutputsOfTypeInternal(const Folder* n, QVector<T*>& list, bool recursive)
{
foreach (const Node::OutputConnection& c, n->output_connections()) {
Node* connected = c.second.node();
template <typename T>
static void ListOutputsOfTypeInternal(const Folder *n, QVector<T *> &list,
bool recursive)
{
foreach (const Node::OutputConnection &c, n->output_connections()) {
Node *connected = c.second.node();
T* cast_test = dynamic_cast<T*>(connected);
T *cast_test = dynamic_cast<T *>(connected);
if (cast_test) {
// Avoid duplicates
if (!list.contains(cast_test)) {
list.append(cast_test);
}
}
if (cast_test) {
// Avoid duplicates
if (!list.contains(cast_test)) {
list.append(cast_test);
}
}
if (recursive) {
Folder* subfolder = dynamic_cast<Folder*>(connected);
if (recursive) {
Folder *subfolder = dynamic_cast<Folder *>(connected);
if (subfolder) {
ListOutputsOfTypeInternal(subfolder, list, recursive);
}
}
}
}
QVector<Node*> item_children_;
QVector<int> item_element_index_;
if (subfolder) {
ListOutputsOfTypeInternal(subfolder, list, recursive);
}
}
}
}
QVector<Node *> item_children_;
QVector<int> item_element_index_;
};
class FolderAddChild : public UndoCommand
{
class FolderAddChild : public UndoCommand {
public:
FolderAddChild(Folder* folder, Node* child);
FolderAddChild(Folder *folder, Node *child);
virtual Project * GetRelevantProject() const override;
virtual Project *GetRelevantProject() const override;
protected:
virtual void redo() override;
virtual void redo() override;
virtual void undo() override;
virtual void undo() override;
private:
Folder* folder_;
Node* child_;
Folder *folder_;
Node *child_;
};
}
File diff suppressed because it is too large Load Diff
+92 -82
View File
@@ -31,7 +31,8 @@
#include "render/cancelatom.h"
#include "render/videoparams.h"
namespace olive {
namespace olive
{
/**
* @brief A reference to an external media file with metadata in a project structure
@@ -40,40 +41,40 @@ namespace olive {
* Footage objects store a list of Stream objects which store the majority of video/audio metadata. These streams
* are identical to the stream data in the files.
*/
class Footage : public ViewerOutput
{
Q_OBJECT
class Footage : public ViewerOutput {
Q_OBJECT
public:
/**
/**
* @brief Footage Constructor
*/
Footage(const QString& filename = QString());
Footage(const QString &filename = QString());
NODE_DEFAULT_FUNCTIONS(Footage)
NODE_DEFAULT_FUNCTIONS(Footage)
virtual QString Name() const override
{
return tr("Media");
}
virtual QString Name() const override
{
return tr("Media");
}
virtual QString id() const override
{
return QStringLiteral("org.olivevideoeditor.Olive.footage");
}
virtual QString id() const override
{
return QStringLiteral("org.olivevideoeditor.Olive.footage");
}
virtual QVector<CategoryID> Category() const override
{
return {kCategoryProject};
}
virtual QVector<CategoryID> Category() const override
{
return { kCategoryProject };
}
virtual QString Description() const override
{
return tr("Import video, audio, or still image files into the composition.");
}
virtual QString Description() const override
{
return tr(
"Import video, audio, or still image files into the composition.");
}
virtual void Retranslate() override;
virtual void Retranslate() override;
/**
/**
* @brief Reset Footage state ready for running through Probe() again
*
* If a Footage object needs to be re-probed (e.g. source file changes or Footage is linked to a new file), its
@@ -83,24 +84,24 @@ public:
* In most cases, you'll be using olive::ProbeMedia() for re-probing which already runs Clear(), so you won't need
* to worry about this.
*/
void Clear();
void Clear();
bool IsValid() const
{
return valid_;
}
bool IsValid() const
{
return valid_;
}
/**
/**
* @brief Sets this footage to valid and ready to use
*/
void SetValid();
void SetValid();
/**
/**
* @brief Return the current filename of this Footage object
*/
QString filename() const;
QString filename() const;
/**
/**
* @brief Set the filename
*
* NOTE: This does not automtaically clear the old streams and re-probe for new ones. If the file link has been
@@ -110,17 +111,17 @@ public:
*
* New filename
*/
void set_filename(const QString& s);
void set_filename(const QString &s);
/**
/**
* @brief Retrieve the last modified time/date
*
* The file's last modified timestamp is stored for potential organization in the ProjectExplorer. It can be
* retrieved here.
*/
const qint64 &timestamp() const;
const qint64 &timestamp() const;
/**
/**
* @brief Set the last modified time/date
*
* This should probably only be done on import or replace.
@@ -129,89 +130,98 @@ public:
*
* New last modified time/date
*/
void set_timestamp(const qint64 &t);
void set_timestamp(const qint64 &t);
void SetCancelPointer(CancelAtom *c)
{
cancelled_ = c;
}
void SetCancelPointer(CancelAtom *c)
{
cancelled_ = c;
}
int GetStreamIndex(Track::Type type, int index) const;
int GetStreamIndex(const Track::Reference& ref) const
{
return GetStreamIndex(ref.type(), ref.index());
}
int GetStreamIndex(Track::Type type, int index) const;
int GetStreamIndex(const Track::Reference &ref) const
{
return GetStreamIndex(ref.type(), ref.index());
}
Track::Reference GetReferenceFromRealIndex(int real_index) const;
Track::Reference GetReferenceFromRealIndex(int real_index) const;
/**
/**
* @brief Get the Decoder ID set when this Footage was probed
*
* @return
*
* A decoder ID
*/
const QString& decoder() const;
const QString &decoder() const;
static QString DescribeVideoStream(const VideoParams& params);
static QString DescribeAudioStream(const AudioParams& params);
static QString DescribeSubtitleStream(const SubtitleParams& params);
static QString DescribeVideoStream(const VideoParams &params);
static QString DescribeAudioStream(const AudioParams &params);
static QString DescribeSubtitleStream(const SubtitleParams &params);
virtual void Value(const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
virtual void Value(const NodeValueRow &value, const NodeGlobals &globals,
NodeValueTable *table) const override;
static QString GetStreamTypeName(Track::Type type);
static QString GetStreamTypeName(Track::Type type);
virtual Node *GetConnectedTextureOutput() override;
virtual Node *GetConnectedTextureOutput() override;
virtual Node *GetConnectedSampleOutput() override;
virtual Node *GetConnectedSampleOutput() override;
static rational AdjustTimeByLoopMode(rational time, LoopMode loop_mode, const rational& length, VideoParams::Type type, const rational &timebase);
static rational AdjustTimeByLoopMode(rational time, LoopMode loop_mode,
const rational &length,
VideoParams::Type type,
const rational &timebase);
virtual QVariant data(const DataType &d) const override;
virtual QVariant data(const DataType &d) const override;
virtual int GetTotalStreamCount() const override { return total_stream_count_; }
virtual int GetTotalStreamCount() const override
{
return total_stream_count_;
}
virtual bool LoadCustom(QXmlStreamReader *reader, SerializedData *data) override;
virtual void SaveCustom(QXmlStreamWriter *writer) const override;
virtual bool LoadCustom(QXmlStreamReader *reader,
SerializedData *data) override;
virtual void SaveCustom(QXmlStreamWriter *writer) const override;
static const QString kFilenameInput;
static const QString kFilenameInput;
virtual void AddedToGraphEvent(Project *p) override;
virtual void RemovedFromGraphEvent(Project *p) override;
virtual void AddedToGraphEvent(Project *p) override;
virtual void RemovedFromGraphEvent(Project *p) override;
protected:
virtual void InputValueChangedEvent(const QString &input, int element) override;
virtual void InputValueChangedEvent(const QString &input,
int element) override;
virtual rational VerifyLengthInternal(Track::Type type) const override;
virtual rational VerifyLengthInternal(Track::Type type) const override;
private:
QString GetColorspaceToUse(const VideoParams& params) const;
QString GetColorspaceToUse(const VideoParams &params) const;
void Reprobe();
void Reprobe();
VideoParams MergeVideoStream(const VideoParams &base, const VideoParams &over);
VideoParams MergeVideoStream(const VideoParams &base,
const VideoParams &over);
/**
/**
* @brief Internal timestamp object
*/
qint64 timestamp_;
qint64 timestamp_;
/**
/**
* @brief Internal attached decoder ID
*/
QString decoder_;
QString decoder_;
bool valid_;
bool valid_;
CancelAtom *cancelled_;
CancelAtom *cancelled_;
int total_stream_count_;
int total_stream_count_;
private slots:
void CheckFootage();
void DefaultColorSpaceChanged();
void CheckFootage();
void DefaultColorSpaceChanged();
};
}
+104 -95
View File
@@ -27,134 +27,143 @@
#include "common/xmlutils.h"
#include "node/project/serializer/typeserializer.h"
namespace olive {
namespace olive
{
bool FootageDescription::Load(const QString &filename)
{
// Reset self
*this = FootageDescription();
// Reset self
*this = FootageDescription();
QFile file(filename);
QFile file(filename);
if (file.open(QFile::ReadOnly)) {
QXmlStreamReader reader(&file);
if (file.open(QFile::ReadOnly)) {
QXmlStreamReader reader(&file);
while (XMLReadNextStartElement(&reader)) {
if (reader.name() == QStringLiteral("streamcache")) {
// Default to first version of metadata (which wasn't versioned at all)
unsigned version = 1;
while (XMLReadNextStartElement(&reader)) {
if (reader.name() == QStringLiteral("streamcache")) {
// Default to first version of metadata (which wasn't versioned at all)
unsigned version = 1;
{
XMLAttributeLoop((&reader), attr) {
if (attr.name() == QStringLiteral("version")) {
version = attr.value().toUInt();
}
}
}
{
XMLAttributeLoop((&reader), attr)
{
if (attr.name() == QStringLiteral("version")) {
version = attr.value().toUInt();
}
}
}
if (version != kFootageMetaVersion) {
// If this is a different version, discard so we can probe new data
return false;
}
if (version != kFootageMetaVersion) {
// If this is a different version, discard so we can probe new data
return false;
}
while (XMLReadNextStartElement(&reader)) {
if (reader.name() == QStringLiteral("decoder")) {
decoder_ = reader.readElementText();
} else if (reader.name() == QStringLiteral("streams")) {
{
XMLAttributeLoop((&reader), attr) {
if (attr.name() == QStringLiteral("count")) {
total_stream_count_ = attr.value().toInt();
}
}
}
while (XMLReadNextStartElement(&reader)) {
if (reader.name() == QStringLiteral("decoder")) {
decoder_ = reader.readElementText();
} else if (reader.name() == QStringLiteral("streams")) {
{
XMLAttributeLoop((&reader), attr)
{
if (attr.name() == QStringLiteral("count")) {
total_stream_count_ = attr.value().toInt();
}
}
}
while (XMLReadNextStartElement(&reader)) {
if (reader.name() == QStringLiteral("video")) {
VideoParams vp;
vp.Load(&reader);
AddVideoStream(vp);
} else if (reader.name() == QStringLiteral("audio")) {
AudioParams ap = TypeSerializer::LoadAudioParams(&reader);
AddAudioStream(ap);
} else if (reader.name() == QStringLiteral("subtitle")) {
SubtitleParams sp;
sp.Load(&reader);
AddSubtitleStream(sp);
} else {
reader.skipCurrentElement();
}
}
} else {
reader.skipCurrentElement();
}
}
} else {
reader.skipCurrentElement();
}
}
while (XMLReadNextStartElement(&reader)) {
if (reader.name() == QStringLiteral("video")) {
VideoParams vp;
vp.Load(&reader);
AddVideoStream(vp);
} else if (reader.name() ==
QStringLiteral("audio")) {
AudioParams ap =
TypeSerializer::LoadAudioParams(&reader);
AddAudioStream(ap);
} else if (reader.name() ==
QStringLiteral("subtitle")) {
SubtitleParams sp;
sp.Load(&reader);
AddSubtitleStream(sp);
} else {
reader.skipCurrentElement();
}
}
} else {
reader.skipCurrentElement();
}
}
} else {
reader.skipCurrentElement();
}
}
file.close();
file.close();
if (reader.hasError()) {
qWarning() << "Failed to load footage description for" << filename << reader.errorString();
} else {
return true;
}
}
if (reader.hasError()) {
qWarning() << "Failed to load footage description for" << filename
<< reader.errorString();
} else {
return true;
}
}
return false;
return false;
}
bool FootageDescription::Save(const QString &filename) const
{
QFile file(filename);
QFile file(filename);
if (!file.open(QFile::WriteOnly)) {
return false;
}
if (!file.open(QFile::WriteOnly)) {
return false;
}
QXmlStreamWriter writer(&file);
QXmlStreamWriter writer(&file);
writer.writeStartDocument();
writer.writeStartDocument();
writer.writeStartElement(QStringLiteral("streamcache"));
writer.writeStartElement(QStringLiteral("streamcache"));
writer.writeAttribute(QStringLiteral("version"), QString::number(kFootageMetaVersion));
writer.writeAttribute(QStringLiteral("version"),
QString::number(kFootageMetaVersion));
writer.writeTextElement(QStringLiteral("decoder"), decoder_);
writer.writeTextElement(QStringLiteral("decoder"), decoder_);
writer.writeStartElement(QStringLiteral("streams"));
writer.writeStartElement(QStringLiteral("streams"));
writer.writeAttribute(QStringLiteral("count"), QString::number(total_stream_count_));
writer.writeAttribute(QStringLiteral("count"),
QString::number(total_stream_count_));
foreach (const VideoParams& vp, video_streams_) {
writer.writeStartElement(QStringLiteral("video"));
vp.Save(&writer);
writer.writeEndElement(); // video
}
foreach (const VideoParams &vp, video_streams_) {
writer.writeStartElement(QStringLiteral("video"));
vp.Save(&writer);
writer.writeEndElement(); // video
}
foreach (const AudioParams& ap, audio_streams_) {
writer.writeStartElement(QStringLiteral("audio"));
TypeSerializer::SaveAudioParams(&writer, ap);
writer.writeEndElement(); // audio
}
foreach (const AudioParams &ap, audio_streams_) {
writer.writeStartElement(QStringLiteral("audio"));
TypeSerializer::SaveAudioParams(&writer, ap);
writer.writeEndElement(); // audio
}
foreach (const SubtitleParams& sp, subtitle_streams_) {
writer.writeStartElement(QStringLiteral("subtitle"));
sp.Save(&writer);
writer.writeEndElement(); // audio
}
foreach (const SubtitleParams &sp, subtitle_streams_) {
writer.writeStartElement(QStringLiteral("subtitle"));
sp.Save(&writer);
writer.writeEndElement(); // audio
}
writer.writeEndElement(); // streams
writer.writeEndElement(); // streams
writer.writeEndElement(); // streamcache
writer.writeEndElement(); // streamcache
writer.writeEndDocument();
writer.writeEndDocument();
file.close();
file.close();
return true;
return true;
}
}
+117 -91
View File
@@ -25,128 +25,154 @@
#include "render/subtitleparams.h"
#include "render/videoparams.h"
namespace olive {
class FootageDescription
namespace olive
{
class FootageDescription {
public:
FootageDescription(const QString& decoder = QString()) :
decoder_(decoder),
total_stream_count_(0)
{
}
FootageDescription(const QString &decoder = QString())
: decoder_(decoder)
, total_stream_count_(0)
{
}
bool IsValid() const
{
return !decoder_.isEmpty() && (!video_streams_.isEmpty() || !audio_streams_.isEmpty() || !subtitle_streams_.isEmpty());
}
bool IsValid() const
{
return !decoder_.isEmpty() &&
(!video_streams_.isEmpty() || !audio_streams_.isEmpty() ||
!subtitle_streams_.isEmpty());
}
const QString& decoder() const
{
return decoder_;
}
const QString &decoder() const
{
return decoder_;
}
void AddVideoStream(const VideoParams& video_params)
{
Q_ASSERT(!HasStreamIndex(video_params.stream_index()));
void AddVideoStream(const VideoParams &video_params)
{
Q_ASSERT(!HasStreamIndex(video_params.stream_index()));
video_streams_.append(video_params);
}
video_streams_.append(video_params);
}
void AddAudioStream(const AudioParams& audio_params)
{
Q_ASSERT(!HasStreamIndex(audio_params.stream_index()));
void AddAudioStream(const AudioParams &audio_params)
{
Q_ASSERT(!HasStreamIndex(audio_params.stream_index()));
audio_streams_.append(audio_params);
}
audio_streams_.append(audio_params);
}
void AddSubtitleStream(const SubtitleParams& sub_params)
{
Q_ASSERT(!HasStreamIndex(sub_params.stream_index()));
void AddSubtitleStream(const SubtitleParams &sub_params)
{
Q_ASSERT(!HasStreamIndex(sub_params.stream_index()));
subtitle_streams_.append(sub_params);
}
subtitle_streams_.append(sub_params);
}
Track::Type GetTypeOfStream(int index)
{
if (StreamIsVideo(index)) {
return Track::kVideo;
} else if (StreamIsAudio(index)) {
return Track::kAudio;
} else if (StreamIsSubtitle(index)) {
return Track::kSubtitle;
} else {
return Track::kNone;
}
}
Track::Type GetTypeOfStream(int index)
{
if (StreamIsVideo(index)) {
return Track::kVideo;
} else if (StreamIsAudio(index)) {
return Track::kAudio;
} else if (StreamIsSubtitle(index)) {
return Track::kSubtitle;
} else {
return Track::kNone;
}
}
bool StreamIsVideo(int index) const
{
foreach (const VideoParams& vp, video_streams_) {
if (vp.stream_index() == index) {
return true;
}
}
bool StreamIsVideo(int index) const
{
foreach (const VideoParams &vp, video_streams_) {
if (vp.stream_index() == index) {
return true;
}
}
return false;
}
return false;
}
bool StreamIsAudio(int index) const
{
foreach (const AudioParams& ap, audio_streams_) {
if (ap.stream_index() == index) {
return true;
}
}
bool StreamIsAudio(int index) const
{
foreach (const AudioParams &ap, audio_streams_) {
if (ap.stream_index() == index) {
return true;
}
}
return false;
}
return false;
}
bool StreamIsSubtitle(int index) const
{
foreach (const SubtitleParams& sp, subtitle_streams_) {
if (sp.stream_index() == index) {
return true;
}
}
bool StreamIsSubtitle(int index) const
{
foreach (const SubtitleParams &sp, subtitle_streams_) {
if (sp.stream_index() == index) {
return true;
}
}
return false;
}
return false;
}
bool HasStreamIndex(int index) const
{
return StreamIsVideo(index) || StreamIsAudio(index) || StreamIsSubtitle(index);
}
bool HasStreamIndex(int index) const
{
return StreamIsVideo(index) || StreamIsAudio(index) ||
StreamIsSubtitle(index);
}
int GetStreamCount() const { return total_stream_count_; }
void SetStreamCount(int s) { total_stream_count_ = s; }
int GetStreamCount() const
{
return total_stream_count_;
}
void SetStreamCount(int s)
{
total_stream_count_ = s;
}
bool Load(const QString& filename);
bool Load(const QString &filename);
bool Save(const QString& filename) const;
bool Save(const QString &filename) const;
const QVector<VideoParams>& GetVideoStreams() const { return video_streams_; }
QVector<VideoParams>& GetVideoStreams() { return video_streams_; }
const QVector<VideoParams> &GetVideoStreams() const
{
return video_streams_;
}
QVector<VideoParams> &GetVideoStreams()
{
return video_streams_;
}
const QVector<AudioParams>& GetAudioStreams() const { return audio_streams_; }
QVector<AudioParams>& GetAudioStreams() { return audio_streams_; }
const QVector<AudioParams> &GetAudioStreams() const
{
return audio_streams_;
}
QVector<AudioParams> &GetAudioStreams()
{
return audio_streams_;
}
const QVector<SubtitleParams>& GetSubtitleStreams() const { return subtitle_streams_; }
QVector<SubtitleParams>& GetSubtitleStreams() { return subtitle_streams_; }
const QVector<SubtitleParams> &GetSubtitleStreams() const
{
return subtitle_streams_;
}
QVector<SubtitleParams> &GetSubtitleStreams()
{
return subtitle_streams_;
}
private:
static constexpr unsigned kFootageMetaVersion = 6;
static constexpr unsigned kFootageMetaVersion = 6;
QString decoder_;
QString decoder_;
QVector<VideoParams> video_streams_;
QVector<VideoParams> video_streams_;
QVector<AudioParams> audio_streams_;
QVector<AudioParams> audio_streams_;
QVector<SubtitleParams> subtitle_streams_;
int total_stream_count_;
QVector<SubtitleParams> subtitle_streams_;
int total_stream_count_;
};
}
+114 -104
View File
@@ -26,7 +26,8 @@
#include "ui/icons/icons.h"
#include "timeline/timelineundogeneral.h"
namespace olive {
namespace olive
{
const QString Sequence::kTrackInputFormat = QStringLiteral("track_in_%1");
@@ -34,157 +35,166 @@ const QString Sequence::kTrackInputFormat = QStringLiteral("track_in_%1");
Sequence::Sequence()
{
SetFlag(kIsItem);
SetFlag(kIsItem);
// Create TrackList instances
track_lists_.resize(Track::kCount);
// Create TrackList instances
track_lists_.resize(Track::kCount);
for (int i=0;i<Track::kCount;i++) {
// Create track input
QString track_input_id = kTrackInputFormat.arg(i);
for (int i = 0; i < Track::kCount; i++) {
// Create track input
QString track_input_id = kTrackInputFormat.arg(i);
AddInput(track_input_id, NodeValue::kNone, InputFlags(kInputFlagNotKeyframable | kInputFlagArray | kInputFlagHidden | kInputFlagIgnoreInvalidations));
AddInput(track_input_id, NodeValue::kNone,
InputFlags(kInputFlagNotKeyframable | kInputFlagArray |
kInputFlagHidden | kInputFlagIgnoreInvalidations));
TrackList* list = new TrackList(this, static_cast<Track::Type>(i), track_input_id);
track_lists_.replace(i, list);
connect(list, &TrackList::TrackListChanged, this, &Sequence::UpdateTrackCache);
connect(list, &TrackList::LengthChanged, this, &Sequence::VerifyLength);
connect(list, &TrackList::TrackAdded, this, &Sequence::TrackAdded);
connect(list, &TrackList::TrackRemoved, this, &Sequence::TrackRemoved);
}
TrackList *list =
new TrackList(this, static_cast<Track::Type>(i), track_input_id);
track_lists_.replace(i, list);
connect(list, &TrackList::TrackListChanged, this,
&Sequence::UpdateTrackCache);
connect(list, &TrackList::LengthChanged, this, &Sequence::VerifyLength);
connect(list, &TrackList::TrackAdded, this, &Sequence::TrackAdded);
connect(list, &TrackList::TrackRemoved, this, &Sequence::TrackRemoved);
}
}
void Sequence::add_default_nodes(MultiUndoCommand* command)
void Sequence::add_default_nodes(MultiUndoCommand *command)
{
// Create tracks and connect them to the viewer
UndoCommand* video_track_command = new TimelineAddTrackCommand(track_list(Track::kVideo));
UndoCommand* audio_track_command = new TimelineAddTrackCommand(track_list(Track::kAudio));
// Create tracks and connect them to the viewer
UndoCommand *video_track_command =
new TimelineAddTrackCommand(track_list(Track::kVideo));
UndoCommand *audio_track_command =
new TimelineAddTrackCommand(track_list(Track::kAudio));
if (command) {
command->add_child(video_track_command);
command->add_child(audio_track_command);
} else {
video_track_command->redo_now();
audio_track_command->redo_now();
delete video_track_command;
delete audio_track_command;
}
if (command) {
command->add_child(video_track_command);
command->add_child(audio_track_command);
} else {
video_track_command->redo_now();
audio_track_command->redo_now();
delete video_track_command;
delete audio_track_command;
}
}
QVariant Sequence::data(const DataType &d) const
{
if (d == ICON) {
return icon::Sequence;
}
if (d == ICON) {
return icon::Sequence;
}
return super::data(d);
return super::data(d);
}
QVector<Track *> Sequence::GetUnlockedTracks() const
{
QVector<Track*> tracks = GetTracks();
QVector<Track *> tracks = GetTracks();
for (int i=0;i<tracks.size();i++) {
if (tracks.at(i)->IsLocked()) {
tracks.removeAt(i);
i--;
}
}
for (int i = 0; i < tracks.size(); i++) {
if (tracks.at(i)->IsLocked()) {
tracks.removeAt(i);
i--;
}
}
return tracks;
return tracks;
}
void Sequence::Retranslate()
{
super::Retranslate();
super::Retranslate();
for (int i=0;i<Track::kCount;i++) {
QString input_name;
for (int i = 0; i < Track::kCount; i++) {
QString input_name;
switch (static_cast<Track::Type>(i)) {
case Track::kVideo:
input_name = tr("Video Tracks");
break;
case Track::kAudio:
input_name = tr("Audio Tracks");
break;
case Track::kSubtitle:
input_name = tr("Subtitle Tracks");
break;
case Track::kNone:
case Track::kCount:
break;
}
switch (static_cast<Track::Type>(i)) {
case Track::kVideo:
input_name = tr("Video Tracks");
break;
case Track::kAudio:
input_name = tr("Audio Tracks");
break;
case Track::kSubtitle:
input_name = tr("Subtitle Tracks");
break;
case Track::kNone:
case Track::kCount:
break;
}
if (!input_name.isEmpty()) {
SetInputName(kTrackInputFormat.arg(i), input_name);
}
}
if (!input_name.isEmpty()) {
SetInputName(kTrackInputFormat.arg(i), input_name);
}
}
}
void Sequence::InvalidateCache(const TimeRange &range, const QString &from, int element, InvalidateCacheOptions options)
void Sequence::InvalidateCache(const TimeRange &range, const QString &from,
int element, InvalidateCacheOptions options)
{
if (from == kTrackInputFormat.arg(Track::kSubtitle)) {
emit SubtitlesChanged(range);
}
if (from == kTrackInputFormat.arg(Track::kSubtitle)) {
emit SubtitlesChanged(range);
}
super::InvalidateCache(range, from, element, options);
super::InvalidateCache(range, from, element, options);
}
rational Sequence::VerifyLengthInternal(Track::Type type) const
{
if (!track_lists_.isEmpty()) {
switch (type) {
case Track::kVideo:
return track_lists_.at(Track::kVideo)->GetTotalLength();
case Track::kAudio:
return track_lists_.at(Track::kAudio)->GetTotalLength();
case Track::kSubtitle:
return track_lists_.at(Track::kSubtitle)->GetTotalLength();
case Track::kNone:
case Track::kCount:
break;
}
}
if (!track_lists_.isEmpty()) {
switch (type) {
case Track::kVideo:
return track_lists_.at(Track::kVideo)->GetTotalLength();
case Track::kAudio:
return track_lists_.at(Track::kAudio)->GetTotalLength();
case Track::kSubtitle:
return track_lists_.at(Track::kSubtitle)->GetTotalLength();
case Track::kNone:
case Track::kCount:
break;
}
}
return 0;
return 0;
}
void Sequence::InputConnectedEvent(const QString &input, int element, Node *output)
void Sequence::InputConnectedEvent(const QString &input, int element,
Node *output)
{
foreach (TrackList* list, track_lists_) {
if (list->track_input() == input) {
// Return because we found our input
list->TrackConnected(output, element);
return;
}
}
foreach (TrackList *list, track_lists_) {
if (list->track_input() == input) {
// Return because we found our input
list->TrackConnected(output, element);
return;
}
}
super::InputConnectedEvent(input, element, output);
super::InputConnectedEvent(input, element, output);
}
void Sequence::InputDisconnectedEvent(const QString &input, int element, Node *output)
void Sequence::InputDisconnectedEvent(const QString &input, int element,
Node *output)
{
foreach (TrackList* list, track_lists_) {
if (list->track_input() == input) {
// Return because we found our input
list->TrackDisconnected(output, element);
return;
}
}
foreach (TrackList *list, track_lists_) {
if (list->track_input() == input) {
// Return because we found our input
list->TrackDisconnected(output, element);
return;
}
}
super::InputDisconnectedEvent(input, element, output);
super::InputDisconnectedEvent(input, element, output);
}
void Sequence::UpdateTrackCache()
{
track_cache_.clear();
track_cache_.clear();
foreach (TrackList* list, track_lists_) {
foreach (Track* track, list->GetTracks()) {
track_cache_.append(track);
}
}
foreach (TrackList *list, track_lists_) {
foreach (Track *track, list->GetTracks()) {
track_cache_.append(track);
}
}
}
}
+55 -51
View File
@@ -24,90 +24,94 @@
#include "node/output/track/tracklist.h"
#include "node/output/viewer/viewer.h"
namespace olive {
namespace olive
{
/**
* @brief The main timeline object, an graph of edited clips that forms a complete edit
*/
class Sequence : public ViewerOutput
{
Q_OBJECT
class Sequence : public ViewerOutput {
Q_OBJECT
public:
Sequence();
Sequence();
NODE_DEFAULT_FUNCTIONS(Sequence)
NODE_DEFAULT_FUNCTIONS(Sequence)
virtual QString Name() const override
{
return tr("Sequence");
}
virtual QString Name() const override
{
return tr("Sequence");
}
virtual QString id() const override
{
return QStringLiteral("org.olivevideoeditor.Olive.sequence");
}
virtual QString id() const override
{
return QStringLiteral("org.olivevideoeditor.Olive.sequence");
}
virtual QVector<CategoryID> Category() const override
{
return {kCategoryProject};
}
virtual QVector<CategoryID> Category() const override
{
return { kCategoryProject };
}
virtual QString Description() const override
{
return tr("A series of cuts that result in an edited video. Also called a timeline.");
}
virtual QString Description() const override
{
return tr(
"A series of cuts that result in an edited video. Also called a timeline.");
}
void add_default_nodes(MultiUndoCommand *command = nullptr);
void add_default_nodes(MultiUndoCommand *command = nullptr);
virtual QVariant data(const DataType &d) const override;
virtual QVariant data(const DataType &d) const override;
const QVector<Track *> &GetTracks() const
{
return track_cache_;
}
const QVector<Track *> &GetTracks() const
{
return track_cache_;
}
Track* GetTrackFromReference(const Track::Reference& track_ref) const
{
return track_lists_.at(track_ref.type())->GetTrackAt(track_ref.index());
}
Track *GetTrackFromReference(const Track::Reference &track_ref) const
{
return track_lists_.at(track_ref.type())->GetTrackAt(track_ref.index());
}
/**
/**
* @brief Same as GetTracks() but omits tracks that are locked.
*/
QVector<Track *> GetUnlockedTracks() const;
QVector<Track *> GetUnlockedTracks() const;
TrackList* track_list(Track::Type type) const
{
return track_lists_.at(type);
}
TrackList *track_list(Track::Type type) const
{
return track_lists_.at(type);
}
virtual void Retranslate() override;
virtual void Retranslate() override;
virtual void InvalidateCache(const TimeRange& range, const QString& from, int element, InvalidateCacheOptions options) override;
virtual void InvalidateCache(const TimeRange &range, const QString &from,
int element,
InvalidateCacheOptions options) override;
static const QString kTrackInputFormat;
static const QString kTrackInputFormat;
protected:
virtual void InputConnectedEvent(const QString &input, int element, Node *output) override;
virtual void InputConnectedEvent(const QString &input, int element,
Node *output) override;
virtual void InputDisconnectedEvent(const QString &input, int element, Node *output) override;
virtual void InputDisconnectedEvent(const QString &input, int element,
Node *output) override;
virtual rational VerifyLengthInternal(Track::Type type) const override;
virtual rational VerifyLengthInternal(Track::Type type) const override;
signals:
void TrackAdded(Track* track);
void TrackRemoved(Track* track);
void TrackAdded(Track *track);
void TrackRemoved(Track *track);
void SubtitlesChanged(const TimeRange &range);
void SubtitlesChanged(const TimeRange &range);
private:
QVector<TrackList*> track_lists_;
QVector<TrackList *> track_lists_;
QVector<Track*> track_cache_;
QVector<Track *> track_cache_;
private slots:
void UpdateTrackCache();
void UpdateTrackCache();
};
}
+214 -189
View File
@@ -34,274 +34,299 @@
#include "serializer220403.h"
#include "serializer230220.h"
namespace olive {
namespace olive
{
QVector<ProjectSerializer*> ProjectSerializer::instances_;
QVector<ProjectSerializer *> ProjectSerializer::instances_;
void ProjectSerializer::Initialize()
{
// Make sure to order these from oldest to newest
// Make sure to order these from oldest to newest
// FIXME: Implement this - yes it's a 0.1 project loader
//instances_.append(new ProjectSerializer190219);
// FIXME: Implement this - yes it's a 0.1 project loader
//instances_.append(new ProjectSerializer190219);
instances_.append(new ProjectSerializer210528);
instances_.append(new ProjectSerializer210907);
instances_.append(new ProjectSerializer211228);
instances_.append(new ProjectSerializer220403);
instances_.append(new ProjectSerializer230220);
instances_.append(new ProjectSerializer210528);
instances_.append(new ProjectSerializer210907);
instances_.append(new ProjectSerializer211228);
instances_.append(new ProjectSerializer220403);
instances_.append(new ProjectSerializer230220);
}
void ProjectSerializer::Destroy()
{
qDeleteAll(instances_);
instances_.clear();
qDeleteAll(instances_);
instances_.clear();
}
ProjectSerializer::Result ProjectSerializer::Load(Project *project, const QString &filename, LoadType load_type)
ProjectSerializer::Result ProjectSerializer::Load(Project *project,
const QString &filename,
LoadType load_type)
{
QFile project_file(filename);
QFile project_file(filename);
if (project_file.open(QFile::ReadOnly)) {
// Some project files are compressed, marked with "OVEC" at the beginning of the file. Check for
// that signature now.
std::unique_ptr<QXmlStreamReader> reader;
if (CheckCompressedID(&project_file)) {
// File is compressed, decompress into memory
QByteArray b;
b = qUncompress(project_file.readAll());
reader.reset(new QXmlStreamReader(b));
} else {
project_file.seek(0);
reader.reset(new QXmlStreamReader(&project_file));
}
if (project_file.open(QFile::ReadOnly)) {
// Some project files are compressed, marked with "OVEC" at the beginning of the file. Check for
// that signature now.
std::unique_ptr<QXmlStreamReader> reader;
if (CheckCompressedID(&project_file)) {
// File is compressed, decompress into memory
QByteArray b;
b = qUncompress(project_file.readAll());
reader.reset(new QXmlStreamReader(b));
} else {
project_file.seek(0);
reader.reset(new QXmlStreamReader(&project_file));
}
Result inner_result = Load(project, reader.get(), load_type);
Result inner_result = Load(project, reader.get(), load_type);
project_file.close();
project_file.close();
if (inner_result.code() != kSuccess) {
return inner_result;
}
if (inner_result.code() != kSuccess) {
return inner_result;
}
if (reader->hasError()) {
Result r(kXmlError);
r.SetDetails(reader->errorString());
return r;
} else {
return inner_result;
}
} else {
return kFileError;
}
if (reader->hasError()) {
Result r(kXmlError);
r.SetDetails(reader->errorString());
return r;
} else {
return inner_result;
}
} else {
return kFileError;
}
}
ProjectSerializer::Result ProjectSerializer::Load(Project *project, QXmlStreamReader *reader, LoadType load_type)
ProjectSerializer::Result ProjectSerializer::Load(Project *project,
QXmlStreamReader *reader,
LoadType load_type)
{
// Determine project version
uint version = 0;
Result res = kUnknownVersion;
// Determine project version
uint version = 0;
Result res = kUnknownVersion;
while (XMLReadNextStartElement(reader)) {
if (reader->name() == QStringLiteral("olive")
|| reader->name() == QStringLiteral("project")) { // 0.1 projects only
while (XMLReadNextStartElement(reader)) {
if (reader->name() == QStringLiteral("olive") ||
reader->name() == QStringLiteral("project")) { // 0.1 projects only
XMLAttributeLoop(reader, attr) {
if (attr.name() == QStringLiteral("version")) { // 230220+ projects
version = attr.value().toUInt();
} else if (reader->name() == QStringLiteral("url")) { // 230220+ projects
project->SetSavedURL(attr.value().toString());
}
}
XMLAttributeLoop(reader, attr)
{
if (attr.name() ==
QStringLiteral("version")) { // 230220+ projects
version = attr.value().toUInt();
} else if (reader->name() ==
QStringLiteral("url")) { // 230220+ projects
project->SetSavedURL(attr.value().toString());
}
}
while (XMLReadNextStartElement(reader)) {
if (reader->name() == QStringLiteral("version")) { // projects <= 220403
version = reader->readElementText().toUInt();
} else if (reader->name() == QStringLiteral("url")) { // projects <= 220403
if (project) {
project->SetSavedURL(reader->readElementText());
} else {
reader->skipCurrentElement();
}
} else {
// Handle any other value with the serializer
res = LoadWithSerializerVersion(version, project, reader, load_type);
}
}
} else {
reader->skipCurrentElement();
}
}
while (XMLReadNextStartElement(reader)) {
if (reader->name() ==
QStringLiteral("version")) { // projects <= 220403
version = reader->readElementText().toUInt();
} else if (reader->name() ==
QStringLiteral("url")) { // projects <= 220403
if (project) {
project->SetSavedURL(reader->readElementText());
} else {
reader->skipCurrentElement();
}
} else {
// Handle any other value with the serializer
res = LoadWithSerializerVersion(version, project, reader,
load_type);
}
}
} else {
reader->skipCurrentElement();
}
}
return res;
return res;
}
ProjectSerializer::Result ProjectSerializer::Paste(LoadType load_type, Project *project)
ProjectSerializer::Result ProjectSerializer::Paste(LoadType load_type,
Project *project)
{
QString clipboard = Core::PasteStringFromClipboard();
if (clipboard.isEmpty()) {
return kNoData;
}
QString clipboard = Core::PasteStringFromClipboard();
if (clipboard.isEmpty()) {
return kNoData;
}
QXmlStreamReader reader(clipboard);
QXmlStreamReader reader(clipboard);
return ProjectSerializer::Load(project, &reader, load_type);
return ProjectSerializer::Load(project, &reader, load_type);
}
ProjectSerializer::Result ProjectSerializer::Save(const SaveData &data, bool compress)
ProjectSerializer::Result ProjectSerializer::Save(const SaveData &data,
bool compress)
{
QString temp_save = FileFunctions::GetSafeTemporaryFilename(data.GetFilename());
QString temp_save =
FileFunctions::GetSafeTemporaryFilename(data.GetFilename());
QFile project_file(temp_save);
QFile project_file(temp_save);
if (project_file.open(QFile::WriteOnly)) {
QByteArray b;
QXmlStreamWriter writer(&b);
if (project_file.open(QFile::WriteOnly)) {
QByteArray b;
QXmlStreamWriter writer(&b);
Result inner_result = Save(&writer, data);
Result inner_result = Save(&writer, data);
if (writer.hasError()) {
Result r(kXmlError);
return r;
}
if (writer.hasError()) {
Result r(kXmlError);
return r;
}
if (compress) {
project_file.write("OVEC");
project_file.write(qCompress(b));
} else {
project_file.write(b);
}
if (compress) {
project_file.write("OVEC");
project_file.write(qCompress(b));
} else {
project_file.write(b);
}
project_file.close();
project_file.close();
if (inner_result != kSuccess) {
return inner_result;
}
if (inner_result != kSuccess) {
return inner_result;
}
// Save was successful, we can now rewrite the original file
if (FileFunctions::RenameFileAllowOverwrite(temp_save, data.GetFilename())) {
return kSuccess;
} else {
Result r(kOverwriteError);
r.SetDetails(temp_save);
return r;
}
} else {
Result r(kFileError);
r.SetDetails(temp_save);
return r;
}
// Save was successful, we can now rewrite the original file
if (FileFunctions::RenameFileAllowOverwrite(temp_save,
data.GetFilename())) {
return kSuccess;
} else {
Result r(kOverwriteError);
r.SetDetails(temp_save);
return r;
}
} else {
Result r(kFileError);
r.SetDetails(temp_save);
return r;
}
}
ProjectSerializer::Result ProjectSerializer::Save(QXmlStreamWriter *writer, const SaveData &data)
ProjectSerializer::Result ProjectSerializer::Save(QXmlStreamWriter *writer,
const SaveData &data)
{
writer->setAutoFormatting(true);
writer->setAutoFormatting(true);
writer->writeStartDocument();
writer->writeStartDocument();
writer->writeStartElement("olive");
writer->writeStartElement("olive");
// By default, save as last serializer which, assuming the instances are ordered correctly,
// will be the newest file format. But we may allow saving as older versions later on.
ProjectSerializer *serializer = instances_.last();
// By default, save as last serializer which, assuming the instances are ordered correctly,
// will be the newest file format. But we may allow saving as older versions later on.
ProjectSerializer *serializer = instances_.last();
// Version is stored in YYMMDD from whenever the project format was last changed
// Allows easy integer math for checking project versions.
writer->writeAttribute(QStringLiteral("version"), QString::number(serializer->Version()));
// Version is stored in YYMMDD from whenever the project format was last changed
// Allows easy integer math for checking project versions.
writer->writeAttribute(QStringLiteral("version"),
QString::number(serializer->Version()));
if (!data.GetFilename().isEmpty()) {
writer->writeAttribute("url", data.GetFilename());
}
if (!data.GetFilename().isEmpty()) {
writer->writeAttribute("url", data.GetFilename());
}
serializer->Save(writer, data, nullptr);
serializer->Save(writer, data, nullptr);
writer->writeEndElement(); // olive
writer->writeEndElement(); // olive
writer->writeEndDocument();
writer->writeEndDocument();
if (writer->hasError()) {
return kXmlError;
}
if (writer->hasError()) {
return kXmlError;
}
return kSuccess;
return kSuccess;
}
ProjectSerializer::Result ProjectSerializer::Copy(const SaveData &data)
{
QString copy_str;
QXmlStreamWriter writer(&copy_str);
QString copy_str;
QXmlStreamWriter writer(&copy_str);
ProjectSerializer::Result res = ProjectSerializer::Save(&writer, data);
ProjectSerializer::Result res = ProjectSerializer::Save(&writer, data);
if (res == kSuccess) {
Core::CopyStringToClipboard(copy_str);
}
if (res == kSuccess) {
Core::CopyStringToClipboard(copy_str);
}
return res;
return res;
}
bool ProjectSerializer::CheckCompressedID(QFile *file)
{
QByteArray b = file->read(4);
return !memcmp(b.data(), "OVEC", 4);
QByteArray b = file->read(4);
return !memcmp(b.data(), "OVEC", 4);
}
bool ProjectSerializer::IsCancelled() const
{
return false;
return false;
}
ProjectSerializer::Result ProjectSerializer::LoadWithSerializerVersion(uint version, Project *project, QXmlStreamReader *reader, LoadType load_type)
ProjectSerializer::Result
ProjectSerializer::LoadWithSerializerVersion(uint version, Project *project,
QXmlStreamReader *reader,
LoadType load_type)
{
// Failed to find version in file
if (version == 0) {
return kUnknownVersion;
}
// Failed to find version in file
if (version == 0) {
return kUnknownVersion;
}
// We should now have the version, if we have a serializer for it, use it to load the project
ProjectSerializer *serializer = nullptr;
// We should now have the version, if we have a serializer for it, use it to load the project
ProjectSerializer *serializer = nullptr;
foreach (ProjectSerializer *s, instances_) {
if (version == s->Version()) {
serializer = s;
break;
} else if (version < s->Version()) {
// Assuming the instance list is in order, if the project version is less than any version
// we find, we must not support it anymore
return kProjectTooOld;
}
}
foreach (ProjectSerializer *s, instances_) {
if (version == s->Version()) {
serializer = s;
break;
} else if (version < s->Version()) {
// Assuming the instance list is in order, if the project version is less than any version
// we find, we must not support it anymore
return kProjectTooOld;
}
}
if (serializer) {
LoadData ld = serializer->Load(project, reader, load_type, nullptr);
Result r(kSuccess);
if (reader->hasError()) {
r = Result(kXmlError);
r.SetDetails(QCoreApplication::translate("Serializer", "%1 on line %2").arg(reader->errorString(), QString::number(reader->lineNumber())));
}
r.SetLoadData(ld);
return r;
} else {
// Reached the end of the list with no serializer, assume too new
return kProjectTooNew;
}
if (serializer) {
LoadData ld = serializer->Load(project, reader, load_type, nullptr);
Result r(kSuccess);
if (reader->hasError()) {
r = Result(kXmlError);
r.SetDetails(
QCoreApplication::translate("Serializer", "%1 on line %2")
.arg(reader->errorString(),
QString::number(reader->lineNumber())));
}
r.SetLoadData(ld);
return r;
} else {
// Reached the end of the list with no serializer, assume too new
return kProjectTooNew;
}
}
void ProjectSerializer::SaveData::SetOnlySerializeNodesAndResolveGroups(QVector<Node *> nodes)
void ProjectSerializer::SaveData::SetOnlySerializeNodesAndResolveGroups(
QVector<Node *> nodes)
{
// For any groups, add children
for (int i=0; i<nodes.size(); i++) {
// If this is a group, add the child nodes too
if (NodeGroup *g = dynamic_cast<NodeGroup*>(nodes.at(i))) {
for (auto it=g->GetContextPositions().cbegin(); it!=g->GetContextPositions().cend(); it++) {
if (!nodes.contains(it.key())) {
nodes.append(it.key());
}
}
}
}
// For any groups, add children
for (int i = 0; i < nodes.size(); i++) {
// If this is a group, add the child nodes too
if (NodeGroup *g = dynamic_cast<NodeGroup *>(nodes.at(i))) {
for (auto it = g->GetContextPositions().cbegin();
it != g->GetContextPositions().cend(); it++) {
if (!nodes.contains(it.key())) {
nodes.append(it.key());
}
}
}
}
SetOnlySerializeNodes(nodes);
SetOnlySerializeNodes(nodes);
}
}
+179 -109
View File
@@ -27,7 +27,8 @@
#include "node/project.h"
#include "typeserializer.h"
namespace olive {
namespace olive
{
/**
* @brief An abstract base class for serializing/deserializing project data
@@ -35,167 +36,236 @@ namespace olive {
* The goal of this is to further abstract serialized project data from their
* in-memory representations.
*/
class ProjectSerializer
{
class ProjectSerializer {
public:
enum LoadType
{
kProject,
kOnlyNodes,
kOnlyClips,
kOnlyMarkers,
kOnlyKeyframes
};
enum LoadType {
kProject,
kOnlyNodes,
kOnlyClips,
kOnlyMarkers,
kOnlyKeyframes
};
ProjectSerializer() = default;
ProjectSerializer() = default;
virtual ~ProjectSerializer(){}
virtual ~ProjectSerializer()
{
}
DISABLE_COPY_MOVE(ProjectSerializer)
DISABLE_COPY_MOVE(ProjectSerializer)
enum ResultCode {
kSuccess,
kProjectTooOld,
kProjectTooNew,
kUnknownVersion,
kFileError,
kXmlError,
kOverwriteError,
kNoData
};
enum ResultCode {
kSuccess,
kProjectTooOld,
kProjectTooNew,
kUnknownVersion,
kFileError,
kXmlError,
kOverwriteError,
kNoData
};
using SerializedProperties = QHash<Node*, QMap<QString, QString> >;
using SerializedKeyframes = QHash<QString, QVector<NodeKeyframe*> >;
using SerializedProperties = QHash<Node *, QMap<QString, QString>>;
using SerializedKeyframes = QHash<QString, QVector<NodeKeyframe *>>;
class LoadData
{
public:
LoadData() = default;
class LoadData {
public:
LoadData() = default;
SerializedProperties properties;
SerializedProperties properties;
std::vector<TimelineMarker*> markers;
std::vector<TimelineMarker *> markers;
SerializedKeyframes keyframes;
SerializedKeyframes keyframes;
MainWindowLayoutInfo layout;
MainWindowLayoutInfo layout;
QVector<Node*> nodes;
QVector<Node *> nodes;
Node::OutputConnections promised_connections;
Node::OutputConnections promised_connections;
};
};
class Result {
public:
Result(const ResultCode &code)
: code_(code)
{
}
class Result
{
public:
Result(const ResultCode &code) :
code_(code)
{}
bool operator==(const ResultCode &code)
{
return code_ == code;
}
bool operator!=(const ResultCode &code)
{
return code_ != code;
}
bool operator==(const ResultCode &code) { return code_ == code; }
bool operator!=(const ResultCode &code) { return code_ != code; }
const ResultCode &code() const
{
return code_;
}
const ResultCode &code() const { return code_; }
const QString &GetDetails() const
{
return details_;
}
const QString &GetDetails() const { return details_; }
void SetDetails(const QString &s)
{
details_ = s;
}
void SetDetails(const QString &s) { details_ = s; }
const LoadData &GetLoadData() const
{
return load_data_;
}
const LoadData &GetLoadData() const { return load_data_; }
void SetLoadData(const LoadData &p)
{
load_data_ = p;
}
void SetLoadData(const LoadData &p) { load_data_ = p; }
private:
ResultCode code_;
private:
ResultCode code_;
QString details_;
QString details_;
LoadData load_data_;
};
LoadData load_data_;
class SaveData {
public:
SaveData(LoadType type, Project *project = nullptr,
const QString &filename = QString())
{
type_ = type;
project_ = project;
filename_ = filename;
}
};
Project *GetProject() const
{
return project_;
}
void SetProject(Project *p)
{
project_ = p;
}
class SaveData
{
public:
SaveData(LoadType type, Project *project = nullptr, const QString &filename = QString())
{
type_ = type;
project_ = project;
filename_ = filename;
}
const QString &GetFilename() const
{
return filename_;
}
void SetFilename(const QString &s)
{
filename_ = s;
}
Project *GetProject() const { return project_; }
void SetProject(Project *p) { project_ = p; }
LoadType type() const
{
return type_;
}
const QString &GetFilename() const { return filename_; }
void SetFilename(const QString &s) { filename_ = s; }
const MainWindowLayoutInfo &GetLayout() const
{
return layout_;
}
void SetLayout(const MainWindowLayoutInfo &layout)
{
layout_ = layout;
}
LoadType type() const { return type_; }
const QVector<Node *> &GetOnlySerializeNodes() const
{
return only_serialize_nodes_;
}
void SetOnlySerializeNodes(const QVector<Node *> &only)
{
only_serialize_nodes_ = only;
}
void SetOnlySerializeNodesAndResolveGroups(QVector<Node *> only);
const MainWindowLayoutInfo &GetLayout() const { return layout_; }
void SetLayout(const MainWindowLayoutInfo &layout) { layout_ = layout; }
const std::vector<TimelineMarker *> &GetOnlySerializeMarkers() const
{
return only_serialize_markers_;
}
void SetOnlySerializeMarkers(const std::vector<TimelineMarker *> &only)
{
only_serialize_markers_ = only;
}
const QVector<Node*> &GetOnlySerializeNodes() const { return only_serialize_nodes_; }
void SetOnlySerializeNodes(const QVector<Node*> &only) { only_serialize_nodes_ = only; }
void SetOnlySerializeNodesAndResolveGroups(QVector<Node*> only);
const std::vector<NodeKeyframe *> &GetOnlySerializeKeyframes() const
{
return only_serialize_keyframes_;
}
void SetOnlySerializeKeyframes(const std::vector<NodeKeyframe *> &only)
{
only_serialize_keyframes_ = only;
}
const std::vector<TimelineMarker*> &GetOnlySerializeMarkers() const { return only_serialize_markers_; }
void SetOnlySerializeMarkers(const std::vector<TimelineMarker*> &only) { only_serialize_markers_ = only; }
const SerializedProperties &GetProperties() const
{
return properties_;
}
void SetProperties(const SerializedProperties &p)
{
properties_ = p;
}
const std::vector<NodeKeyframe*> &GetOnlySerializeKeyframes() const { return only_serialize_keyframes_; }
void SetOnlySerializeKeyframes(const std::vector<NodeKeyframe*> &only) { only_serialize_keyframes_ = only; }
private:
LoadType type_;
const SerializedProperties &GetProperties() const { return properties_; }
void SetProperties(const SerializedProperties &p) { properties_ = p; }
Project *project_;
private:
LoadType type_;
QString filename_;
Project *project_;
MainWindowLayoutInfo layout_;
QString filename_;
QVector<Node *> only_serialize_nodes_;
MainWindowLayoutInfo layout_;
SerializedProperties properties_;
QVector<Node*> only_serialize_nodes_;
std::vector<TimelineMarker *> only_serialize_markers_;
SerializedProperties properties_;
std::vector<NodeKeyframe *> only_serialize_keyframes_;
};
std::vector<TimelineMarker*> only_serialize_markers_;
static void Initialize();
std::vector<NodeKeyframe*> only_serialize_keyframes_;
static void Destroy();
};
static Result Load(Project *project, const QString &filename,
LoadType load_type);
static Result Load(Project *project, QXmlStreamReader *read_device,
LoadType load_type);
static Result Paste(LoadType load_type, Project *project = nullptr);
static void Initialize();
static Result Save(const SaveData &data, bool compress);
static Result Save(QXmlStreamWriter *write_device, const SaveData &data);
static Result Copy(const SaveData &data);
static void Destroy();
static Result Load(Project *project, const QString &filename, LoadType load_type);
static Result Load(Project *project, QXmlStreamReader *read_device, LoadType load_type);
static Result Paste(LoadType load_type, Project *project = nullptr);
static Result Save(const SaveData &data, bool compress);
static Result Save(QXmlStreamWriter *write_device, const SaveData &data);
static Result Copy(const SaveData &data);
static bool CheckCompressedID(QFile *file);
static bool CheckCompressedID(QFile *file);
protected:
virtual LoadData Load(Project *project, QXmlStreamReader *reader, LoadType load_type, void *reserved) const = 0;
virtual LoadData Load(Project *project, QXmlStreamReader *reader,
LoadType load_type, void *reserved) const = 0;
virtual void Save(QXmlStreamWriter *writer, const SaveData &data, void *reserved) const {}
virtual void Save(QXmlStreamWriter *writer, const SaveData &data,
void *reserved) const
{
}
virtual uint Version() const = 0;
virtual uint Version() const = 0;
bool IsCancelled() const;
bool IsCancelled() const;
private:
static Result LoadWithSerializerVersion(uint version, Project *project, QXmlStreamReader *reader, LoadType load_type);
static QVector<ProjectSerializer*> instances_;
static Result LoadWithSerializerVersion(uint version, Project *project,
QXmlStreamReader *reader,
LoadType load_type);
static QVector<ProjectSerializer *> instances_;
};
}
@@ -20,11 +20,14 @@
#include "serializer190219.h"
namespace olive {
ProjectSerializer::LoadData ProjectSerializer190219::Load(Project *project, QXmlStreamReader *reader, LoadType load_type, void *reserved) const
namespace olive
{
return LoadData();
ProjectSerializer::LoadData
ProjectSerializer190219::Load(Project *project, QXmlStreamReader *reader,
LoadType load_type, void *reserved) const
{
return LoadData();
}
}
+10 -10
View File
@@ -23,21 +23,21 @@
#include "serializer.h"
namespace olive {
class ProjectSerializer190219 : public ProjectSerializer
namespace olive
{
class ProjectSerializer190219 : public ProjectSerializer {
public:
ProjectSerializer190219() = default;
ProjectSerializer190219() = default;
protected:
virtual LoadData Load(Project *project, QXmlStreamReader *reader, LoadType load_type, void *reserved) const override;
virtual uint Version() const override
{
return 190219;
}
virtual LoadData Load(Project *project, QXmlStreamReader *reader,
LoadType load_type, void *reserved) const override;
virtual uint Version() const override
{
return 190219;
}
};
}
File diff suppressed because it is too large Load Diff
+53 -45
View File
@@ -23,73 +23,81 @@
#include "serializer.h"
namespace olive {
class ProjectSerializer210528 : public ProjectSerializer
namespace olive
{
class ProjectSerializer210528 : public ProjectSerializer {
public:
ProjectSerializer210528() = default;
ProjectSerializer210528() = default;
protected:
virtual LoadData Load(Project *project, QXmlStreamReader *reader, LoadType load_type, void *reserved) const override;
virtual LoadData Load(Project *project, QXmlStreamReader *reader,
LoadType load_type, void *reserved) const override;
virtual uint Version() const override
{
return 210528;
}
virtual uint Version() const override
{
return 210528;
}
private:
struct XMLNodeData {
struct SerializedConnection {
NodeInput input;
quintptr output_node;
QString output_param;
};
struct XMLNodeData {
struct SerializedConnection {
NodeInput input;
quintptr output_node;
QString output_param;
};
struct BlockLink {
Node* block;
quintptr link;
};
struct BlockLink {
Node *block;
quintptr link;
};
struct GroupLink {
NodeGroup *group;
quintptr input_node;
QString input_id;
int input_element;
};
struct GroupLink {
NodeGroup *group;
quintptr input_node;
QString input_id;
int input_element;
};
QHash<quintptr, Node*> node_ptrs;
QList<SerializedConnection> desired_connections;
QList<BlockLink> block_links;
QVector<GroupLink> group_input_links;
QHash<NodeGroup*, quintptr> group_output_links;
QHash<quintptr, Node *> node_ptrs;
QList<SerializedConnection> desired_connections;
QList<BlockLink> block_links;
QVector<GroupLink> group_input_links;
QHash<NodeGroup *, quintptr> group_output_links;
};
};
void LoadNode(Node *node, XMLNodeData &xml_node_data,
QXmlStreamReader *reader) const;
void LoadNode(Node *node, XMLNodeData &xml_node_data, QXmlStreamReader *reader) const;
void LoadColorManager(QXmlStreamReader *reader, Project *project) const;
void LoadColorManager(QXmlStreamReader* reader, Project *project) const;
void LoadProjectSettings(QXmlStreamReader *reader, Project *project) const;
void LoadProjectSettings(QXmlStreamReader* reader, Project *project) const;
void LoadInput(Node *node, QXmlStreamReader *reader,
XMLNodeData &xml_node_data) const;
void LoadInput(Node *node, QXmlStreamReader* reader, XMLNodeData &xml_node_data) const;
void LoadImmediate(QXmlStreamReader *reader, Node *node,
const QString &input, int element,
XMLNodeData &xml_node_data) const;
void LoadImmediate(QXmlStreamReader *reader, Node *node, const QString& input, int element, XMLNodeData& xml_node_data) const;
bool LoadPosition(QXmlStreamReader *reader, quintptr *node_ptr,
Node::Position *pos) const;
bool LoadPosition(QXmlStreamReader *reader, quintptr *node_ptr, Node::Position *pos) const;
void PostConnect(const XMLNodeData &xml_node_data) const;
void PostConnect(const XMLNodeData &xml_node_data) const;
void LoadNodeCustom(QXmlStreamReader *reader, Node *node,
XMLNodeData &xml_node_data) const;
void LoadNodeCustom(QXmlStreamReader *reader, Node *node, XMLNodeData &xml_node_data) const;
void LoadTimelinePoints(QXmlStreamReader *reader,
ViewerOutput *points) const;
void LoadTimelinePoints(QXmlStreamReader *reader, ViewerOutput *points) const;
void LoadWorkArea(QXmlStreamReader *reader,
TimelineWorkArea *workarea) const;
void LoadWorkArea(QXmlStreamReader *reader, TimelineWorkArea *workarea) const;
void LoadMarkerList(QXmlStreamReader *reader, TimelineMarkerList *markers) const;
void LoadValueHint(Node::ValueHint *hint, QXmlStreamReader *reader) const;
void LoadMarkerList(QXmlStreamReader *reader,
TimelineMarkerList *markers) const;
void LoadValueHint(Node::ValueHint *hint, QXmlStreamReader *reader) const;
};
}
File diff suppressed because it is too large Load Diff
+52 -44
View File
@@ -23,72 +23,80 @@
#include "serializer.h"
namespace olive {
class ProjectSerializer210907 : public ProjectSerializer
namespace olive
{
class ProjectSerializer210907 : public ProjectSerializer {
public:
ProjectSerializer210907() = default;
ProjectSerializer210907() = default;
protected:
virtual LoadData Load(Project *project, QXmlStreamReader *reader, LoadType load_type, void *reserved) const override;
virtual LoadData Load(Project *project, QXmlStreamReader *reader,
LoadType load_type, void *reserved) const override;
virtual uint Version() const override
{
return 210907;
}
virtual uint Version() const override
{
return 210907;
}
private:
struct XMLNodeData {
struct SerializedConnection {
NodeInput input;
quintptr output_node;
};
struct XMLNodeData {
struct SerializedConnection {
NodeInput input;
quintptr output_node;
};
struct BlockLink {
Node* block;
quintptr link;
};
struct BlockLink {
Node *block;
quintptr link;
};
struct GroupLink {
NodeGroup *group;
quintptr input_node;
QString input_id;
int input_element;
};
struct GroupLink {
NodeGroup *group;
quintptr input_node;
QString input_id;
int input_element;
};
QHash<quintptr, Node*> node_ptrs;
QList<SerializedConnection> desired_connections;
QList<BlockLink> block_links;
QVector<GroupLink> group_input_links;
QHash<NodeGroup*, quintptr> group_output_links;
QHash<quintptr, Node *> node_ptrs;
QList<SerializedConnection> desired_connections;
QList<BlockLink> block_links;
QVector<GroupLink> group_input_links;
QHash<NodeGroup *, quintptr> group_output_links;
};
};
void LoadNode(Node *node, XMLNodeData &xml_node_data,
QXmlStreamReader *reader) const;
void LoadNode(Node *node, XMLNodeData &xml_node_data, QXmlStreamReader *reader) const;
void LoadColorManager(QXmlStreamReader *reader, Project *project) const;
void LoadColorManager(QXmlStreamReader* reader, Project *project) const;
void LoadProjectSettings(QXmlStreamReader *reader, Project *project) const;
void LoadProjectSettings(QXmlStreamReader* reader, Project *project) const;
void LoadInput(Node *node, QXmlStreamReader *reader,
XMLNodeData &xml_node_data) const;
void LoadInput(Node *node, QXmlStreamReader* reader, XMLNodeData &xml_node_data) const;
void LoadImmediate(QXmlStreamReader *reader, Node *node,
const QString &input, int element,
XMLNodeData &xml_node_data) const;
void LoadImmediate(QXmlStreamReader *reader, Node *node, const QString& input, int element, XMLNodeData& xml_node_data) const;
bool LoadPosition(QXmlStreamReader *reader, quintptr *node_ptr,
Node::Position *pos) const;
bool LoadPosition(QXmlStreamReader *reader, quintptr *node_ptr, Node::Position *pos) const;
void PostConnect(const XMLNodeData &xml_node_data) const;
void PostConnect(const XMLNodeData &xml_node_data) const;
void LoadNodeCustom(QXmlStreamReader *reader, Node *node,
XMLNodeData &xml_node_data) const;
void LoadNodeCustom(QXmlStreamReader *reader, Node *node, XMLNodeData &xml_node_data) const;
void LoadTimelinePoints(QXmlStreamReader *reader,
ViewerOutput *points) const;
void LoadTimelinePoints(QXmlStreamReader *reader, ViewerOutput *points) const;
void LoadWorkArea(QXmlStreamReader *reader,
TimelineWorkArea *workarea) const;
void LoadWorkArea(QXmlStreamReader *reader, TimelineWorkArea *workarea) const;
void LoadMarkerList(QXmlStreamReader *reader, TimelineMarkerList *markers) const;
void LoadValueHint(Node::ValueHint *hint, QXmlStreamReader *reader) const;
void LoadMarkerList(QXmlStreamReader *reader,
TimelineMarkerList *markers) const;
void LoadValueHint(Node::ValueHint *hint, QXmlStreamReader *reader) const;
};
}
File diff suppressed because it is too large Load Diff
+53 -45
View File
@@ -23,73 +23,81 @@
#include "serializer.h"
namespace olive {
class ProjectSerializer211228 : public ProjectSerializer
namespace olive
{
class ProjectSerializer211228 : public ProjectSerializer {
public:
ProjectSerializer211228() = default;
ProjectSerializer211228() = default;
protected:
virtual LoadData Load(Project *project, QXmlStreamReader *reader, LoadType load_type, void *reserved) const override;
virtual LoadData Load(Project *project, QXmlStreamReader *reader,
LoadType load_type, void *reserved) const override;
virtual uint Version() const override
{
return 211228;
}
virtual uint Version() const override
{
return 211228;
}
private:
struct XMLNodeData {
struct SerializedConnection {
NodeInput input;
quintptr output_node;
};
struct XMLNodeData {
struct SerializedConnection {
NodeInput input;
quintptr output_node;
};
struct BlockLink {
Node* block;
quintptr link;
};
struct BlockLink {
Node *block;
quintptr link;
};
struct GroupLink {
NodeGroup *group;
quintptr input_node;
QString input_id;
int input_element;
};
struct GroupLink {
NodeGroup *group;
quintptr input_node;
QString input_id;
int input_element;
};
QHash<quintptr, Node*> node_ptrs;
QList<SerializedConnection> desired_connections;
QList<BlockLink> block_links;
QVector<GroupLink> group_input_links;
QHash<NodeGroup*, quintptr> group_output_links;
QHash<Node*, QUuid> node_uuids;
QHash<quintptr, Node *> node_ptrs;
QList<SerializedConnection> desired_connections;
QList<BlockLink> block_links;
QVector<GroupLink> group_input_links;
QHash<NodeGroup *, quintptr> group_output_links;
QHash<Node *, QUuid> node_uuids;
};
};
void LoadNode(Node *node, XMLNodeData &xml_node_data,
QXmlStreamReader *reader) const;
void LoadNode(Node *node, XMLNodeData &xml_node_data, QXmlStreamReader *reader) const;
void LoadColorManager(QXmlStreamReader *reader, Project *project) const;
void LoadColorManager(QXmlStreamReader* reader, Project *project) const;
void LoadProjectSettings(QXmlStreamReader *reader, Project *project) const;
void LoadProjectSettings(QXmlStreamReader* reader, Project *project) const;
void LoadInput(Node *node, QXmlStreamReader *reader,
XMLNodeData &xml_node_data) const;
void LoadInput(Node *node, QXmlStreamReader* reader, XMLNodeData &xml_node_data) const;
void LoadImmediate(QXmlStreamReader *reader, Node *node,
const QString &input, int element,
XMLNodeData &xml_node_data) const;
void LoadImmediate(QXmlStreamReader *reader, Node *node, const QString& input, int element, XMLNodeData& xml_node_data) const;
bool LoadPosition(QXmlStreamReader *reader, quintptr *node_ptr,
Node::Position *pos) const;
bool LoadPosition(QXmlStreamReader *reader, quintptr *node_ptr, Node::Position *pos) const;
void PostConnect(const XMLNodeData &xml_node_data) const;
void PostConnect(const XMLNodeData &xml_node_data) const;
void LoadNodeCustom(QXmlStreamReader *reader, Node *node,
XMLNodeData &xml_node_data) const;
void LoadNodeCustom(QXmlStreamReader *reader, Node *node, XMLNodeData &xml_node_data) const;
void LoadTimelinePoints(QXmlStreamReader *reader,
ViewerOutput *points) const;
void LoadTimelinePoints(QXmlStreamReader *reader, ViewerOutput *points) const;
void LoadWorkArea(QXmlStreamReader *reader,
TimelineWorkArea *workarea) const;
void LoadWorkArea(QXmlStreamReader *reader, TimelineWorkArea *workarea) const;
void LoadMarkerList(QXmlStreamReader *reader, TimelineMarkerList *markers) const;
void LoadValueHint(Node::ValueHint *hint, QXmlStreamReader *reader) const;
void LoadMarkerList(QXmlStreamReader *reader,
TimelineMarkerList *markers) const;
void LoadValueHint(Node::ValueHint *hint, QXmlStreamReader *reader) const;
};
}
File diff suppressed because it is too large Load Diff
+62 -53
View File
@@ -23,83 +23,92 @@
#include "serializer.h"
namespace olive {
class ProjectSerializer220403 : public ProjectSerializer
namespace olive
{
class ProjectSerializer220403 : public ProjectSerializer {
public:
ProjectSerializer220403() = default;
ProjectSerializer220403() = default;
protected:
virtual LoadData Load(Project *project, QXmlStreamReader *reader, LoadType load_type, void *reserved) const override;
virtual LoadData Load(Project *project, QXmlStreamReader *reader,
LoadType load_type, void *reserved) const override;
virtual uint Version() const override
{
return 220403;
}
virtual uint Version() const override
{
return 220403;
}
private:
struct XMLNodeData {
struct SerializedConnection {
NodeInput input;
quintptr output_node;
};
struct XMLNodeData {
struct SerializedConnection {
NodeInput input;
quintptr output_node;
};
struct BlockLink {
Node* block;
quintptr link;
};
struct BlockLink {
Node *block;
quintptr link;
};
struct GroupLink {
NodeGroup *group;
QString passthrough_id;
quintptr input_node;
QString input_id;
int input_element;
QString custom_name;
InputFlags custom_flags;
NodeValue::Type data_type;
QVariant default_val;
QHash<QString, QVariant> custom_properties;
};
struct GroupLink {
NodeGroup *group;
QString passthrough_id;
quintptr input_node;
QString input_id;
int input_element;
QString custom_name;
InputFlags custom_flags;
NodeValue::Type data_type;
QVariant default_val;
QHash<QString, QVariant> custom_properties;
};
QHash<quintptr, Node*> node_ptrs;
QList<SerializedConnection> desired_connections;
QList<BlockLink> block_links;
QVector<GroupLink> group_input_links;
QHash<NodeGroup*, quintptr> group_output_links;
QHash<Node*, QUuid> node_uuids;
QHash<quintptr, Node *> node_ptrs;
QList<SerializedConnection> desired_connections;
QList<BlockLink> block_links;
QVector<GroupLink> group_input_links;
QHash<NodeGroup *, quintptr> group_output_links;
QHash<Node *, QUuid> node_uuids;
};
};
void LoadNode(Node *node, XMLNodeData &xml_node_data,
QXmlStreamReader *reader) const;
void LoadNode(Node *node, XMLNodeData &xml_node_data, QXmlStreamReader *reader) const;
void LoadColorManager(QXmlStreamReader *reader, Project *project) const;
void LoadColorManager(QXmlStreamReader* reader, Project *project) const;
void LoadProjectSettings(QXmlStreamReader *reader, Project *project) const;
void LoadProjectSettings(QXmlStreamReader* reader, Project *project) const;
void LoadInput(Node *node, QXmlStreamReader *reader,
XMLNodeData &xml_node_data) const;
void LoadInput(Node *node, QXmlStreamReader* reader, XMLNodeData &xml_node_data) const;
void LoadImmediate(QXmlStreamReader *reader, Node *node,
const QString &input, int element,
XMLNodeData &xml_node_data) const;
void LoadImmediate(QXmlStreamReader *reader, Node *node, const QString& input, int element, XMLNodeData& xml_node_data) const;
void LoadKeyframe(QXmlStreamReader *reader, NodeKeyframe *key,
NodeValue::Type data_type) const;
void LoadKeyframe(QXmlStreamReader *reader, NodeKeyframe *key, NodeValue::Type data_type) const;
bool LoadPosition(QXmlStreamReader *reader, quintptr *node_ptr,
Node::Position *pos) const;
bool LoadPosition(QXmlStreamReader *reader, quintptr *node_ptr, Node::Position *pos) const;
void PostConnect(const XMLNodeData &xml_node_data) const;
void PostConnect(const XMLNodeData &xml_node_data) const;
void LoadNodeCustom(QXmlStreamReader *reader, Node *node,
XMLNodeData &xml_node_data) const;
void LoadNodeCustom(QXmlStreamReader *reader, Node *node, XMLNodeData &xml_node_data) const;
void LoadTimelinePoints(QXmlStreamReader *reader,
ViewerOutput *viewer) const;
void LoadTimelinePoints(QXmlStreamReader *reader, ViewerOutput *viewer) const;
void LoadMarker(QXmlStreamReader *reader, TimelineMarker *marker) const;
void LoadMarker(QXmlStreamReader *reader, TimelineMarker *marker) const;
void LoadWorkArea(QXmlStreamReader *reader,
TimelineWorkArea *workarea) const;
void LoadWorkArea(QXmlStreamReader *reader, TimelineWorkArea *workarea) const;
void LoadMarkerList(QXmlStreamReader *reader, TimelineMarkerList *markers) const;
void LoadValueHint(Node::ValueHint *hint, QXmlStreamReader *reader) const;
void LoadMarkerList(QXmlStreamReader *reader,
TimelineMarkerList *markers) const;
void LoadValueHint(Node::ValueHint *hint, QXmlStreamReader *reader) const;
};
}
+501 -433
View File
@@ -26,459 +26,527 @@
#include "node/group/group.h"
#include "node/serializeddata.h"
#include <QtCore>
namespace olive {
ProjectSerializer230220::LoadData ProjectSerializer230220::Load(Project *project, QXmlStreamReader *reader, LoadType load_type, void *reserved) const
namespace olive
{
QMap<quintptr, QMap<QString, QString> > properties;
QMap<quintptr, QMap<quintptr, Node::Position> > positions;
LoadData load_data;
SerializedData project_data;
switch (load_type) {
case kProject:
{
if (reader->name() == QStringLiteral("project")) {
while (XMLReadNextStartElement(reader)) {
if (reader->name() == QStringLiteral("project")) {
project_data = project->Load(reader);
} else if (reader->name() == QStringLiteral("layout")) {
load_data.layout = MainWindowLayoutInfo::fromXml(reader, project_data.node_ptrs);
} else {
reader->skipCurrentElement();
}
}
PostConnect(project->nodes(), &project_data);
} else {
reader->skipCurrentElement();
}
break;
}
case kOnlyMarkers:
{
if (reader->name() == QStringLiteral("markers")) {
while (XMLReadNextStartElement(reader)) {
if (reader->name() == QStringLiteral("marker")) {
TimelineMarker *marker = new TimelineMarker();
marker->load(reader);
load_data.markers.push_back(marker);
} else {
reader->skipCurrentElement();
}
}
} else {
reader->skipCurrentElement();
}
break;
}
case kOnlyKeyframes:
{
if (reader->name() == QStringLiteral("keyframes")) {
while (XMLReadNextStartElement(reader)) {
if (reader->name() == QStringLiteral("node")) {
QString node_id;
XMLAttributeLoop(reader, attr) {
if (attr.name() == QStringLiteral("id")) {
node_id = attr.value().toString();
break;
}
}
Node *n = nullptr;
if (!node_id.isEmpty()) {
n = NodeFactory::CreateFromID(node_id);
}
if (!n) {
reader->skipCurrentElement();
} else {
while (XMLReadNextStartElement(reader)) {
if (reader->name() == QStringLiteral("input")) {
QString input_id;
XMLAttributeLoop(reader, attr) {
if (attr.name() == QStringLiteral("id")) {
input_id = attr.value().toString();
break;
}
}
if (input_id.isEmpty()) {
reader->skipCurrentElement();
} else {
while (XMLReadNextStartElement(reader)) {
if (reader->name() == QStringLiteral("element")) {
QString element_id;
XMLAttributeLoop(reader, attr) {
if (attr.name() == QStringLiteral("id")) {
element_id = attr.value().toString();
break;
}
}
if (element_id.isEmpty()) {
reader->skipCurrentElement();
} else {
while (XMLReadNextStartElement(reader)) {
if (reader->name() == QStringLiteral("track")) {
QString track_id;
XMLAttributeLoop(reader, attr) {
if (attr.name() == QStringLiteral("id")) {
track_id = attr.value().toString();
break;
}
}
if (track_id.isEmpty()) {
reader->skipCurrentElement();
} else {
while (XMLReadNextStartElement(reader)) {
if (reader->name() == QStringLiteral("key")) {
NodeKeyframe *key = new NodeKeyframe();
key->set_input(input_id);
key->set_element(element_id.toInt());
key->set_track(track_id.toInt());
key->load(reader, n->GetInputDataType(input_id));
load_data.keyframes[node_id].append(key);
} else {
reader->skipCurrentElement();
}
}
}
} else {
reader->skipCurrentElement();
}
}
}
} else {
reader->skipCurrentElement();
}
}
}
} else {
reader->skipCurrentElement();
}
}
}
delete n;
} else {
reader->skipCurrentElement();
}
}
} else {
reader->skipCurrentElement();
}
break;
}
case kOnlyClips:
case kOnlyNodes:
{
if ((load_type == kOnlyNodes && reader->name() == QStringLiteral("nodes")) || (load_type == kOnlyClips && reader->name() == QStringLiteral("timeline"))) {
QMap<quintptr, Node*> skipped_items;
while (XMLReadNextStartElement(reader)) {
if (reader->name() == QStringLiteral("node")) {
QString id;
quintptr ptr = 0;
QVector<quintptr> items;
XMLAttributeLoop(reader, attr) {
if (attr.name() == QStringLiteral("id")) {
id = attr.value().toString();
} else if (attr.name() == QStringLiteral("ptr")) {
ptr = attr.value().toULongLong();
} else if (attr.name() == QStringLiteral("items")) {
QVector<QStringView> l = attr.value().split(',');
items.reserve(l.size());
for (const QStringView &s : l) {
items.append(s.toULongLong());
}
}
}
if (id.isEmpty()) {
qWarning() << "Failed to load node with empty ID";
reader->skipCurrentElement();
} else {
bool dependency_of_item = false;
if (project && !items.empty()) {
for (quintptr p : items) {
if (project->nodes().contains(reinterpret_cast<Node*>(p))) {
dependency_of_item = true;
break;
}
}
}
if (dependency_of_item) {
reader->skipCurrentElement();
} else {
Node* node = NodeFactory::CreateFromID(id);
if (!node) {
qWarning() << "Failed to find node with ID" << id;
reader->skipCurrentElement();
} else {
if (project && node->IsItem() && ptr) {
// If we're pasting an object into the same project, we should re-use the item
// rather than duplicate.
Node *existing = reinterpret_cast<Node *>(ptr);
if (project->nodes().contains(existing)) {
// Connect this
skipped_items.insert(ptr, existing);
// Don't continue loading this
delete node;
node = nullptr;
// Skip element
reader->skipCurrentElement();
}
}
if (node) {
// Disable cache while node is being loaded (we'll re-enable it later)
node->SetCachesEnabled(false);
node->Load(reader, &project_data);
load_data.nodes.append(node);
}
}
}
}
} else if (reader->name() == QStringLiteral("properties")) {
while (XMLReadNextStartElement(reader)) {
if (reader->name() == QStringLiteral("node")) {
quintptr ptr = 0;
XMLAttributeLoop(reader, attr) {
if (attr.name() == QStringLiteral("ptr")) {
ptr = attr.value().toULongLong();
// Only attribute we're looking for right now
break;
}
}
if (ptr) {
QMap<QString, QString> properties_for_node;
while (XMLReadNextStartElement(reader)) {
properties_for_node.insert(reader->name().toString(), reader->readElementText());
}
properties.insert(ptr, properties_for_node);
}
} else {
reader->skipCurrentElement();
}
}
} else {
reader->skipCurrentElement();
}
}
if (!skipped_items.empty()) {
for (auto it = project_data.desired_connections.begin(); it != project_data.desired_connections.end(); ) {
const SerializedData::SerializedConnection &sc = *it;
if (Node *si = skipped_items.value(sc.output_node)) {
// Convert this to a promised connection
Node::OutputConnection oc = {si, sc.input};
load_data.promised_connections.push_back(oc);
it = project_data.desired_connections.erase(it);
} else {
it++;
}
}
}
// Resolve serialized properties (if any)
for (auto it=properties.cbegin(); it!=properties.cend(); it++) {
Node *node = project_data.node_ptrs.value(it.key());
if (node) {
load_data.properties.insert(node, it.value());
}
}
PostConnect(load_data.nodes, &project_data);
} else {
reader->skipCurrentElement();
}
break;
}
}
return load_data;
}
void WriteNodeMap(QXmlStreamWriter *writer, Node *node, const QVector<Node*> &nodes)
ProjectSerializer230220::LoadData
ProjectSerializer230220::Load(Project *project, QXmlStreamReader *reader,
LoadType load_type, void *reserved) const
{
writer->writeStartElement(QStringLiteral("node"));
QMap<quintptr, QMap<QString, QString>> properties;
QMap<quintptr, QMap<quintptr, Node::Position>> positions;
LoadData load_data;
SerializedData project_data;
writer->writeAttribute(QStringLiteral("ptr"), QString::number(reinterpret_cast<quintptr>(node)));
switch (load_type) {
case kProject: {
if (reader->name() == QStringLiteral("project")) {
while (XMLReadNextStartElement(reader)) {
if (reader->name() == QStringLiteral("project")) {
project_data = project->Load(reader);
} else if (reader->name() == QStringLiteral("layout")) {
load_data.layout = MainWindowLayoutInfo::fromXml(
reader, project_data.node_ptrs);
} else {
reader->skipCurrentElement();
}
}
for (auto oc : node->output_connections()) {
if (nodes.contains(oc.second.node())) {
WriteNodeMap(writer, oc.second.node(), nodes);
}
}
PostConnect(project->nodes(), &project_data);
} else {
reader->skipCurrentElement();
}
break;
}
case kOnlyMarkers: {
if (reader->name() == QStringLiteral("markers")) {
while (XMLReadNextStartElement(reader)) {
if (reader->name() == QStringLiteral("marker")) {
TimelineMarker *marker = new TimelineMarker();
marker->load(reader);
load_data.markers.push_back(marker);
} else {
reader->skipCurrentElement();
}
}
} else {
reader->skipCurrentElement();
}
break;
}
case kOnlyKeyframes: {
if (reader->name() == QStringLiteral("keyframes")) {
while (XMLReadNextStartElement(reader)) {
if (reader->name() == QStringLiteral("node")) {
QString node_id;
XMLAttributeLoop(reader, attr)
{
if (attr.name() == QStringLiteral("id")) {
node_id = attr.value().toString();
break;
}
}
writer->writeEndElement();
Node *n = nullptr;
if (!node_id.isEmpty()) {
n = NodeFactory::CreateFromID(node_id);
}
if (!n) {
reader->skipCurrentElement();
} else {
while (XMLReadNextStartElement(reader)) {
if (reader->name() == QStringLiteral("input")) {
QString input_id;
XMLAttributeLoop(reader, attr)
{
if (attr.name() == QStringLiteral("id")) {
input_id = attr.value().toString();
break;
}
}
if (input_id.isEmpty()) {
reader->skipCurrentElement();
} else {
while (XMLReadNextStartElement(reader)) {
if (reader->name() ==
QStringLiteral("element")) {
QString element_id;
XMLAttributeLoop(reader, attr)
{
if (attr.name() ==
QStringLiteral("id")) {
element_id =
attr.value().toString();
break;
}
}
if (element_id.isEmpty()) {
reader->skipCurrentElement();
} else {
while (XMLReadNextStartElement(
reader)) {
if (reader->name() ==
QStringLiteral(
"track")) {
QString track_id;
XMLAttributeLoop(reader,
attr)
{
if (attr.name() ==
QStringLiteral(
"id")) {
track_id =
attr.value()
.toString();
break;
}
}
if (track_id.isEmpty()) {
reader
->skipCurrentElement();
} else {
while (
XMLReadNextStartElement(
reader)) {
if (reader
->name() ==
QStringLiteral(
"key")) {
NodeKeyframe *key =
new NodeKeyframe();
key->set_input(
input_id);
key->set_element(
element_id
.toInt());
key->set_track(
track_id
.toInt());
key->load(
reader,
n->GetInputDataType(
input_id));
load_data
.keyframes
[node_id]
.append(
key);
} else {
reader
->skipCurrentElement();
}
}
}
} else {
reader
->skipCurrentElement();
}
}
}
} else {
reader->skipCurrentElement();
}
}
}
} else {
reader->skipCurrentElement();
}
}
}
delete n;
} else {
reader->skipCurrentElement();
}
}
} else {
reader->skipCurrentElement();
}
break;
}
case kOnlyClips:
case kOnlyNodes: {
if ((load_type == kOnlyNodes &&
reader->name() == QStringLiteral("nodes")) ||
(load_type == kOnlyClips &&
reader->name() == QStringLiteral("timeline"))) {
QMap<quintptr, Node *> skipped_items;
while (XMLReadNextStartElement(reader)) {
if (reader->name() == QStringLiteral("node")) {
QString id;
quintptr ptr = 0;
QVector<quintptr> items;
XMLAttributeLoop(reader, attr)
{
if (attr.name() == QStringLiteral("id")) {
id = attr.value().toString();
} else if (attr.name() == QStringLiteral("ptr")) {
ptr = attr.value().toULongLong();
} else if (attr.name() == QStringLiteral("items")) {
QVector<QStringView> l = attr.value().split(',');
items.reserve(l.size());
for (const QStringView &s : l) {
items.append(s.toULongLong());
}
}
}
if (id.isEmpty()) {
qWarning() << "Failed to load node with empty ID";
reader->skipCurrentElement();
} else {
bool dependency_of_item = false;
if (project && !items.empty()) {
for (quintptr p : items) {
if (project->nodes().contains(
reinterpret_cast<Node *>(p))) {
dependency_of_item = true;
break;
}
}
}
if (dependency_of_item) {
reader->skipCurrentElement();
} else {
Node *node = NodeFactory::CreateFromID(id);
if (!node) {
qWarning()
<< "Failed to find node with ID" << id;
reader->skipCurrentElement();
} else {
if (project && node->IsItem() && ptr) {
// If we're pasting an object into the same project, we should re-use the item
// rather than duplicate.
Node *existing =
reinterpret_cast<Node *>(ptr);
if (project->nodes().contains(existing)) {
// Connect this
skipped_items.insert(ptr, existing);
// Don't continue loading this
delete node;
node = nullptr;
// Skip element
reader->skipCurrentElement();
}
}
if (node) {
// Disable cache while node is being loaded (we'll re-enable it later)
node->SetCachesEnabled(false);
node->Load(reader, &project_data);
load_data.nodes.append(node);
}
}
}
}
} else if (reader->name() == QStringLiteral("properties")) {
while (XMLReadNextStartElement(reader)) {
if (reader->name() == QStringLiteral("node")) {
quintptr ptr = 0;
XMLAttributeLoop(reader, attr)
{
if (attr.name() == QStringLiteral("ptr")) {
ptr = attr.value().toULongLong();
// Only attribute we're looking for right now
break;
}
}
if (ptr) {
QMap<QString, QString> properties_for_node;
while (XMLReadNextStartElement(reader)) {
properties_for_node.insert(
reader->name().toString(),
reader->readElementText());
}
properties.insert(ptr, properties_for_node);
}
} else {
reader->skipCurrentElement();
}
}
} else {
reader->skipCurrentElement();
}
}
if (!skipped_items.empty()) {
for (auto it = project_data.desired_connections.begin();
it != project_data.desired_connections.end();) {
const SerializedData::SerializedConnection &sc = *it;
if (Node *si = skipped_items.value(sc.output_node)) {
// Convert this to a promised connection
Node::OutputConnection oc = { si, sc.input };
load_data.promised_connections.push_back(oc);
it = project_data.desired_connections.erase(it);
} else {
it++;
}
}
}
// Resolve serialized properties (if any)
for (auto it = properties.cbegin(); it != properties.cend(); it++) {
Node *node = project_data.node_ptrs.value(it.key());
if (node) {
load_data.properties.insert(node, it.value());
}
}
PostConnect(load_data.nodes, &project_data);
} else {
reader->skipCurrentElement();
}
break;
}
}
return load_data;
}
void ProjectSerializer230220::Save(QXmlStreamWriter *writer, const SaveData &data, void *reserved) const
void WriteNodeMap(QXmlStreamWriter *writer, Node *node,
const QVector<Node *> &nodes)
{
if (!data.GetOnlySerializeMarkers().empty()) {
writer->writeStartElement(QStringLiteral("markers"));
writer->writeStartElement(QStringLiteral("node"));
writer->writeAttribute(QStringLiteral("version"), QString::number(1));
writer->writeAttribute(QStringLiteral("ptr"),
QString::number(reinterpret_cast<quintptr>(node)));
for (auto it=data.GetOnlySerializeMarkers().cbegin(); it!=data.GetOnlySerializeMarkers().cend(); it++) {
TimelineMarker *marker = *it;
writer->writeStartElement(QStringLiteral("marker"));
marker->save(writer);
writer->writeEndElement(); // marker
}
for (auto oc : node->output_connections()) {
if (nodes.contains(oc.second.node())) {
WriteNodeMap(writer, oc.second.node(), nodes);
}
}
writer->writeEndElement(); // markers
} else if (!data.GetOnlySerializeKeyframes().empty()) {
writer->writeStartElement(QStringLiteral("keyframes"));
writer->writeAttribute(QStringLiteral("version"), QString::number(1));
// Organize keyframes into node+input
QHash<QString, QHash<QString, QMap<int, QMap<int, QVector<NodeKeyframe*> > > > > organized;
for (auto it=data.GetOnlySerializeKeyframes().cbegin(); it!=data.GetOnlySerializeKeyframes().cend(); it++) {
NodeKeyframe *key = *it;
organized[key->parent()->id()][key->input()][key->element()][key->track()].append(key);
}
for (auto it=organized.cbegin(); it!=organized.cend(); it++) {
writer->writeStartElement(QStringLiteral("node"));
writer->writeAttribute(QStringLiteral("id"), it.key());
for (auto jt=it.value().cbegin(); jt!=it.value().cend(); jt++) {
writer->writeStartElement(QStringLiteral("input"));
writer->writeAttribute(QStringLiteral("id"), jt.key());
for (auto kt=jt.value().cbegin(); kt!=jt.value().cend(); kt++) {
writer->writeStartElement(QStringLiteral("element"));
writer->writeAttribute(QStringLiteral("id"), QString::number(kt.key()));
for (auto lt=kt.value().cbegin(); lt!=kt.value().cend(); lt++) {
const QVector<NodeKeyframe *> &keys = lt.value();
writer->writeStartElement(QStringLiteral("track"));
writer->writeAttribute(QStringLiteral("id"), QString::number(lt.key()));
for (NodeKeyframe *key : keys) {
writer->writeStartElement(QStringLiteral("key"));
key->save(writer, key->parent()->GetInputDataType(key->input()));
writer->writeEndElement(); // key
}
writer->writeEndElement(); // track
}
writer->writeEndElement(); // element
}
writer->writeEndElement(); // input
}
writer->writeEndElement(); // node;
}
writer->writeEndElement(); // keyframes
} else if (!data.GetOnlySerializeNodes().empty()) {
if (data.type() == kOnlyClips) {
writer->writeStartElement(QStringLiteral("timeline"));
} else {
writer->writeStartElement(QStringLiteral("nodes"));
}
writer->writeAttribute(QStringLiteral("version"), QString::number(1));
for (Node *n : data.GetOnlySerializeNodes()) {
writer->writeStartElement(QStringLiteral("node"));
QStringList item_list;
for (Node *i : data.GetOnlySerializeNodes()) {
if (i->IsItem() && i->InputsFrom(n, true)) {
item_list.append(QString::number(reinterpret_cast<quintptr>(i)));
}
}
if (!item_list.empty()) {
writer->writeAttribute(QStringLiteral("items"), item_list.join(','));
}
n->Save(writer);
writer->writeEndElement(); // node
}
if (!data.GetProperties().empty()) {
writer->writeStartElement(QStringLiteral("properties"));
for (auto it=data.GetProperties().cbegin(); it!=data.GetProperties().cend(); it++) {
writer->writeStartElement(QStringLiteral("node"));
writer->writeAttribute(QStringLiteral("ptr"), QString::number(reinterpret_cast<quintptr>(it.key())));
for (auto jt=it.value().cbegin(); jt!=it.value().cend(); jt++) {
writer->writeTextElement(jt.key(), jt.value());
}
writer->writeEndElement(); // node
}
writer->writeEndElement(); // properties
}
writer->writeEndElement(); // nodes
} else if (Project *project = data.GetProject()) {
writer->writeStartElement(QStringLiteral("project"));
writer->writeStartElement(QStringLiteral("project"));
project->Save(writer);
writer->writeEndElement(); // project
writer->writeStartElement(QStringLiteral("layout"));
data.GetLayout().toXml(writer);
writer->writeEndElement(); // layout
writer->writeEndElement(); // project
} else {
qCritical() << "ProjectSerializer provided nothing to save";
}
writer->writeEndElement();
}
void ProjectSerializer230220::PostConnect(const QVector<Node *> &nodes, SerializedData *project_data) const
void ProjectSerializer230220::Save(QXmlStreamWriter *writer,
const SaveData &data, void *reserved) const
{
foreach (const SerializedData::SerializedConnection& con, project_data->desired_connections) {
if (Node *out = project_data->node_ptrs.value(con.output_node)) {
Node::ConnectEdge(out, con.input);
}
}
if (!data.GetOnlySerializeMarkers().empty()) {
writer->writeStartElement(QStringLiteral("markers"));
foreach (const SerializedData::BlockLink& l, project_data->block_links) {
Node *a = l.block;
Node *b = project_data->node_ptrs.value(l.link);
writer->writeAttribute(QStringLiteral("version"), QString::number(1));
Node::Link(a, b);
}
for (auto it = data.GetOnlySerializeMarkers().cbegin();
it != data.GetOnlySerializeMarkers().cend(); it++) {
TimelineMarker *marker = *it;
writer->writeStartElement(QStringLiteral("marker"));
marker->save(writer);
writer->writeEndElement(); // marker
}
for (auto it = nodes.cbegin(); it != nodes.cend(); it++){
Node *n = *it;
writer->writeEndElement(); // markers
} else if (!data.GetOnlySerializeKeyframes().empty()) {
writer->writeStartElement(QStringLiteral("keyframes"));
n->PostLoadEvent(project_data);
writer->writeAttribute(QStringLiteral("version"), QString::number(1));
n->SetCachesEnabled(true);
}
// Organize keyframes into node+input
QHash<QString,
QHash<QString, QMap<int, QMap<int, QVector<NodeKeyframe *>>>>>
organized;
for (auto it = data.GetOnlySerializeKeyframes().cbegin();
it != data.GetOnlySerializeKeyframes().cend(); it++) {
NodeKeyframe *key = *it;
organized[key->parent()->id()][key->input()][key->element()]
[key->track()]
.append(key);
}
for (auto it = organized.cbegin(); it != organized.cend(); it++) {
writer->writeStartElement(QStringLiteral("node"));
writer->writeAttribute(QStringLiteral("id"), it.key());
for (auto jt = it.value().cbegin(); jt != it.value().cend(); jt++) {
writer->writeStartElement(QStringLiteral("input"));
writer->writeAttribute(QStringLiteral("id"), jt.key());
for (auto kt = jt.value().cbegin(); kt != jt.value().cend();
kt++) {
writer->writeStartElement(QStringLiteral("element"));
writer->writeAttribute(QStringLiteral("id"),
QString::number(kt.key()));
for (auto lt = kt.value().cbegin(); lt != kt.value().cend();
lt++) {
const QVector<NodeKeyframe *> &keys = lt.value();
writer->writeStartElement(QStringLiteral("track"));
writer->writeAttribute(QStringLiteral("id"),
QString::number(lt.key()));
for (NodeKeyframe *key : keys) {
writer->writeStartElement(QStringLiteral("key"));
key->save(writer, key->parent()->GetInputDataType(
key->input()));
writer->writeEndElement(); // key
}
writer->writeEndElement(); // track
}
writer->writeEndElement(); // element
}
writer->writeEndElement(); // input
}
writer->writeEndElement(); // node;
}
writer->writeEndElement(); // keyframes
} else if (!data.GetOnlySerializeNodes().empty()) {
if (data.type() == kOnlyClips) {
writer->writeStartElement(QStringLiteral("timeline"));
} else {
writer->writeStartElement(QStringLiteral("nodes"));
}
writer->writeAttribute(QStringLiteral("version"), QString::number(1));
for (Node *n : data.GetOnlySerializeNodes()) {
writer->writeStartElement(QStringLiteral("node"));
QStringList item_list;
for (Node *i : data.GetOnlySerializeNodes()) {
if (i->IsItem() && i->InputsFrom(n, true)) {
item_list.append(
QString::number(reinterpret_cast<quintptr>(i)));
}
}
if (!item_list.empty()) {
writer->writeAttribute(QStringLiteral("items"),
item_list.join(','));
}
n->Save(writer);
writer->writeEndElement(); // node
}
if (!data.GetProperties().empty()) {
writer->writeStartElement(QStringLiteral("properties"));
for (auto it = data.GetProperties().cbegin();
it != data.GetProperties().cend(); it++) {
writer->writeStartElement(QStringLiteral("node"));
writer->writeAttribute(
QStringLiteral("ptr"),
QString::number(reinterpret_cast<quintptr>(it.key())));
for (auto jt = it.value().cbegin(); jt != it.value().cend();
jt++) {
writer->writeTextElement(jt.key(), jt.value());
}
writer->writeEndElement(); // node
}
writer->writeEndElement(); // properties
}
writer->writeEndElement(); // nodes
} else if (Project *project = data.GetProject()) {
writer->writeStartElement(QStringLiteral("project"));
writer->writeStartElement(QStringLiteral("project"));
project->Save(writer);
writer->writeEndElement(); // project
writer->writeStartElement(QStringLiteral("layout"));
data.GetLayout().toXml(writer);
writer->writeEndElement(); // layout
writer->writeEndElement(); // project
} else {
qCritical() << "ProjectSerializer provided nothing to save";
}
}
void ProjectSerializer230220::PostConnect(const QVector<Node *> &nodes,
SerializedData *project_data) const
{
foreach (const SerializedData::SerializedConnection &con,
project_data->desired_connections) {
if (Node *out = project_data->node_ptrs.value(con.output_node)) {
Node::ConnectEdge(out, con.input);
}
}
foreach (const SerializedData::BlockLink &l, project_data->block_links) {
Node *a = l.block;
Node *b = project_data->node_ptrs.value(l.link);
Node::Link(a, b);
}
for (auto it = nodes.cbegin(); it != nodes.cend(); it++) {
Node *n = *it;
n->PostLoadEvent(project_data);
n->SetCachesEnabled(true);
}
}
}
+14 -12
View File
@@ -23,26 +23,28 @@
#include "serializer.h"
namespace olive {
class ProjectSerializer230220 : public ProjectSerializer
namespace olive
{
class ProjectSerializer230220 : public ProjectSerializer {
public:
ProjectSerializer230220() = default;
ProjectSerializer230220() = default;
protected:
virtual LoadData Load(Project *project, QXmlStreamReader *reader, LoadType load_type, void *reserved) const override;
virtual LoadData Load(Project *project, QXmlStreamReader *reader,
LoadType load_type, void *reserved) const override;
virtual void Save(QXmlStreamWriter *writer, const SaveData &data, void *reserved) const override;
virtual void Save(QXmlStreamWriter *writer, const SaveData &data,
void *reserved) const override;
virtual uint Version() const override
{
return 230220;
}
virtual uint Version() const override
{
return 230220;
}
private:
void PostConnect(const QVector<Node*> &nodes, SerializedData *project_data) const;
void PostConnect(const QVector<Node *> &nodes,
SerializedData *project_data) const;
};
}
+41 -30
View File
@@ -20,44 +20,55 @@
#include "typeserializer.h"
namespace olive {
namespace olive
{
AudioParams TypeSerializer::LoadAudioParams(QXmlStreamReader *reader)
{
AudioParams a;
AudioParams a;
while (XMLReadNextStartElement(reader)) {
if (reader->name() == QStringLiteral("samplerate")) {
a.set_sample_rate(reader->readElementText().toInt());
} else if (reader->name() == QStringLiteral("channellayout")) {
a.set_channel_layout(reader->readElementText().toULongLong());
} else if (reader->name() == QStringLiteral("format")) {
a.set_format(SampleFormat::from_string(reader->readElementText().toStdString()));
} else if (reader->name() == QStringLiteral("enabled")) {
a.set_enabled(reader->readElementText().toInt());
} else if (reader->name() == QStringLiteral("streamindex")) {
a.set_stream_index(reader->readElementText().toInt());
} else if (reader->name() == QStringLiteral("duration")) {
a.set_duration(reader->readElementText().toLongLong());
} else if (reader->name() == QStringLiteral("timebase")) {
a.set_time_base(rational::fromString(reader->readElementText().toStdString()));
} else {
reader->skipCurrentElement();
}
}
while (XMLReadNextStartElement(reader)) {
if (reader->name() == QStringLiteral("samplerate")) {
a.set_sample_rate(reader->readElementText().toInt());
} else if (reader->name() == QStringLiteral("channellayout")) {
a.set_channel_layout(reader->readElementText().toULongLong());
} else if (reader->name() == QStringLiteral("format")) {
a.set_format(SampleFormat::from_string(
reader->readElementText().toStdString()));
} else if (reader->name() == QStringLiteral("enabled")) {
a.set_enabled(reader->readElementText().toInt());
} else if (reader->name() == QStringLiteral("streamindex")) {
a.set_stream_index(reader->readElementText().toInt());
} else if (reader->name() == QStringLiteral("duration")) {
a.set_duration(reader->readElementText().toLongLong());
} else if (reader->name() == QStringLiteral("timebase")) {
a.set_time_base(
rational::fromString(reader->readElementText().toStdString()));
} else {
reader->skipCurrentElement();
}
}
return a;
return a;
}
void TypeSerializer::SaveAudioParams(QXmlStreamWriter *writer, const AudioParams &a)
void TypeSerializer::SaveAudioParams(QXmlStreamWriter *writer,
const AudioParams &a)
{
writer->writeTextElement(QStringLiteral("samplerate"), QString::number(a.sample_rate()));
writer->writeTextElement(QStringLiteral("channellayout"), QString::number(a.channel_layout().u.mask));
writer->writeTextElement(QStringLiteral("format"), QString::fromStdString(a.format().to_string()));
writer->writeTextElement(QStringLiteral("enabled"), QString::number(a.enabled()));
writer->writeTextElement(QStringLiteral("streamindex"), QString::number(a.stream_index()));
writer->writeTextElement(QStringLiteral("duration"), QString::number(a.duration()));
writer->writeTextElement(QStringLiteral("timebase"), QString::fromStdString(a.time_base().toString()));
writer->writeTextElement(QStringLiteral("samplerate"),
QString::number(a.sample_rate()));
writer->writeTextElement(QStringLiteral("channellayout"),
QString::number(a.channel_layout().u.mask));
writer->writeTextElement(QStringLiteral("format"),
QString::fromStdString(a.format().to_string()));
writer->writeTextElement(QStringLiteral("enabled"),
QString::number(a.enabled()));
writer->writeTextElement(QStringLiteral("streamindex"),
QString::number(a.stream_index()));
writer->writeTextElement(QStringLiteral("duration"),
QString::number(a.duration()));
writer->writeTextElement(QStringLiteral("timebase"),
QString::fromStdString(a.time_base().toString()));
}
}
+6 -7
View File
@@ -27,18 +27,17 @@
#include "common/xmlutils.h"
namespace olive {
namespace olive
{
using namespace core;
class TypeSerializer
{
class TypeSerializer {
public:
TypeSerializer() = default;
static AudioParams LoadAudioParams(QXmlStreamReader *reader);
static void SaveAudioParams(QXmlStreamWriter *writer, const AudioParams &a);
TypeSerializer() = default;
static AudioParams LoadAudioParams(QXmlStreamReader *reader);
static void SaveAudioParams(QXmlStreamWriter *writer, const AudioParams &a);
};
}