From 04a0b6024e8c20ff0c98d1bb3b7ce4255ffde559 Mon Sep 17 00:00:00 2001 From: Thomas Wilshaw Date: Tue, 9 Nov 2021 14:44:51 +0000 Subject: [PATCH] otioload: Add simple dialog to change settings Adds a table of sequences in the OTIO file and allows the settings to be changed. The dialog takes a list of sequences and relies on each OTIO timeline having a unique name. The dialog has to be called from the main thread so there is a wrapper function in Core. --- app/core.cpp | 7 ++ app/core.h | 5 ++ app/dialog/CMakeLists.txt | 3 + app/dialog/otioproperties/CMakeLists.txt | 22 ++++++ .../otioproperties/otiopropertiesdialog.cpp | 79 +++++++++++++++++++ .../otioproperties/otiopropertiesdialog.h | 39 +++++++++ app/task/project/loadotio/loadotio.cpp | 36 ++++++++- 7 files changed, 187 insertions(+), 4 deletions(-) create mode 100644 app/dialog/otioproperties/CMakeLists.txt create mode 100644 app/dialog/otioproperties/otiopropertiesdialog.cpp create mode 100644 app/dialog/otioproperties/otiopropertiesdialog.h diff --git a/app/core.cpp b/app/core.cpp index 48830651a..06a47ea01 100644 --- a/app/core.cpp +++ b/app/core.cpp @@ -43,6 +43,7 @@ #include "dialog/autorecovery/autorecoverydialog.h" #include "dialog/export/export.h" #include "dialog/footagerelink/footagerelinkdialog.h" +#include "dialog/otioproperties/otiopropertiesdialog.h" #include "dialog/sequence/sequence.h" #include "dialog/task/task.h" #include "dialog/preferences/preferences.h" @@ -379,6 +380,12 @@ void Core::DialogExportShow() } } +void Core::DialogImportOTIOShow(QList sequences) { + Project* active_project = GetActiveProject(); + OTIOPropertiesDialog opd(sequences, active_project); + opd.exec(); +} + void Core::CreateNewFolder() { // Locate the most recently focused Project panel (assume that's the panel the user wants to import into) diff --git a/app/core.h b/app/core.h index 3ac9b1e70..4222b7bd5 100644 --- a/app/core.h +++ b/app/core.h @@ -398,6 +398,11 @@ public slots: */ void DialogExportShow(); + /** + * @brief Show OTIO import dialog + */ + void DialogImportOTIOShow(QList sequences); + /** * @brief Create a new folder in the currently active project */ diff --git a/app/dialog/CMakeLists.txt b/app/dialog/CMakeLists.txt index ff82a6b2c..a86a301af 100644 --- a/app/dialog/CMakeLists.txt +++ b/app/dialog/CMakeLists.txt @@ -24,6 +24,9 @@ add_subdirectory(export) add_subdirectory(footagerelink) add_subdirectory(keyframeproperties) add_subdirectory(nodeproperties) +if(OpenTimelineIO_FOUND) + add_subdirectory(otioproperties) +endif() add_subdirectory(preferences) add_subdirectory(progress) add_subdirectory(rendercancel) diff --git a/app/dialog/otioproperties/CMakeLists.txt b/app/dialog/otioproperties/CMakeLists.txt new file mode 100644 index 000000000..8a07ce76a --- /dev/null +++ b/app/dialog/otioproperties/CMakeLists.txt @@ -0,0 +1,22 @@ +# Olive - Non-Linear Video Editor +# Copyright (C) 2019 Olive Team +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +set(OLIVE_SOURCES + ${OLIVE_SOURCES} + dialog/otioproperties/otiopropertiesdialog.h + dialog/otioproperties/otiopropertiesdialog.cpp + PARENT_SCOPE +) diff --git a/app/dialog/otioproperties/otiopropertiesdialog.cpp b/app/dialog/otioproperties/otiopropertiesdialog.cpp new file mode 100644 index 000000000..72797a9fa --- /dev/null +++ b/app/dialog/otioproperties/otiopropertiesdialog.cpp @@ -0,0 +1,79 @@ +/*** + Olive - Non-Linear Video Editor + Copyright (C) 2019 Olive Team + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***/ + +#include "otiopropertiesdialog.h" + +#include +#include +#include +#include +#include +#include + +#include "core.h" +#include "dialog/sequence/sequence.h" + +namespace olive { + +OTIOPropertiesDialog::OTIOPropertiesDialog(QList sequences, Project* active_project, QWidget* parent) : + QDialog(parent), + sequences_(sequences) +{ + QVBoxLayout* layout = new QVBoxLayout(this); + + layout->addWidget(new QLabel("Change settings for each OTIO sequence to be loaded")); + + table_ = new QTreeWidget(); + table_->setColumnCount(2); + table_->setHeaderLabels({tr("Sequence"), tr("Actions")}); + table_->setRootIsDecorated(false); + + for (int i = 0; i < sequences.size(); i++) { + QTreeWidgetItem* item = new QTreeWidgetItem(); + Sequence* s = sequences.at(i); + + QWidget* item_actions = new QWidget(); + QHBoxLayout* item_actions_layout = new QHBoxLayout(item_actions); + QPushButton* item_settings_btn = new QPushButton(tr("Settings")); + item_settings_btn->setProperty("index", i); + connect(item_settings_btn, &QPushButton::clicked, this, &OTIOPropertiesDialog::SetupSequence); + item_actions_layout->addWidget(item_settings_btn); + + item->setText(0, s->GetLabel()); + + table_->addTopLevelItem(item); + + table_->setItemWidget(item, 1, item_actions); + } + + layout->addWidget(table_); + + QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel); + connect(buttons, &QDialogButtonBox::accepted, this, &OTIOPropertiesDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, this, &OTIOPropertiesDialog::reject); + layout->addWidget(buttons); + + setWindowTitle(tr("Load OTIO File")); +} + +void OTIOPropertiesDialog::SetupSequence() { + int index = sender()->property("index").toInt(); + Sequence* s = sequences_.at(index); + SequenceDialog sd(s, SequenceDialog::kNew); + sd.SetUndoable(false); + sd.exec(); +} + +} // namespace olive diff --git a/app/dialog/otioproperties/otiopropertiesdialog.h b/app/dialog/otioproperties/otiopropertiesdialog.h new file mode 100644 index 000000000..541e016b9 --- /dev/null +++ b/app/dialog/otioproperties/otiopropertiesdialog.h @@ -0,0 +1,39 @@ + +#ifndef OTIOPROPERTIESDIALOG_H +#define OTIOPROPERTIESDIALOG_H + +#include +#include + +#include "common/define.h" +#include "opentimelineio/timeline.h" +#include "node/project/sequence/sequence.h" +#include "node/project/project.h" + +namespace olive { + + /** + * @brief Dialog to load setting for OTIO sequences. + * + * Takes a list of Sequences and allows the setting of options for each. + */ + class OTIOPropertiesDialog : public QDialog { + Q_OBJECT + public: + OTIOPropertiesDialog(QList sequences, Project* active_project, QWidget* parent = nullptr); + + private: + QTreeWidget* table_; + + QList sequences_; + + private slots: + /** + * @brief Brings up the Sequence settings dialog. + */ + void SetupSequence(); + }; + +} //namespace olive + +#endif // OTIOPROPERTIESDIALOG_H diff --git a/app/task/project/loadotio/loadotio.cpp b/app/task/project/loadotio/loadotio.cpp index bc1983c41..3dfd96bb1 100644 --- a/app/task/project/loadotio/loadotio.cpp +++ b/app/task/project/loadotio/loadotio.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include "core.h" #include "node/audio/volume/volume.h" @@ -88,10 +89,40 @@ bool LoadOTIOTask::Run() // Keep track of imported footage QMap imported_footage; + QList sequences; + + // Generate a list of sequences with the same names as the timelines. + // Assumes each timeline has a unique name. + foreach (auto timeline, timelines) { + Sequence* sequence = new Sequence(); + sequence->SetLabel(QString::fromStdString(timeline->name())); + // Set default params incase they aren't edited. + sequence->set_default_parameters(); + sequences.append(sequence); + } + + // Dialog has to be called from the main thread so we pass the list of sequences here. + QMetaObject::invokeMethod(Core::instance(), + "DialogImportOTIOShow", + Qt::BlockingQueuedConnection, + Q_ARG(QList,sequences)); foreach (auto timeline, timelines) { // Create sequence - Sequence* sequence = new Sequence(); + Sequence* sequence; + + // Find correct sequence based on itmeline name. + foreach (Sequence* seq, sequences) { + if (seq->GetLabel() == QString::fromStdString(timeline->name())) { + sequence = seq; + break; + } + } + + if (!sequence) { + return false; + } + sequence->SetLabel(QString::fromStdString(timeline->name())); sequence->setParent(project_); FolderAddChild(project_->root(), sequence).redo_now(); @@ -102,9 +133,6 @@ bool LoadOTIOTask::Run() sequence_footage->setParent(project_); FolderAddChild(project_->root(), sequence_footage).redo_now(); - // FIXME: As far as I know, OTIO doesn't store video/audio parameters? - sequence->set_default_parameters(); - // Iterate through tracks for (auto c : timeline->tracks()->children()) { auto otio_track = static_cast(c.value);