FIX: Undo/redo delete/add page

Now we can undo adding or deleting worksheets
This commit is contained in:
Nicolás Hatcher
2025-02-05 21:43:20 +01:00
committed by Nicolás Hatcher Andrés
parent d866e283e9
commit dc8bb6da21
6 changed files with 102 additions and 20 deletions

View File

@@ -16,6 +16,7 @@ mod test_paste_csv;
mod test_rename_sheet;
mod test_row_column;
mod test_sheet_state;
mod test_sheets_undo_redo;
mod test_styles;
mod test_to_from_bytes;
mod test_undo_redo;

View File

@@ -25,9 +25,6 @@ fn add_undo_redo() {
assert_eq!(model.get_formatted_cell_value(2, 1, 1), Ok("6".to_string()));
model.delete_sheet(1).unwrap();
assert!(!model.can_undo());
assert!(!model.can_redo());
}
#[test]

View File

@@ -0,0 +1,52 @@
#![allow(clippy::unwrap_used)]
use crate::test::util::new_empty_model;
use crate::UserModel;
#[test]
fn basic_undo_redo() {
let model = new_empty_model();
let mut model = UserModel::from_model(model);
assert_eq!(model.get_selected_sheet(), 0);
model.new_sheet().unwrap();
assert_eq!(model.get_selected_sheet(), 1);
model.undo().unwrap();
assert_eq!(model.get_selected_sheet(), 0);
{
let props = model.get_worksheets_properties();
assert_eq!(props.len(), 1);
let view = model.get_selected_view();
assert_eq!(view.sheet, 0);
}
model.redo().unwrap();
assert_eq!(model.get_selected_sheet(), 1);
{
let props = model.get_worksheets_properties();
assert_eq!(props.len(), 2);
let view = model.get_selected_view();
assert_eq!(view.sheet, 1);
}
}
#[test]
fn delete_undo() {
let model = new_empty_model();
let mut model = UserModel::from_model(model);
assert_eq!(model.get_selected_sheet(), 0);
model.new_sheet().unwrap();
assert_eq!(model.get_selected_sheet(), 1);
model.set_user_input(1, 1, 1, "42").unwrap();
model.set_user_input(1, 1, 2, "=A1*2").unwrap();
model.delete_sheet(1).unwrap();
assert_eq!(model.get_selected_sheet(), 0);
model.undo().unwrap();
assert_eq!(model.get_selected_sheet(), 1);
model.redo().unwrap();
assert_eq!(model.get_selected_sheet(), 0);
}

View File

@@ -412,9 +412,13 @@ impl UserModel {
/// See also:
/// * [Model::delete_sheet]
pub fn delete_sheet(&mut self, sheet: u32) -> Result<(), String> {
self.push_diff_list(vec![Diff::DeleteSheet { sheet }]);
// There is no coming back
self.history.clear();
let worksheet = self.model.workbook.worksheet(sheet)?;
self.push_diff_list(vec![Diff::DeleteSheet {
sheet,
old_data: Box::new(worksheet.clone()),
}]);
let sheet_count = self.model.workbook.worksheets.len() as u32;
// If we are deleting the last sheet we need to change the selected sheet
if sheet == sheet_count - 1 && sheet_count > 1 {
@@ -1972,11 +1976,11 @@ impl UserModel {
new_value: _,
old_value,
} => self.model.set_frozen_columns(*sheet, *old_value)?,
Diff::DeleteSheet { sheet: _ } => {
// do nothing
}
Diff::NewSheet { index, name: _ } => {
self.model.delete_sheet(*index)?;
if *index > 0 {
self.set_selected_sheet(*index - 1)?;
}
}
Diff::RenameSheet {
index,
@@ -2043,6 +2047,32 @@ impl UserModel {
self.model
.set_cell_style(*sheet, *row, *column, old_style)?;
}
Diff::DeleteSheet { sheet, old_data } => {
needs_evaluation = true;
let sheet_name = &old_data.name.clone();
let sheet_index = *sheet;
let sheet_id = old_data.sheet_id;
self.model
.insert_sheet(sheet_name, sheet_index, Some(sheet_id))?;
let worksheet = self.model.workbook.worksheet_mut(*sheet)?;
for (row, row_data) in &old_data.sheet_data {
for (column, cell) in row_data {
worksheet.update_cell(*row, *column, cell.clone())?;
}
}
worksheet.rows = old_data.rows.clone();
worksheet.cols = old_data.cols.clone();
worksheet.show_grid_lines = old_data.show_grid_lines;
worksheet.frozen_columns = old_data.frozen_columns;
worksheet.frozen_rows = old_data.frozen_rows;
worksheet.state = old_data.state.clone();
worksheet.color = old_data.color.clone();
worksheet.merge_cells = old_data.merge_cells.clone();
worksheet.shared_formulas = old_data.shared_formulas.clone();
self.model.reset_parsed_structures();
self.set_selected_sheet(sheet_index)?;
}
}
}
if needs_evaluation {
@@ -2145,9 +2175,15 @@ impl UserModel {
new_value,
old_value: _,
} => self.model.set_frozen_columns(*sheet, *new_value)?,
Diff::DeleteSheet { sheet } => self.model.delete_sheet(*sheet)?,
Diff::DeleteSheet { sheet, old_data: _ } => {
self.model.delete_sheet(*sheet)?;
if *sheet > 0 {
self.set_selected_sheet(*sheet - 1)?;
}
}
Diff::NewSheet { index, name } => {
self.model.insert_sheet(name, *index, None)?;
self.set_selected_sheet(*index)?;
}
Diff::RenameSheet {
index,

View File

@@ -2,7 +2,7 @@ use std::collections::HashMap;
use bitcode::{Decode, Encode};
use crate::types::{Cell, Col, Row, SheetState, Style};
use crate::types::{Cell, Col, Row, SheetState, Style, Worksheet};
#[derive(Clone, Encode, Decode)]
pub(crate) struct RowData {
@@ -83,6 +83,10 @@ pub(crate) enum Diff {
column: i32,
old_data: Box<ColumnData>,
},
DeleteSheet {
sheet: u32,
old_data: Box<Worksheet>,
},
SetFrozenRowsCount {
sheet: u32,
new_value: i32,
@@ -93,9 +97,6 @@ pub(crate) enum Diff {
new_value: i32,
old_value: i32,
},
DeleteSheet {
sheet: u32,
},
NewSheet {
index: u32,
name: String,
@@ -174,11 +175,6 @@ impl History {
None => None,
}
}
pub fn clear(&mut self) {
self.redo_stack = vec![];
self.undo_stack = vec![];
}
}
#[derive(Clone, Encode, Decode)]