Skip to content

Commit

Permalink
Merge pull request #3426 from Programatic/undo_redo
Browse files Browse the repository at this point in the history
UI: Implement Undo/Redo System
  • Loading branch information
jp9000 authored Mar 30, 2021
2 parents a52012e + d0dfae6 commit 5d87f3c
Show file tree
Hide file tree
Showing 31 changed files with 2,058 additions and 58 deletions.
6 changes: 4 additions & 2 deletions UI/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,8 @@ set(obs_SOURCES
obs-proxy-style.cpp
locked-checkbox.cpp
visibility-checkbox.cpp
media-slider.cpp)
media-slider.cpp
undo-stack-obs.cpp)

set(obs_HEADERS
${obs_PLATFORM_HEADERS}
Expand Down Expand Up @@ -331,7 +332,8 @@ set(obs_HEADERS
log-viewer.hpp
obs-proxy-style.hpp
obs-proxy-style.hpp
media-slider.hpp)
media-slider.hpp
undo-stack-obs.hpp)

set(obs_importers_HEADERS
importers/importers.hpp)
Expand Down
78 changes: 78 additions & 0 deletions UI/context-bar-controls.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include "window-basic-main.hpp"
#include "context-bar-controls.hpp"
#include "qt-wrappers.hpp"
#include "obs-app.hpp"
Expand Down Expand Up @@ -33,6 +34,63 @@ SourceToolbar::SourceToolbar(QWidget *parent, OBSSource source)
{
}

void SourceToolbar::SaveOldProperties(obs_source_t *source)
{
if (oldData)
obs_data_release(oldData);

oldData = obs_data_create();
obs_data_t *oldSettings = obs_source_get_settings(source);
obs_data_apply(oldData, oldSettings);
obs_data_set_string(oldData, "undo_sname", obs_source_get_name(source));
obs_data_release(oldSettings);
obs_data_release(oldData);
}

void SourceToolbar::SetUndoProperties(obs_source_t *source)
{
OBSBasic *main = reinterpret_cast<OBSBasic *>(App()->GetMainWindow());

std::string scene_name =
obs_source_get_name(main->GetCurrentSceneSource());
auto undo_redo = [scene_name,
main = std::move(main)](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_t *scene_source =
obs_get_source_by_name(scene_name.c_str());
main->SetCurrentScene(scene_source);
obs_source_release(scene_source);

obs_data_release(settings);
obs_source_release(source);

main->UpdateContextBar();
};

OBSData new_settings = obs_data_create();
OBSData 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));

std::string undo_data(obs_data_get_json(oldData));
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, nullptr);

obs_data_release(new_settings);
obs_data_release(curr_settings);
obs_data_release(oldData);
}

/* ========================================================================= */

BrowserToolbar::BrowserToolbar(QWidget *parent, OBSSource source)
Expand Down Expand Up @@ -163,8 +221,10 @@ void ComboSelectToolbar::on_device_currentIndexChanged(int idx)
return;
}

SaveOldProperties(source);
UpdateSourceComboToolbarValue(ui->device, source, idx, prop_name,
is_int);
SetUndoProperties(source);
}

AudioCaptureToolbar::AudioCaptureToolbar(QWidget *parent, OBSSource source)
Expand Down Expand Up @@ -370,10 +430,12 @@ void GameCaptureToolbar::on_mode_currentIndexChanged(int idx)

QString id = ui->mode->itemData(idx).toString();

SaveOldProperties(source);
obs_data_t *settings = obs_data_create();
obs_data_set_string(settings, "capture_mode", QT_TO_UTF8(id));
obs_source_update(source, settings);
obs_data_release(settings);
SetUndoProperties(source);

UpdateWindowVisibility();
}
Expand All @@ -387,10 +449,12 @@ void GameCaptureToolbar::on_window_currentIndexChanged(int idx)

QString id = ui->window->itemData(idx).toString();

SaveOldProperties(source);
obs_data_t *settings = obs_data_create();
obs_data_set_string(settings, "window", QT_TO_UTF8(id));
obs_source_update(source, settings);
obs_data_release(settings);
SetUndoProperties(source);
}

/* ========================================================================= */
Expand Down Expand Up @@ -434,10 +498,12 @@ void ImageSourceToolbar::on_browse_clicked()

ui->path->setText(path);

SaveOldProperties(source);
obs_data_t *settings = obs_data_create();
obs_data_set_string(settings, "file", QT_TO_UTF8(path));
obs_source_update(source, settings);
obs_data_release(settings);
SetUndoProperties(source);
}

/* ========================================================================= */
Expand Down Expand Up @@ -518,10 +584,14 @@ void ColorSourceToolbar::on_choose_clicked()
color = newColor;
UpdateColor();

SaveOldProperties(source);

obs_data_t *settings = obs_data_create();
obs_data_set_int(settings, "color", color_to_int(color));
obs_source_update(source, settings);
obs_data_release(settings);

SetUndoProperties(source);
}

/* ========================================================================= */
Expand Down Expand Up @@ -596,13 +666,17 @@ void TextSourceToolbar::on_selectFont_clicked()
flags |= font.strikeOut() ? OBS_FONT_STRIKEOUT : 0;
obs_data_set_int(font_obj, "flags", flags);

SaveOldProperties(source);

obs_data_t *settings = obs_data_create();

obs_data_set_obj(settings, "font", font_obj);
obs_data_release(font_obj);

obs_source_update(source, settings);
obs_data_release(settings);

SetUndoProperties(source);
}

