1use rusqlite::{Connection, Row};
8
9use crate::catalog::CatalogVersion;
10use crate::content::Content;
11use crate::fromdb::FromDb;
12use crate::lrobject::{LrId, LrObject};
13
14#[derive(Clone)]
17pub struct Folder {
18 id: LrId,
19 uuid: String,
20 pub path_from_root: String,
22 pub root_folder: LrId,
24 pub content: Option<Content>,
25}
26
27impl LrObject for Folder {
28 fn id(&self) -> LrId {
29 self.id
30 }
31 fn uuid(&self) -> &str {
32 &self.uuid
33 }
34}
35
36impl FromDb for Folder {
37 fn read_from(_version: CatalogVersion, row: &Row) -> crate::Result<Self> {
38 Ok(Folder {
39 id: row.get(0)?,
40 uuid: row.get(1)?,
41 path_from_root: row.get(2)?,
42 root_folder: row.get(3)?,
43 content: None,
44 })
45 }
46 fn read_db_tables(_version: CatalogVersion) -> &'static str {
47 "AgLibraryFolder"
48 }
49 fn read_db_columns(_version: CatalogVersion) -> &'static str {
50 "id_local,id_global,pathFromRoot,rootFolder"
51 }
52}
53
54impl Folder {
55 pub fn new(id: LrId, uuid: &str) -> Folder {
56 Folder {
57 id,
58 uuid: String::from(uuid),
59 path_from_root: String::from(""),
60 root_folder: 0,
61 content: None,
62 }
63 }
64 pub fn read_content(&self, conn: &Connection) -> Content {
65 Content::from_db(conn, "AgFolderContent", "containingFolder", self.id)
66 }
67}
68
69#[derive(Clone)]
72pub struct RootFolder {
73 id: LrId,
74 uuid: String,
75 pub absolute_path: String,
77 pub name: String,
79 pub relative_path_from_catalog: Option<String>,
82}
83
84impl LrObject for RootFolder {
85 fn id(&self) -> LrId {
86 self.id
87 }
88 fn uuid(&self) -> &str {
89 &self.uuid
90 }
91}
92
93impl RootFolder {
94 pub fn new(id: LrId, uuid: &str) -> RootFolder {
96 RootFolder {
97 id,
98 uuid: String::from(uuid),
99 absolute_path: String::from(""),
100 name: String::from(""),
101 relative_path_from_catalog: None,
102 }
103 }
104}
105
106impl FromDb for RootFolder {
107 fn read_from(_version: CatalogVersion, row: &Row) -> crate::Result<Self> {
108 Ok(RootFolder {
109 id: row.get(0)?,
110 uuid: row.get(1)?,
111 absolute_path: row.get(2)?,
112 name: row.get(3)?,
113 relative_path_from_catalog: row.get(4).ok(),
114 })
115 }
116
117 fn read_db_tables(_version: CatalogVersion) -> &'static str {
118 "AgLibraryRootFolder"
119 }
120
121 fn read_db_columns(_version: CatalogVersion) -> &'static str {
122 "id_local,id_global,absolutePath,name,relativePathFromCatalog"
123 }
124}
125
126#[derive(Clone, Default)]
128pub struct Folders {
129 pub roots: Vec<RootFolder>,
131 pub folders: Vec<Folder>,
133}
134
135impl Folders {
136 pub fn new() -> Folders {
137 Folders::default()
138 }
139
140 pub fn is_empty(&self) -> bool {
142 self.roots.is_empty() && self.folders.is_empty()
143 }
144
145 pub fn add_folder(&mut self, folder: Folder) {
147 self.folders.push(folder);
148 }
149
150 pub fn add_root_folder(&mut self, root_folder: RootFolder) {
152 self.roots.push(root_folder);
153 }
154
155 pub fn append_folders(&mut self, mut folders: Vec<Folder>) {
157 self.folders.append(&mut folders);
158 }
159
160 pub fn append_root_folders(&mut self, mut root_folders: Vec<RootFolder>) {
162 self.roots.append(&mut root_folders);
163 }
164
165 pub fn find_root_folder(&self, id: LrId) -> Option<&RootFolder> {
167 self.roots.iter().find(|&root| root.id() == id)
168 }
169
170 pub fn resolve_folder_path(&self, folder: &Folder) -> Option<String> {
174 let root_folder = self.find_root_folder(folder.root_folder)?;
175 let mut root_path = root_folder.absolute_path.clone();
176 root_path += &folder.path_from_root;
177 Some(root_path)
178 }
179}
180
181#[cfg(test)]
182#[test]
183fn test_resolve_folder_path() {
184 let mut folders = Folders::new();
185
186 let mut rfolder = RootFolder::new(24, "toplevel");
187 rfolder.absolute_path = String::from("/home/hub/Pictures");
188 rfolder.name = String::from("Pictures");
189 folders.add_root_folder(rfolder);
190
191 let mut folder = Folder::new(42, "foobar");
192 folder.root_folder = 24;
193 folder.path_from_root = String::from("/2017/10");
194 folders.add_folder(folder);
195
196 let resolved = folders.resolve_folder_path(&folders.folders[0]);
197 assert!(resolved.is_some());
198 let resolved = resolved.unwrap();
199 assert_eq!(resolved, "/home/hub/Pictures/2017/10");
200}