166 lines
3.4 KiB
C++
166 lines
3.4 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, const undo_redo_cb &undo,
|
|
const undo_redo_cb &redo,
|
|
const std::string &undo_data,
|
|
const std::string &redo_data, bool repeatable)
|
|
{
|
|
if (!is_enabled())
|
|
return;
|
|
|
|
while (undo_items.size() >= MAX_STACK_SIZE) {
|
|
undo_redo_t item = undo_items.back();
|
|
undo_items.pop_back();
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
undo_redo_t n = {name, undo_data, redo_data, undo, redo};
|
|
|
|
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 || !is_enabled())
|
|
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 || !is_enabled())
|
|
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_internal()
|
|
{
|
|
last_is_repeatable = false;
|
|
|
|
ui->actionMainUndo->setDisabled(false);
|
|
if (redo_items.size() > 0)
|
|
ui->actionMainRedo->setDisabled(false);
|
|
}
|
|
|
|
void undo_stack::disable_internal()
|
|
{
|
|
last_is_repeatable = false;
|
|
|
|
ui->actionMainUndo->setDisabled(true);
|
|
ui->actionMainRedo->setDisabled(true);
|
|
}
|
|
|
|
void undo_stack::enable()
|
|
{
|
|
enabled = true;
|
|
if (is_enabled())
|
|
enable_internal();
|
|
}
|
|
|
|
void undo_stack::disable()
|
|
{
|
|
if (is_enabled())
|
|
disable_internal();
|
|
enabled = false;
|
|
}
|
|
|
|
void undo_stack::push_disabled()
|
|
{
|
|
if (is_enabled())
|
|
disable_internal();
|
|
disable_refs++;
|
|
}
|
|
|
|
void undo_stack::pop_disabled()
|
|
{
|
|
disable_refs--;
|
|
if (is_enabled())
|
|
enable_internal();
|
|
}
|
|
|
|
void undo_stack::clear_redo()
|
|
{
|
|
redo_items.clear();
|
|
}
|