From bcd491a3d6ab7c9ae7b697c51913ce2cf28c85e1 Mon Sep 17 00:00:00 2001 From: cg2121 Date: Sat, 25 Mar 2017 04:19:29 -0700 Subject: [PATCH] UI: Add copying/pasting of sources/filters Closes jp9000/obs-studio#860 --- UI/data/locale/en-US.ini | 8 +++ UI/forms/OBSBasic.ui | 50 +++++++++++++++ UI/window-basic-main-scene-collections.cpp | 2 + UI/window-basic-main.cpp | 72 ++++++++++++++++++++++ UI/window-basic-main.hpp | 11 ++++ UI/window-basic-source-select.cpp | 41 +++++++++++- UI/window-basic-source-select.hpp | 2 + 7 files changed, 184 insertions(+), 2 deletions(-) diff --git a/UI/data/locale/en-US.ini b/UI/data/locale/en-US.ini index 31addcbe..c8aad986 100644 --- a/UI/data/locale/en-US.ini +++ b/UI/data/locale/en-US.ini @@ -61,6 +61,14 @@ Deprecated="Deprecated" ReplayBuffer="Replay Buffer" Import="Import" Export="Export" +Copy="Copy" +Paste="Paste" +PasteReference="Paste (Reference)" +PasteDuplicate="Paste (Duplicate)" + +# copy filters +Copy.Filters="Copy Filters" +Paste.Filters="Paste Filters" # updater Updater.Title="New update available" diff --git a/UI/forms/OBSBasic.ui b/UI/forms/OBSBasic.ui index 92aa8ed1..92b8252a 100644 --- a/UI/forms/OBSBasic.ui +++ b/UI/forms/OBSBasic.ui @@ -892,6 +892,51 @@ + + + Copy + + + Ctrl+C + + + + + false + + + PasteReference + + + PasteReference + + + PasteReference + + + Ctrl+V + + + + + Copy.Filters + + + + + false + + + Paste.Filters + + + + + + + + + @@ -1409,6 +1454,11 @@ Basic.MainMenu.Edit.Scale.Output + + + PasteDuplicate + + diff --git a/UI/window-basic-main-scene-collections.cpp b/UI/window-basic-main-scene-collections.cpp index a7154419..03753c19 100644 --- a/UI/window-basic-main-scene-collections.cpp +++ b/UI/window-basic-main-scene-collections.cpp @@ -225,6 +225,8 @@ void OBSBasic::RefreshSceneCollections() OBSBasic *main = reinterpret_cast(App()->GetMainWindow()); main->OpenSavedProjectors(); + main->ui->actionPasteRef->setEnabled(false); + main->ui->actionPasteDup->setEnabled(false); } void OBSBasic::on_actionNewSceneCollection_triggered() diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp index b8486c14..420d126e 100644 --- a/UI/window-basic-main.cpp +++ b/UI/window-basic-main.cpp @@ -3347,6 +3347,19 @@ void OBSBasic::CreateSourcePopupMenu(QListWidgetItem *item, bool preview) if (addSourceMenu) popup.addMenu(addSourceMenu); + ui->actionCopyFilters->setEnabled(false); + + popup.addSeparator(); + popup.addAction(ui->actionCopySource); + popup.addAction(ui->actionPasteRef); + popup.addAction(ui->actionPasteDup); + popup.addSeparator(); + + popup.addSeparator(); + popup.addAction(ui->actionCopyFilters); + popup.addAction(ui->actionPasteFilters); + popup.addSeparator(); + if (item) { if (addSourceMenu) popup.addSeparator(); @@ -3393,6 +3406,8 @@ void OBSBasic::CreateSourcePopupMenu(QListWidgetItem *item, bool preview) SLOT(OpenFilters())); popup.addAction(QTStr("Properties"), this, SLOT(on_actionSourceProperties_triggered())); + + ui->actionCopyFilters->setEnabled(true); } popup.exec(QCursor::pos()); @@ -5270,3 +5285,60 @@ bool OBSBasic::sysTrayMinimizeToTray() return config_get_bool(GetGlobalConfig(), "BasicWindow", "SysTrayMinimizeToTray"); } + +void OBSBasic::on_actionCopySource_triggered() +{ + on_actionCopyTransform_triggered(); + + OBSSceneItem item = GetCurrentSceneItem(); + + if (!item) + return; + + OBSSource source = obs_sceneitem_get_source(item); + + copyString = obs_source_get_name(source); + copyVisible = obs_sceneitem_visible(item); + + ui->actionPasteRef->setEnabled(true); + ui->actionPasteDup->setEnabled(true); +} + +void OBSBasic::on_actionPasteRef_triggered() +{ + OBSBasicSourceSelect::SourcePaste(copyString, copyVisible, false); + on_actionPasteTransform_triggered(); +} + +void OBSBasic::on_actionPasteDup_triggered() +{ + OBSBasicSourceSelect::SourcePaste(copyString, copyVisible, true); + on_actionPasteTransform_triggered(); +} + +void OBSBasic::on_actionCopyFilters_triggered() +{ + OBSSceneItem item = GetCurrentSceneItem(); + + if (!item) + return; + + OBSSource source = obs_sceneitem_get_source(item); + + copyFiltersString = obs_source_get_name(source); + + ui->actionPasteFilters->setEnabled(true); +} + +void OBSBasic::on_actionPasteFilters_triggered() +{ + OBSSource source = obs_get_source_by_name(copyFiltersString); + OBSSceneItem sceneItem = GetCurrentSceneItem(); + + OBSSource dstSource = obs_sceneitem_get_source(sceneItem); + + if (source == dstSource) + return; + + obs_source_copy_filters(dstSource, source); +} diff --git a/UI/window-basic-main.hpp b/UI/window-basic-main.hpp index d89be138..a4e18a87 100644 --- a/UI/window-basic-main.hpp +++ b/UI/window-basic-main.hpp @@ -119,6 +119,10 @@ private: bool projectChanged = false; bool previewEnabled = true; + const char *copyString; + const char *copyFiltersString; + bool copyVisible = true; + QPointer updateCheckThread; QPointer logUploadThread; @@ -413,6 +417,13 @@ private slots: void ToggleShowHide(); + void on_actionCopySource_triggered(); + void on_actionPasteRef_triggered(); + void on_actionPasteDup_triggered(); + + void on_actionCopyFilters_triggered(); + void on_actionPasteFilters_triggered(); + private: /* OBS Callbacks */ static void SceneReordered(void *data, calldata_t *params); diff --git a/UI/window-basic-source-select.cpp b/UI/window-basic-source-select.cpp index b66ba088..de6db69f 100644 --- a/UI/window-basic-source-select.cpp +++ b/UI/window-basic-source-select.cpp @@ -93,7 +93,28 @@ static void AddSource(void *_data, obs_scene_t *scene) obs_sceneitem_set_visible(sceneitem, data->visible); } -static void AddExisting(const char *name, const bool visible) +static char *get_new_source_name(const char *name) +{ + struct dstr new_name = {0}; + int inc = 0; + + dstr_copy(&new_name, name); + + for (;;) { + obs_source_t *existing_source = obs_get_source_by_name( + new_name.array); + if (!existing_source) + break; + + obs_source_release(existing_source); + + dstr_printf(&new_name, "%s %d", name, ++inc + 1); + } + + return new_name.array; +} + +static void AddExisting(const char *name, bool visible, bool duplicate) { OBSBasic *main = reinterpret_cast(App()->GetMainWindow()); OBSScene scene = main->GetCurrentScene(); @@ -102,6 +123,17 @@ static void AddExisting(const char *name, const bool visible) obs_source_t *source = obs_get_source_by_name(name); if (source) { + if (duplicate) { + obs_source_t *from = source; + char *new_name = get_new_source_name(name); + source = obs_source_duplicate(from, new_name, false); + bfree(new_name); + obs_source_release(from); + + if (!source) + return; + } + AddSourceData data; data.source = source; data.visible = visible; @@ -155,7 +187,7 @@ void OBSBasicSourceSelect::on_buttonBox_accepted() if (!item) return; - AddExisting(QT_TO_UTF8(item->text()), visible); + AddExisting(QT_TO_UTF8(item->text()), visible, false); } else { if (ui->sourceName->text().isEmpty()) { QMessageBox::information(this, @@ -243,3 +275,8 @@ OBSBasicSourceSelect::OBSBasicSourceSelect(OBSBasic *parent, const char *id_) obs_enum_sources(EnumSources, this); } } + +void OBSBasicSourceSelect::SourcePaste(const char *name, bool visible, bool dup) +{ + AddExisting(name, visible, dup); +} diff --git a/UI/window-basic-source-select.hpp b/UI/window-basic-source-select.hpp index bdfdc21e..7bab4768 100644 --- a/UI/window-basic-source-select.hpp +++ b/UI/window-basic-source-select.hpp @@ -47,4 +47,6 @@ public: OBSBasicSourceSelect(OBSBasic *parent, const char *id); OBSSource newSource; + + static void SourcePaste(const char *name, bool visible, bool duplicate); }; -- GitLab