void TextSourceToolbar::on_selectColor_clicked()
Expand All @@ -628,6 +702,8 @@ void TextSourceToolbar::on_selectColor_clicked()

color = newColor;

SaveOldProperties(source);

obs_data_t *settings = obs_data_create();
if (!strncmp(obs_source_get_id(source), "text_ft2_source", 15)) {
obs_data_set_int(settings, "color1", color_to_int(color));
Expand All @@ -637,6 +713,8 @@ void TextSourceToolbar::on_selectColor_clicked()
}
obs_source_update(source, settings);
obs_data_release(settings);

SetUndoProperties(source);
}

void TextSourceToolbar::on_text_textChanged()
Expand Down
4 changes: 4 additions & 0 deletions UI/context-bar-controls.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ class SourceToolbar : public QWidget {
std::unique_ptr<obs_properties_t, properties_delete_t>;

properties_t props;
OBSData oldData;

void SaveOldProperties(obs_source_t *source);
void SetUndoProperties(obs_source_t *source);

public:
SourceToolbar(QWidget *parent, OBSSource source);
Expand Down
28 changes: 28 additions & 0 deletions UI/data/locale/en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,34 @@ Basic.SceneTransitions="Scene Transitions"
Basic.TransitionDuration="Duration"
Basic.TogglePreviewProgramMode="Studio Mode"

# undo
Undo.Undo="Undo"
Undo.Redo="Redo"
Undo.Add="Add '%1'"
Undo.Delete="Delete '%1'"
Undo.Rename="Rename '%1'"
Undo.SceneCollection.Switch="Switch to '%1'"
Undo.Item.Undo="Undo %1"
Undo.Item.Redo="Redo %1"
Undo.Sources.Multi="Delete %1 Sources"
Undo.Filters="Filter Changes on '%1'"
Undo.Transform="Transform source(s) In '%1'"
Undo.Transform.Paste="Paste Transformation in '%1'"
Undo.Transform.Rotate="Rotation In '%1'"
Undo.Transform.Reset="Transform Reset In '%1'"
Undo.Transform.HFlip="Horizontal Flip In '%1'"
Undo.Transform.VFlip="Vertical Flip In '%1'"
Undo.Transform.FitToScren="Fit to Screen In '%1'"
Undo.Transform.StretchToScreen="Stretch to Screen in '%1'"
Undo.Transform.Center="Center to Screen in '%1'"
Undo.Transform.VCenter="Vertical Center to Screen in '%1'"
Undo.Transform.HCenter="Horizontal Center to Screen in '%1'"
Undo.Volume.Change="Volume Change on '%1'"
Undo.Audio="Audio Changes"
Undo.Properties="Property Change on '%1'"
Undo.Scene.Duplicate="Duplicate Scene '%1'"


# transition name dialog
TransitionNameDlg.Text="Please enter the name of the transition"
TransitionNameDlg.Title="Transition Name"
Expand Down
22 changes: 21 additions & 1 deletion UI/forms/OBSBasic.ui
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,9 @@
<string>Paste.Filters</string>
</property>
</action>
<addaction name="actionMainUndo"/>
<addaction name="actionMainRedo"/>
<addaction name="separator"/>
<addaction name="actionCopySource"/>
<addaction name="actionPasteRef"/>
<addaction name="actionPasteDup"/>
Expand All @@ -599,6 +602,7 @@
<addaction name="actionLockPreview"/>
<addaction name="separator"/>
<addaction name="actionAdvAudioProperties"/>
<addaction name="separator"/>
</widget>
<widget class="QMenu" name="profileMenu">
<property name="title">
Expand Down Expand Up @@ -2034,7 +2038,23 @@
<string>Basic.MainMenu.View.ContextBar</string>
</property>
</action>
</widget>
<action name="actionMainUndo">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Undo</string>
</property>
</action>
<action name="actionMainRedo">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Redo</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
<class>OBSBasicPreview</class>
Expand Down
41 changes: 38 additions & 3 deletions UI/properties-view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <QStackedWidget>
#include <QDir>
#include <QGroupBox>
#include <QObject>
#include "double-slider.hpp"
#include "slider-ignorewheel.hpp"
#include "spinbox-ignorewheel.hpp"
Expand All @@ -31,6 +32,9 @@

#include <cstdlib>
#include <initializer_list>
#include <obs-data.h>
#include <obs.h>
#include <qtimer.h>
#include <string>

using namespace std;
Expand Down Expand Up @@ -171,13 +175,14 @@ void OBSPropertiesView::GetScrollPos(int &h, int &v)
OBSPropertiesView::OBSPropertiesView(OBSData settings_, void *obj_,
PropertiesReloadCallback reloadCallback,
PropertiesUpdateCallback callback_,
int minSize_)
PropertiesVisualUpdateCb cb_, int minSize_)
: VScrollArea(nullptr),
properties(nullptr, obs_properties_destroy),
settings(settings_),
obj(obj_),
reloadCallback(reloadCallback),
callback(callback_),
cb(cb_),
minSize(minSize_)
{
setFrameShape(QFrame::NoFrame);
Expand Down Expand Up @@ -1885,6 +1890,12 @@ void WidgetInfo::ControlChanged()
const char *setting = obs_property_name(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) {
case OBS_PROPERTY_INVALID:
return;
Expand Down Expand Up @@ -1933,8 +1944,32 @@ void WidgetInfo::ControlChanged()
break;
}

if (view->callback && !view->deferUpdate)
view->callback(view->obj, view->settings);
if (!recently_updated) {
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();

Expand Down
Loading

0 comments on commit 5d87f3c

Please sign in to comment.