mirror of
https://github.com/obsproject/obs-studio.git
synced 2026-09-24 23:31:36 +08:00
UI: Undo/Redo Properties and Filters
Implements undo/redo for both properties and filters. Works by creating a new callback that gets called to save undo/redo states after a timer is fired. Also disabled undo/redo until the actions have completed to prevent a user from being able to disrupt the stack by perfoming actions before others have finished.
This commit is contained in:
+38
-3
@@ -20,6 +20,7 @@
|
|||||||
#include <QStackedWidget>
|
#include <QStackedWidget>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
|
#include <QObject>
|
||||||
#include "double-slider.hpp"
|
#include "double-slider.hpp"
|
||||||
#include "slider-ignorewheel.hpp"
|
#include "slider-ignorewheel.hpp"
|
||||||
#include "spinbox-ignorewheel.hpp"
|
#include "spinbox-ignorewheel.hpp"
|
||||||
@@ -31,6 +32,9 @@
|
|||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
|
#include <obs-data.h>
|
||||||
|
#include <obs.h>
|
||||||
|
#include <qtimer.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@@ -171,13 +175,14 @@ void OBSPropertiesView::GetScrollPos(int &h, int &v)
|
|||||||
OBSPropertiesView::OBSPropertiesView(OBSData settings_, void *obj_,
|
OBSPropertiesView::OBSPropertiesView(OBSData settings_, void *obj_,
|
||||||
PropertiesReloadCallback reloadCallback,
|
PropertiesReloadCallback reloadCallback,
|
||||||
PropertiesUpdateCallback callback_,
|
PropertiesUpdateCallback callback_,
|
||||||
int minSize_)
|
PropertiesVisualUpdateCb cb_, int minSize_)
|
||||||
: VScrollArea(nullptr),
|
: VScrollArea(nullptr),
|
||||||
properties(nullptr, obs_properties_destroy),
|
properties(nullptr, obs_properties_destroy),
|
||||||
settings(settings_),
|
settings(settings_),
|
||||||
obj(obj_),
|
obj(obj_),
|
||||||
reloadCallback(reloadCallback),
|
reloadCallback(reloadCallback),
|
||||||
callback(callback_),
|
callback(callback_),
|
||||||
|
cb(cb_),
|
||||||
minSize(minSize_)
|
minSize(minSize_)
|
||||||
{
|
{
|
||||||
setFrameShape(QFrame::NoFrame);
|
setFrameShape(QFrame::NoFrame);
|
||||||
@@ -1885,6 +1890,12 @@ void WidgetInfo::ControlChanged()
|
|||||||
const char *setting = obs_property_name(property);
|
const char *setting = obs_property_name(property);
|
||||||
obs_property_type type = obs_property_get_type(property);
|
obs_property_type type = obs_property_get_type(property);
|
||||||
|
|
||||||
|
if (!recently_updated) {
|
||||||
|
old_settings_cache = obs_data_create();
|
||||||
|
obs_data_apply(old_settings_cache, view->settings);
|
||||||
|
obs_data_release(old_settings_cache);
|
||||||
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case OBS_PROPERTY_INVALID:
|
case OBS_PROPERTY_INVALID:
|
||||||
return;
|
return;
|
||||||
@@ -1933,8 +1944,32 @@ void WidgetInfo::ControlChanged()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (view->callback && !view->deferUpdate)
|
if (!recently_updated) {
|
||||||
view->callback(view->obj, view->settings);
|
recently_updated = true;
|
||||||
|
update_timer = new QTimer;
|
||||||
|
connect(update_timer, &QTimer::timeout,
|
||||||
|
[this, &ru = recently_updated]() {
|
||||||
|
if (view->callback && !view->deferUpdate) {
|
||||||
|
view->callback(view->obj,
|
||||||
|
old_settings_cache,
|
||||||
|
view->settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
ru = false;
|
||||||
|
});
|
||||||
|
connect(update_timer, &QTimer::timeout, &QTimer::deleteLater);
|
||||||
|
update_timer->setSingleShot(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (update_timer) {
|
||||||
|
update_timer->stop();
|
||||||
|
update_timer->start(500);
|
||||||
|
} else {
|
||||||
|
blog(LOG_DEBUG, "No update timer or no callback!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (view->cb && !view->deferUpdate)
|
||||||
|
view->cb(view->obj, view->settings);
|
||||||
|
|
||||||
view->SignalChanged();
|
view->SignalChanged();
|
||||||
|
|
||||||
|
|||||||
+23
-3
@@ -1,7 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "vertical-scroll-area.hpp"
|
#include "vertical-scroll-area.hpp"
|
||||||
|
#include <obs-data.h>
|
||||||
#include <obs.hpp>
|
#include <obs.hpp>
|
||||||
|
#include <qtimer.h>
|
||||||
|
#include <QPointer>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@@ -10,7 +13,9 @@ class OBSPropertiesView;
|
|||||||
class QLabel;
|
class QLabel;
|
||||||
|
|
||||||
typedef obs_properties_t *(*PropertiesReloadCallback)(void *obj);
|
typedef obs_properties_t *(*PropertiesReloadCallback)(void *obj);
|
||||||
typedef void (*PropertiesUpdateCallback)(void *obj, obs_data_t *settings);
|
typedef void (*PropertiesUpdateCallback)(void *obj, obs_data_t *old_settings,
|
||||||
|
obs_data_t *new_settings);
|
||||||
|
typedef void (*PropertiesVisualUpdateCb)(void *obj, obs_data_t *settings);
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
@@ -23,6 +28,9 @@ private:
|
|||||||
OBSPropertiesView *view;
|
OBSPropertiesView *view;
|
||||||
obs_property_t *property;
|
obs_property_t *property;
|
||||||
QWidget *widget;
|
QWidget *widget;
|
||||||
|
QPointer<QTimer> update_timer;
|
||||||
|
bool recently_updated = false;
|
||||||
|
OBSData old_settings_cache;
|
||||||
|
|
||||||
void BoolChanged(const char *setting);
|
void BoolChanged(const char *setting);
|
||||||
void IntChanged(const char *setting);
|
void IntChanged(const char *setting);
|
||||||
@@ -47,6 +55,15 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~WidgetInfo()
|
||||||
|
{
|
||||||
|
if (update_timer) {
|
||||||
|
update_timer->stop();
|
||||||
|
update_timer->deleteLater();
|
||||||
|
obs_data_release(old_settings_cache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void ControlChanged();
|
void ControlChanged();
|
||||||
@@ -83,6 +100,7 @@ private:
|
|||||||
std::string type;
|
std::string type;
|
||||||
PropertiesReloadCallback reloadCallback;
|
PropertiesReloadCallback reloadCallback;
|
||||||
PropertiesUpdateCallback callback = nullptr;
|
PropertiesUpdateCallback callback = nullptr;
|
||||||
|
PropertiesVisualUpdateCb cb = nullptr;
|
||||||
int minSize;
|
int minSize;
|
||||||
std::vector<std::unique_ptr<WidgetInfo>> children;
|
std::vector<std::unique_ptr<WidgetInfo>> children;
|
||||||
std::string lastFocused;
|
std::string lastFocused;
|
||||||
@@ -135,13 +153,15 @@ signals:
|
|||||||
public:
|
public:
|
||||||
OBSPropertiesView(OBSData settings, void *obj,
|
OBSPropertiesView(OBSData settings, void *obj,
|
||||||
PropertiesReloadCallback reloadCallback,
|
PropertiesReloadCallback reloadCallback,
|
||||||
PropertiesUpdateCallback callback, int minSize = 0);
|
PropertiesUpdateCallback callback,
|
||||||
|
PropertiesVisualUpdateCb cb = nullptr,
|
||||||
|
int minSize = 0);
|
||||||
OBSPropertiesView(OBSData settings, const char *type,
|
OBSPropertiesView(OBSData settings, const char *type,
|
||||||
PropertiesReloadCallback reloadCallback,
|
PropertiesReloadCallback reloadCallback,
|
||||||
int minSize = 0);
|
int minSize = 0);
|
||||||
|
|
||||||
inline obs_data_t *GetSettings() const { return settings; }
|
inline obs_data_t *GetSettings() const { return settings; }
|
||||||
|
|
||||||
inline void UpdateSettings() { callback(obj, settings); }
|
inline void UpdateSettings() { callback(obj, nullptr, settings); }
|
||||||
inline bool DeferUpdate() const { return deferUpdate; }
|
inline bool DeferUpdate() const { return deferUpdate; }
|
||||||
};
|
};
|
||||||
|
|||||||
+251
-2
@@ -15,6 +15,7 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "properties-view.hpp"
|
||||||
#include "window-namedialog.hpp"
|
#include "window-namedialog.hpp"
|
||||||
#include "window-basic-main.hpp"
|
#include "window-basic-main.hpp"
|
||||||
#include "window-basic-filters.hpp"
|
#include "window-basic-filters.hpp"
|
||||||
@@ -23,9 +24,13 @@
|
|||||||
#include "visibility-item-widget.hpp"
|
#include "visibility-item-widget.hpp"
|
||||||
#include "item-widget-helpers.hpp"
|
#include "item-widget-helpers.hpp"
|
||||||
#include "obs-app.hpp"
|
#include "obs-app.hpp"
|
||||||
|
#include "undo-stack-obs.hpp"
|
||||||
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QCloseEvent>
|
#include <QCloseEvent>
|
||||||
|
#include <obs-data.h>
|
||||||
|
#include <obs.h>
|
||||||
|
#include <util/base.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
@@ -202,10 +207,82 @@ void OBSBasicFilters::UpdatePropertiesView(int row, bool async)
|
|||||||
|
|
||||||
obs_data_t *settings = obs_source_get_settings(filter);
|
obs_data_t *settings = obs_source_get_settings(filter);
|
||||||
|
|
||||||
|
auto filter_change = [](void *vp, obs_data_t *nd_old_settings,
|
||||||
|
obs_data_t *new_settings) {
|
||||||
|
obs_source_t *source = reinterpret_cast<obs_source_t *>(vp);
|
||||||
|
obs_source_t *parent = obs_filter_get_parent(source);
|
||||||
|
const char *source_name = obs_source_get_name(source);
|
||||||
|
OBSBasic *main = OBSBasic::Get();
|
||||||
|
|
||||||
|
obs_data_t *redo_wrapper = obs_data_create();
|
||||||
|
obs_data_set_string(redo_wrapper, "name", source_name);
|
||||||
|
obs_data_set_string(redo_wrapper, "settings",
|
||||||
|
obs_data_get_json(new_settings));
|
||||||
|
obs_data_set_string(redo_wrapper, "parent",
|
||||||
|
obs_source_get_name(parent));
|
||||||
|
|
||||||
|
obs_data_t *filter_settings = obs_source_get_settings(source);
|
||||||
|
obs_data_t *old_settings =
|
||||||
|
obs_data_get_defaults(filter_settings);
|
||||||
|
obs_data_apply(old_settings, nd_old_settings);
|
||||||
|
|
||||||
|
obs_data_t *undo_wrapper = obs_data_create();
|
||||||
|
obs_data_set_string(undo_wrapper, "name", source_name);
|
||||||
|
obs_data_set_string(undo_wrapper, "settings",
|
||||||
|
obs_data_get_json(old_settings));
|
||||||
|
obs_data_set_string(undo_wrapper, "parent",
|
||||||
|
obs_source_get_name(parent));
|
||||||
|
|
||||||
|
auto undo_redo = [](const std::string &data) {
|
||||||
|
obs_data_t *dat =
|
||||||
|
obs_data_create_from_json(data.c_str());
|
||||||
|
obs_source_t *parent_source = obs_get_source_by_name(
|
||||||
|
obs_data_get_string(dat, "parent"));
|
||||||
|
const char *filter_name =
|
||||||
|
obs_data_get_string(dat, "name");
|
||||||
|
obs_source_t *filter = obs_source_get_filter_by_name(
|
||||||
|
parent_source, filter_name);
|
||||||
|
obs_data_t *settings = obs_data_create_from_json(
|
||||||
|
obs_data_get_string(dat, "settings"));
|
||||||
|
|
||||||
|
obs_source_update(filter, settings);
|
||||||
|
obs_source_update_properties(filter);
|
||||||
|
|
||||||
|
obs_data_release(dat);
|
||||||
|
obs_data_release(settings);
|
||||||
|
obs_source_release(filter);
|
||||||
|
obs_source_release(parent_source);
|
||||||
|
};
|
||||||
|
std::string name = std::string(obs_source_get_name(source));
|
||||||
|
std::string undo_data = obs_data_get_json(undo_wrapper);
|
||||||
|
std::string redo_data = obs_data_get_json(redo_wrapper);
|
||||||
|
main->undo_s.add_action(QTStr("Undo.Filters").arg(name.c_str()),
|
||||||
|
undo_redo, undo_redo, undo_data,
|
||||||
|
redo_data, NULL);
|
||||||
|
|
||||||
|
obs_data_release(redo_wrapper);
|
||||||
|
obs_data_release(undo_wrapper);
|
||||||
|
obs_data_release(old_settings);
|
||||||
|
obs_data_release(filter_settings);
|
||||||
|
|
||||||
|
obs_source_update(source, new_settings);
|
||||||
|
|
||||||
|
main->undo_s.enable_undo_redo();
|
||||||
|
};
|
||||||
|
|
||||||
|
auto disabled_undo = [](void *vp, obs_data_t *settings) {
|
||||||
|
OBSBasic *main =
|
||||||
|
reinterpret_cast<OBSBasic *>(App()->GetMainWindow());
|
||||||
|
main->undo_s.disable_undo_redo();
|
||||||
|
obs_source_t *source = reinterpret_cast<obs_source_t *>(vp);
|
||||||
|
obs_source_update(source, settings);
|
||||||
|
};
|
||||||
|
|
||||||
view = new OBSPropertiesView(
|
view = new OBSPropertiesView(
|
||||||
settings, filter,
|
settings, filter,
|
||||||
(PropertiesReloadCallback)obs_source_properties,
|
(PropertiesReloadCallback)obs_source_properties,
|
||||||
(PropertiesUpdateCallback)obs_source_update);
|
(PropertiesUpdateCallback)filter_change,
|
||||||
|
(PropertiesVisualUpdateCb)disabled_undo);
|
||||||
|
|
||||||
updatePropertiesSignal.Connect(obs_source_get_signal_handler(filter),
|
updatePropertiesSignal.Connect(obs_source_get_signal_handler(filter),
|
||||||
"update_properties",
|
"update_properties",
|
||||||
@@ -240,6 +317,7 @@ void OBSBasicFilters::AddFilter(OBSSource filter, bool focus)
|
|||||||
list->addItem(item);
|
list->addItem(item);
|
||||||
if (focus)
|
if (focus)
|
||||||
list->setCurrentItem(item);
|
list->setCurrentItem(item);
|
||||||
|
|
||||||
SetupVisibilityItem(list, item, filter);
|
SetupVisibilityItem(list, item, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -486,6 +564,68 @@ void OBSBasicFilters::AddNewFilter(const char *id)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
obs_data_t *wrapper = obs_data_create();
|
||||||
|
obs_data_set_string(wrapper, "sname",
|
||||||
|
obs_source_get_name(source));
|
||||||
|
obs_data_set_string(wrapper, "fname", name.c_str());
|
||||||
|
std::string scene_name = obs_source_get_name(
|
||||||
|
reinterpret_cast<OBSBasic *>(App()->GetMainWindow())
|
||||||
|
->GetCurrentSceneSource());
|
||||||
|
auto undo = [scene_name](const std::string &data) {
|
||||||
|
obs_source_t *ssource =
|
||||||
|
obs_get_source_by_name(scene_name.c_str());
|
||||||
|
reinterpret_cast<OBSBasic *>(App()->GetMainWindow())
|
||||||
|
->SetCurrentScene(ssource);
|
||||||
|
obs_source_release(ssource);
|
||||||
|
|
||||||
|
obs_data_t *dat =
|
||||||
|
obs_data_create_from_json(data.c_str());
|
||||||
|
obs_source_t *source = obs_get_source_by_name(
|
||||||
|
obs_data_get_string(dat, "sname"));
|
||||||
|
obs_source_t *filter = obs_source_get_filter_by_name(
|
||||||
|
source, obs_data_get_string(dat, "fname"));
|
||||||
|
obs_source_filter_remove(source, filter);
|
||||||
|
|
||||||
|
obs_data_release(dat);
|
||||||
|
obs_source_release(source);
|
||||||
|
obs_source_release(filter);
|
||||||
|
};
|
||||||
|
|
||||||
|
obs_data_t *rwrapper = obs_data_create();
|
||||||
|
obs_data_set_string(rwrapper, "sname",
|
||||||
|
obs_source_get_name(source));
|
||||||
|
auto redo = [scene_name, id = std::string(id),
|
||||||
|
name](const std::string &data) {
|
||||||
|
obs_source_t *ssource =
|
||||||
|
obs_get_source_by_name(scene_name.c_str());
|
||||||
|
reinterpret_cast<OBSBasic *>(App()->GetMainWindow())
|
||||||
|
->SetCurrentScene(ssource);
|
||||||
|
obs_source_release(ssource);
|
||||||
|
|
||||||
|
obs_data_t *dat =
|
||||||
|
obs_data_create_from_json(data.c_str());
|
||||||
|
obs_source_t *source = obs_get_source_by_name(
|
||||||
|
obs_data_get_string(dat, "sname"));
|
||||||
|
|
||||||
|
obs_source_t *filter = obs_source_create(
|
||||||
|
id.c_str(), name.c_str(), nullptr, nullptr);
|
||||||
|
if (filter) {
|
||||||
|
obs_source_filter_add(source, filter);
|
||||||
|
obs_source_release(filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
obs_data_release(dat);
|
||||||
|
obs_source_release(source);
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string undo_data(obs_data_get_json(wrapper));
|
||||||
|
std::string redo_data(obs_data_get_json(rwrapper));
|
||||||
|
main->undo_s.add_action(QTStr("Undo.Add").arg(name.c_str()),
|
||||||
|
undo, redo, undo_data, redo_data, NULL);
|
||||||
|
|
||||||
|
obs_data_release(wrapper);
|
||||||
|
obs_data_release(rwrapper);
|
||||||
|
|
||||||
obs_source_t *filter =
|
obs_source_t *filter =
|
||||||
obs_source_create(id, name.c_str(), nullptr, nullptr);
|
obs_source_create(id, name.c_str(), nullptr, nullptr);
|
||||||
if (filter) {
|
if (filter) {
|
||||||
@@ -674,8 +814,75 @@ void OBSBasicFilters::on_removeEffectFilter_clicked()
|
|||||||
{
|
{
|
||||||
OBSSource filter = GetFilter(ui->effectFilters->currentRow(), false);
|
OBSSource filter = GetFilter(ui->effectFilters->currentRow(), false);
|
||||||
if (filter) {
|
if (filter) {
|
||||||
if (QueryRemove(this, filter))
|
if (QueryRemove(this, filter)) {
|
||||||
|
obs_data_t *wrapper = obs_save_source(filter);
|
||||||
|
std::string parent_name(obs_source_get_name(source));
|
||||||
|
obs_data_set_string(wrapper, "undo_name",
|
||||||
|
parent_name.c_str());
|
||||||
|
|
||||||
|
std::string scene_name = obs_source_get_name(
|
||||||
|
reinterpret_cast<OBSBasic *>(
|
||||||
|
App()->GetMainWindow())
|
||||||
|
->GetCurrentSceneSource());
|
||||||
|
auto undo = [scene_name](const std::string &data) {
|
||||||
|
obs_source_t *ssource = obs_get_source_by_name(
|
||||||
|
scene_name.c_str());
|
||||||
|
reinterpret_cast<OBSBasic *>(
|
||||||
|
App()->GetMainWindow())
|
||||||
|
->SetCurrentScene(ssource);
|
||||||
|
obs_source_release(ssource);
|
||||||
|
|
||||||
|
obs_data_t *dat =
|
||||||
|
obs_data_create_from_json(data.c_str());
|
||||||
|
obs_source_t *source = obs_get_source_by_name(
|
||||||
|
obs_data_get_string(dat, "undo_name"));
|
||||||
|
obs_source_t *filter = obs_load_source(dat);
|
||||||
|
obs_source_filter_add(source, filter);
|
||||||
|
|
||||||
|
obs_data_release(dat);
|
||||||
|
obs_source_release(source);
|
||||||
|
obs_source_release(filter);
|
||||||
|
};
|
||||||
|
|
||||||
|
obs_data_t *rwrapper = obs_data_create();
|
||||||
|
obs_data_set_string(rwrapper, "fname",
|
||||||
|
obs_source_get_name(filter));
|
||||||
|
obs_data_set_string(rwrapper, "sname",
|
||||||
|
parent_name.c_str());
|
||||||
|
auto redo = [scene_name](const std::string &data) {
|
||||||
|
obs_source_t *ssource = obs_get_source_by_name(
|
||||||
|
scene_name.c_str());
|
||||||
|
reinterpret_cast<OBSBasic *>(
|
||||||
|
App()->GetMainWindow())
|
||||||
|
->SetCurrentScene(ssource);
|
||||||
|
obs_source_release(ssource);
|
||||||
|
|
||||||
|
obs_data_t *dat =
|
||||||
|
obs_data_create_from_json(data.c_str());
|
||||||
|
obs_source_t *source = obs_get_source_by_name(
|
||||||
|
obs_data_get_string(dat, "sname"));
|
||||||
|
obs_source_t *filter =
|
||||||
|
obs_source_get_filter_by_name(
|
||||||
|
source, obs_data_get_string(
|
||||||
|
dat, "fname"));
|
||||||
obs_source_filter_remove(source, filter);
|
obs_source_filter_remove(source, filter);
|
||||||
|
|
||||||
|
obs_data_release(dat);
|
||||||
|
obs_source_release(filter);
|
||||||
|
obs_source_release(source);
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string undo_data(obs_data_get_json(wrapper));
|
||||||
|
std::string redo_data(obs_data_get_json(rwrapper));
|
||||||
|
main->undo_s.add_action(
|
||||||
|
QTStr("Undo.Delete")
|
||||||
|
.arg(obs_source_get_name(filter)),
|
||||||
|
undo, redo, undo_data, redo_data, NULL);
|
||||||
|
obs_source_filter_remove(source, filter);
|
||||||
|
|
||||||
|
obs_data_release(wrapper);
|
||||||
|
obs_data_release(rwrapper);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -918,6 +1125,48 @@ void OBSBasicFilters::FilterNameEdited(QWidget *editor, QListWidget *list)
|
|||||||
|
|
||||||
listItem->setText(QT_UTF8(name.c_str()));
|
listItem->setText(QT_UTF8(name.c_str()));
|
||||||
obs_source_set_name(filter, name.c_str());
|
obs_source_set_name(filter, name.c_str());
|
||||||
|
|
||||||
|
std::string scene_name = obs_source_get_name(
|
||||||
|
reinterpret_cast<OBSBasic *>(App()->GetMainWindow())
|
||||||
|
->GetCurrentSceneSource());
|
||||||
|
auto undo = [scene_name, prev = std::string(prevName),
|
||||||
|
name](const std::string &data) {
|
||||||
|
obs_source_t *ssource =
|
||||||
|
obs_get_source_by_name(scene_name.c_str());
|
||||||
|
reinterpret_cast<OBSBasic *>(App()->GetMainWindow())
|
||||||
|
->SetCurrentScene(ssource);
|
||||||
|
obs_source_release(ssource);
|
||||||
|
|
||||||
|
obs_source_t *source =
|
||||||
|
obs_get_source_by_name(data.c_str());
|
||||||
|
obs_source_t *filter = obs_source_get_filter_by_name(
|
||||||
|
source, name.c_str());
|
||||||
|
obs_source_set_name(filter, prev.c_str());
|
||||||
|
obs_source_release(source);
|
||||||
|
obs_source_release(filter);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto redo = [scene_name, prev = std::string(prevName),
|
||||||
|
name](const std::string &data) {
|
||||||
|
obs_source_t *ssource =
|
||||||
|
obs_get_source_by_name(scene_name.c_str());
|
||||||
|
reinterpret_cast<OBSBasic *>(App()->GetMainWindow())
|
||||||
|
->SetCurrentScene(ssource);
|
||||||
|
obs_source_release(ssource);
|
||||||
|
|
||||||
|
obs_source_t *source =
|
||||||
|
obs_get_source_by_name(data.c_str());
|
||||||
|
obs_source_t *filter = obs_source_get_filter_by_name(
|
||||||
|
source, prev.c_str());
|
||||||
|
obs_source_set_name(filter, name.c_str());
|
||||||
|
obs_source_release(source);
|
||||||
|
obs_source_release(filter);
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string undo_data(sourceName);
|
||||||
|
std::string redo_data(sourceName);
|
||||||
|
main->undo_s.add_action(QTStr("Undo.Rename").arg(name.c_str()),
|
||||||
|
undo, redo, undo_data, redo_data, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
listItem->setText(QString());
|
listItem->setText(QString());
|
||||||
|
|||||||
@@ -26,6 +26,10 @@
|
|||||||
#include <QScreen>
|
#include <QScreen>
|
||||||
#include <QWindow>
|
#include <QWindow>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <obs-data.h>
|
||||||
|
#include <obs.h>
|
||||||
|
#include <qpointer.h>
|
||||||
|
#include <util/c99defs.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@@ -74,14 +78,28 @@ OBSBasicProperties::OBSBasicProperties(QWidget *parent, OBSSource source_)
|
|||||||
/* The OBSData constructor increments the reference once */
|
/* The OBSData constructor increments the reference once */
|
||||||
obs_data_release(oldSettings);
|
obs_data_release(oldSettings);
|
||||||
|
|
||||||
OBSData settings = obs_source_get_settings(source);
|
OBSData nd_settings = obs_source_get_settings(source);
|
||||||
|
OBSData settings = obs_data_get_defaults(nd_settings);
|
||||||
|
obs_data_apply(settings, nd_settings);
|
||||||
obs_data_apply(oldSettings, settings);
|
obs_data_apply(oldSettings, settings);
|
||||||
obs_data_release(settings);
|
obs_data_release(settings);
|
||||||
|
obs_data_release(nd_settings);
|
||||||
|
|
||||||
|
auto handle_memory = [](void *vp, obs_data_t *old_settings,
|
||||||
|
obs_data_t *new_settings) {
|
||||||
|
obs_source_t *source = reinterpret_cast<obs_source_t *>(vp);
|
||||||
|
|
||||||
|
obs_source_update(source, new_settings);
|
||||||
|
|
||||||
|
UNUSED_PARAMETER(old_settings);
|
||||||
|
UNUSED_PARAMETER(vp);
|
||||||
|
};
|
||||||
|
|
||||||
view = new OBSPropertiesView(
|
view = new OBSPropertiesView(
|
||||||
settings, source,
|
nd_settings, source,
|
||||||
(PropertiesReloadCallback)obs_source_properties,
|
(PropertiesReloadCallback)obs_source_properties,
|
||||||
(PropertiesUpdateCallback)obs_source_update);
|
(PropertiesUpdateCallback)handle_memory,
|
||||||
|
(PropertiesVisualUpdateCb)obs_source_update);
|
||||||
view->setMinimumHeight(150);
|
view->setMinimumHeight(150);
|
||||||
|
|
||||||
preview->setMinimumSize(20, 150);
|
preview->setMinimumSize(20, 150);
|
||||||
@@ -341,6 +359,51 @@ void OBSBasicProperties::on_buttonBox_clicked(QAbstractButton *button)
|
|||||||
QDialogButtonBox::ButtonRole val = buttonBox->buttonRole(button);
|
QDialogButtonBox::ButtonRole val = buttonBox->buttonRole(button);
|
||||||
|
|
||||||
if (val == QDialogButtonBox::AcceptRole) {
|
if (val == QDialogButtonBox::AcceptRole) {
|
||||||
|
|
||||||
|
std::string scene_name =
|
||||||
|
obs_source_get_name(main->GetCurrentSceneSource());
|
||||||
|
|
||||||
|
auto undo_redo = [scene_name](const std::string &data) {
|
||||||
|
obs_data_t *settings =
|
||||||
|
obs_data_create_from_json(data.c_str());
|
||||||
|
obs_source_t *source = obs_get_source_by_name(
|
||||||
|
obs_data_get_string(settings, "undo_sname"));
|
||||||
|
obs_source_update(source, settings);
|
||||||
|
|
||||||
|
obs_source_update_properties(source);
|
||||||
|
|
||||||
|
obs_source_t *scene_source =
|
||||||
|
obs_get_source_by_name(scene_name.c_str());
|
||||||
|
|
||||||
|
OBSBasic::Get()->SetCurrentScene(source);
|
||||||
|
|
||||||
|
obs_source_release(scene_source);
|
||||||
|
|
||||||
|
obs_data_release(settings);
|
||||||
|
obs_source_release(source);
|
||||||
|
};
|
||||||
|
|
||||||
|
obs_data_t *new_settings = obs_data_create();
|
||||||
|
obs_data_t *curr_settings = obs_source_get_settings(source);
|
||||||
|
obs_data_apply(new_settings, curr_settings);
|
||||||
|
obs_data_set_string(new_settings, "undo_sname",
|
||||||
|
obs_source_get_name(source));
|
||||||
|
obs_data_set_string(oldSettings, "undo_sname",
|
||||||
|
obs_source_get_name(source));
|
||||||
|
|
||||||
|
std::string undo_data(obs_data_get_json(oldSettings));
|
||||||
|
std::string redo_data(obs_data_get_json(new_settings));
|
||||||
|
|
||||||
|
if (undo_data.compare(redo_data) != 0)
|
||||||
|
main->undo_s.add_action(
|
||||||
|
QTStr("Undo.Properties")
|
||||||
|
.arg(obs_source_get_name(source)),
|
||||||
|
undo_redo, undo_redo, undo_data, redo_data,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
obs_data_release(new_settings);
|
||||||
|
obs_data_release(curr_settings);
|
||||||
|
|
||||||
acceptClicked = true;
|
acceptClicked = true;
|
||||||
close();
|
close();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user