From 04a0b6024e8c20ff0c98d1bb3b7ce4255ffde559 Mon Sep 17 00:00:00 2001 From: Thomas Wilshaw Date: Tue, 9 Nov 2021 14:44:51 +0000 Subject: [PATCH 1/8] 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); From dc11358b8516633bcdf13e35656aeee1acff14b9 Mon Sep 17 00:00:00 2001 From: Thomas Wilshaw Date: Tue, 9 Nov 2021 14:50:34 +0000 Subject: [PATCH 2/8] loadotio: Update loading bar --- app/task/project/loadotio/loadotio.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/task/project/loadotio/loadotio.cpp b/app/task/project/loadotio/loadotio.cpp index 3dfd96bb1..84d039903 100644 --- a/app/task/project/loadotio/loadotio.cpp +++ b/app/task/project/loadotio/loadotio.cpp @@ -91,6 +91,10 @@ bool LoadOTIOTask::Run() QMap imported_footage; QList sequences; + // Variables used for loading bar + float number_of_clips = 0; + float clips_done = 0; + // Generate a list of sequences with the same names as the timelines. // Assumes each timeline has a unique name. foreach (auto timeline, timelines) { @@ -99,6 +103,12 @@ bool LoadOTIOTask::Run() // Set default params incase they aren't edited. sequence->set_default_parameters(); sequences.append(sequence); + + // Get number of clips for loading bar + foreach (auto track, timeline->tracks()->children()) { + auto otio_track = static_cast(track.value); + number_of_clips += otio_track->children().size(); + } } // Dialog has to be called from the main thread so we pass the list of sequences here. @@ -305,6 +315,8 @@ bool LoadOTIOTask::Run() } } } + clips_done++; + emit ProgressChanged(clips_done / number_of_clips); } } } From ee801e7bbb1813b5bf316f29811a0cd7733de1f4 Mon Sep 17 00:00:00 2001 From: Thomas Wilshaw Date: Tue, 9 Nov 2021 14:57:15 +0000 Subject: [PATCH 3/8] core: add OTIO guards --- app/core.cpp | 4 ++++ app/core.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/app/core.cpp b/app/core.cpp index 06a47ea01..a665099c9 100644 --- a/app/core.cpp +++ b/app/core.cpp @@ -43,7 +43,9 @@ #include "dialog/autorecovery/autorecoverydialog.h" #include "dialog/export/export.h" #include "dialog/footagerelink/footagerelinkdialog.h" +#ifdef USE_OTIO #include "dialog/otioproperties/otiopropertiesdialog.h" +#endif #include "dialog/sequence/sequence.h" #include "dialog/task/task.h" #include "dialog/preferences/preferences.h" @@ -380,11 +382,13 @@ void Core::DialogExportShow() } } +#ifdef USE_OTIO void Core::DialogImportOTIOShow(QList sequences) { Project* active_project = GetActiveProject(); OTIOPropertiesDialog opd(sequences, active_project); opd.exec(); } +#endif void Core::CreateNewFolder() { diff --git a/app/core.h b/app/core.h index 4222b7bd5..99018f377 100644 --- a/app/core.h +++ b/app/core.h @@ -401,7 +401,9 @@ public slots: /** * @brief Show OTIO import dialog */ +#ifdef USE_OTIO void DialogImportOTIOShow(QList sequences); +#endif /** * @brief Create a new folder in the currently active project From 90a0077c0203f9eb5df806c40f4065caab08f608 Mon Sep 17 00:00:00 2001 From: Thomas Wilshaw Date: Mon, 15 Nov 2021 15:10:26 +0000 Subject: [PATCH 4/8] Fix uninitialized memory build error Join Sequences and timelines together in a QMap for simpler code. --- app/task/project/loadotio/loadotio.cpp | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/app/task/project/loadotio/loadotio.cpp b/app/task/project/loadotio/loadotio.cpp index 84d039903..1b3d82ccf 100644 --- a/app/task/project/loadotio/loadotio.cpp +++ b/app/task/project/loadotio/loadotio.cpp @@ -89,7 +89,7 @@ bool LoadOTIOTask::Run() // Keep track of imported footage QMap imported_footage; - QList sequences; + QMap timeline_sequnce_map; // Variables used for loading bar float number_of_clips = 0; @@ -102,7 +102,7 @@ bool LoadOTIOTask::Run() sequence->SetLabel(QString::fromStdString(timeline->name())); // Set default params incase they aren't edited. sequence->set_default_parameters(); - sequences.append(sequence); + timeline_sequnce_map.insert(timeline, sequence); // Get number of clips for loading bar foreach (auto track, timeline->tracks()->children()) { @@ -115,25 +115,10 @@ bool LoadOTIOTask::Run() QMetaObject::invokeMethod(Core::instance(), "DialogImportOTIOShow", Qt::BlockingQueuedConnection, - Q_ARG(QList,sequences)); + Q_ARG(QList,timeline_sequnce_map.values())); - foreach (auto timeline, timelines) { - // Create 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())); + foreach (auto timeline, timeline_sequnce_map.keys()) { + Sequence* sequence = timeline_sequnce_map.value(timeline); sequence->setParent(project_); FolderAddChild(project_->root(), sequence).redo_now(); From f78469513364e5245c600f33ac59eaaa2fc14160 Mon Sep 17 00:00:00 2001 From: Thomas Wilshaw Date: Wed, 5 Jan 2022 16:27:41 +0000 Subject: [PATCH 5/8] Fix PR comments --- app/core.cpp | 2 +- app/core.h | 2 +- app/dialog/otioproperties/otiopropertiesdialog.cpp | 5 +++-- app/dialog/otioproperties/otiopropertiesdialog.h | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/app/core.cpp b/app/core.cpp index a665099c9..8b9859c9b 100644 --- a/app/core.cpp +++ b/app/core.cpp @@ -383,7 +383,7 @@ void Core::DialogExportShow() } #ifdef USE_OTIO -void Core::DialogImportOTIOShow(QList sequences) { +void Core::DialogImportOTIOShow(const QList& sequences) { Project* active_project = GetActiveProject(); OTIOPropertiesDialog opd(sequences, active_project); opd.exec(); diff --git a/app/core.h b/app/core.h index 99018f377..5b439a8f0 100644 --- a/app/core.h +++ b/app/core.h @@ -402,7 +402,7 @@ public slots: * @brief Show OTIO import dialog */ #ifdef USE_OTIO - void DialogImportOTIOShow(QList sequences); + void DialogImportOTIOShow(const QList& sequences); #endif /** diff --git a/app/dialog/otioproperties/otiopropertiesdialog.cpp b/app/dialog/otioproperties/otiopropertiesdialog.cpp index 72797a9fa..9c5794a02 100644 --- a/app/dialog/otioproperties/otiopropertiesdialog.cpp +++ b/app/dialog/otioproperties/otiopropertiesdialog.cpp @@ -27,13 +27,14 @@ namespace olive { -OTIOPropertiesDialog::OTIOPropertiesDialog(QList sequences, Project* active_project, QWidget* parent) : +OTIOPropertiesDialog::OTIOPropertiesDialog(const 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")); + layout->addWidget(new QLabel(tr("Change settings for each OTIO sequence to be loaded"))); table_ = new QTreeWidget(); table_->setColumnCount(2); diff --git a/app/dialog/otioproperties/otiopropertiesdialog.h b/app/dialog/otioproperties/otiopropertiesdialog.h index 541e016b9..ad66bbd9f 100644 --- a/app/dialog/otioproperties/otiopropertiesdialog.h +++ b/app/dialog/otioproperties/otiopropertiesdialog.h @@ -20,12 +20,12 @@ namespace olive { class OTIOPropertiesDialog : public QDialog { Q_OBJECT public: - OTIOPropertiesDialog(QList sequences, Project* active_project, QWidget* parent = nullptr); + OTIOPropertiesDialog(const QList& sequences, Project* active_project, QWidget* parent = nullptr); private: QTreeWidget* table_; - QList sequences_; + const QList sequences_; private slots: /** From 836903cbe9685033b929a0f8d124b5458e376507 Mon Sep 17 00:00:00 2001 From: Thomas Wilshaw Date: Fri, 7 Jan 2022 00:02:46 +0000 Subject: [PATCH 6/8] Fix PR comments --- app/core.cpp | 4 ++-- app/core.h | 2 +- .../otioproperties/otiopropertiesdialog.cpp | 5 +++-- app/task/project/loadotio/loadotio.cpp | 17 ++++++++++++++++- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/app/core.cpp b/app/core.cpp index 8b9859c9b..09ea47e83 100644 --- a/app/core.cpp +++ b/app/core.cpp @@ -383,10 +383,10 @@ void Core::DialogExportShow() } #ifdef USE_OTIO -void Core::DialogImportOTIOShow(const QList& sequences) { +bool Core::DialogImportOTIOShow(const QList& sequences) { Project* active_project = GetActiveProject(); OTIOPropertiesDialog opd(sequences, active_project); - opd.exec(); + return opd.exec() == QDialog::Accepted; } #endif diff --git a/app/core.h b/app/core.h index 5b439a8f0..45e99ee1e 100644 --- a/app/core.h +++ b/app/core.h @@ -402,7 +402,7 @@ public slots: * @brief Show OTIO import dialog */ #ifdef USE_OTIO - void DialogImportOTIOShow(const QList& sequences); + bool DialogImportOTIOShow(const QList& sequences); #endif /** diff --git a/app/dialog/otioproperties/otiopropertiesdialog.cpp b/app/dialog/otioproperties/otiopropertiesdialog.cpp index 9c5794a02..4d9fffc36 100644 --- a/app/dialog/otioproperties/otiopropertiesdialog.cpp +++ b/app/dialog/otioproperties/otiopropertiesdialog.cpp @@ -34,7 +34,8 @@ OTIOPropertiesDialog::OTIOPropertiesDialog(const QList& sequences, Pr { QVBoxLayout* layout = new QVBoxLayout(this); - layout->addWidget(new QLabel(tr("Change settings for each OTIO sequence to be loaded"))); + layout->addWidget(new QLabel(tr("OpenTimelineIO files to not store sequence properties (resolution, framerate etc.).\n" + "Set the correct parameters here or they will be left at the default setting."))); table_ = new QTreeWidget(); table_->setColumnCount(2); @@ -66,7 +67,7 @@ OTIOPropertiesDialog::OTIOPropertiesDialog(const QList& sequences, Pr connect(buttons, &QDialogButtonBox::rejected, this, &OTIOPropertiesDialog::reject); layout->addWidget(buttons); - setWindowTitle(tr("Load OTIO File")); + setWindowTitle(tr("Load OpenTimelineIO File")); } void OTIOPropertiesDialog::SetupSequence() { diff --git a/app/task/project/loadotio/loadotio.cpp b/app/task/project/loadotio/loadotio.cpp index 1b3d82ccf..e5d902df1 100644 --- a/app/task/project/loadotio/loadotio.cpp +++ b/app/task/project/loadotio/loadotio.cpp @@ -97,9 +97,17 @@ bool LoadOTIOTask::Run() // Generate a list of sequences with the same names as the timelines. // Assumes each timeline has a unique name. + int unnamedSequenceCount = 1; foreach (auto timeline, timelines) { Sequence* sequence = new Sequence(); - sequence->SetLabel(QString::fromStdString(timeline->name())); + if (!timeline->name().empty()) { + sequence->SetLabel(QString::fromStdString(timeline->name())); + } else { + // If the otio timeline does not provide a name, create a default one here + QString label = "Sequence " + QString::number(unnamedSequenceCount); + sequence->SetLabel(QString::fromStdString(label.toStdString())); + unnamedSequenceCount++; + } // Set default params incase they aren't edited. sequence->set_default_parameters(); timeline_sequnce_map.insert(timeline, sequence); @@ -112,11 +120,18 @@ bool LoadOTIOTask::Run() } // Dialog has to be called from the main thread so we pass the list of sequences here. + bool accepted = false; QMetaObject::invokeMethod(Core::instance(), "DialogImportOTIOShow", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(bool, accepted), Q_ARG(QList,timeline_sequnce_map.values())); + if (!accepted) { + SetError(tr("Loading OpenTimelineIO file(s) was canceled")); + return false; + } + foreach (auto timeline, timeline_sequnce_map.keys()) { Sequence* sequence = timeline_sequnce_map.value(timeline); sequence->setParent(project_); From 764c7bb088baf799bc765d013d575485e6e5d328 Mon Sep 17 00:00:00 2001 From: Thomas Wilshaw Date: Fri, 7 Jan 2022 01:20:38 +0000 Subject: [PATCH 7/8] Add tr to string and fix variable name --- app/task/project/loadotio/loadotio.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/task/project/loadotio/loadotio.cpp b/app/task/project/loadotio/loadotio.cpp index bab14d906..8d9e14f2e 100644 --- a/app/task/project/loadotio/loadotio.cpp +++ b/app/task/project/loadotio/loadotio.cpp @@ -97,16 +97,16 @@ bool LoadOTIOTask::Run() // Generate a list of sequences with the same names as the timelines. // Assumes each timeline has a unique name. - int unnamedSequenceCount = 1; + int unnamed_sequence_count = 0; foreach (auto timeline, timelines) { Sequence* sequence = new Sequence(); if (!timeline->name().empty()) { sequence->SetLabel(QString::fromStdString(timeline->name())); } else { // If the otio timeline does not provide a name, create a default one here - QString label = "Sequence " + QString::number(unnamedSequenceCount); + unnamed_sequence_count++; + QString label = tr("Sequence") + QString(" ") + QString::number(unnamed_sequence_count); sequence->SetLabel(QString::fromStdString(label.toStdString())); - unnamedSequenceCount++; } // Set default params incase they aren't edited. sequence->set_default_parameters(); From da00d94b60efe2ae7313b39de7af933096b4c67e Mon Sep 17 00:00:00 2001 From: Thomas Wilshaw Date: Fri, 7 Jan 2022 01:24:29 +0000 Subject: [PATCH 8/8] Fix string creation --- app/task/project/loadotio/loadotio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/task/project/loadotio/loadotio.cpp b/app/task/project/loadotio/loadotio.cpp index 8d9e14f2e..7a0ec6f87 100644 --- a/app/task/project/loadotio/loadotio.cpp +++ b/app/task/project/loadotio/loadotio.cpp @@ -105,7 +105,7 @@ bool LoadOTIOTask::Run() } else { // If the otio timeline does not provide a name, create a default one here unnamed_sequence_count++; - QString label = tr("Sequence") + QString(" ") + QString::number(unnamed_sequence_count); + QString label = tr("Sequence %1").arg(unnamed_sequence_count); sequence->SetLabel(QString::fromStdString(label.toStdString())); } // Set default params incase they aren't edited.