feat: add new commands for records mode and category management
Add new commands for enhanced data entry and category management. AddRecordRow: Adds a new record row in records mode with empty value. TogglePruneEmpty: Toggles pruning of empty rows/columns in pivot mode. ToggleRecordsMode: Switches between records and pivot layout. DeleteCategoryAtCursor: Removes a category and all its cells. ToggleCatExpand: Expands/collapses a category in the tree. FilterToItem: Filters to show only items matching cursor position. Model gains remove_category() and remove_item() to delete categories and items along with all referencing cells and formulas. Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
This commit is contained in:
@ -107,6 +107,47 @@ impl Model {
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
/// Remove a category and all cells that reference it.
|
||||
pub fn remove_category(&mut self, name: &str) {
|
||||
if !self.categories.contains_key(name) {
|
||||
return;
|
||||
}
|
||||
self.categories.shift_remove(name);
|
||||
// Remove from all views
|
||||
for view in self.views.values_mut() {
|
||||
view.on_category_removed(name);
|
||||
}
|
||||
// Remove cells that have a coord in this category
|
||||
let to_remove: Vec<CellKey> = self
|
||||
.data
|
||||
.iter_cells()
|
||||
.filter(|(k, _)| k.get(name).is_some())
|
||||
.map(|(k, _)| k)
|
||||
.collect();
|
||||
for k in to_remove {
|
||||
self.data.remove(&k);
|
||||
}
|
||||
// Remove formulas targeting this category
|
||||
self.formulas
|
||||
.retain(|f| f.target_category != name);
|
||||
}
|
||||
|
||||
/// Remove an item from a category and all cells that reference it.
|
||||
pub fn remove_item(&mut self, cat_name: &str, item_name: &str) {
|
||||
if let Some(cat) = self.categories.get_mut(cat_name) {
|
||||
cat.remove_item(item_name);
|
||||
}
|
||||
let to_remove: Vec<CellKey> = self
|
||||
.data
|
||||
.iter_cells()
|
||||
.filter(|(k, _)| k.get(cat_name) == Some(item_name))
|
||||
.map(|(k, _)| k)
|
||||
.collect();
|
||||
for k in to_remove {
|
||||
self.data.remove(&k);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn category_mut(&mut self, name: &str) -> Option<&mut Category> {
|
||||
self.categories.get_mut(name)
|
||||
}
|
||||
@ -527,6 +568,31 @@ mod model_tests {
|
||||
assert_eq!(m.get_cell(&k4), Some(&CellValue::Number(40.0)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_category_deletes_category_and_cells() {
|
||||
let mut m = Model::new("Test");
|
||||
m.add_category("Region").unwrap();
|
||||
m.add_category("Product").unwrap();
|
||||
m.category_mut("Region").unwrap().add_item("East");
|
||||
m.category_mut("Product").unwrap().add_item("Shirts");
|
||||
m.set_cell(
|
||||
coord(&[("Region", "East"), ("Product", "Shirts")]),
|
||||
CellValue::Number(42.0),
|
||||
);
|
||||
m.remove_category("Region");
|
||||
assert!(m.category("Region").is_none());
|
||||
// Cells referencing Region should be gone
|
||||
assert_eq!(
|
||||
m.data.iter_cells().count(),
|
||||
0,
|
||||
"all cells with Region coord should be removed"
|
||||
);
|
||||
// Views should no longer know about Region
|
||||
// (axis_of would panic for unknown category, so check categories_on)
|
||||
let v = m.active_view();
|
||||
assert!(v.categories_on(crate::view::Axis::Row).is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_view_copies_category_structure() {
|
||||
let mut m = Model::new("Test");
|
||||
|
||||
Reference in New Issue
Block a user