1use crate::{Database, Schema, Table};
2
3#[derive(Debug, Clone)]
4pub struct TreeItemInfo {
5 indent: u8,
6 visible: bool,
7}
8
9impl TreeItemInfo {
10 pub const fn new(indent: u8, visible: bool) -> Self {
11 Self { indent, visible }
12 }
13
14 pub const fn is_visible(&self) -> bool {
15 self.visible
16 }
17
18 pub const fn indent(&self) -> u8 {
19 self.indent
20 }
21
22 pub fn unindent(&mut self) {
23 self.indent = self.indent.saturating_sub(1);
24 }
25
26 pub fn set_visible(&mut self, visible: bool) {
27 self.visible = visible;
28 }
29}
30
31#[derive(PartialEq, Debug, Clone)]
33pub enum DatabaseTreeItemKind {
34 Database {
35 name: String,
36 collapsed: bool,
37 },
38 Table {
39 database: Database,
40 table: Table,
41 },
42 Schema {
43 database: Database,
44 schema: Schema,
45 collapsed: bool,
46 },
47}
48
49impl DatabaseTreeItemKind {
50 pub const fn is_database(&self) -> bool {
51 matches!(self, Self::Database { .. })
52 }
53
54 pub const fn is_table(&self) -> bool {
55 matches!(self, Self::Table { .. })
56 }
57
58 pub const fn is_schema(&self) -> bool {
59 matches!(self, Self::Schema { .. })
60 }
61
62 pub const fn is_database_collapsed(&self) -> bool {
63 match self {
64 Self::Database { collapsed, .. } => *collapsed,
65 Self::Table { .. } => false,
66 Self::Schema { .. } => false,
67 }
68 }
69
70 pub const fn is_schema_collapsed(&self) -> bool {
71 match self {
72 Self::Database { .. } => false,
73 Self::Table { .. } => false,
74 Self::Schema { collapsed, .. } => *collapsed,
75 }
76 }
77
78 pub fn name(&self) -> String {
79 match self {
80 Self::Database { name, .. } => name.to_string(),
81 Self::Table { table, .. } => table.name.clone(),
82 Self::Schema { schema, .. } => schema.name.clone(),
83 }
84 }
85
86 pub fn database_name(&self) -> Option<String> {
87 match self {
88 Self::Database { .. } => None,
89 Self::Table { database, .. } => Some(database.name.clone()),
90 Self::Schema { database, .. } => Some(database.name.clone()),
91 }
92 }
93
94 pub fn schema_name(&self) -> Option<String> {
95 match self {
96 Self::Database { .. } => None,
97 Self::Table { table, .. } => table.schema.clone(),
98 Self::Schema { .. } => None,
99 }
100 }
101}
102
103#[derive(Debug, Clone)]
105pub struct DatabaseTreeItem {
106 info: TreeItemInfo,
107 kind: DatabaseTreeItemKind,
108}
109
110impl DatabaseTreeItem {
111 pub fn new_table(database: &Database, table: &Table) -> Self {
112 Self {
113 info: TreeItemInfo::new(if table.schema.is_some() { 2 } else { 1 }, false),
114 kind: DatabaseTreeItemKind::Table {
115 database: database.clone(),
116 table: table.clone(),
117 },
118 }
119 }
120
121 pub fn new_schema(database: &Database, schema: &Schema, _collapsed: bool) -> Self {
122 Self {
123 info: TreeItemInfo::new(1, false),
124 kind: DatabaseTreeItemKind::Schema {
125 database: database.clone(),
126 schema: schema.clone(),
127 collapsed: true,
128 },
129 }
130 }
131
132 pub fn new_database(database: &Database, _collapsed: bool) -> Self {
133 Self {
134 info: TreeItemInfo::new(0, true),
135 kind: DatabaseTreeItemKind::Database {
136 name: database.name.to_string(),
137 collapsed: true,
138 },
139 }
140 }
141
142 pub fn set_collapsed(&mut self, collapsed: bool) {
143 if let DatabaseTreeItemKind::Database { name, .. } = self.kind() {
144 self.kind = DatabaseTreeItemKind::Database {
145 name: name.to_string(),
146 collapsed,
147 }
148 }
149 }
150
151 pub const fn info(&self) -> &TreeItemInfo {
152 &self.info
153 }
154
155 pub fn info_mut(&mut self) -> &mut TreeItemInfo {
156 &mut self.info
157 }
158
159 pub const fn kind(&self) -> &DatabaseTreeItemKind {
160 &self.kind
161 }
162
163 pub fn collapse_database(&mut self) {
164 if let DatabaseTreeItemKind::Database { name, .. } = &self.kind {
165 self.kind = DatabaseTreeItemKind::Database {
166 name: name.to_string(),
167 collapsed: true,
168 }
169 }
170 }
171
172 pub fn expand_database(&mut self) {
173 if let DatabaseTreeItemKind::Database { name, .. } = &self.kind {
174 self.kind = DatabaseTreeItemKind::Database {
175 name: name.to_string(),
176 collapsed: false,
177 };
178 }
179 }
180
181 pub fn collapse_schema(&mut self) {
182 if let DatabaseTreeItemKind::Schema {
183 schema, database, ..
184 } = &self.kind
185 {
186 self.kind = DatabaseTreeItemKind::Schema {
187 database: database.clone(),
188 schema: schema.clone(),
189 collapsed: true,
190 }
191 }
192 }
193
194 pub fn expand_schema(&mut self) {
195 if let DatabaseTreeItemKind::Schema {
196 schema, database, ..
197 } = &self.kind
198 {
199 self.kind = DatabaseTreeItemKind::Schema {
200 database: database.clone(),
201 schema: schema.clone(),
202 collapsed: false,
203 };
204 }
205 }
206
207 pub fn show(&mut self) {
208 self.info.visible = true;
209 }
210
211 pub fn hide(&mut self) {
212 self.info.visible = false;
213 }
214
215 pub fn is_match(&self, filter_text: &str) -> bool {
216 match self.kind.clone() {
217 DatabaseTreeItemKind::Database { name, .. } => name.contains(filter_text),
218 DatabaseTreeItemKind::Table { table, .. } => table.name.contains(filter_text),
219 DatabaseTreeItemKind::Schema { schema, .. } => schema.name.contains(filter_text),
220 }
221 }
222
223 pub fn is_database(&self) -> bool {
224 self.kind.is_database()
225 }
226}
227
228impl Eq for DatabaseTreeItem {}
229
230impl PartialEq for DatabaseTreeItem {
231 fn eq(&self, other: &Self) -> bool {
232 if self.kind.is_database() && other.kind().is_database() {
233 return self.kind.name().eq(&other.kind.name());
234 }
235 if !self.kind.is_database() && !other.kind.is_database() {
236 return self.kind.name().eq(&other.kind.name());
237 }
238 false
239 }
240}
241
242impl PartialOrd for DatabaseTreeItem {
243 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
244 self.kind.name().partial_cmp(&other.kind.name())
245 }
246}
247
248impl Ord for DatabaseTreeItem {
249 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
250 self.kind.name().cmp(&other.kind.name())
251 }
252}