From 2b50263d5c6e4016df509b230c9af7a984f20346 Mon Sep 17 00:00:00 2001 From: Clayton Groeneveld Date: Thu, 12 Dec 2019 15:53:47 -0600 Subject: [PATCH] UI, libobs: Add ability to copy/paste single filter --- UI/window-basic-filters.cpp | 38 +++++++++++++++++++++++++++++++++++++ UI/window-basic-filters.hpp | 3 +++ UI/window-basic-main.cpp | 1 + UI/window-basic-main.hpp | 2 ++ libobs/obs-source.c | 28 +++++++++++++++++++++++++++ libobs/obs.h | 2 ++ 6 files changed, 74 insertions(+) diff --git a/UI/window-basic-filters.cpp b/UI/window-basic-filters.cpp index bffa3d812..63d57f8f6 100644 --- a/UI/window-basic-filters.cpp +++ b/UI/window-basic-filters.cpp @@ -741,8 +741,25 @@ void OBSBasicFilters::CustomContextMenu(const QPoint &pos, bool async) popup.addSeparator(); popup.addAction(QTStr("Rename"), this, renameSlot); popup.addAction(QTStr("Remove"), this, removeSlot); + popup.addSeparator(); + + QAction *copyAction = new QAction(QTStr("Copy")); + connect(copyAction, SIGNAL(triggered()), this, + SLOT(CopyFilter())); + copyAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_C)); + ui->effectWidget->addAction(copyAction); + ui->asyncWidget->addAction(copyAction); + popup.addAction(copyAction); } + QAction *pasteAction = new QAction(QTStr("Paste")); + pasteAction->setEnabled(main->copyFilter); + connect(pasteAction, SIGNAL(triggered()), this, SLOT(PasteFilter())); + pasteAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_V)); + ui->effectWidget->addAction(pasteAction); + ui->asyncWidget->addAction(pasteAction); + popup.addAction(pasteAction); + popup.exec(QCursor::pos()); } @@ -864,3 +881,24 @@ void OBSBasicFilters::ResetFilters() view->RefreshProperties(); } + +void OBSBasicFilters::CopyFilter() +{ + OBSSource filter = nullptr; + + if (isAsync) + filter = GetFilter(ui->asyncFilters->currentRow(), true); + else + filter = GetFilter(ui->effectFilters->currentRow(), false); + + main->copyFilter = OBSGetWeakRef(filter); +} + +void OBSBasicFilters::PasteFilter() +{ + OBSSource filter = OBSGetStrongRef(main->copyFilter); + if (!filter) + return; + + obs_source_copy_single_filter(source, filter); +} diff --git a/UI/window-basic-filters.hpp b/UI/window-basic-filters.hpp index ff7f5d1d3..6932836b1 100644 --- a/UI/window-basic-filters.hpp +++ b/UI/window-basic-filters.hpp @@ -111,6 +111,9 @@ private slots: void EffectFilterNameEdited(QWidget *editor, QAbstractItemDelegate::EndEditHint endHint); + void CopyFilter(); + void PasteFilter(); + public: OBSBasicFilters(QWidget *parent, OBSSource source_); ~OBSBasicFilters(); diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp index c425287f1..e2ca1eb47 100644 --- a/UI/window-basic-main.cpp +++ b/UI/window-basic-main.cpp @@ -1112,6 +1112,7 @@ retryScene: copyStrings.clear(); copyFiltersString = nullptr; + copyFilter = nullptr; LogScenes(); diff --git a/UI/window-basic-main.hpp b/UI/window-basic-main.hpp index 3af7ef058..9d3601b61 100644 --- a/UI/window-basic-main.hpp +++ b/UI/window-basic-main.hpp @@ -840,6 +840,8 @@ public: QIcon GetGroupIcon() const; QIcon GetSceneIcon() const; + OBSWeakSource copyFilter = nullptr; + protected: virtual void closeEvent(QCloseEvent *event) override; virtual void changeEvent(QEvent *event) override; diff --git a/libobs/obs-source.c b/libobs/obs-source.c index 409463d25..41b2184bb 100644 --- a/libobs/obs-source.c +++ b/libobs/obs-source.c @@ -31,6 +31,8 @@ #include "obs.h" #include "obs-internal.h" +static bool filter_compatible(obs_source_t *source, obs_source_t *filter); + static inline bool data_valid(const struct obs_source *source, const char *f) { return obs_source_valid(source, f) && source->context.data; @@ -493,6 +495,32 @@ void obs_source_copy_filters(obs_source_t *dst, obs_source_t *src) duplicate_filters(dst, src, dst->context.private); } +static void duplicate_filter(obs_source_t *dst, obs_source_t *filter) +{ + if (!filter_compatible(dst, filter)) + return; + + char *new_name = get_new_filter_name(dst, filter->context.name); + bool enabled = obs_source_enabled(filter); + + obs_source_t *dst_filter = obs_source_duplicate(filter, new_name, true); + obs_source_set_enabled(dst_filter, enabled); + + bfree(new_name); + obs_source_filter_add(dst, dst_filter); + obs_source_release(dst_filter); +} + +void obs_source_copy_single_filter(obs_source_t *dst, obs_source_t *filter) +{ + if (!obs_source_valid(dst, "obs_source_copy_single_filter")) + return; + if (!obs_source_valid(filter, "obs_source_copy_single_filter")) + return; + + duplicate_filter(dst, filter); +} + obs_source_t *obs_source_duplicate(obs_source_t *source, const char *new_name, bool create_private) { diff --git a/libobs/obs.h b/libobs/obs.h index 09ab78d56..a2ada8bd0 100644 --- a/libobs/obs.h +++ b/libobs/obs.h @@ -1085,6 +1085,8 @@ EXPORT obs_source_t *obs_source_get_filter_by_name(obs_source_t *source, const char *name); EXPORT void obs_source_copy_filters(obs_source_t *dst, obs_source_t *src); +EXPORT void obs_source_copy_single_filter(obs_source_t *dst, + obs_source_t *filter); EXPORT bool obs_source_enabled(const obs_source_t *source); EXPORT void obs_source_set_enabled(obs_source_t *source, bool enabled); -- GitLab