diff --git a/UI/undo-stack-obs.cpp b/UI/undo-stack-obs.cpp index fb0862bc1..6261a95ff 100644 --- a/UI/undo-stack-obs.cpp +++ b/UI/undo-stack-obs.cpp @@ -4,12 +4,24 @@ #define MAX_STACK_SIZE 5000 -undo_stack::undo_stack(ui_ptr ui) : ui(ui) {} +undo_stack::undo_stack(ui_ptr ui) : ui(ui) +{ + QObject::connect(&repeat_reset_timer, &QTimer::timeout, this, + &undo_stack::reset_repeatable_state); + repeat_reset_timer.setSingleShot(true); + repeat_reset_timer.setInterval(3000); +} + +void undo_stack::reset_repeatable_state() +{ + last_is_repeatable = false; +} void undo_stack::clear() { undo_items.clear(); redo_items.clear(); + last_is_repeatable = false; ui->actionMainUndo->setText(QTStr("Undo.Undo")); ui->actionMainRedo->setText(QTStr("Undo.Redo")); @@ -20,7 +32,7 @@ void undo_stack::clear() void undo_stack::add_action(const QString &name, undo_redo_cb undo, undo_redo_cb redo, std::string undo_data, - std::string redo_data) + std::string redo_data, bool repeatable) { while (undo_items.size() >= MAX_STACK_SIZE) { undo_redo_t item = undo_items.back(); @@ -29,6 +41,17 @@ void undo_stack::add_action(const QString &name, undo_redo_cb undo, undo_redo_t n = {name, undo_data, redo_data, undo, redo}; + if (repeatable) { + repeat_reset_timer.start(); + } + + if (last_is_repeatable && repeatable && name == undo_items[0].name) { + undo_items[0].redo = redo; + undo_items[0].redo_data = redo_data; + return; + } + + last_is_repeatable = repeatable; undo_items.push_front(n); clear_redo(); @@ -44,6 +67,8 @@ void undo_stack::undo() if (undo_items.size() == 0 || disabled) return; + last_is_repeatable = false; + undo_redo_t temp = undo_items.front(); temp.undo(temp.undo_data); redo_items.push_front(temp); @@ -66,6 +91,8 @@ void undo_stack::redo() if (redo_items.size() == 0 || disabled) return; + last_is_repeatable = false; + undo_redo_t temp = redo_items.front(); temp.redo(temp.redo_data); undo_items.push_front(temp); @@ -86,6 +113,7 @@ void undo_stack::redo() void undo_stack::enable_undo_redo() { disabled = false; + last_is_repeatable = false; ui->actionMainUndo->setDisabled(false); ui->actionMainRedo->setDisabled(false); @@ -94,6 +122,7 @@ void undo_stack::enable_undo_redo() void undo_stack::disable_undo_redo() { disabled = true; + last_is_repeatable = false; ui->actionMainUndo->setDisabled(true); ui->actionMainRedo->setDisabled(true); diff --git a/UI/undo-stack-obs.hpp b/UI/undo-stack-obs.hpp index 936de1414..fb6344266 100644 --- a/UI/undo-stack-obs.hpp +++ b/UI/undo-stack-obs.hpp @@ -1,6 +1,8 @@ #pragma once +#include #include +#include #include #include @@ -9,7 +11,9 @@ #include "ui_OBSBasic.h" -class undo_stack { +class undo_stack : public QObject { + Q_OBJECT + typedef std::function undo_redo_cb; typedef std::function func; typedef std::unique_ptr &ui_ptr; @@ -26,9 +30,15 @@ class undo_stack { std::deque undo_items; std::deque redo_items; bool disabled = false; + bool last_is_repeatable = false; + + QTimer repeat_reset_timer; void clear_redo(); +private slots: + void reset_repeatable_state(); + public: undo_stack(ui_ptr ui); @@ -38,7 +48,7 @@ public: void clear(); void add_action(const QString &name, undo_redo_cb undo, undo_redo_cb redo, std::string undo_data, - std::string redo_data); + std::string redo_data, bool repeatable = false); void undo(); void redo(); };