use crate::{error::Result, treeitems_iter::TreeItemsIterator}; use crate::{item::DatabaseTreeItemKind, DatabaseTreeItem}; use crate::{Child, Database}; use std::{ collections::{BTreeSet, HashMap}, usize, }; #[derive(Default)] pub struct DatabaseTreeItems { pub tree_items: Vec, } impl DatabaseTreeItems { /// pub fn new(list: &[Database], collapsed: &BTreeSet<&String>) -> Result { Ok(Self { tree_items: Self::create_items(list, collapsed)?, }) } pub fn filter(&self, filter_text: String) -> Self { Self { tree_items: self .tree_items .iter() .filter(|item| item.is_database() || item.is_match(&filter_text)) .map(|item| { let mut item = item.clone(); if item.is_database() { item.set_collapsed(false); item } else { let mut item = item; item.show(); item } }) .collect::>(), } } fn create_items( list: &[Database], collapsed: &BTreeSet<&String>, ) -> Result> { let mut items = Vec::with_capacity(list.len()); let mut items_added: HashMap = HashMap::with_capacity(list.len()); for e in list { { Self::push_databases(e, &mut items, &mut items_added, collapsed)?; } for child in &e.children { match child { Child::Table(table) => items.push(DatabaseTreeItem::new_table(e, table)), Child::Schema(schema) => { items.push(DatabaseTreeItem::new_schema(e, schema, true)); for table in &schema.tables { items.push(DatabaseTreeItem::new_table(e, table)) } } } } } Ok(items) } /// how many individual items are in the list pub fn len(&self) -> usize { self.tree_items.len() } /// iterates visible elements pub const fn iterate(&self, start: usize, max_amount: usize) -> TreeItemsIterator<'_> { TreeItemsIterator::new(self, start, max_amount) } fn push_databases<'a>( database: &'a Database, nodes: &mut Vec, items_added: &mut HashMap, collapsed: &BTreeSet<&String>, ) -> Result<()> { let c = database.name.clone(); if !items_added.contains_key(&c) { // add node and set count to have no children items_added.insert(c.clone(), 0); // increase the number of children in the parent node count *items_added.entry(database.name.clone()).or_insert(0) += 1; let is_collapsed = collapsed.contains(&c); nodes.push(DatabaseTreeItem::new_database(database, is_collapsed)); } // increase child count in parent node (the above ancenstor ignores the leaf component) *items_added.entry(database.name.clone()).or_insert(0) += 1; Ok(()) } pub fn collapse(&mut self, index: usize, recursive: bool) { if self.tree_items[index].kind().is_database() { self.tree_items[index].collapse_database(); let name = self.tree_items[index].kind().name(); for i in index + 1..self.tree_items.len() { let item = &mut self.tree_items[i]; if recursive && item.kind().is_database() { item.collapse_database(); } if let Some(db) = item.kind().database_name() { if db == name { item.hide(); } } else { return; } } } if self.tree_items[index].kind().is_schema() { self.tree_items[index].collapse_schema(); let name = self.tree_items[index].kind().name(); for i in index + 1..self.tree_items.len() { let item = &mut self.tree_items[i]; if recursive && item.kind().is_schema() { item.collapse_schema(); } if let Some(schema) = item.kind().schema_name() { if schema == name { item.hide(); } } else { return; } } } } pub fn expand(&mut self, index: usize, recursive: bool) { if self.tree_items[index].kind().is_database() { self.tree_items[index].expand_database(); let tree_item = self.tree_items[index].clone(); let name = self.tree_items[index].kind().name(); let kind = tree_item.kind(); if recursive { for i in index + 1..self.tree_items.len() { let item = &mut self.tree_items[i]; if let Some(db) = item.kind().database_name() { if *db != name { break; } } if item.kind().is_database() && item.kind().is_database_collapsed() { item.expand_database(); } } } self.update_visibility(kind, index + 1); } if self.tree_items[index].kind().is_schema() { self.tree_items[index].expand_schema(); let tree_item = self.tree_items[index].clone(); let name = self.tree_items[index].kind().name(); let kind = tree_item.kind(); if recursive { for i in index + 1..self.tree_items.len() { let item = &mut self.tree_items[i]; if let Some(schema) = item.kind().schema_name() { if *schema != name { break; } } if item.kind().is_schema() && item.kind().is_schema_collapsed() { item.expand_schema(); } } } self.update_visibility(kind, index + 1); } } fn update_visibility(&mut self, prefix: &DatabaseTreeItemKind, start_idx: usize) { let mut inner_collapsed: Option = None; for i in start_idx..self.tree_items.len() { if let Some(ref collapsed_item) = inner_collapsed { match collapsed_item { DatabaseTreeItemKind::Database { name, .. } => { if let DatabaseTreeItemKind::Schema { database, .. } = self.tree_items[i].kind().clone() { if database.name == *name { continue; } } if let DatabaseTreeItemKind::Table { database, .. } = self.tree_items[i].kind().clone() { if database.name == *name { continue; } } } DatabaseTreeItemKind::Schema { schema, .. } => { if let DatabaseTreeItemKind::Table { table, .. } = self.tree_items[i].kind().clone() { if matches!(table.schema, Some(table_schema) if schema.name == table_schema) { continue; } } } _ => (), } inner_collapsed = None; } let item_kind = self.tree_items[i].kind().clone(); if matches!(item_kind, DatabaseTreeItemKind::Database{ collapsed, .. } if collapsed) || matches!(item_kind, DatabaseTreeItemKind::Schema{ collapsed, .. } if collapsed) { inner_collapsed = Some(item_kind.clone()); } match prefix { DatabaseTreeItemKind::Database { name, .. } => { if let DatabaseTreeItemKind::Schema { database, .. } = item_kind.clone() { if *name == database.name { self.tree_items[i].info_mut().set_visible(true); } } if let DatabaseTreeItemKind::Table { database, .. } = item_kind { if *name == database.name { self.tree_items[i].info_mut().set_visible(true); } } } DatabaseTreeItemKind::Schema { schema, .. } => { if let DatabaseTreeItemKind::Table { table, .. } = item_kind { if matches!(table.schema, Some(table_schema) if schema.name == table_schema) { self.tree_items[i].info_mut().set_visible(true); } } } _ => (), } } } }