database_tree/
databasetreeitems.rs1use crate::{error::Result, treeitems_iter::TreeItemsIterator};
2use crate::{item::DatabaseTreeItemKind, DatabaseTreeItem};
3use crate::{Child, Database};
4use std::{
5 collections::{BTreeSet, HashMap},
6 usize,
7};
8
9#[derive(Default)]
10pub struct DatabaseTreeItems {
11 pub tree_items: Vec<DatabaseTreeItem>,
12}
13
14impl DatabaseTreeItems {
15 pub fn new(list: &[Database], collapsed: &BTreeSet<&String>) -> Result<Self> {
17 Ok(Self {
18 tree_items: Self::create_items(list, collapsed)?,
19 })
20 }
21
22 pub fn filter(&self, filter_text: String) -> Self {
23 Self {
24 tree_items: self
25 .tree_items
26 .iter()
27 .filter(|item| {
28 item.is_database() || item.kind().is_schema() || item.is_match(&filter_text)
29 })
30 .map(|item| {
31 let mut item = item.clone();
32 if item.is_database() {
33 item.set_collapsed(false);
34 item
35 } else {
36 let mut item = item;
37 item.show();
38 item
39 }
40 })
41 .collect::<Vec<DatabaseTreeItem>>(),
42 }
43 }
44
45 fn create_items(
46 list: &[Database],
47 collapsed: &BTreeSet<&String>,
48 ) -> Result<Vec<DatabaseTreeItem>> {
49 let mut items = Vec::with_capacity(list.len());
50 let mut items_added: HashMap<String, usize> = HashMap::with_capacity(list.len());
51
52 for e in list {
53 {
54 Self::push_databases(e, &mut items, &mut items_added, collapsed)?;
55 }
56 for child in &e.children {
57 match child {
58 Child::Table(table) => items.push(DatabaseTreeItem::new_table(e, table)),
59 Child::Schema(schema) => {
60 items.push(DatabaseTreeItem::new_schema(e, schema, true));
61 for table in &schema.tables {
62 items.push(DatabaseTreeItem::new_table(e, table))
63 }
64 }
65 }
66 }
67 }
68
69 Ok(items)
70 }
71
72 pub fn len(&self) -> usize {
74 self.tree_items.len()
75 }
76
77 pub const fn iterate(&self, start: usize, max_amount: usize) -> TreeItemsIterator<'_> {
79 TreeItemsIterator::new(self, start, max_amount)
80 }
81
82 fn push_databases<'a>(
83 database: &'a Database,
84 nodes: &mut Vec<DatabaseTreeItem>,
85 items_added: &mut HashMap<String, usize>,
86 collapsed: &BTreeSet<&String>,
87 ) -> Result<()> {
88 let c = database.name.clone();
89 if !items_added.contains_key(&c) {
90 items_added.insert(c.clone(), 0);
92
93 *items_added.entry(database.name.clone()).or_insert(0) += 1;
95
96 let is_collapsed = collapsed.contains(&c);
97 nodes.push(DatabaseTreeItem::new_database(database, is_collapsed));
98 }
99
100 *items_added.entry(database.name.clone()).or_insert(0) += 1;
102
103 Ok(())
104 }
105
106 pub fn collapse(&mut self, index: usize, recursive: bool) {
107 if self.tree_items[index].kind().is_database() {
108 self.tree_items[index].collapse_database();
109
110 let name = self.tree_items[index].kind().name();
111
112 for i in index + 1..self.tree_items.len() {
113 let item = &mut self.tree_items[i];
114
115 if recursive && item.kind().is_database() {
116 item.collapse_database();
117 }
118
119 if let Some(db) = item.kind().database_name() {
120 if db == name {
121 item.hide();
122 }
123 } else {
124 return;
125 }
126 }
127 }
128
129 if self.tree_items[index].kind().is_schema() {
130 self.tree_items[index].collapse_schema();
131
132 let name = self.tree_items[index].kind().name();
133
134 for i in index + 1..self.tree_items.len() {
135 let item = &mut self.tree_items[i];
136
137 if recursive && item.kind().is_schema() {
138 item.collapse_schema();
139 }
140
141 if let Some(schema) = item.kind().schema_name() {
142 if schema == name {
143 item.hide();
144 }
145 } else {
146 return;
147 }
148 }
149 }
150 }
151
152 pub fn expand(&mut self, index: usize, recursive: bool) {
153 if self.tree_items[index].kind().is_database() {
154 self.tree_items[index].expand_database();
155
156 let tree_item = self.tree_items[index].clone();
157 let name = self.tree_items[index].kind().name();
158 let kind = tree_item.kind();
159
160 if recursive {
161 for i in index + 1..self.tree_items.len() {
162 let item = &mut self.tree_items[i];
163
164 if let Some(db) = item.kind().database_name() {
165 if *db != name {
166 break;
167 }
168 }
169
170 if item.kind().is_database() && item.kind().is_database_collapsed() {
171 item.expand_database();
172 }
173 }
174 }
175
176 self.update_visibility(kind, index + 1);
177 }
178
179 if self.tree_items[index].kind().is_schema() {
180 self.tree_items[index].expand_schema();
181
182 let tree_item = self.tree_items[index].clone();
183 let name = self.tree_items[index].kind().name();
184 let kind = tree_item.kind();
185
186 if recursive {
187 for i in index + 1..self.tree_items.len() {
188 let item = &mut self.tree_items[i];
189
190 if let Some(schema) = item.kind().schema_name() {
191 if *schema != name {
192 break;
193 }
194 }
195
196 if item.kind().is_schema() && item.kind().is_schema_collapsed() {
197 item.expand_schema();
198 }
199 }
200 }
201
202 self.update_visibility(kind, index + 1);
203 }
204 }
205
206 fn update_visibility(&mut self, prefix: &DatabaseTreeItemKind, start_idx: usize) {
207 let mut inner_collapsed: Option<DatabaseTreeItemKind> = None;
208
209 for i in start_idx..self.tree_items.len() {
210 if let Some(ref collapsed_item) = inner_collapsed {
211 match collapsed_item {
212 DatabaseTreeItemKind::Database { name, .. } => {
213 if let DatabaseTreeItemKind::Schema { database, .. } =
214 self.tree_items[i].kind().clone()
215 {
216 if database.name == *name {
217 continue;
218 }
219 }
220 if let DatabaseTreeItemKind::Table { database, .. } =
221 self.tree_items[i].kind().clone()
222 {
223 if database.name == *name {
224 continue;
225 }
226 }
227 }
228 DatabaseTreeItemKind::Schema { schema, .. } => {
229 if let DatabaseTreeItemKind::Table { table, .. } =
230 self.tree_items[i].kind().clone()
231 {
232 if matches!(table.schema, Some(table_schema) if schema.name == table_schema)
233 {
234 continue;
235 }
236 }
237 }
238 _ => (),
239 }
240 inner_collapsed = None;
241 }
242
243 let item_kind = self.tree_items[i].kind().clone();
244
245 if matches!(item_kind, DatabaseTreeItemKind::Database{ collapsed, .. } if collapsed)
246 || matches!(item_kind, DatabaseTreeItemKind::Schema{ collapsed, .. } if collapsed)
247 {
248 inner_collapsed = Some(item_kind.clone());
249 }
250
251 match prefix {
252 DatabaseTreeItemKind::Database { name, .. } => {
253 if let DatabaseTreeItemKind::Schema { database, .. } = item_kind.clone() {
254 if *name == database.name {
255 self.tree_items[i].info_mut().set_visible(true);
256 }
257 }
258
259 if let DatabaseTreeItemKind::Table { database, .. } = item_kind {
260 if *name == database.name {
261 self.tree_items[i].info_mut().set_visible(true);
262 }
263 }
264 }
265 DatabaseTreeItemKind::Schema { schema, .. } => {
266 if let DatabaseTreeItemKind::Table { table, .. } = item_kind {
267 if matches!(table.schema, Some(table_schema) if schema.name == table_schema)
268 {
269 self.tree_items[i].info_mut().set_visible(true);
270 }
271 }
272 }
273 _ => (),
274 }
275 }
276 }
277}