From eced5a320bc9dfc7ef62185eb0cc433a890e2ab4 Mon Sep 17 00:00:00 2001 From: Ford Smith Date: Sun, 21 Mar 2021 22:16:17 -0400 Subject: [PATCH] UI: Initial Undo/Redo Starting to develop Undo/Redo. This just implmements the undo/redo stack and its api. --- UI/data/locale/en-US.ini | 28 +++++++++++ UI/undo-stack-obs.cpp | 101 +++++++++++++++++++++++++++++++++++++++ UI/undo-stack-obs.hpp | 46 ++++++++++++++++++ 3 files changed, 175 insertions(+) create mode 100644 UI/undo-stack-obs.cpp create mode 100644 UI/undo-stack-obs.hpp diff --git a/UI/data/locale/en-US.ini b/UI/data/locale/en-US.ini index 1aba3994e..3397900e1 100644 --- a/UI/data/locale/en-US.ini +++ b/UI/data/locale/en-US.ini @@ -262,6 +262,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" diff --git a/UI/undo-stack-obs.cpp b/UI/undo-stack-obs.cpp new file mode 100644 index 000000000..7d1365c1c --- /dev/null +++ b/UI/undo-stack-obs.cpp @@ -0,0 +1,101 @@ +#include "undo-stack-obs.hpp" + +#include + +undo_stack::undo_stack(ui_ptr ui) : ui(ui) {} + +void undo_stack::release() +{ + for (auto f : undo_items) + if (f.d) + f.d(true); + + for (auto f : redo_items) + if (f.d) + f.d(false); +} + +void undo_stack::add_action(const QString &name, undo_redo_cb undo, + undo_redo_cb redo, std::string undo_data, + std::string redo_data, func d) +{ + undo_redo_t n = {name, undo_data, redo_data, undo, redo, d}; + + undo_items.push_front(n); + clear_redo(); + + ui->actionMainUndo->setText(QTStr("Undo.Item.Undo").arg(name)); + ui->actionMainUndo->setEnabled(true); + + ui->actionMainRedo->setText(QTStr("Undo.Redo")); + ui->actionMainRedo->setDisabled(true); +} + +void undo_stack::undo() +{ + if (undo_items.size() == 0 || disabled) + return; + + undo_redo_t temp = undo_items.front(); + temp.undo(temp.undo_data); + redo_items.push_front(temp); + undo_items.pop_front(); + + ui->actionMainRedo->setText(QTStr("Undo.Item.Redo").arg(temp.name)); + ui->actionMainRedo->setEnabled(true); + + if (undo_items.size() == 0) { + ui->actionMainUndo->setDisabled(true); + ui->actionMainUndo->setText(QTStr("Undo.Undo")); + } else { + ui->actionMainUndo->setText( + QTStr("Undo.Item.Undo").arg(undo_items.front().name)); + } +} + +void undo_stack::redo() +{ + if (redo_items.size() == 0 || disabled) + return; + + undo_redo_t temp = redo_items.front(); + temp.redo(temp.redo_data); + undo_items.push_front(temp); + redo_items.pop_front(); + + ui->actionMainUndo->setText(QTStr("Undo.Item.Undo").arg(temp.name)); + ui->actionMainUndo->setEnabled(true); + + if (redo_items.size() == 0) { + ui->actionMainRedo->setDisabled(true); + ui->actionMainRedo->setText(QTStr("Undo.Redo")); + } else { + ui->actionMainRedo->setText( + QTStr("Undo.Item.Redo").arg(redo_items.front().name)); + } +} + +void undo_stack::enable_undo_redo() +{ + disabled = false; + + ui->actionMainUndo->setDisabled(false); + ui->actionMainRedo->setDisabled(false); +} + +void undo_stack::disable_undo_redo() +{ + disabled = true; + + ui->actionMainUndo->setDisabled(true); + ui->actionMainRedo->setDisabled(true); +} + +void undo_stack::clear_redo() +{ + for (auto f : redo_items) + if (f.d) + f.d(false); + + redo_items.clear(); +} diff --git a/UI/undo-stack-obs.hpp b/UI/undo-stack-obs.hpp new file mode 100644 index 000000000..e1643b13d --- /dev/null +++ b/UI/undo-stack-obs.hpp @@ -0,0 +1,46 @@ +#pragma once + +#include + +#include +#include +#include +#include + +#include "ui_OBSBasic.h" + +typedef std::function undo_redo_cb; +typedef std::function func; +typedef std::unique_ptr &ui_ptr; + +struct undo_redo_t { + QString name; + std::string undo_data; + std::string redo_data; + undo_redo_cb undo; + undo_redo_cb redo; + func d; +}; + +class undo_stack { +private: + ui_ptr ui; + std::deque undo_items; + std::deque redo_items; + bool disabled = false; + + void clear_redo(); + +public: + undo_stack(ui_ptr ui); + + void enable_undo_redo(); + void disable_undo_redo(); + + void release(); + void add_action(const QString &name, undo_redo_cb undo, + undo_redo_cb redo, std::string undo_data, + std::string redo_data, func d); + void undo(); + void redo(); +};