FIX: Undo/redo delete/add page
Now we can undo adding or deleting worksheets
This commit is contained in:
committed by
Nicolás Hatcher Andrés
parent
d866e283e9
commit
dc8bb6da21
@@ -16,6 +16,7 @@ mod test_paste_csv;
|
|||||||
mod test_rename_sheet;
|
mod test_rename_sheet;
|
||||||
mod test_row_column;
|
mod test_row_column;
|
||||||
mod test_sheet_state;
|
mod test_sheet_state;
|
||||||
|
mod test_sheets_undo_redo;
|
||||||
mod test_styles;
|
mod test_styles;
|
||||||
mod test_to_from_bytes;
|
mod test_to_from_bytes;
|
||||||
mod test_undo_redo;
|
mod test_undo_redo;
|
||||||
|
|||||||
@@ -25,9 +25,6 @@ fn add_undo_redo() {
|
|||||||
assert_eq!(model.get_formatted_cell_value(2, 1, 1), Ok("6".to_string()));
|
assert_eq!(model.get_formatted_cell_value(2, 1, 1), Ok("6".to_string()));
|
||||||
|
|
||||||
model.delete_sheet(1).unwrap();
|
model.delete_sheet(1).unwrap();
|
||||||
|
|
||||||
assert!(!model.can_undo());
|
|
||||||
assert!(!model.can_redo());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
52
base/src/test/user_model/test_sheets_undo_redo.rs
Normal file
52
base/src/test/user_model/test_sheets_undo_redo.rs
Normal 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);
|
||||||
|
}
|
||||||
@@ -412,9 +412,13 @@ impl UserModel {
|
|||||||
/// See also:
|
/// See also:
|
||||||
/// * [Model::delete_sheet]
|
/// * [Model::delete_sheet]
|
||||||
pub fn delete_sheet(&mut self, sheet: u32) -> Result<(), String> {
|
pub fn delete_sheet(&mut self, sheet: u32) -> Result<(), String> {
|
||||||
self.push_diff_list(vec![Diff::DeleteSheet { sheet }]);
|
let worksheet = self.model.workbook.worksheet(sheet)?;
|
||||||
// There is no coming back
|
|
||||||
self.history.clear();
|
self.push_diff_list(vec![Diff::DeleteSheet {
|
||||||
|
sheet,
|
||||||
|
old_data: Box::new(worksheet.clone()),
|
||||||
|
}]);
|
||||||
|
|
||||||
let sheet_count = self.model.workbook.worksheets.len() as u32;
|
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 we are deleting the last sheet we need to change the selected sheet
|
||||||
if sheet == sheet_count - 1 && sheet_count > 1 {
|
if sheet == sheet_count - 1 && sheet_count > 1 {
|
||||||
@@ -1972,11 +1976,11 @@ impl UserModel {
|
|||||||
new_value: _,
|
new_value: _,
|
||||||
old_value,
|
old_value,
|
||||||
} => self.model.set_frozen_columns(*sheet, *old_value)?,
|
} => self.model.set_frozen_columns(*sheet, *old_value)?,
|
||||||
Diff::DeleteSheet { sheet: _ } => {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
Diff::NewSheet { index, name: _ } => {
|
Diff::NewSheet { index, name: _ } => {
|
||||||
self.model.delete_sheet(*index)?;
|
self.model.delete_sheet(*index)?;
|
||||||
|
if *index > 0 {
|
||||||
|
self.set_selected_sheet(*index - 1)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Diff::RenameSheet {
|
Diff::RenameSheet {
|
||||||
index,
|
index,
|
||||||
@@ -2043,6 +2047,32 @@ impl UserModel {
|
|||||||
self.model
|
self.model
|
||||||
.set_cell_style(*sheet, *row, *column, old_style)?;
|
.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 {
|
if needs_evaluation {
|
||||||
@@ -2145,9 +2175,15 @@ impl UserModel {
|
|||||||
new_value,
|
new_value,
|
||||||
old_value: _,
|
old_value: _,
|
||||||
} => self.model.set_frozen_columns(*sheet, *new_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 } => {
|
Diff::NewSheet { index, name } => {
|
||||||
self.model.insert_sheet(name, *index, None)?;
|
self.model.insert_sheet(name, *index, None)?;
|
||||||
|
self.set_selected_sheet(*index)?;
|
||||||
}
|
}
|
||||||
Diff::RenameSheet {
|
Diff::RenameSheet {
|
||||||
index,
|
index,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
use bitcode::{Decode, Encode};
|
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)]
|
#[derive(Clone, Encode, Decode)]
|
||||||
pub(crate) struct RowData {
|
pub(crate) struct RowData {
|
||||||
@@ -83,6 +83,10 @@ pub(crate) enum Diff {
|
|||||||
column: i32,
|
column: i32,
|
||||||
old_data: Box<ColumnData>,
|
old_data: Box<ColumnData>,
|
||||||
},
|
},
|
||||||
|
DeleteSheet {
|
||||||
|
sheet: u32,
|
||||||
|
old_data: Box<Worksheet>,
|
||||||
|
},
|
||||||
SetFrozenRowsCount {
|
SetFrozenRowsCount {
|
||||||
sheet: u32,
|
sheet: u32,
|
||||||
new_value: i32,
|
new_value: i32,
|
||||||
@@ -93,9 +97,6 @@ pub(crate) enum Diff {
|
|||||||
new_value: i32,
|
new_value: i32,
|
||||||
old_value: i32,
|
old_value: i32,
|
||||||
},
|
},
|
||||||
DeleteSheet {
|
|
||||||
sheet: u32,
|
|
||||||
},
|
|
||||||
NewSheet {
|
NewSheet {
|
||||||
index: u32,
|
index: u32,
|
||||||
name: String,
|
name: String,
|
||||||
@@ -174,11 +175,6 @@ impl History {
|
|||||||
None => None,
|
None => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear(&mut self) {
|
|
||||||
self.redo_stack = vec![];
|
|
||||||
self.undo_stack = vec![];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Encode, Decode)]
|
#[derive(Clone, Encode, Decode)]
|
||||||
|
|||||||
@@ -71,7 +71,7 @@
|
|||||||
},
|
},
|
||||||
"sheet_delete": {
|
"sheet_delete": {
|
||||||
"title": "Are you sure?",
|
"title": "Are you sure?",
|
||||||
"message": "The sheet '{{sheetName}}' will be permanently deleted. This action cannot be undone.",
|
"message": "The sheet '{{sheetName}}' will be deleted.",
|
||||||
"confirm": "Yes, delete sheet",
|
"confirm": "Yes, delete sheet",
|
||||||
"cancel": "Cancel"
|
"cancel": "Cancel"
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user