serializer: ensure backwards compatibility
This commit is contained in:
+94
-61
@@ -1185,16 +1185,24 @@ bool Node::AreLinked(Node *a, Node *b)
|
||||
|
||||
bool Node::Load(QXmlStreamReader *reader, SerializedData *data)
|
||||
{
|
||||
uint version = 0;
|
||||
|
||||
XMLAttributeLoop(reader, attr) {
|
||||
if (attr.name() == QStringLiteral("ptr")) {
|
||||
quintptr ptr = attr.value().toULongLong();
|
||||
data->node_ptrs.insert(ptr, this);
|
||||
} else if (attr.name() == QStringLiteral("version")) {
|
||||
version = attr.value().toUInt();
|
||||
}
|
||||
}
|
||||
|
||||
Q_UNUSED(version)
|
||||
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
if (reader->name() == QStringLiteral("input")) {
|
||||
LoadInput(reader, data);
|
||||
} else if (reader->name() == QStringLiteral("ptr")) {
|
||||
quintptr ptr = reader->readElementText().toULongLong();
|
||||
data->node_ptrs.insert(ptr, this);
|
||||
} else if (reader->name() == QStringLiteral("label")) {
|
||||
this->SetLabel(reader->readElementText());
|
||||
} else if (reader->name() == QStringLiteral("uuid")) {
|
||||
data->node_uuids.insert(this, QUuid::fromString(reader->readElementText()));
|
||||
} else if (reader->name() == QStringLiteral("color")) {
|
||||
this->SetOverrideColor(reader->readElementText().toInt());
|
||||
} else if (reader->name() == QStringLiteral("links")) {
|
||||
@@ -1278,7 +1286,7 @@ bool Node::Load(QXmlStreamReader *reader, SerializedData *data)
|
||||
if (!node_pos.load(reader)) {
|
||||
return false;
|
||||
}
|
||||
data->positions[reinterpret_cast<quintptr>(this)].insert(node_ptr, node_pos);
|
||||
data->positions[this].insert(node_ptr, node_pos);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -1313,11 +1321,16 @@ bool Node::Load(QXmlStreamReader *reader, SerializedData *data)
|
||||
void Node::Save(QXmlStreamWriter *writer) const
|
||||
{
|
||||
writer->writeAttribute(QStringLiteral("version"), QString::number(1));
|
||||
writer->writeAttribute(QStringLiteral("id"), this->id());
|
||||
writer->writeAttribute(QStringLiteral("ptr"), QString::number(reinterpret_cast<quintptr>(this)));
|
||||
|
||||
writer->writeTextElement(QStringLiteral("ptr"), QString::number(reinterpret_cast<quintptr>(this)));
|
||||
if (!this->GetLabel().isEmpty()) {
|
||||
writer->writeTextElement(QStringLiteral("label"), this->GetLabel());
|
||||
}
|
||||
|
||||
writer->writeTextElement(QStringLiteral("label"), this->GetLabel());
|
||||
writer->writeTextElement(QStringLiteral("color"), QString::number(this->GetOverrideColor()));
|
||||
if (this->GetOverrideColor() != -1) {
|
||||
writer->writeTextElement(QStringLiteral("color"), QString::number(this->GetOverrideColor()));
|
||||
}
|
||||
|
||||
foreach (const QString& input, this->inputs()) {
|
||||
writer->writeStartElement(QStringLiteral("input"));
|
||||
@@ -1327,52 +1340,58 @@ void Node::Save(QXmlStreamWriter *writer) const
|
||||
writer->writeEndElement(); // input
|
||||
}
|
||||
|
||||
writer->writeStartElement(QStringLiteral("links"));
|
||||
foreach (Node* link, this->links()) {
|
||||
writer->writeTextElement(QStringLiteral("link"), QString::number(reinterpret_cast<quintptr>(link)));
|
||||
if (!this->links().empty()) {
|
||||
writer->writeStartElement(QStringLiteral("links"));
|
||||
foreach (Node* link, this->links()) {
|
||||
writer->writeTextElement(QStringLiteral("link"), QString::number(reinterpret_cast<quintptr>(link)));
|
||||
}
|
||||
writer->writeEndElement(); // links
|
||||
}
|
||||
writer->writeEndElement(); // links
|
||||
|
||||
writer->writeStartElement(QStringLiteral("connections"));
|
||||
for (auto it=this->input_connections().cbegin(); it!=this->input_connections().cend(); it++) {
|
||||
writer->writeStartElement(QStringLiteral("connection"));
|
||||
if (!this->input_connections().empty()) {
|
||||
writer->writeStartElement(QStringLiteral("connections"));
|
||||
for (auto it=this->input_connections().cbegin(); it!=this->input_connections().cend(); it++) {
|
||||
writer->writeStartElement(QStringLiteral("connection"));
|
||||
|
||||
writer->writeAttribute(QStringLiteral("input"), it->first.input());
|
||||
writer->writeAttribute(QStringLiteral("element"), QString::number(it->first.element()));
|
||||
writer->writeAttribute(QStringLiteral("input"), it->first.input());
|
||||
writer->writeAttribute(QStringLiteral("element"), QString::number(it->first.element()));
|
||||
|
||||
writer->writeTextElement(QStringLiteral("output"), QString::number(reinterpret_cast<quintptr>(it->second)));
|
||||
writer->writeTextElement(QStringLiteral("output"), QString::number(reinterpret_cast<quintptr>(it->second)));
|
||||
|
||||
writer->writeEndElement(); // connection
|
||||
writer->writeEndElement(); // connection
|
||||
}
|
||||
writer->writeEndElement(); // connections
|
||||
}
|
||||
writer->writeEndElement(); // connections
|
||||
|
||||
writer->writeStartElement(QStringLiteral("hints"));
|
||||
for (auto it=this->GetValueHints().cbegin(); it!=this->GetValueHints().cend(); it++) {
|
||||
writer->writeStartElement(QStringLiteral("hint"));
|
||||
if (!this->GetValueHints().empty()) {
|
||||
writer->writeStartElement(QStringLiteral("hints"));
|
||||
for (auto it=this->GetValueHints().cbegin(); it!=this->GetValueHints().cend(); it++) {
|
||||
writer->writeStartElement(QStringLiteral("hint"));
|
||||
|
||||
writer->writeAttribute(QStringLiteral("input"), it.key().input);
|
||||
writer->writeAttribute(QStringLiteral("element"), QString::number(it.key().element));
|
||||
writer->writeAttribute(QStringLiteral("input"), it.key().input);
|
||||
writer->writeAttribute(QStringLiteral("element"), QString::number(it.key().element));
|
||||
|
||||
it.value().save(writer);
|
||||
it.value().save(writer);
|
||||
|
||||
writer->writeEndElement(); // hint
|
||||
writer->writeEndElement(); // hint
|
||||
}
|
||||
writer->writeEndElement(); // hints
|
||||
}
|
||||
writer->writeEndElement(); // hints
|
||||
|
||||
writer->writeStartElement(QStringLiteral("context"));
|
||||
|
||||
const Node::PositionMap &map = this->GetContextPositions();
|
||||
|
||||
if (!map.isEmpty()) {
|
||||
writer->writeStartElement(QStringLiteral("context"));
|
||||
|
||||
for (auto jt=map.cbegin(); jt!=map.cend(); jt++) {
|
||||
writer->writeStartElement(QStringLiteral("node"));
|
||||
writer->writeAttribute(QStringLiteral("ptr"), QString::number(reinterpret_cast<quintptr>(this)));
|
||||
writer->writeAttribute(QStringLiteral("ptr"), QString::number(reinterpret_cast<quintptr>(jt.key())));
|
||||
jt.value().save(writer);
|
||||
writer->writeEndElement(); // node
|
||||
}
|
||||
}
|
||||
|
||||
writer->writeEndElement(); // context
|
||||
writer->writeEndElement(); // context
|
||||
}
|
||||
|
||||
writer->writeStartElement(QStringLiteral("caches"));
|
||||
|
||||
@@ -1399,8 +1418,7 @@ bool Node::LoadCustom(QXmlStreamReader *reader, SerializedData *data)
|
||||
void Node::PostLoadEvent(SerializedData *data)
|
||||
{
|
||||
// Resolve positions
|
||||
quintptr this_ptr = data->node_ptrs.key(this);
|
||||
const QMap<quintptr, Node::Position> &positions = data->positions.value(this_ptr);
|
||||
const QMap<quintptr, Node::Position> &positions = data->positions.value(this);
|
||||
|
||||
for (auto jt=positions.cbegin(); jt!=positions.cend(); jt++) {
|
||||
Node *n = data->node_ptrs.value(jt.key());
|
||||
@@ -1479,27 +1497,31 @@ void Node::SaveInput(QXmlStreamWriter *writer, const QString &id) const
|
||||
{
|
||||
writer->writeAttribute(QStringLiteral("id"), id);
|
||||
|
||||
writer->writeStartElement(QStringLiteral("primary"));
|
||||
if (!GetStandardValue(id, -1).isNull()) {
|
||||
writer->writeStartElement(QStringLiteral("primary"));
|
||||
|
||||
SaveImmediate(writer, id, -1);
|
||||
SaveImmediate(writer, id, -1);
|
||||
|
||||
writer->writeEndElement(); // primary
|
||||
|
||||
writer->writeStartElement(QStringLiteral("subelements"));
|
||||
writer->writeEndElement(); // primary
|
||||
}
|
||||
|
||||
int arr_sz = this->InputArraySize(id);
|
||||
|
||||
writer->writeAttribute(QStringLiteral("count"), QString::number(arr_sz));
|
||||
if (arr_sz > 0) {
|
||||
writer->writeStartElement(QStringLiteral("subelements"));
|
||||
|
||||
for (int i=0; i<arr_sz; i++) {
|
||||
writer->writeStartElement(QStringLiteral("element"));
|
||||
writer->writeAttribute(QStringLiteral("count"), QString::number(arr_sz));
|
||||
|
||||
SaveImmediate(writer, id, i);
|
||||
for (int i=0; i<arr_sz; i++) {
|
||||
writer->writeStartElement(QStringLiteral("element"));
|
||||
|
||||
writer->writeEndElement(); // element
|
||||
SaveImmediate(writer, id, i);
|
||||
|
||||
writer->writeEndElement(); // element
|
||||
}
|
||||
|
||||
writer->writeEndElement(); // subelements
|
||||
}
|
||||
|
||||
writer->writeEndElement(); // subelements
|
||||
}
|
||||
|
||||
bool Node::LoadImmediate(QXmlStreamReader *reader, const QString &input, int element, SerializedData *data)
|
||||
@@ -1545,8 +1567,11 @@ bool Node::LoadImmediate(QXmlStreamReader *reader, const QString &input, int ele
|
||||
reader->skipCurrentElement();
|
||||
}
|
||||
}
|
||||
} else if (reader->name() == QStringLiteral("keyframing") && this->IsInputKeyframable(input)) {
|
||||
this->SetInputIsKeyframing(input, reader->readElementText().toInt(), element);
|
||||
} else if (reader->name() == QStringLiteral("keyframing")) {
|
||||
bool k = reader->readElementText().toInt();
|
||||
if (this->IsInputKeyframable(input)) {
|
||||
this->SetInputIsKeyframing(input, k, element);
|
||||
}
|
||||
} else if (reader->name() == QStringLiteral("keyframes")) {
|
||||
int track = 0;
|
||||
|
||||
@@ -1583,12 +1608,16 @@ bool Node::LoadImmediate(QXmlStreamReader *reader, const QString &input, int ele
|
||||
reader->skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Node::SaveImmediate(QXmlStreamWriter *writer, const QString &input, int element) const
|
||||
{
|
||||
bool is_keyframing = this->IsInputKeyframing(input, element);
|
||||
|
||||
if (this->IsInputKeyframable(input)) {
|
||||
writer->writeTextElement(QStringLiteral("keyframing"), QString::number(this->IsInputKeyframing(input, element)));
|
||||
writer->writeTextElement(QStringLiteral("keyframing"), QString::number(is_keyframing));
|
||||
}
|
||||
|
||||
NodeValue::Type data_type = this->GetInputDataType(input);
|
||||
@@ -1613,24 +1642,26 @@ void Node::SaveImmediate(QXmlStreamWriter *writer, const QString &input, int ele
|
||||
writer->writeEndElement(); // standard
|
||||
|
||||
// Write keyframes
|
||||
writer->writeStartElement(QStringLiteral("keyframes"));
|
||||
if (is_keyframing) {
|
||||
writer->writeStartElement(QStringLiteral("keyframes"));
|
||||
|
||||
for (const NodeKeyframeTrack& track : this->GetKeyframeTracks(input, element)) {
|
||||
writer->writeStartElement(QStringLiteral("track"));
|
||||
for (const NodeKeyframeTrack& track : this->GetKeyframeTracks(input, element)) {
|
||||
writer->writeStartElement(QStringLiteral("track"));
|
||||
|
||||
for (NodeKeyframe* key : track) {
|
||||
writer->writeStartElement(QStringLiteral("key"));
|
||||
for (NodeKeyframe* key : track) {
|
||||
writer->writeStartElement(QStringLiteral("key"));
|
||||
|
||||
key->save(writer, data_type);
|
||||
key->save(writer, data_type);
|
||||
|
||||
writer->writeEndElement(); // key
|
||||
writer->writeEndElement(); // key
|
||||
}
|
||||
|
||||
writer->writeEndElement(); // track
|
||||
}
|
||||
|
||||
writer->writeEndElement(); // track
|
||||
writer->writeEndElement(); // keyframes
|
||||
}
|
||||
|
||||
writer->writeEndElement(); // keyframes
|
||||
|
||||
if (data_type == NodeValue::kColor) {
|
||||
// Save color management information
|
||||
writer->writeTextElement(QStringLiteral("csinput"), this->GetInputProperty(input, QStringLiteral("col_input")).toString());
|
||||
@@ -2417,6 +2448,8 @@ bool Node::ValueHint::load(QXmlStreamReader *reader)
|
||||
reader->skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Node::ValueHint::save(QXmlStreamWriter *writer) const
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ namespace olive {
|
||||
|
||||
class Folder;
|
||||
class Project;
|
||||
class SerializedData;
|
||||
struct SerializedData;
|
||||
|
||||
/**
|
||||
* @brief A single processing unit that can be connected with others to create intricate processing systems
|
||||
|
||||
+3
-25
@@ -83,7 +83,7 @@ void Project::Clear()
|
||||
}
|
||||
}
|
||||
|
||||
void Project::Load(QXmlStreamReader *reader)
|
||||
SerializedData Project::Load(QXmlStreamReader *reader)
|
||||
{
|
||||
SerializedData data;
|
||||
|
||||
@@ -156,32 +156,12 @@ void Project::Load(QXmlStreamReader *reader)
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = this->nodes().cbegin(); it != this->nodes().cend(); it++){
|
||||
(*it)->PostLoadEvent(&data);
|
||||
}
|
||||
|
||||
foreach (const SerializedData::SerializedConnection& con, data.desired_connections) {
|
||||
if (Node *out = data.node_ptrs.value(con.output_node)) {
|
||||
Node::ConnectEdge(out, con.input);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (const SerializedData::BlockLink& l, data.block_links) {
|
||||
Node *a = l.block;
|
||||
Node *b = data.node_ptrs.value(l.link);
|
||||
|
||||
Node::Link(a, b);
|
||||
}
|
||||
|
||||
// Re-enable caches and resolve tracks
|
||||
for (Node *n : this->nodes()) {
|
||||
n->SetCachesEnabled(true);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
void Project::Save(QXmlStreamWriter *writer) const
|
||||
{
|
||||
writer->writeAttribute(QStringLiteral("version"), QString::number(230220));
|
||||
writer->writeAttribute(QStringLiteral("version"), QString::number(1));
|
||||
|
||||
writer->writeTextElement(QStringLiteral("uuid"), this->GetUuid().toString());
|
||||
|
||||
@@ -198,8 +178,6 @@ void Project::Save(QXmlStreamWriter *writer) const
|
||||
writer->writeAttribute(QStringLiteral("settings"), QStringLiteral("1"));
|
||||
}
|
||||
|
||||
writer->writeAttribute(QStringLiteral("id"), node->id());
|
||||
|
||||
node->Save(writer);
|
||||
|
||||
writer->writeEndElement(); // node
|
||||
|
||||
+1
-1
@@ -70,7 +70,7 @@ public:
|
||||
return default_nodes_;
|
||||
}
|
||||
|
||||
void Load(QXmlStreamReader *reader);
|
||||
SerializedData Load(QXmlStreamReader *reader);
|
||||
void Save(QXmlStreamWriter *writer) const;
|
||||
|
||||
int GetNumberOfContextsNodeIsIn(Node *node, bool except_itself = false) const;
|
||||
|
||||
@@ -58,7 +58,7 @@ void ProjectSerializer::Destroy()
|
||||
instances_.clear();
|
||||
}
|
||||
|
||||
ProjectSerializer::Result ProjectSerializer::Load(Project *project, const QString &filename, const QString &type)
|
||||
ProjectSerializer::Result ProjectSerializer::Load(Project *project, const QString &filename, LoadType load_type)
|
||||
{
|
||||
QFile project_file(filename);
|
||||
|
||||
@@ -76,7 +76,7 @@ ProjectSerializer::Result ProjectSerializer::Load(Project *project, const QStrin
|
||||
reader.reset(new QXmlStreamReader(&project_file));
|
||||
}
|
||||
|
||||
Result inner_result = Load(project, reader.get(), type);
|
||||
Result inner_result = Load(project, reader.get(), load_type);
|
||||
|
||||
project_file.close();
|
||||
|
||||
@@ -89,14 +89,14 @@ ProjectSerializer::Result ProjectSerializer::Load(Project *project, const QStrin
|
||||
r.SetDetails(reader->errorString());
|
||||
return r;
|
||||
} else {
|
||||
return kSuccess;
|
||||
return inner_result;
|
||||
}
|
||||
} else {
|
||||
return kFileError;
|
||||
}
|
||||
}
|
||||
|
||||
ProjectSerializer::Result ProjectSerializer::Load(Project *project, QXmlStreamReader *reader, const QString &type)
|
||||
ProjectSerializer::Result ProjectSerializer::Load(Project *project, QXmlStreamReader *reader, LoadType load_type)
|
||||
{
|
||||
// Determine project version
|
||||
uint version = 0;
|
||||
@@ -106,24 +106,26 @@ ProjectSerializer::Result ProjectSerializer::Load(Project *project, QXmlStreamRe
|
||||
if (reader->name() == QStringLiteral("olive")
|
||||
|| reader->name() == QStringLiteral("project")) { // 0.1 projects only
|
||||
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
if (reader->name() == QStringLiteral("version")) {
|
||||
version = reader->readElementText().toUInt();
|
||||
} else if (reader->name() == QStringLiteral("url")) {
|
||||
project->SetSavedURL(reader->readElementText());
|
||||
|
||||
// HACK for 0.1 projects
|
||||
if (version == 190219) {
|
||||
res = LoadWithSerializerVersion(version, project, reader);
|
||||
}
|
||||
} else if (reader->name() == type) {
|
||||
// Found our data
|
||||
res = LoadWithSerializerVersion(version, project, reader);
|
||||
} else {
|
||||
reader->skipCurrentElement();
|
||||
XMLAttributeLoop(reader, attr) {
|
||||
if (attr.name() == QStringLiteral("version")) { // 230220+ projects
|
||||
version = attr.value().toUInt();
|
||||
}
|
||||
}
|
||||
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
if (reader->name() == QStringLiteral("version")) { // projects <= 220403
|
||||
version = reader->readElementText().toUInt();
|
||||
} else if (reader->name() == QStringLiteral("url")) {
|
||||
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();
|
||||
}
|
||||
@@ -132,7 +134,7 @@ ProjectSerializer::Result ProjectSerializer::Load(Project *project, QXmlStreamRe
|
||||
return res;
|
||||
}
|
||||
|
||||
ProjectSerializer::Result ProjectSerializer::Paste(const QString &type)
|
||||
ProjectSerializer::Result ProjectSerializer::Paste(LoadType load_type)
|
||||
{
|
||||
QString clipboard = Core::PasteStringFromClipboard();
|
||||
if (clipboard.isEmpty()) {
|
||||
@@ -141,28 +143,10 @@ ProjectSerializer::Result ProjectSerializer::Paste(const QString &type)
|
||||
|
||||
QXmlStreamReader reader(clipboard);
|
||||
|
||||
Project temp;
|
||||
ProjectSerializer::Result res = ProjectSerializer::Load(&temp, &reader, type);
|
||||
|
||||
if (res.code() != ProjectSerializer::kSuccess) {
|
||||
return res;
|
||||
}
|
||||
|
||||
QVector<Node*> pasted_nodes;
|
||||
foreach (Node *n, temp.nodes()) {
|
||||
if (!temp.default_nodes().contains(n)) {
|
||||
// Move nodes out of Project
|
||||
n->setParent(nullptr);
|
||||
pasted_nodes.append(n);
|
||||
}
|
||||
}
|
||||
|
||||
res.SetLoadedNodes(pasted_nodes);
|
||||
|
||||
return res;
|
||||
return ProjectSerializer::Load(nullptr, &reader, load_type);
|
||||
}
|
||||
|
||||
ProjectSerializer::Result ProjectSerializer::Save(const SaveData &data, const QString &type, bool compress)
|
||||
ProjectSerializer::Result ProjectSerializer::Save(const SaveData &data, bool compress)
|
||||
{
|
||||
QString temp_save = FileFunctions::GetSafeTemporaryFilename(data.GetFilename());
|
||||
|
||||
@@ -172,7 +156,7 @@ ProjectSerializer::Result ProjectSerializer::Save(const SaveData &data, const QS
|
||||
QByteArray b;
|
||||
QXmlStreamWriter writer(&b);
|
||||
|
||||
Result inner_result = Save(&writer, data, type);
|
||||
Result inner_result = Save(&writer, data);
|
||||
|
||||
if (writer.hasError()) {
|
||||
Result r(kXmlError);
|
||||
@@ -207,7 +191,7 @@ ProjectSerializer::Result ProjectSerializer::Save(const SaveData &data, const QS
|
||||
}
|
||||
}
|
||||
|
||||
ProjectSerializer::Result ProjectSerializer::Save(QXmlStreamWriter *writer, const SaveData &data, const QString &type)
|
||||
ProjectSerializer::Result ProjectSerializer::Save(QXmlStreamWriter *writer, const SaveData &data)
|
||||
{
|
||||
writer->setAutoFormatting(true);
|
||||
|
||||
@@ -221,18 +205,14 @@ ProjectSerializer::Result ProjectSerializer::Save(QXmlStreamWriter *writer, cons
|
||||
|
||||
// Version is stored in YYMMDD from whenever the project format was last changed
|
||||
// Allows easy integer math for checking project versions.
|
||||
writer->writeTextElement(QStringLiteral("version"), QString::number(serializer->Version()));
|
||||
writer->writeAttribute(QStringLiteral("version"), QString::number(serializer->Version()));
|
||||
|
||||
if (!data.GetFilename().isEmpty()) {
|
||||
writer->writeTextElement("url", data.GetFilename());
|
||||
}
|
||||
|
||||
writer->writeStartElement(type);
|
||||
|
||||
serializer->Save(writer, data, nullptr);
|
||||
|
||||
writer->writeEndElement(); // [type]
|
||||
|
||||
writer->writeEndElement(); // olive
|
||||
|
||||
writer->writeEndDocument();
|
||||
@@ -244,12 +224,12 @@ ProjectSerializer::Result ProjectSerializer::Save(QXmlStreamWriter *writer, cons
|
||||
return kSuccess;
|
||||
}
|
||||
|
||||
ProjectSerializer::Result ProjectSerializer::Copy(const SaveData &data, const QString &type)
|
||||
ProjectSerializer::Result ProjectSerializer::Copy(const SaveData &data)
|
||||
{
|
||||
QString copy_str;
|
||||
QXmlStreamWriter writer(©_str);
|
||||
|
||||
ProjectSerializer::Result res = ProjectSerializer::Save(&writer, data, type);
|
||||
ProjectSerializer::Result res = ProjectSerializer::Save(&writer, data);
|
||||
|
||||
if (res == kSuccess) {
|
||||
Core::CopyStringToClipboard(copy_str);
|
||||
@@ -269,7 +249,7 @@ bool ProjectSerializer::IsCancelled() const
|
||||
return false;
|
||||
}
|
||||
|
||||
ProjectSerializer::Result ProjectSerializer::LoadWithSerializerVersion(uint version, Project *project, QXmlStreamReader *reader)
|
||||
ProjectSerializer::Result ProjectSerializer::LoadWithSerializerVersion(uint version, Project *project, QXmlStreamReader *reader, LoadType load_type)
|
||||
{
|
||||
// Failed to find version in file
|
||||
if (version == 0) {
|
||||
@@ -291,7 +271,7 @@ ProjectSerializer::Result ProjectSerializer::LoadWithSerializerVersion(uint vers
|
||||
}
|
||||
|
||||
if (serializer) {
|
||||
LoadData ld = serializer->Load(project, reader, nullptr);
|
||||
LoadData ld = serializer->Load(project, reader, load_type, nullptr);
|
||||
Result r(kSuccess);
|
||||
if (reader->hasError()) {
|
||||
r = Result(kXmlError);
|
||||
|
||||
@@ -38,6 +38,14 @@ namespace olive {
|
||||
class ProjectSerializer
|
||||
{
|
||||
public:
|
||||
enum LoadType
|
||||
{
|
||||
kProject,
|
||||
kOnlyNodes,
|
||||
kOnlyMarkers,
|
||||
kOnlyKeyframes
|
||||
};
|
||||
|
||||
ProjectSerializer() = default;
|
||||
|
||||
virtual ~ProjectSerializer(){}
|
||||
@@ -69,6 +77,10 @@ public:
|
||||
|
||||
SerializedKeyframes keyframes;
|
||||
|
||||
MainWindowLayoutInfo layout;
|
||||
|
||||
QVector<Node*> nodes;
|
||||
|
||||
};
|
||||
|
||||
class Result
|
||||
@@ -91,10 +103,6 @@ public:
|
||||
|
||||
void SetLoadData(const LoadData &p) { load_data_ = p; }
|
||||
|
||||
const QVector<Node*> &GetLoadedNodes() const { return loaded_nodes_; }
|
||||
|
||||
void SetLoadedNodes(const QVector<Node*> &n) { loaded_nodes_ = n; }
|
||||
|
||||
private:
|
||||
ResultCode code_;
|
||||
|
||||
@@ -102,28 +110,28 @@ public:
|
||||
|
||||
LoadData load_data_;
|
||||
|
||||
QVector<Node*> loaded_nodes_;
|
||||
|
||||
};
|
||||
|
||||
class SaveData
|
||||
{
|
||||
public:
|
||||
SaveData(Project *project = nullptr, const QString &filename = QString())
|
||||
SaveData(LoadType type, Project *project = nullptr, const QString &filename = QString())
|
||||
{
|
||||
type_ = type;
|
||||
project_ = project;
|
||||
filename_ = filename;
|
||||
}
|
||||
|
||||
Project *GetProject() const
|
||||
{
|
||||
return project_;
|
||||
}
|
||||
Project *GetProject() const { return project_; }
|
||||
void SetProject(Project *p) { project_ = p; }
|
||||
|
||||
const QString &GetFilename() const
|
||||
{
|
||||
return filename_;
|
||||
}
|
||||
const QString &GetFilename() const { return filename_; }
|
||||
void SetFilename(const QString &s) { filename_ = s; }
|
||||
|
||||
LoadType type() const { return type_; }
|
||||
|
||||
const MainWindowLayoutInfo &GetLayout() const { return layout_; }
|
||||
void SetLayout(const MainWindowLayoutInfo &layout) { layout_ = layout; }
|
||||
|
||||
const QVector<Node*> &GetOnlySerializeNodes() const { return only_serialize_nodes_; }
|
||||
void SetOnlySerializeNodes(const QVector<Node*> &only) { only_serialize_nodes_ = only; }
|
||||
@@ -139,10 +147,14 @@ public:
|
||||
void SetProperties(const SerializedProperties &p) { properties_ = p; }
|
||||
|
||||
private:
|
||||
LoadType type_;
|
||||
|
||||
Project *project_;
|
||||
|
||||
QString filename_;
|
||||
|
||||
MainWindowLayoutInfo layout_;
|
||||
|
||||
QVector<Node*> only_serialize_nodes_;
|
||||
|
||||
SerializedProperties properties_;
|
||||
@@ -157,18 +169,18 @@ public:
|
||||
|
||||
static void Destroy();
|
||||
|
||||
static Result Load(Project *project, const QString &filename, const QString &type);
|
||||
static Result Load(Project *project, QXmlStreamReader *read_device, const QString &type);
|
||||
static Result Paste(const QString &type);
|
||||
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);
|
||||
|
||||
static Result Save(const SaveData &data, const QString &type, bool compress);
|
||||
static Result Save(QXmlStreamWriter *write_device, const SaveData &data, const QString &type);
|
||||
static Result Copy(const SaveData &data, const QString &type);
|
||||
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);
|
||||
|
||||
protected:
|
||||
virtual LoadData Load(Project *project, QXmlStreamReader *reader, 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 {}
|
||||
|
||||
@@ -177,7 +189,7 @@ protected:
|
||||
bool IsCancelled() const;
|
||||
|
||||
private:
|
||||
static Result LoadWithSerializerVersion(uint version, Project *project, QXmlStreamReader *reader);
|
||||
static Result LoadWithSerializerVersion(uint version, Project *project, QXmlStreamReader *reader, LoadType load_type);
|
||||
|
||||
static QVector<ProjectSerializer*> instances_;
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
ProjectSerializer::LoadData ProjectSerializer190219::Load(Project *project, QXmlStreamReader *reader, void *reserved) const
|
||||
ProjectSerializer::LoadData ProjectSerializer190219::Load(Project *project, QXmlStreamReader *reader, LoadType load_type, void *reserved) const
|
||||
{
|
||||
return LoadData();
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
ProjectSerializer190219() = default;
|
||||
|
||||
protected:
|
||||
virtual LoadData Load(Project *project, QXmlStreamReader *reader, void *reserved) const override;
|
||||
virtual LoadData Load(Project *project, QXmlStreamReader *reader, LoadType load_type, void *reserved) const override;
|
||||
|
||||
virtual uint Version() const override
|
||||
{
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
ProjectSerializer210528::LoadData ProjectSerializer210528::Load(Project *project, QXmlStreamReader *reader, void *reserved) const
|
||||
ProjectSerializer210528::LoadData ProjectSerializer210528::Load(Project *project, QXmlStreamReader *reader, LoadType load_type, void *reserved) const
|
||||
{
|
||||
XMLNodeData xml_node_data;
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
ProjectSerializer210528() = default;
|
||||
|
||||
protected:
|
||||
virtual LoadData Load(Project *project, QXmlStreamReader *reader, void *reserved) const override;
|
||||
virtual LoadData Load(Project *project, QXmlStreamReader *reader, LoadType load_type, void *reserved) const override;
|
||||
|
||||
virtual uint Version() const override
|
||||
{
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
ProjectSerializer210907::LoadData ProjectSerializer210907::Load(Project *project, QXmlStreamReader *reader, void *reserved) const
|
||||
ProjectSerializer210907::LoadData ProjectSerializer210907::Load(Project *project, QXmlStreamReader *reader, LoadType load_type, void *reserved) const
|
||||
{
|
||||
XMLNodeData xml_node_data;
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
ProjectSerializer210907() = default;
|
||||
|
||||
protected:
|
||||
virtual LoadData Load(Project *project, QXmlStreamReader *reader, void *reserved) const override;
|
||||
virtual LoadData Load(Project *project, QXmlStreamReader *reader, LoadType load_type, void *reserved) const override;
|
||||
|
||||
virtual uint Version() const override
|
||||
{
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
ProjectSerializer211228::LoadData ProjectSerializer211228::Load(Project *project, QXmlStreamReader *reader, void *reserved) const
|
||||
ProjectSerializer211228::LoadData ProjectSerializer211228::Load(Project *project, QXmlStreamReader *reader, LoadType load_type, void *reserved) const
|
||||
{
|
||||
QMap<quintptr, QMap<QString, QString> > properties;
|
||||
QMap<quintptr, QMap<quintptr, Node::Position> > positions;
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
ProjectSerializer211228() = default;
|
||||
|
||||
protected:
|
||||
virtual LoadData Load(Project *project, QXmlStreamReader *reader, void *reserved) const override;
|
||||
virtual LoadData Load(Project *project, QXmlStreamReader *reader, LoadType load_type, void *reserved) const override;
|
||||
|
||||
virtual uint Version() const override
|
||||
{
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
ProjectSerializer220403::LoadData ProjectSerializer220403::Load(Project *project, QXmlStreamReader *reader, void *reserved) const
|
||||
ProjectSerializer220403::LoadData ProjectSerializer220403::Load(Project *project, QXmlStreamReader *reader, LoadType load_type, void *reserved) const
|
||||
{
|
||||
QMap<quintptr, QMap<QString, QString> > properties;
|
||||
QMap<quintptr, QMap<quintptr, Node::Position> > positions;
|
||||
@@ -34,253 +34,275 @@ ProjectSerializer220403::LoadData ProjectSerializer220403::Load(Project *project
|
||||
|
||||
LoadData load_data;
|
||||
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
if (reader->name() == QStringLiteral("uuid")) {
|
||||
if ((load_type == kProject && reader->name() == QStringLiteral("project"))
|
||||
|| (load_type == kOnlyNodes && (reader->name() == QStringLiteral("nodes") || reader->name() == QStringLiteral("timeline")))
|
||||
|| (load_type == kOnlyKeyframes && reader->name() == QStringLiteral("keyframes"))
|
||||
|| (load_type == kOnlyMarkers && reader->name() == QStringLiteral("markers"))) {
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
if (reader->name() == QStringLiteral("layout")) {
|
||||
|
||||
project->SetUuid(QUuid::fromString(reader->readElementText()));
|
||||
// Since the main window's functions have to occur in the GUI thread (and we're likely
|
||||
// loading in a secondary thread), we load all necessary data into a separate struct so we
|
||||
// can continue loading and queue it with the main window so it can handle the data
|
||||
// appropriately in its own thread.
|
||||
|
||||
} else if (reader->name() == QStringLiteral("nodes")) {
|
||||
load_data.layout = MainWindowLayoutInfo::fromXml(reader, xml_node_data.node_ptrs);
|
||||
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
if (reader->name() == QStringLiteral("node")) {
|
||||
bool is_root = false;
|
||||
bool is_cm = false;
|
||||
bool is_settings = false;
|
||||
QString id;
|
||||
} else if (reader->name() == QStringLiteral("uuid")) {
|
||||
|
||||
{
|
||||
XMLAttributeLoop(reader, attr) {
|
||||
if (attr.name() == QStringLiteral("id")) {
|
||||
id = attr.value().toString();
|
||||
} else if (attr.name() == QStringLiteral("root") && attr.value() == QStringLiteral("1")) {
|
||||
is_root = true;
|
||||
} else if (attr.name() == QStringLiteral("cm") && attr.value() == QStringLiteral("1")) {
|
||||
is_cm = true;
|
||||
} else if (attr.name() == QStringLiteral("settings") && attr.value() == QStringLiteral("1")) {
|
||||
is_settings = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (id.isEmpty()) {
|
||||
qWarning() << "Failed to load node with empty ID";
|
||||
reader->skipCurrentElement();
|
||||
} else {
|
||||
Node* node;
|
||||
|
||||
if (is_root) {
|
||||
node = project->root();
|
||||
} else if (is_cm) {
|
||||
node = project->color_manager();
|
||||
} else if (is_settings) {
|
||||
node = project->settings();
|
||||
} else {
|
||||
node = NodeFactory::CreateFromID(id);
|
||||
}
|
||||
|
||||
if (!node) {
|
||||
qWarning() << "Failed to find node with ID" << id;
|
||||
reader->skipCurrentElement();
|
||||
} else {
|
||||
// Disable cache while node is being loaded (we'll re-enable it later)
|
||||
node->SetCachesEnabled(false);
|
||||
|
||||
LoadNode(node, xml_node_data, reader);
|
||||
|
||||
node->setParent(project);
|
||||
}
|
||||
}
|
||||
if (project) {
|
||||
project->SetUuid(QUuid::fromString(reader->readElementText()));
|
||||
} else {
|
||||
reader->skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
} else if (reader->name() == QStringLiteral("keyframes")) {
|
||||
} else if (reader->name() == QStringLiteral("nodes")) {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
if (reader->name() == QStringLiteral("node")) {
|
||||
bool is_root = false;
|
||||
bool is_cm = false;
|
||||
bool is_settings = false;
|
||||
QString id;
|
||||
|
||||
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;
|
||||
}
|
||||
{
|
||||
XMLAttributeLoop(reader, attr) {
|
||||
if (attr.name() == QStringLiteral("id")) {
|
||||
id = attr.value().toString();
|
||||
} else if (attr.name() == QStringLiteral("root") && attr.value() == QStringLiteral("1")) {
|
||||
is_root = true;
|
||||
} else if (attr.name() == QStringLiteral("cm") && attr.value() == QStringLiteral("1")) {
|
||||
is_cm = true;
|
||||
} else if (attr.name() == QStringLiteral("settings") && attr.value() == QStringLiteral("1")) {
|
||||
is_settings = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (input_id.isEmpty()) {
|
||||
reader->skipCurrentElement();
|
||||
if (id.isEmpty()) {
|
||||
qWarning() << "Failed to load node with empty ID";
|
||||
reader->skipCurrentElement();
|
||||
} else {
|
||||
Node* node;
|
||||
|
||||
if (is_root) {
|
||||
node = project->root();
|
||||
} else if (is_cm) {
|
||||
node = project->color_manager();
|
||||
} else if (is_settings) {
|
||||
node = project->settings();
|
||||
} else {
|
||||
node = NodeFactory::CreateFromID(id);
|
||||
}
|
||||
|
||||
if (!node) {
|
||||
qWarning() << "Failed to find node with ID" << id;
|
||||
reader->skipCurrentElement();
|
||||
} else {
|
||||
// Disable cache while node is being loaded (we'll re-enable it later)
|
||||
node->SetCachesEnabled(false);
|
||||
|
||||
LoadNode(node, xml_node_data, reader);
|
||||
|
||||
if (project) {
|
||||
node->setParent(project);
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
load_data.nodes.append(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
reader->skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
} else if (reader->name() == QStringLiteral("keyframes")) {
|
||||
|
||||
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());
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
LoadKeyframe(reader, key, n->GetInputDataType(input_id));
|
||||
Node *n = nullptr;
|
||||
if (!node_id.isEmpty()) {
|
||||
n = NodeFactory::CreateFromID(node_id);
|
||||
}
|
||||
|
||||
load_data.keyframes[node_id].append(key);
|
||||
} else {
|
||||
reader->skipCurrentElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
reader->skipCurrentElement();
|
||||
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());
|
||||
|
||||
LoadKeyframe(reader, key, 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 if (reader->name() == QStringLiteral("markers")) {
|
||||
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
if (reader->name() == QStringLiteral("marker")) {
|
||||
TimelineMarker *marker = new TimelineMarker();
|
||||
LoadMarker(reader, marker);
|
||||
load_data.markers.push_back(marker);
|
||||
} else {
|
||||
reader->skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
} else if (reader->name() == QStringLiteral("positions")) {
|
||||
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
|
||||
if (reader->name() == QStringLiteral("context")) {
|
||||
|
||||
quintptr context_ptr = 0;
|
||||
XMLAttributeLoop(reader, attr) {
|
||||
if (attr.name() == QStringLiteral("ptr")) {
|
||||
context_ptr = attr.value().toULongLong();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (context_ptr) {
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
if (reader->name() == QStringLiteral("node")) {
|
||||
quintptr node_ptr;
|
||||
Node::Position node_pos;
|
||||
|
||||
if (LoadPosition(reader, &node_ptr, &node_pos)) {
|
||||
if (node_ptr) {
|
||||
positions[context_ptr].insert(node_ptr, node_pos);
|
||||
} else {
|
||||
qWarning() << "Failed to find pointer for node position";
|
||||
reader->skipCurrentElement();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
reader->skipCurrentElement();
|
||||
}
|
||||
} else {
|
||||
reader->skipCurrentElement();
|
||||
}
|
||||
} else {
|
||||
qWarning() << "Attempted to load context with no pointer";
|
||||
reader->skipCurrentElement();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
reader->skipCurrentElement();
|
||||
|
||||
}
|
||||
|
||||
delete n;
|
||||
} else {
|
||||
reader->skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
} else if (reader->name() == QStringLiteral("markers")) {
|
||||
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
if (reader->name() == QStringLiteral("marker")) {
|
||||
TimelineMarker *marker = new TimelineMarker();
|
||||
LoadMarker(reader, marker);
|
||||
load_data.markers.push_back(marker);
|
||||
} else {
|
||||
reader->skipCurrentElement();
|
||||
}
|
||||
}
|
||||
} else if (reader->name() == QStringLiteral("properties")) {
|
||||
|
||||
} else if (reader->name() == QStringLiteral("positions")) {
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
if (reader->name() == QStringLiteral("node")) {
|
||||
quintptr ptr = 0;
|
||||
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
XMLAttributeLoop(reader, attr) {
|
||||
if (attr.name() == QStringLiteral("ptr")) {
|
||||
ptr = attr.value().toULongLong();
|
||||
|
||||
if (reader->name() == QStringLiteral("context")) {
|
||||
|
||||
quintptr context_ptr = 0;
|
||||
XMLAttributeLoop(reader, attr) {
|
||||
if (attr.name() == QStringLiteral("ptr")) {
|
||||
context_ptr = attr.value().toULongLong();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (context_ptr) {
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
if (reader->name() == QStringLiteral("node")) {
|
||||
quintptr node_ptr;
|
||||
Node::Position node_pos;
|
||||
|
||||
if (LoadPosition(reader, &node_ptr, &node_pos)) {
|
||||
if (node_ptr) {
|
||||
positions[context_ptr].insert(node_ptr, node_pos);
|
||||
} else {
|
||||
qWarning() << "Failed to find pointer for node position";
|
||||
reader->skipCurrentElement();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
reader->skipCurrentElement();
|
||||
// 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 {
|
||||
qWarning() << "Attempted to load context with no pointer";
|
||||
reader->skipCurrentElement();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
reader->skipCurrentElement();
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Skip this
|
||||
reader->skipCurrentElement();
|
||||
|
||||
}
|
||||
|
||||
|
||||
} 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 {
|
||||
|
||||
// Skip this
|
||||
reader->skipCurrentElement();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,7 +331,8 @@ ProjectSerializer220403::LoadData ProjectSerializer220403::Load(Project *project
|
||||
}
|
||||
|
||||
// Re-enable caches and resolve tracks
|
||||
for (Node *n : project->nodes()) {
|
||||
const QVector<Node*> &nodes = project ? project->nodes() : load_data.nodes;
|
||||
for (Node *n : nodes) {
|
||||
n->SetCachesEnabled(true);
|
||||
|
||||
if (Track *t = dynamic_cast<Track *>(n)) {
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
ProjectSerializer220403() = default;
|
||||
|
||||
protected:
|
||||
virtual LoadData Load(Project *project, QXmlStreamReader *reader, void *reserved) const override;
|
||||
virtual LoadData Load(Project *project, QXmlStreamReader *reader, LoadType load_type, void *reserved) const override;
|
||||
|
||||
virtual uint Version() const override
|
||||
{
|
||||
|
||||
@@ -23,21 +23,349 @@
|
||||
#include "config/config.h"
|
||||
#include "node/factory.h"
|
||||
#include "node/group/group.h"
|
||||
#include "node/serializeddata.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
ProjectSerializer230220::LoadData ProjectSerializer230220::Load(Project *project, QXmlStreamReader *reader, void *reserved) const
|
||||
ProjectSerializer230220::LoadData ProjectSerializer230220::Load(Project *project, QXmlStreamReader *reader, LoadType load_type, void *reserved) const
|
||||
{
|
||||
QMap<quintptr, QMap<QString, QString> > properties;
|
||||
QMap<quintptr, QMap<quintptr, Node::Position> > positions;
|
||||
LoadData load_data;
|
||||
SerializedData project_data;
|
||||
|
||||
project->Load(reader);
|
||||
switch (load_type) {
|
||||
case kProject:
|
||||
{
|
||||
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);
|
||||
break;
|
||||
}
|
||||
case kOnlyMarkers:
|
||||
{
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
if (reader->name() == QStringLiteral("marker")) {
|
||||
TimelineMarker *marker = new TimelineMarker();
|
||||
marker->load(reader);
|
||||
load_data.markers.push_back(marker);
|
||||
} else {
|
||||
reader->skipCurrentElement();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kOnlyKeyframes:
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kOnlyNodes:
|
||||
{
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
if (reader->name() == QStringLiteral("node")) {
|
||||
QString id;
|
||||
|
||||
XMLAttributeLoop(reader, attr) {
|
||||
if (attr.name() == QStringLiteral("id")) {
|
||||
id = attr.value().toString();
|
||||
}
|
||||
}
|
||||
|
||||
if (id.isEmpty()) {
|
||||
qWarning() << "Failed to load node with empty ID";
|
||||
reader->skipCurrentElement();
|
||||
} else {
|
||||
Node* node = NodeFactory::CreateFromID(id);
|
||||
if (!node) {
|
||||
qWarning() << "Failed to find node with ID" << id;
|
||||
reader->skipCurrentElement();
|
||||
} else {
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
||||
PostConnect(load_data.nodes, &project_data);
|
||||
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return load_data;
|
||||
}
|
||||
|
||||
void ProjectSerializer230220::Save(QXmlStreamWriter *writer, const SaveData &data, void *reserved) const
|
||||
{
|
||||
if (!data.GetOnlySerializeMarkers().empty()) {
|
||||
writer->writeStartElement(QStringLiteral("markers"));
|
||||
|
||||
writer->writeAttribute(QStringLiteral("version"), QString::number(1));
|
||||
|
||||
for (auto it=data.GetOnlySerializeMarkers().cbegin(); it!=data.GetOnlySerializeMarkers().cend(); it++) {
|
||||
TimelineMarker *marker = *it;
|
||||
writer->writeStartElement(QStringLiteral("marker"));
|
||||
marker->save(writer);
|
||||
writer->writeEndElement(); // marker
|
||||
}
|
||||
|
||||
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()) {
|
||||
writer->writeStartElement(QStringLiteral("nodes"));
|
||||
|
||||
writer->writeAttribute(QStringLiteral("version"), QString::number(1));
|
||||
|
||||
for (Node *n : data.GetOnlySerializeNodes()) {
|
||||
writer->writeStartElement(QStringLiteral("node"));
|
||||
n->Save(writer);
|
||||
writer->writeEndElement();
|
||||
}
|
||||
|
||||
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"));
|
||||
project->Save(writer);
|
||||
writer->writeEndElement();
|
||||
|
||||
writer->writeStartElement(QStringLiteral("layout"));
|
||||
data.GetLayout().toXml(writer);
|
||||
writer->writeEndElement();
|
||||
} else {
|
||||
qCritical() << "ProjectSerializer provided nothing to save";
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectSerializer230220::PostConnect(const QVector<Node *> &nodes, SerializedData *project_data) const
|
||||
{
|
||||
for (auto it = nodes.cbegin(); it != nodes.cend(); it++){
|
||||
Node *n = *it;
|
||||
|
||||
n->PostLoadEvent(project_data);
|
||||
|
||||
n->SetCachesEnabled(true);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
ProjectSerializer230220() = default;
|
||||
|
||||
protected:
|
||||
virtual LoadData Load(Project *project, QXmlStreamReader *reader, 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;
|
||||
|
||||
@@ -40,6 +40,9 @@ protected:
|
||||
return 230220;
|
||||
}
|
||||
|
||||
private:
|
||||
void PostConnect(const QVector<Node*> &nodes, SerializedData *project_data) const;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ struct SerializedData {
|
||||
QHash<QString, QVariant> custom_properties;
|
||||
};
|
||||
|
||||
QMap<quintptr, QMap<quintptr, Node::Position> > positions;
|
||||
QMap<Node *, QMap<quintptr, Node::Position> > positions;
|
||||
QHash<quintptr, Node*> node_ptrs;
|
||||
QList<SerializedConnection> desired_connections;
|
||||
QList<BlockLink> block_links;
|
||||
|
||||
@@ -37,7 +37,9 @@ bool ProjectLoadTask::Run()
|
||||
|
||||
project_->set_filename(GetFilename());
|
||||
|
||||
ProjectSerializer::Result result = ProjectSerializer::Load(project_, GetFilename(), QStringLiteral("project"));
|
||||
ProjectSerializer::Result result = ProjectSerializer::Load(project_, GetFilename(), ProjectSerializer::kProject);
|
||||
|
||||
layout_ = result.GetLoadData().layout;
|
||||
|
||||
switch (result.code()) {
|
||||
case ProjectSerializer::kSuccess:
|
||||
|
||||
@@ -50,11 +50,11 @@ public:
|
||||
protected:
|
||||
Project* project_;
|
||||
|
||||
MainWindowLayoutInfo layout_;
|
||||
|
||||
private:
|
||||
QString filename_;
|
||||
|
||||
MainWindowLayoutInfo layout_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -41,9 +41,13 @@ bool ProjectSaveTask::Run()
|
||||
{
|
||||
QString using_filename = override_filename_.isEmpty() ? project_->filename() : override_filename_;
|
||||
|
||||
ProjectSerializer::SaveData data(project_, using_filename);
|
||||
ProjectSerializer::SaveData data(ProjectSerializer::kProject);
|
||||
|
||||
ProjectSerializer::Result result = ProjectSerializer::Save(data, QStringLiteral("project"), use_compression_);
|
||||
data.SetFilename(using_filename);
|
||||
data.SetProject(project_);
|
||||
data.SetLayout(layout_);
|
||||
|
||||
ProjectSerializer::Result result = ProjectSerializer::Save(data, use_compression_);
|
||||
|
||||
bool success = false;
|
||||
|
||||
|
||||
@@ -164,6 +164,8 @@ bool TimelineMarker::load(QXmlStreamReader *reader)
|
||||
|
||||
// This element has no inner text, so just skip it
|
||||
reader->skipCurrentElement();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TimelineMarker::save(QXmlStreamWriter *writer) const
|
||||
|
||||
@@ -66,6 +66,7 @@ bool TimelineWorkArea::load(QXmlStreamReader *reader)
|
||||
version = attr.value().toUInt();
|
||||
}
|
||||
}
|
||||
Q_UNUSED(version)
|
||||
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
if (reader->name() == QStringLiteral("enabled")) {
|
||||
|
||||
@@ -188,10 +188,10 @@ void KeyframeView::SelectionManagerDeselectEvent(void *obj)
|
||||
bool KeyframeView::CopySelected(bool cut)
|
||||
{
|
||||
if (!selection_manager_.GetSelectedObjects().empty()) {
|
||||
ProjectSerializer::SaveData sdata;
|
||||
ProjectSerializer::SaveData sdata(ProjectSerializer::kOnlyKeyframes);
|
||||
sdata.SetOnlySerializeKeyframes(selection_manager_.GetSelectedObjects());
|
||||
|
||||
ProjectSerializer::Copy(sdata, QStringLiteral("keyframes"));
|
||||
ProjectSerializer::Copy(sdata);
|
||||
|
||||
if (cut) {
|
||||
DeleteSelected();
|
||||
@@ -209,7 +209,7 @@ bool KeyframeView::Paste(std::function<Node *(const QString &)> find_node_functi
|
||||
return false;
|
||||
}
|
||||
|
||||
ProjectSerializer::Result res = ProjectSerializer::Paste(QStringLiteral("keyframes"));
|
||||
ProjectSerializer::Result res = ProjectSerializer::Paste(ProjectSerializer::kOnlyKeyframes);
|
||||
if (res == ProjectSerializer::kSuccess) {
|
||||
const ProjectSerializer::SerializedKeyframes &keys = res.GetLoadData().keyframes;
|
||||
|
||||
|
||||
@@ -537,7 +537,7 @@ bool NodeParamView::CopySelected(bool cut)
|
||||
return false;
|
||||
}
|
||||
|
||||
ProjectSerializer::SaveData sdata(contexts_.first()->project());
|
||||
ProjectSerializer::SaveData sdata(ProjectSerializer::kOnlyNodes);
|
||||
ProjectSerializer::SerializedProperties properties;
|
||||
QVector<Node*> nodes;
|
||||
|
||||
@@ -558,7 +558,7 @@ bool NodeParamView::CopySelected(bool cut)
|
||||
sdata.SetOnlySerializeNodesAndResolveGroups(nodes);
|
||||
sdata.SetProperties(properties);
|
||||
|
||||
ProjectSerializer::Copy(sdata, QStringLiteral("nodes"));
|
||||
ProjectSerializer::Copy(sdata);
|
||||
|
||||
if (cut) {
|
||||
DeleteSelected();
|
||||
@@ -580,15 +580,15 @@ bool NodeParamView::Paste()
|
||||
|
||||
bool NodeParamView::Paste(QWidget *parent, std::function<QHash<Node *, Node*>(const ProjectSerializer::Result &)> get_existing_map_function)
|
||||
{
|
||||
ProjectSerializer::Result res = ProjectSerializer::Paste(QStringLiteral("nodes"));
|
||||
if (res.GetLoadedNodes().isEmpty()) {
|
||||
ProjectSerializer::Result res = ProjectSerializer::Paste(ProjectSerializer::kOnlyNodes);
|
||||
if (res.GetLoadData().nodes.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Determine if any nodes of this type are already in the editor
|
||||
QHash<Node*, Node*> existing_nodes = get_existing_map_function(res);
|
||||
|
||||
QVector<Node*> nodes_to_paste_as_new = res.GetLoadedNodes();
|
||||
QVector<Node*> nodes_to_paste_as_new = res.GetLoadData().nodes;
|
||||
MultiUndoCommand *command = new MultiUndoCommand();
|
||||
|
||||
if (!existing_nodes.empty()) {
|
||||
@@ -835,7 +835,7 @@ QHash<Node *, Node *> NodeParamView::GenerateExistingPasteMap(const ProjectSeria
|
||||
{
|
||||
QVector<Node*> ignore_nodes;
|
||||
QHash<Node*, Node*> existing_nodes;
|
||||
for (Node *n : r.GetLoadedNodes()) {
|
||||
for (Node *n : r.GetLoadData().nodes) {
|
||||
if (Node *existing = GetNodeWithIDAndIgnoreList(n->id(), ignore_nodes)) {
|
||||
existing_nodes.insert(existing, n);
|
||||
ignore_nodes.append(existing);
|
||||
|
||||
@@ -225,7 +225,7 @@ void NodeView::CopySelected(bool cut)
|
||||
QString copy_str;
|
||||
QXmlStreamWriter writer(©_str);
|
||||
|
||||
ProjectSerializer::SaveData sdata(selected_nodes_.first()->project());
|
||||
ProjectSerializer::SaveData sdata(ProjectSerializer::kOnlyNodes);
|
||||
sdata.SetOnlySerializeNodesAndResolveGroups(selected_nodes_);
|
||||
|
||||
ProjectSerializer::SerializedProperties properties;
|
||||
@@ -244,7 +244,7 @@ void NodeView::CopySelected(bool cut)
|
||||
|
||||
sdata.SetProperties(properties);
|
||||
|
||||
ProjectSerializer::Save(&writer, sdata, QStringLiteral("nodes"));
|
||||
ProjectSerializer::Save(&writer, sdata);
|
||||
|
||||
Core::CopyStringToClipboard(copy_str);
|
||||
|
||||
@@ -259,8 +259,8 @@ void NodeView::Paste()
|
||||
return;
|
||||
}
|
||||
|
||||
ProjectSerializer::Result res = ProjectSerializer::Paste(QStringLiteral("nodes"));
|
||||
if (res.GetLoadedNodes().isEmpty()) {
|
||||
ProjectSerializer::Result res = ProjectSerializer::Paste(ProjectSerializer::kOnlyNodes);
|
||||
if (res.GetLoadData().nodes.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -274,12 +274,10 @@ void NodeView::Paste()
|
||||
pos.position.setY(node_props.value(QStringLiteral("y")).toDouble());
|
||||
pos.expanded = node_props.value(QStringLiteral("expanded")).toDouble();
|
||||
|
||||
qDebug() << it.key() << pos.position;
|
||||
|
||||
map.insert(it.key(), pos);
|
||||
}
|
||||
|
||||
PostPaste(res.GetLoadedNodes(), map);
|
||||
PostPaste(res.GetLoadData().nodes, map);
|
||||
}
|
||||
|
||||
void NodeView::Duplicate()
|
||||
|
||||
@@ -911,7 +911,7 @@ void TimeBasedWidget::HideSnaps()
|
||||
|
||||
bool TimeBasedWidget::CopySelected(bool cut)
|
||||
{
|
||||
if (ruler()->hasFocus() && ruler()->CopySelected(cut)) {
|
||||
if (ruler()->CopySelected(cut)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -920,7 +920,7 @@ bool TimeBasedWidget::CopySelected(bool cut)
|
||||
|
||||
bool TimeBasedWidget::Paste()
|
||||
{
|
||||
if (ruler()->hasFocus() && ruler()->PasteMarkers()) {
|
||||
if (ruler()->PasteMarkers()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -646,7 +646,7 @@ bool TimelineWidget::CopySelected(bool cut)
|
||||
}
|
||||
}
|
||||
|
||||
ProjectSerializer::SaveData sdata(selected_nodes.first()->project());
|
||||
ProjectSerializer::SaveData sdata(ProjectSerializer::kOnlyNodes);
|
||||
sdata.SetOnlySerializeNodesAndResolveGroups(selected_nodes);
|
||||
|
||||
// Cache the earliest in point so all copied clips have a "relative" in point that can be pasted anywhere
|
||||
@@ -664,7 +664,7 @@ bool TimelineWidget::CopySelected(bool cut)
|
||||
|
||||
sdata.SetProperties(properties);
|
||||
|
||||
ProjectSerializer::Copy(sdata, QStringLiteral("timeline"));
|
||||
ProjectSerializer::Copy(sdata);
|
||||
|
||||
if (cut) {
|
||||
DeleteSelected();
|
||||
@@ -1958,14 +1958,14 @@ bool TimelineWidget::PasteInternal(bool insert)
|
||||
return false;
|
||||
}
|
||||
|
||||
ProjectSerializer::Result res = ProjectSerializer::Paste(QStringLiteral("timeline"));
|
||||
if (res.GetLoadedNodes().isEmpty()) {
|
||||
ProjectSerializer::Result res = ProjectSerializer::Paste(ProjectSerializer::kOnlyNodes);
|
||||
if (res.GetLoadData().nodes.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MultiUndoCommand *command = new MultiUndoCommand();
|
||||
|
||||
foreach (Node *n, res.GetLoadedNodes()) {
|
||||
foreach (Node *n, res.GetLoadData().nodes) {
|
||||
command->add_child(new NodeAddCommand(GetConnectedNode()->project(), n));
|
||||
}
|
||||
|
||||
@@ -2013,7 +2013,7 @@ QHash<Node *, Node *> TimelineWidget::GenerateExistingPasteMap(const ProjectSeri
|
||||
{
|
||||
QHash<Node *, Node *> m;
|
||||
|
||||
for (Node *n : r.GetLoadedNodes()) {
|
||||
for (Node *n : r.GetLoadData().nodes) {
|
||||
for (Block *b : qAsConst(this->selected_blocks_)) {
|
||||
for (auto it=b->GetContextPositions().cbegin(); it!=b->GetContextPositions().cend(); it++) {
|
||||
if (it.key()->id() == n->id() && !m.contains(it.key())) {
|
||||
|
||||
@@ -123,10 +123,10 @@ void SeekableWidget::DeleteSelected()
|
||||
bool SeekableWidget::CopySelected(bool cut)
|
||||
{
|
||||
if (!selection_manager_.GetSelectedObjects().empty()) {
|
||||
ProjectSerializer::SaveData sdata;
|
||||
ProjectSerializer::SaveData sdata(ProjectSerializer::kOnlyMarkers);
|
||||
sdata.SetOnlySerializeMarkers(selection_manager_.GetSelectedObjects());
|
||||
|
||||
ProjectSerializer::Copy(sdata, QStringLiteral("markers"));
|
||||
ProjectSerializer::Copy(sdata);
|
||||
|
||||
if (cut) {
|
||||
DeleteSelected();
|
||||
@@ -140,7 +140,7 @@ bool SeekableWidget::CopySelected(bool cut)
|
||||
|
||||
bool SeekableWidget::PasteMarkers()
|
||||
{
|
||||
ProjectSerializer::Result res = ProjectSerializer::Paste(QStringLiteral("markers"));
|
||||
ProjectSerializer::Result res = ProjectSerializer::Paste(ProjectSerializer::kOnlyMarkers);
|
||||
if (res == ProjectSerializer::kSuccess) {
|
||||
const std::vector<TimelineMarker*> &markers = res.GetLoadData().markers;
|
||||
if (!markers.empty()) {
|
||||
|
||||
@@ -4,8 +4,6 @@ namespace olive {
|
||||
|
||||
void MainWindowLayoutInfo::toXml(QXmlStreamWriter *writer) const
|
||||
{
|
||||
writer->writeStartElement(QStringLiteral("layout"));
|
||||
|
||||
writer->writeAttribute(QStringLiteral("version"), QString::number(kVersion));
|
||||
|
||||
writer->writeStartElement(QStringLiteral("folders"));
|
||||
@@ -56,8 +54,6 @@ void MainWindowLayoutInfo::toXml(QXmlStreamWriter *writer) const
|
||||
writer->writeEndElement(); // data
|
||||
|
||||
writer->writeTextElement(QStringLiteral("state"), QString(state_.toBase64()));
|
||||
|
||||
writer->writeEndElement(); // layout
|
||||
}
|
||||
|
||||
MainWindowLayoutInfo MainWindowLayoutInfo::fromXml(QXmlStreamReader *reader, const QHash<quintptr, Node *> &node_ptrs)
|
||||
|
||||
Reference in New Issue
Block a user