mirror of
https://github.com/obsproject/obs-studio.git
synced 2026-01-18 11:18:36 -05:00
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.
135 lines
3.0 KiB
C++
135 lines
3.0 KiB
C++
#include "undo-stack-obs.hpp"
|
|
|
|
#include <util/util.hpp>
|
|
|
|
#define MAX_STACK_SIZE 5000
|
|
|
|
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"));
|
|
|
|
ui->actionMainUndo->setDisabled(true);
|
|
ui->actionMainRedo->setDisabled(true);
|
|
}
|
|
|
|
void undo_stack::add_action(const QString &name, undo_redo_cb undo,
|
|
undo_redo_cb redo, std::string undo_data,
|
|
std::string redo_data, bool repeatable)
|
|
{
|
|
while (undo_items.size() >= MAX_STACK_SIZE) {
|
|
undo_redo_t item = undo_items.back();
|
|
undo_items.pop_back();
|
|
}
|
|
|
|
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();
|
|
|
|
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;
|
|
|
|
last_is_repeatable = false;
|
|
|
|
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;
|
|
|
|
last_is_repeatable = false;
|
|
|
|
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;
|
|
last_is_repeatable = false;
|
|
|
|
ui->actionMainUndo->setDisabled(false);
|
|
ui->actionMainRedo->setDisabled(false);
|
|
}
|
|
|
|
void undo_stack::disable_undo_redo()
|
|
{
|
|
disabled = true;
|
|
last_is_repeatable = false;
|
|
|
|
ui->actionMainUndo->setDisabled(true);
|
|
ui->actionMainRedo->setDisabled(true);
|
|
}
|
|
|
|
void undo_stack::clear_redo()
|
|
{
|
|
redo_items.clear();
|
|
}
|