implemented much of the project loading logic
Still not functional, but much of the groundwork is done.
This commit is contained in:
@@ -15,6 +15,20 @@ rational rational::fromDouble(const double &flt)
|
||||
return av_d2q(flt, INT_MAX);
|
||||
}
|
||||
|
||||
rational rational::fromString(const QString &str)
|
||||
{
|
||||
QStringList elements = str.split('/');
|
||||
|
||||
switch (elements.size()) {
|
||||
case 0:
|
||||
return rational();
|
||||
case 1:
|
||||
return rational(elements.first().toLongLong());
|
||||
default:
|
||||
return rational(elements.at(0).toLongLong(), elements.at(1).toLongLong());
|
||||
}
|
||||
}
|
||||
|
||||
//Function: print number to cout
|
||||
|
||||
void rational::print(ostream &out) const
|
||||
|
||||
@@ -57,6 +57,8 @@ public:
|
||||
|
||||
static rational fromDouble(const double& flt);
|
||||
|
||||
static rational fromString(const QString& str);
|
||||
|
||||
//Assignment Operators
|
||||
const rational& operator=(const rational &rhs);
|
||||
const rational& operator+=(const rational &rhs);
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#ifndef XMLREADLOOP_H
|
||||
#define XMLREADLOOP_H
|
||||
|
||||
#define XMLReadLoop(reader, section) \
|
||||
while (!reader->atEnd() && !(reader->name() == section && reader->isEndElement()) && reader->readNext())
|
||||
|
||||
#define XMLAttributeLoop(reader, item) \
|
||||
QXmlStreamAttributes __attributes = reader->attributes(); \
|
||||
foreach (const QXmlStreamAttribute& item, __attributes)
|
||||
|
||||
#endif // XMLREADLOOP_H
|
||||
+68
-30
@@ -41,6 +41,7 @@
|
||||
#include "panel/panelmanager.h"
|
||||
#include "panel/project/project.h"
|
||||
#include "panel/viewer/viewer.h"
|
||||
#include "project/projectloadmanager.h"
|
||||
#include "project/projectsavemanager.h"
|
||||
#include "project/item/footage/footage.h"
|
||||
#include "project/item/sequence/sequence.h"
|
||||
@@ -116,9 +117,13 @@ void Core::Start()
|
||||
|
||||
StartGUI(parser.isSet(fullscreen_option));
|
||||
|
||||
// Create new project on startup
|
||||
// FIXME: Load project from startup_project_ instead if not empty
|
||||
AddOpenProject(std::make_shared<Project>());
|
||||
// Load startup project
|
||||
if (startup_project_.isEmpty()) {
|
||||
// If no load project is set, create a new one on open
|
||||
AddOpenProject(std::make_shared<Project>());
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Core::Stop()
|
||||
@@ -408,35 +413,10 @@ void Core::StartGUI(bool full_screen)
|
||||
|
||||
void Core::SaveProjectInternal(Project *project)
|
||||
{
|
||||
// Create save dialog
|
||||
LoadSaveDialog* lsd = new LoadSaveDialog(tr("Saving '%1'").arg(project->filename()), tr("Save Project"), main_window_);
|
||||
lsd->open();
|
||||
|
||||
// Create save manager
|
||||
ProjectSaveManager* psm = new ProjectSaveManager(project);
|
||||
|
||||
// Create a separate thread to save in
|
||||
QThread* save_thread = new QThread();
|
||||
save_thread->start();
|
||||
|
||||
// Move the save manager to this thread
|
||||
psm->moveToThread(save_thread);
|
||||
|
||||
// Connect the save manager progress signal to the progress bar update on the dialog
|
||||
connect(psm, &ProjectSaveManager::ProgressChanged, lsd, &LoadSaveDialog::SetProgress, Qt::QueuedConnection);
|
||||
|
||||
// Connect cancel signal (must be a direct connection or it'll be queued after the save is already finished)
|
||||
connect(lsd, &LoadSaveDialog::Cancelled, psm, &ProjectSaveManager::Cancel, Qt::DirectConnection);
|
||||
|
||||
// Connect cleanup functions (ensure everything new'd in this function is deleteLater'd)
|
||||
connect(psm, &ProjectSaveManager::Finished, lsd, &LoadSaveDialog::accept, Qt::QueuedConnection);
|
||||
connect(psm, &ProjectSaveManager::Finished, lsd, &LoadSaveDialog::deleteLater, Qt::QueuedConnection);
|
||||
connect(psm, &ProjectSaveManager::Finished, psm, &ProjectSaveManager::deleteLater, Qt::QueuedConnection);
|
||||
connect(psm, &ProjectSaveManager::Finished, save_thread, &QThread::quit, Qt::QueuedConnection);
|
||||
connect(psm, &ProjectSaveManager::Finished, save_thread, &QThread::deleteLater, Qt::QueuedConnection);
|
||||
|
||||
// Start the save process
|
||||
QMetaObject::invokeMethod(psm, "Start", Qt::QueuedConnection);
|
||||
InitiateOpenSaveProcess(psm, tr("Saving '%1'").arg(project->filename()), tr("Save Project"));
|
||||
}
|
||||
|
||||
void Core::SaveAutorecovery()
|
||||
@@ -500,7 +480,7 @@ void Core::SaveActiveProjectAs()
|
||||
QString fn = QFileDialog::getSaveFileName(main_window_,
|
||||
tr("Save Project As"),
|
||||
QString(),
|
||||
tr("Olive Project (*.ove)"));
|
||||
GetProjectFilter());
|
||||
|
||||
if (!fn.isEmpty()) {
|
||||
active_project->set_filename(fn);
|
||||
@@ -584,3 +564,61 @@ QString Core::ChannelLayoutToString(const uint64_t &layout)
|
||||
return tr("Unknown (0x%1)").arg(layout, 1, 16);
|
||||
}
|
||||
}
|
||||
|
||||
QString Core::GetProjectFilter() const
|
||||
{
|
||||
return QStringLiteral("%1 (*.ove)").arg("Olive Project");
|
||||
}
|
||||
|
||||
void Core::OpenProjectInternal(const QString &filename)
|
||||
{
|
||||
ProjectLoadManager* plm = new ProjectLoadManager(filename);
|
||||
|
||||
// We use a blocking queued connection here because we want to ensure we have this project instance before the
|
||||
// ProjectLoadManager is destroyed
|
||||
connect(plm, &ProjectLoadManager::ProjectLoaded, this, &Core::AddOpenProject, Qt::BlockingQueuedConnection);
|
||||
|
||||
InitiateOpenSaveProcess(plm, tr("Loading '%1'").arg(filename), tr("Load Project"));
|
||||
}
|
||||
|
||||
void Core::InitiateOpenSaveProcess(ProjectFileManagerBase *manager, const QString& dialog_text, const QString& dialog_title)
|
||||
{
|
||||
// Create save dialog
|
||||
LoadSaveDialog* lsd = new LoadSaveDialog(dialog_text, dialog_title, main_window_);
|
||||
lsd->open();
|
||||
|
||||
// Create a separate thread to save in
|
||||
QThread* save_thread = new QThread();
|
||||
save_thread->start();
|
||||
|
||||
// Move the save manager to this thread
|
||||
manager->moveToThread(save_thread);
|
||||
|
||||
// Connect the save manager progress signal to the progress bar update on the dialog
|
||||
connect(manager, &ProjectFileManagerBase::ProgressChanged, lsd, &LoadSaveDialog::SetProgress, Qt::QueuedConnection);
|
||||
|
||||
// Connect cancel signal (must be a direct connection or it'll be queued after the save is already finished)
|
||||
connect(lsd, &LoadSaveDialog::Cancelled, manager, &ProjectFileManagerBase::Cancel, Qt::DirectConnection);
|
||||
|
||||
// Connect cleanup functions (ensure everything new'd in this function is deleteLater'd)
|
||||
connect(manager, &ProjectFileManagerBase::Finished, lsd, &LoadSaveDialog::accept, Qt::QueuedConnection);
|
||||
connect(manager, &ProjectFileManagerBase::Finished, lsd, &LoadSaveDialog::deleteLater, Qt::QueuedConnection);
|
||||
connect(manager, &ProjectFileManagerBase::Finished, manager, &ProjectFileManagerBase::deleteLater, Qt::QueuedConnection);
|
||||
connect(manager, &ProjectFileManagerBase::Finished, save_thread, &QThread::quit, Qt::QueuedConnection);
|
||||
connect(manager, &ProjectFileManagerBase::Finished, save_thread, &QThread::deleteLater, Qt::QueuedConnection);
|
||||
|
||||
// Start the save process
|
||||
QMetaObject::invokeMethod(manager, "Start", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void Core::OpenProject()
|
||||
{
|
||||
QString file = QFileDialog::getOpenFileName(main_window_,
|
||||
tr("Open Project"),
|
||||
QString(),
|
||||
GetProjectFilter());
|
||||
|
||||
if (!file.isEmpty()) {
|
||||
OpenProjectInternal(file);
|
||||
}
|
||||
}
|
||||
|
||||
+26
-2
@@ -26,6 +26,7 @@
|
||||
|
||||
#include "common/rational.h"
|
||||
#include "project/project.h"
|
||||
#include "project/projectfilemanagerbase.h"
|
||||
#include "project/projectviewmodel.h"
|
||||
#include "task/task.h"
|
||||
#include "tool/tool.h"
|
||||
@@ -174,6 +175,11 @@ public:
|
||||
static QString ChannelLayoutToString(const uint64_t &layout);
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief Starts an open file dialog to load a project from file
|
||||
*/
|
||||
void OpenProject();
|
||||
|
||||
/**
|
||||
* @brief Save the currently active project
|
||||
*
|
||||
@@ -255,9 +261,22 @@ signals:
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Creates an empty project and adds it to the "open projects"
|
||||
* @brief Get the file filter than can be used with QFileDialog to open and save compatible projects
|
||||
*/
|
||||
void AddOpenProject(ProjectPtr p);
|
||||
QString GetProjectFilter() const;
|
||||
|
||||
/**
|
||||
* @brief Internal project open
|
||||
*/
|
||||
void OpenProjectInternal(const QString& filename);
|
||||
|
||||
/**
|
||||
* @brief Initiate a project load or save
|
||||
*
|
||||
* The load and save process are largely similar, both OpenProjectInternal() and SaveProjectInternal() can run
|
||||
* this function with some minor setup differences.
|
||||
*/
|
||||
void InitiateOpenSaveProcess(ProjectFileManagerBase* manager, const QString &dialog_text, const QString &dialog_title);
|
||||
|
||||
/**
|
||||
* @brief Declare custom types/classes for Qt's signal/slot system
|
||||
@@ -334,6 +353,11 @@ private:
|
||||
private slots:
|
||||
void SaveAutorecovery();
|
||||
|
||||
/**
|
||||
* @brief Adds a project to the "open projects" list
|
||||
*/
|
||||
void AddOpenProject(ProjectPtr p);
|
||||
|
||||
};
|
||||
|
||||
#endif // CORE_H
|
||||
|
||||
@@ -40,7 +40,7 @@ ProjectPropertiesDialog::ProjectPropertiesDialog(QWidget *parent) :
|
||||
{
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
|
||||
setWindowTitle(tr("Project Properties"));
|
||||
setWindowTitle(tr("Project Properties for '%1'").arg(working_project_->name()));
|
||||
|
||||
QGroupBox* color_group = new QGroupBox();
|
||||
color_group->setTitle(tr("Color Management"));
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include "common/bezier.h"
|
||||
#include "common/lerp.h"
|
||||
#include "common/xmlreadloop.h"
|
||||
#include "node.h"
|
||||
#include "output.h"
|
||||
#include "inputarray.h"
|
||||
@@ -84,6 +85,85 @@ QString NodeInput::name()
|
||||
return NodeParam::name();
|
||||
}
|
||||
|
||||
void NodeInput::Load(QXmlStreamReader *reader)
|
||||
{
|
||||
XMLAttributeLoop(reader, attr) {
|
||||
if (attr.name() == "keyframing") {
|
||||
set_is_keyframing(attr.value() == "1");
|
||||
}
|
||||
}
|
||||
|
||||
XMLReadLoop(reader, "input") {
|
||||
if (reader->isStartElement()) {
|
||||
if (reader->name() == "standard") {
|
||||
// Load standard value
|
||||
int val_index = 0;
|
||||
|
||||
XMLReadLoop(reader, "standard") {
|
||||
if (reader->name() == "value") {
|
||||
reader->readNext();
|
||||
|
||||
QString value_text = reader->text().toString();
|
||||
|
||||
if (value_text.isEmpty()) {
|
||||
standard_value_.replace(val_index, QVariant());
|
||||
} else {
|
||||
standard_value_.replace(val_index, value_text);
|
||||
}
|
||||
|
||||
val_index++;
|
||||
}
|
||||
}
|
||||
} else if (reader->name() == "keyframes") {
|
||||
int track = 0;
|
||||
|
||||
XMLReadLoop(reader, "keyframes") {
|
||||
if (reader->name() == "track") {
|
||||
XMLReadLoop(reader, "track") {
|
||||
if (reader->name() == "key") {
|
||||
rational key_time;
|
||||
NodeKeyframe::Type key_type;
|
||||
QVariant key_value;
|
||||
QPointF key_in_handle;
|
||||
QPointF key_out_handle;
|
||||
|
||||
XMLAttributeLoop(reader, attr) {
|
||||
if (attr.name() == "time") {
|
||||
key_time = rational::fromString(attr.value().toString());
|
||||
} else if (attr.name() == "type") {
|
||||
key_type = static_cast<NodeKeyframe::Type>(attr.value().toInt());
|
||||
} else if (attr.name() == "inhandlex") {
|
||||
key_in_handle.setX(attr.value().toDouble());
|
||||
} else if (attr.name() == "inhandley") {
|
||||
key_in_handle.setY(attr.value().toDouble());
|
||||
} else if (attr.name() == "outhandlex") {
|
||||
key_out_handle.setX(attr.value().toDouble());
|
||||
} else if (attr.name() == "outhandley") {
|
||||
key_out_handle.setY(attr.value().toDouble());
|
||||
}
|
||||
}
|
||||
|
||||
reader->readNext();
|
||||
|
||||
key_value = reader->text().toString();
|
||||
|
||||
NodeKeyframePtr key = NodeKeyframe::Create(key_time, key_value, key_type, track);
|
||||
key->set_bezier_control_in(key_in_handle);
|
||||
key->set_bezier_control_out(key_out_handle);
|
||||
keyframe_tracks_[track].append(key);
|
||||
}
|
||||
}
|
||||
|
||||
track++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeInput::Save(QXmlStreamWriter *writer) const
|
||||
{
|
||||
writer->writeStartElement("input");
|
||||
@@ -114,6 +194,10 @@ void NodeInput::Save(QXmlStreamWriter *writer) const
|
||||
|
||||
writer->writeAttribute("time", key->time().toString());
|
||||
writer->writeAttribute("type", QString::number(key->type()));
|
||||
writer->writeAttribute("inhandlex", QString::number(key->bezier_control_in().x()));
|
||||
writer->writeAttribute("inhandley", QString::number(key->bezier_control_in().y()));
|
||||
writer->writeAttribute("outhandlex", QString::number(key->bezier_control_out().x()));
|
||||
writer->writeAttribute("outhandley", QString::number(key->bezier_control_out().y()));
|
||||
|
||||
writer->writeCharacters(key->value().toString());
|
||||
|
||||
@@ -137,6 +221,10 @@ const NodeParam::DataType &NodeInput::data_type() const
|
||||
return data_type_;
|
||||
}
|
||||
|
||||
void NodeInput::LoadInternal(QXmlStreamReader *reader)
|
||||
{
|
||||
}
|
||||
|
||||
void NodeInput::SaveInternal(QXmlStreamWriter *writer) const
|
||||
{
|
||||
}
|
||||
|
||||
@@ -54,6 +54,8 @@ public:
|
||||
|
||||
virtual QString name() override;
|
||||
|
||||
virtual void Load(QXmlStreamReader* reader) override;
|
||||
|
||||
virtual void Save(QXmlStreamWriter* writer) const override;
|
||||
|
||||
/**
|
||||
@@ -241,6 +243,8 @@ signals:
|
||||
void KeyframeRemoved(NodeKeyframePtr key);
|
||||
|
||||
protected:
|
||||
virtual void LoadInternal(QXmlStreamReader* reader);
|
||||
|
||||
virtual void SaveInternal(QXmlStreamWriter* writer) const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "inputarray.h"
|
||||
|
||||
#include "common/xmlreadloop.h"
|
||||
#include "node.h"
|
||||
|
||||
NodeInputArray::NodeInputArray(const QString &id, const DataType &type, const QVariant &default_value) :
|
||||
@@ -167,6 +168,18 @@ void NodeInputArray::RemoveAt(int index)
|
||||
RemoveLast();
|
||||
}
|
||||
|
||||
void NodeInputArray::LoadInternal(QXmlStreamReader *reader)
|
||||
{
|
||||
if (reader->name() == "subparameters") {
|
||||
XMLReadLoop(reader, "subparameters") {
|
||||
if (reader->name() == "input") {
|
||||
Append();
|
||||
At(GetSize() - 1)->Load(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeInputArray::SaveInternal(QXmlStreamWriter *writer) const
|
||||
{
|
||||
writer->writeStartElement("subparameters");
|
||||
|
||||
@@ -33,6 +33,8 @@ signals:
|
||||
void SizeChanged(int size);
|
||||
|
||||
protected:
|
||||
virtual void LoadInternal(QXmlStreamReader* reader) override;
|
||||
|
||||
virtual void SaveInternal(QXmlStreamWriter* writer) const override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
|
||||
#include "common/xmlreadloop.h"
|
||||
|
||||
Node::Node() :
|
||||
can_be_deleted_(true)
|
||||
{
|
||||
@@ -47,6 +49,39 @@ Node::~Node()
|
||||
}
|
||||
}
|
||||
|
||||
void Node::Load(QXmlStreamReader *reader)
|
||||
{
|
||||
XMLReadLoop(reader, "node") {
|
||||
if (reader->isStartElement()) {
|
||||
if (reader->name() == "input" || reader->name() == "output") {
|
||||
QString param_id;
|
||||
|
||||
XMLAttributeLoop(reader, attr) {
|
||||
if (attr.name() == "id") {
|
||||
param_id = attr.value().toString();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (param_id.isEmpty()) {
|
||||
qDebug() << "Found parameter with no ID";
|
||||
continue;
|
||||
}
|
||||
|
||||
NodeParam* param = GetParameterWithID(param_id);
|
||||
|
||||
if (!param) {
|
||||
qDebug() << "No parameter in" << id() << "with parameter" << param_id;
|
||||
continue;
|
||||
}
|
||||
|
||||
param->Load(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Node::Save(QXmlStreamWriter *writer) const
|
||||
{
|
||||
writer->writeStartElement("node");
|
||||
|
||||
@@ -65,6 +65,11 @@ public:
|
||||
*/
|
||||
virtual Node* copy() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Clear current node variables and replace them with
|
||||
*/
|
||||
void Load(QXmlStreamReader* reader);
|
||||
|
||||
/**
|
||||
* @brief Save this node into a text/XML format
|
||||
*/
|
||||
|
||||
@@ -41,6 +41,10 @@ QString NodeOutput::name()
|
||||
return NodeParam::name();
|
||||
}
|
||||
|
||||
void NodeOutput::Load(QXmlStreamReader *reader)
|
||||
{
|
||||
}
|
||||
|
||||
void NodeOutput::Save(QXmlStreamWriter *writer) const
|
||||
{
|
||||
writer->writeStartElement("output");
|
||||
|
||||
@@ -42,6 +42,8 @@ public:
|
||||
|
||||
virtual QString name() override;
|
||||
|
||||
virtual void Load(QXmlStreamReader *reader) override;
|
||||
|
||||
virtual void Save(QXmlStreamWriter* writer) const override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -230,6 +230,11 @@ public:
|
||||
|
||||
virtual ~NodeParam() override;
|
||||
|
||||
/**
|
||||
* @brief Load function
|
||||
*/
|
||||
virtual void Load(QXmlStreamReader* reader) = 0;
|
||||
|
||||
/**
|
||||
* @brief Save function
|
||||
*/
|
||||
|
||||
@@ -20,6 +20,10 @@ set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
project/project.h
|
||||
project/project.cpp
|
||||
project/projectfilemanagerbase.h
|
||||
project/projectfilemanagerbase.cpp
|
||||
project/projectloadmanager.h
|
||||
project/projectloadmanager.cpp
|
||||
project/projectsavemanager.h
|
||||
project/projectsavemanager.cpp
|
||||
project/projectviewmodel.h
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
|
||||
#include "folder.h"
|
||||
|
||||
#include "common/xmlreadloop.h"
|
||||
#include "project/item/footage/footage.h"
|
||||
#include "project/item/sequence/sequence.h"
|
||||
#include "ui/icons/icons.h"
|
||||
|
||||
Folder::Folder()
|
||||
@@ -41,6 +44,34 @@ QIcon Folder::icon()
|
||||
return icon::Folder;
|
||||
}
|
||||
|
||||
void Folder::Load(QXmlStreamReader *reader)
|
||||
{
|
||||
XMLAttributeLoop(reader, attr) {
|
||||
if (attr.name() == "name") {
|
||||
set_name(attr.value().toString());
|
||||
}
|
||||
}
|
||||
|
||||
XMLReadLoop(reader, "folder") {
|
||||
if (reader->isStartElement()) {
|
||||
ItemPtr child = nullptr;
|
||||
|
||||
if (reader->name() == "folder") {
|
||||
child = std::make_shared<Folder>();
|
||||
} else if (reader->name() == "footage") {
|
||||
child = std::make_shared<Footage>();
|
||||
} else if (reader->name() == "sequence") {
|
||||
child = std::make_shared<Sequence>();
|
||||
}
|
||||
|
||||
if (child) {
|
||||
child->Load(reader);
|
||||
add_child(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Folder::Save(QXmlStreamWriter *writer) const
|
||||
{
|
||||
writer->writeStartElement("folder");
|
||||
|
||||
@@ -40,6 +40,8 @@ public:
|
||||
|
||||
virtual QIcon icon() override;
|
||||
|
||||
virtual void Load(QXmlStreamReader* reader) override;
|
||||
|
||||
virtual void Save(QXmlStreamWriter* writer) const override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <QCoreApplication>
|
||||
|
||||
#include "common/timecodefunctions.h"
|
||||
#include "common/xmlreadloop.h"
|
||||
#include "ui/icons/icons.h"
|
||||
|
||||
Footage::Footage()
|
||||
@@ -35,6 +36,29 @@ Footage::~Footage()
|
||||
ClearStreams();
|
||||
}
|
||||
|
||||
void Footage::Load(QXmlStreamReader *reader)
|
||||
{
|
||||
QXmlStreamAttributes attributes = reader->attributes();
|
||||
|
||||
foreach (const QXmlStreamAttribute& attr, attributes) {
|
||||
if (attr.name() == "name") {
|
||||
set_name(attr.value().toString());
|
||||
} else if (attr.name() == "filename") {
|
||||
set_filename(attr.value().toString());
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Probe here
|
||||
|
||||
XMLReadLoop(reader, "footage") {
|
||||
if (reader->isStartElement()) {
|
||||
if (reader->name() == "stream") {
|
||||
// FIXME: Load stream custom options here
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Footage::Save(QXmlStreamWriter *writer) const
|
||||
{
|
||||
writer->writeStartElement("footage");
|
||||
|
||||
@@ -60,6 +60,11 @@ public:
|
||||
*/
|
||||
virtual ~Footage() override;
|
||||
|
||||
/**
|
||||
* @brief Load function
|
||||
*/
|
||||
virtual void Load(QXmlStreamReader* reader) override;
|
||||
|
||||
/**
|
||||
* @brief Save function
|
||||
*/
|
||||
|
||||
@@ -63,6 +63,8 @@ public:
|
||||
|
||||
DISABLE_COPY_MOVE(Item)
|
||||
|
||||
virtual void Load(QXmlStreamReader* reader) = 0;
|
||||
|
||||
virtual void Save(QXmlStreamWriter* writer) const = 0;
|
||||
|
||||
virtual Type type() const = 0;
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include "config/config.h"
|
||||
#include "common/channellayout.h"
|
||||
#include "common/timecodefunctions.h"
|
||||
#include "common/xmlreadloop.h"
|
||||
#include "node/factory.h"
|
||||
#include "panel/panelmanager.h"
|
||||
#include "panel/node/node.h"
|
||||
#include "panel/curve/curve.h"
|
||||
@@ -38,6 +40,48 @@ Sequence::Sequence() :
|
||||
{
|
||||
}
|
||||
|
||||
void Sequence::Load(QXmlStreamReader *reader)
|
||||
{
|
||||
XMLAttributeLoop(reader, attr) {
|
||||
if (attr.name() == "name") {
|
||||
set_name(attr.value().toString());
|
||||
}
|
||||
}
|
||||
|
||||
XMLReadLoop(reader, "sequence") {
|
||||
if (reader->isStartElement()) {
|
||||
if (reader->name() == "node") {
|
||||
QString node_id;
|
||||
|
||||
XMLAttributeLoop(reader, attr) {
|
||||
if (attr.name() == "id") {
|
||||
node_id = attr.value().toString();
|
||||
|
||||
// Currently the only thing we need
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (node_id.isEmpty()) {
|
||||
qDebug() << "Found node with no ID";
|
||||
continue;
|
||||
}
|
||||
|
||||
Node* node = NodeFactory::CreateFromID(node_id);
|
||||
|
||||
if (!node) {
|
||||
qDebug() << "Failed to load" << node_id << "- no node with that ID is installed";
|
||||
continue;
|
||||
}
|
||||
|
||||
node->Load(reader);
|
||||
|
||||
AddNode(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Sequence::Save(QXmlStreamWriter *writer) const
|
||||
{
|
||||
writer->writeStartElement("sequence");
|
||||
|
||||
@@ -38,6 +38,11 @@ class Sequence : public Item, public NodeGraph
|
||||
public:
|
||||
Sequence();
|
||||
|
||||
/**
|
||||
* @brief Load function
|
||||
*/
|
||||
virtual void Load(QXmlStreamReader* reader) override;
|
||||
|
||||
/**
|
||||
* @brief Save function
|
||||
*/
|
||||
|
||||
+15
-1
@@ -22,11 +22,25 @@
|
||||
|
||||
#include <QFileInfo>
|
||||
|
||||
#include "common/xmlreadloop.h"
|
||||
|
||||
Project::Project()
|
||||
{
|
||||
root_.set_project(this);
|
||||
}
|
||||
|
||||
void Project::Load(QXmlStreamReader *reader)
|
||||
{
|
||||
XMLReadLoop(reader, "project") {
|
||||
if (reader->isStartElement()) {
|
||||
if (reader->name() == "folder") {
|
||||
// Assume this folder is our root
|
||||
root_.Load(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Project::Save(QXmlStreamWriter *writer) const
|
||||
{
|
||||
writer->writeStartElement("project");
|
||||
@@ -35,7 +49,7 @@ void Project::Save(QXmlStreamWriter *writer) const
|
||||
|
||||
root_.Save(writer);
|
||||
|
||||
|
||||
writer->writeTextElement("ocio", ocio_config_);
|
||||
|
||||
writer->writeEndElement(); // project
|
||||
}
|
||||
|
||||
@@ -44,6 +44,8 @@ class Project : public QObject
|
||||
public:
|
||||
Project();
|
||||
|
||||
void Load(QXmlStreamReader* reader);
|
||||
|
||||
void Save(QXmlStreamWriter* writer) const;
|
||||
|
||||
Folder* root();
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#include "projectfilemanagerbase.h"
|
||||
|
||||
ProjectFileManagerBase::ProjectFileManagerBase() :
|
||||
cancelled_(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ProjectFileManagerBase::Cancel()
|
||||
{
|
||||
cancelled_ = true;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
#ifndef PROJECTFILEMANAGERBASE_H
|
||||
#define PROJECTFILEMANAGERBASE_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "project.h"
|
||||
|
||||
class ProjectFileManagerBase : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ProjectFileManagerBase();
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief Start the save process
|
||||
*
|
||||
* It's recommended to invoke this through Qt signals/slots/QueuedConnection after moving this object to a separate
|
||||
* thread.
|
||||
*/
|
||||
virtual void Start() = 0;
|
||||
|
||||
/**
|
||||
* @brief Cancel the current save
|
||||
*
|
||||
* Always connect to this with a DirectConnection. Otherwise, it'll be queued AFTER the save function is already
|
||||
* complete.
|
||||
*/
|
||||
void Cancel();
|
||||
|
||||
signals:
|
||||
void ProgressChanged(int);
|
||||
|
||||
void Finished();
|
||||
|
||||
private:
|
||||
QAtomicInt cancelled_;
|
||||
|
||||
};
|
||||
|
||||
#endif // PROJECTFILEMANAGERBASE_H
|
||||
@@ -0,0 +1,46 @@
|
||||
#include "projectloadmanager.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QXmlStreamReader>
|
||||
|
||||
ProjectLoadManager::ProjectLoadManager(const QString &filename) :
|
||||
filename_(filename)
|
||||
{
|
||||
}
|
||||
|
||||
void ProjectLoadManager::Start()
|
||||
{
|
||||
QFile project_file(filename_);
|
||||
|
||||
if (project_file.open(QFile::ReadOnly | QFile::Text)) {
|
||||
QXmlStreamReader reader(&project_file);
|
||||
|
||||
while (!reader.atEnd()) {
|
||||
reader.readNext();
|
||||
|
||||
if (reader.isStartElement()) {
|
||||
if (reader.name() == "version") {
|
||||
reader.readNext();
|
||||
|
||||
qDebug() << "Project version:" << reader.text();
|
||||
} else if (reader.name() == "project") {
|
||||
ProjectPtr project = std::make_shared<Project>();
|
||||
|
||||
project->set_filename(filename_);
|
||||
|
||||
project->Load(&reader);
|
||||
|
||||
emit ProjectLoaded(project);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (reader.hasError()) {
|
||||
qDebug() << "Found XML error:" << reader.errorString();
|
||||
}
|
||||
|
||||
project_file.close();
|
||||
}
|
||||
|
||||
emit Finished();
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef PROJECTLOADMANAGER_H
|
||||
#define PROJECTLOADMANAGER_H
|
||||
|
||||
#include "projectfilemanagerbase.h"
|
||||
|
||||
class ProjectLoadManager : public ProjectFileManagerBase
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ProjectLoadManager(const QString& filename);
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief Start the load process
|
||||
*
|
||||
* It's recommended to invoke this through Qt signals/slots/QueuedConnection after moving this object to a separate
|
||||
* thread.
|
||||
*/
|
||||
virtual void Start() override;
|
||||
|
||||
signals:
|
||||
void ProjectLoaded(ProjectPtr project);
|
||||
|
||||
private:
|
||||
QString filename_;
|
||||
|
||||
};
|
||||
|
||||
#endif // PROJECTLOADMANAGER_H
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "projectsavemanager.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
ProjectSaveManager::ProjectSaveManager(Project *project) :
|
||||
project_(project),
|
||||
cancelled_(false)
|
||||
project_(project)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -19,10 +19,14 @@ void ProjectSaveManager::Start()
|
||||
|
||||
writer.writeStartDocument();
|
||||
|
||||
writer.writeStartElement("olive");
|
||||
|
||||
writer.writeTextElement("version", "0.2.0");
|
||||
|
||||
project_->Save(&writer);
|
||||
|
||||
writer.writeEndElement(); // olive
|
||||
|
||||
writer.writeEndDocument();
|
||||
|
||||
project_file.close();
|
||||
@@ -30,8 +34,3 @@ void ProjectSaveManager::Start()
|
||||
|
||||
emit Finished();
|
||||
}
|
||||
|
||||
void ProjectSaveManager::Cancel()
|
||||
{
|
||||
cancelled_ = true;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
#ifndef PROJECTSAVEMANAGER_H
|
||||
#define PROJECTSAVEMANAGER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QXmlStreamWriter>
|
||||
#include "projectfilemanagerbase.h"
|
||||
|
||||
#include "project.h"
|
||||
|
||||
class ProjectSaveManager : public QObject
|
||||
class ProjectSaveManager : public ProjectFileManagerBase
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@@ -19,26 +16,11 @@ public slots:
|
||||
* It's recommended to invoke this through Qt signals/slots/QueuedConnection after moving this object to a separate
|
||||
* thread.
|
||||
*/
|
||||
void Start();
|
||||
|
||||
/**
|
||||
* @brief Cancel the current save
|
||||
*
|
||||
* Always connect to this with a DirectConnection. Otherwise, it'll be queued AFTER the save function is already
|
||||
* complete.
|
||||
*/
|
||||
void Cancel();
|
||||
|
||||
signals:
|
||||
void ProgressChanged(int);
|
||||
|
||||
void Finished();
|
||||
virtual void Start() override;
|
||||
|
||||
private:
|
||||
Project* project_;
|
||||
|
||||
QAtomicInt cancelled_;
|
||||
|
||||
};
|
||||
|
||||
#endif // PROJECTSAVEMANAGER_H
|
||||
|
||||
@@ -41,7 +41,7 @@ MainMenu::MainMenu(QMainWindow *parent) :
|
||||
file_menu_ = new Menu(this, this, SLOT(FileMenuAboutToShow()));
|
||||
file_new_menu_ = new Menu(file_menu_);
|
||||
MenuShared::instance()->AddItemsForNewMenu(file_new_menu_);
|
||||
file_open_item_ = file_menu_->AddItem("openproj", nullptr, nullptr, "Ctrl+O");
|
||||
file_open_item_ = file_menu_->AddItem("openproj", Core::instance(), SLOT(OpenProject()), "Ctrl+O");
|
||||
file_open_recent_menu_ = new Menu(file_menu_);
|
||||
file_open_recent_clear_item_ = file_open_recent_menu_->AddItem("clearopenrecent", nullptr, nullptr);
|
||||
file_save_item_ = file_menu_->AddItem("saveproj", Core::instance(), SLOT(SaveActiveProject()), "Ctrl+S");
|
||||
|
||||
Reference in New Issue
Block a user