UI: Add repeat protection for Undo/Redo
This allows the ability to mark an action as repeatable, which when set, makes it so that it will change only the redo value for the last undo item in the undo stack within the last three seconds. This allows the ability to, for example, scroll a spinbox or change a slider value without creating many unnecessarily duplicated undo/redo actions.
This commit is contained in:
parent
78f1983f7d
commit
ae5ac8fa82
@ -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);
|
||||
|
@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QTimer>
|
||||
|
||||
#include <deque>
|
||||
#include <functional>
|
||||
@ -9,7 +11,9 @@
|
||||
|
||||
#include "ui_OBSBasic.h"
|
||||
|
||||
class undo_stack {
|
||||
class undo_stack : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
typedef std::function<void(const std::string &data)> undo_redo_cb;
|
||||
typedef std::function<void(bool is_undo)> func;
|
||||
typedef std::unique_ptr<Ui::OBSBasic> &ui_ptr;
|
||||
@ -26,9 +30,15 @@ class undo_stack {
|
||||
std::deque<undo_redo_t> undo_items;
|
||||
std::deque<undo_redo_t> 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();
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user