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