diff --git a/app/core.cpp b/app/core.cpp index d737a0563..55f0b2c49 100644 --- a/app/core.cpp +++ b/app/core.cpp @@ -151,6 +151,30 @@ int Core::execute(QCoreApplication* a) return exit_code; } +void Core::DeclareTypesForQt() +{ + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); +} + void Core::Start() { // Reset config (Config sets to default on construction already, but we do it again here as a workaround that fixes @@ -480,9 +504,11 @@ void Core::AddOpenProject(ProjectPtr p) void Core::AddOpenProjectFromTask(Task *task) { QList projects = static_cast(task)->GetLoadedProjects(); + QList layouts = static_cast(task)->GetLoadedLayouts(); - foreach (ProjectPtr p, projects) { - AddOpenProject(p); + for (int i=0; iLoadLayout(layouts.at(i)); } } @@ -629,29 +655,6 @@ void Core::OpenStartupProject() } } -void Core::DeclareTypesForQt() -{ - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); -} - void Core::StartGUI(bool full_screen) { // Set UI style @@ -1011,21 +1014,11 @@ void Core::OpenProjectInternal(const QString &filename) ProjectLoadTask* plm = new ProjectLoadTask(filename); - if (gui_active_) { + TaskDialog* task_dialog = new TaskDialog(plm, tr("Load Project"), main_window()); - TaskDialog* task_dialog = new TaskDialog(plm, tr("Load Project"), main_window()); + connect(task_dialog, &TaskDialog::TaskSucceeded, this, &Core::AddOpenProjectFromTask); - connect(task_dialog, &TaskDialog::TaskSucceeded, this, &Core::AddOpenProjectFromTask); - - task_dialog->open(); - - } else { - - //connect(plm, &ProjectLoadManager::ProjectLoaded, this, &Core::AddOpenProject); - - - - } + task_dialog->open(); } int Core::CountFilesInFileList(const QFileInfoList &filenames) diff --git a/app/project/item/sequence/sequence.cpp b/app/project/item/sequence/sequence.cpp index b2c5a0c22..9e89a0aaa 100644 --- a/app/project/item/sequence/sequence.cpp +++ b/app/project/item/sequence/sequence.cpp @@ -149,7 +149,7 @@ void Sequence::Save(QXmlStreamWriter *writer) const writer->writeAttribute(QStringLiteral("name"), name()); - writer->writeAttribute(QStringLiteral("ptr"), QString::number(reinterpret_cast(viewer_output_))); + writer->writeAttribute(QStringLiteral("ptr"), QString::number(reinterpret_cast(this))); writer->writeStartElement(QStringLiteral("video")); diff --git a/app/project/project.cpp b/app/project/project.cpp index 014489dd6..653202c02 100644 --- a/app/project/project.cpp +++ b/app/project/project.cpp @@ -37,7 +37,7 @@ Project::Project() : root_.set_project(this); } -void Project::Load(QXmlStreamReader *reader, const QAtomicInt* cancelled) +void Project::Load(QXmlStreamReader *reader, MainWindowLayoutInfo* layout, const QAtomicInt* cancelled) { XMLNodeData xml_node_data; @@ -62,7 +62,12 @@ void Project::Load(QXmlStreamReader *reader, const QAtomicInt* cancelled) } else if (reader->name() == QStringLiteral("layout")) { - Core::instance()->main_window()->LoadLayout(reader, xml_node_data); + // 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. + + *layout = MainWindowLayoutInfo::fromXml(reader, xml_node_data); } else { reader->skipCurrentElement(); @@ -93,7 +98,8 @@ void Project::Save(QXmlStreamWriter *writer) const writer->writeEndElement(); // colormanagement // Save main window project layout - Core::instance()->main_window()->SaveLayout(writer); + MainWindowLayoutInfo main_window_info = Core::instance()->main_window()->SaveLayout(); + main_window_info.toXml(writer); writer->writeEndElement(); // project } diff --git a/app/project/project.h b/app/project/project.h index f61fc50da..ff3f8ce35 100644 --- a/app/project/project.h +++ b/app/project/project.h @@ -26,6 +26,7 @@ #include "render/colormanager.h" #include "project/item/folder/folder.h" +#include "window/mainwindow/mainwindowlayoutinfo.h" OLIVE_NAMESPACE_ENTER @@ -46,7 +47,7 @@ class Project : public QObject public: Project(); - void Load(QXmlStreamReader* reader, const QAtomicInt* cancelled); + void Load(QXmlStreamReader* reader, MainWindowLayoutInfo *layout, const QAtomicInt* cancelled); void Save(QXmlStreamWriter* writer) const; diff --git a/app/task/project/load/load.cpp b/app/task/project/load/load.cpp index 932a94c74..27dff9e11 100644 --- a/app/task/project/load/load.cpp +++ b/app/task/project/load/load.cpp @@ -51,13 +51,16 @@ bool ProjectLoadTask::Run() project->set_filename(filename_); - project->Load(&reader, &IsCancelled()); + MainWindowLayoutInfo layout; + + project->Load(&reader, &layout, &IsCancelled()); // Ensure project is in main thread moveToThread(qApp->thread()); if (!IsCancelled()) { projects_.append(project); + layout_info_.append(layout); } } else { reader.skipCurrentElement(); diff --git a/app/task/project/load/load.h b/app/task/project/load/load.h index fa203abfe..398853028 100644 --- a/app/task/project/load/load.h +++ b/app/task/project/load/load.h @@ -23,6 +23,7 @@ #include "project/project.h" #include "task/task.h" +#include "window/mainwindow/mainwindowlayoutinfo.h" OLIVE_NAMESPACE_ENTER @@ -32,17 +33,24 @@ class ProjectLoadTask : public Task public: ProjectLoadTask(const QString& filename); - const QList& GetLoadedProjects() + const QList& GetLoadedProjects() const { return projects_; } + const QList& GetLoadedLayouts() const + { + return layout_info_; + } + protected: virtual bool Run() override; private: QList projects_; + QList layout_info_; + QString filename_; }; diff --git a/app/window/mainwindow/CMakeLists.txt b/app/window/mainwindow/CMakeLists.txt index 151883684..4b70b8f9e 100644 --- a/app/window/mainwindow/CMakeLists.txt +++ b/app/window/mainwindow/CMakeLists.txt @@ -22,5 +22,7 @@ set(OLIVE_SOURCES window/mainwindow/mainstatusbar.cpp window/mainwindow/mainwindow.h window/mainwindow/mainwindow.cpp + window/mainwindow/mainwindowlayoutinfo.h + window/mainwindow/mainwindowlayoutinfo.cpp PARENT_SCOPE ) diff --git a/app/window/mainwindow/mainwindow.cpp b/app/window/mainwindow/mainwindow.cpp index 09286c316..26b765b0d 100644 --- a/app/window/mainwindow/mainwindow.cpp +++ b/app/window/mainwindow/mainwindow.cpp @@ -111,43 +111,37 @@ MainWindow::~MainWindow() #endif } -void MainWindow::LoadLayout(QXmlStreamReader *reader, XMLNodeData &xml_data) +void MainWindow::LoadLayout(const MainWindowLayoutInfo &info) { - QMetaObject::invokeMethod(this, - "LoadLayoutInternal", - Qt::BlockingQueuedConnection, - Q_ARG(QXmlStreamReader*, reader), - Q_ARG(XMLNodeData*, &xml_data)); + foreach (Folder* folder, info.open_folders()) { + FolderOpen(folder->project(), folder, true); + } + + foreach (Sequence* sequence, info.open_sequences()) { + OpenSequence(sequence, false); + } + + restoreState(info.state()); } -void MainWindow::SaveLayout(QXmlStreamWriter *writer) const +MainWindowLayoutInfo MainWindow::SaveLayout() const { - writer->writeStartElement(QStringLiteral("layout")); - - writer->writeStartElement(QStringLiteral("folders")); + MainWindowLayoutInfo info; foreach (ProjectPanel* panel, folder_panels_) { - writer->writeTextElement(QStringLiteral("folder"), - QString::number(reinterpret_cast(panel->get_root_index().internalPointer()))); + info.add_folder(static_cast(panel->get_root_index().internalPointer())); } - writer->writeEndElement(); // folders - - writer->writeStartElement(QStringLiteral("timeline")); - foreach (TimelinePanel* panel, timeline_panels_) { - writer->writeTextElement(QStringLiteral("sequence"), - QString::number(reinterpret_cast(panel->GetConnectedViewer()))); + info.add_sequence(static_cast(panel->GetConnectedViewer()->parent())); } - writer->writeEndElement(); // timeline + info.set_state(saveState()); - writer->writeTextElement(QStringLiteral("state"), QString(saveState().toBase64())); - - writer->writeEndElement(); // layout + return info; } -void MainWindow::OpenSequence(Sequence *sequence) +void MainWindow::OpenSequence(Sequence *sequence, bool enable_focus) { // See if this sequence is already open, and switch to it if so foreach (TimelinePanel* tl, timeline_panels_) { @@ -164,11 +158,14 @@ void MainWindow::OpenSequence(Sequence *sequence) panel = timeline_panels_.first(); } else { panel = AppendTimelinePanel(); + enable_focus = false; } panel->ConnectViewerNode(sequence->viewer_output()); - TimelineFocused(sequence->viewer_output()); + if (enable_focus) { + TimelineFocused(sequence->viewer_output()); + } } void MainWindow::CloseSequence(Sequence *sequence) @@ -467,53 +464,6 @@ void MainWindow::FloatingPanelCloseRequested() panel->deleteLater(); } -void MainWindow::LoadLayoutInternal(QXmlStreamReader *reader, XMLNodeData *xml_data) -{ - while (XMLReadNextStartElement(reader)) { - if (reader->name() == QStringLiteral("folders")) { - - while (XMLReadNextStartElement(reader)) { - if (reader->name() == QStringLiteral("folder")) { - quintptr item_id = reader->readElementText().toULongLong(); - - Item* open_item = xml_data->item_ptrs.value(item_id); - - if (open_item) { - FolderOpen(open_item->project(), open_item, true); - } - } else { - reader->skipCurrentElement(); - } - } - - } else if (reader->name() == QStringLiteral("timeline")) { - - while (XMLReadNextStartElement(reader)) { - if (reader->name() == QStringLiteral("sequence")) { - quintptr item_id = reader->readElementText().toULongLong(); - - Sequence* open_seq = dynamic_cast(xml_data->item_ptrs.value(item_id)); - - if (open_seq) { - OpenSequence(open_seq); - } - } else { - reader->skipCurrentElement(); - } - } - - } else if (reader->name() == QStringLiteral("state")) { - - QByteArray state = QByteArray::fromBase64(reader->readElementText().toLatin1()); - - restoreState(state); - - } else { - reader->skipCurrentElement(); - } - } -} - TimelinePanel* MainWindow::AppendTimelinePanel() { TimelinePanel* panel = AppendPanelInternal(timeline_panels_); diff --git a/app/window/mainwindow/mainwindow.h b/app/window/mainwindow/mainwindow.h index c9f349051..f06b8c0fe 100644 --- a/app/window/mainwindow/mainwindow.h +++ b/app/window/mainwindow/mainwindow.h @@ -23,6 +23,7 @@ #include +#include "mainwindowlayoutinfo.h" #include "panel/panelmanager.h" #include "panel/audiomonitor/audiomonitor.h" #include "panel/curve/curve.h" @@ -55,11 +56,11 @@ public: virtual ~MainWindow() override; - void LoadLayout(QXmlStreamReader* reader, XMLNodeData& xml_data); + void LoadLayout(const MainWindowLayoutInfo &info); - void SaveLayout(QXmlStreamWriter* writer) const; + MainWindowLayoutInfo SaveLayout() const; - void OpenSequence(Sequence* sequence); + void OpenSequence(Sequence* sequence, bool enable_focus = true); void CloseSequence(Sequence* sequence); @@ -167,8 +168,6 @@ private slots: void FloatingPanelCloseRequested(); - void LoadLayoutInternal(QXmlStreamReader* reader, XMLNodeData *xml_data); - void StatusBarDoubleClicked(); #ifdef Q_OS_LINUX diff --git a/app/window/mainwindow/mainwindowlayoutinfo.cpp b/app/window/mainwindow/mainwindowlayoutinfo.cpp new file mode 100644 index 000000000..168978f79 --- /dev/null +++ b/app/window/mainwindow/mainwindowlayoutinfo.cpp @@ -0,0 +1,96 @@ +#include "mainwindowlayoutinfo.h" + +OLIVE_NAMESPACE_ENTER + +void MainWindowLayoutInfo::toXml(QXmlStreamWriter *writer) const +{ + writer->writeStartElement(QStringLiteral("layout")); + + writer->writeStartElement(QStringLiteral("folders")); + + foreach (Folder* folder, open_folders_) { + writer->writeTextElement(QStringLiteral("folder"), + QString::number(reinterpret_cast(folder))); + } + + writer->writeEndElement(); // folders + + writer->writeStartElement(QStringLiteral("timeline")); + + foreach (Sequence* sequence, open_sequences_) { + writer->writeTextElement(QStringLiteral("sequence"), + QString::number(reinterpret_cast(sequence))); + } + + writer->writeEndElement(); // timeline + + writer->writeTextElement(QStringLiteral("state"), QString(state_.toBase64())); + + writer->writeEndElement(); // layout +} + +MainWindowLayoutInfo MainWindowLayoutInfo::fromXml(QXmlStreamReader *reader, XMLNodeData &xml_data) +{ + MainWindowLayoutInfo info; + + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("folders")) { + + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("folder")) { + quintptr item_id = reader->readElementText().toULongLong(); + + Item* open_item = xml_data.item_ptrs.value(item_id); + + if (open_item) { + info.open_folders_.append(static_cast(open_item)); + } + } else { + reader->skipCurrentElement(); + } + } + + } else if (reader->name() == QStringLiteral("timeline")) { + + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("sequence")) { + quintptr item_id = reader->readElementText().toULongLong(); + + Sequence* open_seq = dynamic_cast(xml_data.item_ptrs.value(item_id)); + + if (open_seq) { + info.open_sequences_.append(open_seq); + } + } else { + reader->skipCurrentElement(); + } + } + + } else if (reader->name() == QStringLiteral("state")) { + + info.state_ = QByteArray::fromBase64(reader->readElementText().toLatin1()); + + } else { + reader->skipCurrentElement(); + } + } + + return info; +} + +void MainWindowLayoutInfo::add_folder(olive::Folder *f) +{ + open_folders_.append(f); +} + +void MainWindowLayoutInfo::add_sequence(Sequence *s) +{ + open_sequences_.append(s); +} + +void MainWindowLayoutInfo::set_state(const QByteArray &layout) +{ + state_ = layout; +} + +OLIVE_NAMESPACE_EXIT diff --git a/app/window/mainwindow/mainwindowlayoutinfo.h b/app/window/mainwindow/mainwindowlayoutinfo.h new file mode 100644 index 000000000..5f76cbc2b --- /dev/null +++ b/app/window/mainwindow/mainwindowlayoutinfo.h @@ -0,0 +1,52 @@ +#ifndef MAINWINDOWLAYOUTINFO_H +#define MAINWINDOWLAYOUTINFO_H + +#include "project/item/folder/folder.h" +#include "project/item/sequence/sequence.h" + +OLIVE_NAMESPACE_ENTER + +class MainWindowLayoutInfo +{ +public: + MainWindowLayoutInfo() = default; + + void toXml(QXmlStreamWriter* writer) const; + + static MainWindowLayoutInfo fromXml(QXmlStreamReader* reader, XMLNodeData &xml_data); + + void add_folder(Folder* f); + + void add_sequence(Sequence* s); + + void set_state(const QByteArray& layout); + + const QList& open_folders() const + { + return open_folders_; + } + + const QList& open_sequences() const + { + return open_sequences_; + } + + const QByteArray& state() const + { + return state_; + } + +private: + QByteArray state_; + + QList open_folders_; + + QList open_sequences_; + +}; + +OLIVE_NAMESPACE_EXIT + +Q_DECLARE_METATYPE(OLIVE_NAMESPACE::MainWindowLayoutInfo) + +#endif // MAINWINDOWLAYOUTINFO_H