Warning, /sdk/rust-qt-binding-generator/demo/rust/src/implementation/file_system_tree.rs is written in an unsupported language. File is not indexed.
0001 // Copyright 2017 Jos van den Oever <jos@vandenoever.info> 0002 // 0003 // This program is free software; you can redistribute it and/or 0004 // modify it under the terms of the GNU General Public License as 0005 // published by the Free Software Foundation; either version 2 of 0006 // the License or (at your option) version 3 or any later version 0007 // accepted by the membership of KDE e.V. (or its successor approved 0008 // by the membership of KDE e.V.), which shall act as a proxy 0009 // defined in Section 14 of version 3 of the license. 0010 // 0011 // This program is distributed in the hope that it will be useful, 0012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0014 // GNU General Public License for more details. 0015 // 0016 // You should have received a copy of the GNU General Public License 0017 // along with this program. If not, see <http://www.gnu.org/licenses/>. 0018 0019 use interface::*; 0020 use std::fs::*; 0021 use std::fs::read_dir; 0022 use std::path::PathBuf; 0023 use std::ffi::OsString; 0024 use std::default::Default; 0025 use std::thread; 0026 use std::sync::mpsc::{Receiver, Sender, channel}; 0027 use std::marker::Sync; 0028 0029 pub struct DirEntry { 0030 name: OsString, 0031 metadata: Option<Metadata>, 0032 path: Option<PathBuf>, 0033 icon: Vec<u8>, 0034 } 0035 0036 impl Item for DirEntry { 0037 fn new(name: &str) -> DirEntry { 0038 DirEntry { 0039 name: OsString::from(name), 0040 metadata: metadata(name).ok(), 0041 path: None, 0042 icon: Vec::new(), 0043 } 0044 } 0045 fn can_fetch_more(&self) -> bool { 0046 self.metadata.as_ref().map_or(false, |m| m.is_dir()) 0047 } 0048 fn file_name(&self) -> String { 0049 self.name.to_string_lossy().to_string() 0050 } 0051 fn file_path(&self) -> Option<String> { 0052 self.path.as_ref().map(|p| p.to_string_lossy().into()) 0053 } 0054 fn file_permissions(&self) -> i32 { 0055 42 0056 } 0057 fn file_type(&self) -> i32 { 0058 0 0059 } 0060 fn file_size(&self) -> Option<u64> { 0061 self.metadata.as_ref().map(|m| m.len()) 0062 } 0063 fn icon(&self) -> &[u8] { 0064 &self.icon 0065 } 0066 fn retrieve(id: usize, parents: Vec<&Self>, outgoing: &Sender<(usize, PathBuf)>) { 0067 let path: PathBuf = parents.into_iter().map(|e| &e.name).collect(); 0068 if let Err(e) = outgoing.send((id, path)) { 0069 eprintln!("{}", e); 0070 } 0071 } 0072 fn read_files( 0073 incoming: Receiver<(usize, PathBuf)>, 0074 outgoing: Sender<(usize, Vec<Self>)>, 0075 mut emit: FileSystemTreeEmitter, 0076 ) { 0077 thread::spawn(move || while let Ok((id, path)) = incoming.recv() { 0078 let mut v = Vec::new(); 0079 if let Ok(it) = read_dir(&path) { 0080 for i in it.filter_map(|v| v.ok()) { 0081 let de = DirEntry { 0082 name: i.file_name(), 0083 metadata: i.metadata().ok(), 0084 path: Some(i.path()), 0085 icon: Vec::new(), 0086 }; 0087 v.push(de); 0088 } 0089 } 0090 v.sort_by(|a, b| a.name.cmp(&b.name)); 0091 if let Ok(()) = outgoing.send((id, v)) { 0092 emit.new_data_ready(Some(id)); 0093 } else { 0094 return; 0095 } 0096 }); 0097 } 0098 } 0099 0100 impl Default for DirEntry { 0101 fn default() -> DirEntry { 0102 DirEntry { 0103 name: OsString::new(), 0104 metadata: None, 0105 path: None, 0106 icon: Vec::new(), 0107 } 0108 } 0109 } 0110 0111 pub trait Item: Default { 0112 fn new(name: &str) -> Self; 0113 fn can_fetch_more(&self) -> bool; 0114 fn retrieve(id: usize, parents: Vec<&Self>, outgoing: &Sender<(usize, PathBuf)>); 0115 fn read_files( 0116 incoming: Receiver<(usize, PathBuf)>, 0117 outgoing: Sender<(usize, Vec<Self>)>, 0118 emit: FileSystemTreeEmitter, 0119 ); 0120 fn file_name(&self) -> String; 0121 fn file_path(&self) -> Option<String>; 0122 fn file_permissions(&self) -> i32; 0123 fn file_type(&self) -> i32; 0124 fn file_size(&self) -> Option<u64>; 0125 fn icon(&self) -> &[u8]; 0126 } 0127 0128 pub type FileSystemTree = RGeneralItemModel<DirEntry>; 0129 0130 struct Entry<T: Item> { 0131 parent: Option<usize>, 0132 row: usize, 0133 children: Option<Vec<usize>>, 0134 data: T, 0135 } 0136 0137 pub struct RGeneralItemModel<T: Item> { 0138 emit: FileSystemTreeEmitter, 0139 model: FileSystemTreeTree, 0140 entries: Vec<Entry<T>>, 0141 path: Option<String>, 0142 outgoing: Sender<(usize, PathBuf)>, 0143 incoming: Receiver<(usize, Vec<T>)>, 0144 } 0145 0146 impl<T: Item> RGeneralItemModel<T> 0147 where 0148 T: Sync + Send, 0149 { 0150 fn reset(&mut self) { 0151 self.model.begin_reset_model(); 0152 self.entries.clear(); 0153 if let Some(ref path) = self.path { 0154 let root = Entry { 0155 parent: None, 0156 row: 0, 0157 children: None, 0158 data: T::new(path), 0159 }; 0160 self.entries.push(root); 0161 } 0162 self.model.end_reset_model(); 0163 } 0164 fn get(&self, index: usize) -> &Entry<T> { 0165 &self.entries[index] 0166 } 0167 fn retrieve(&self, index: usize) { 0168 let parents = self.get_parents(index); 0169 T::retrieve(index, parents, &self.outgoing); 0170 } 0171 fn process_incoming(&mut self) { 0172 while let Ok((id, entries)) = self.incoming.try_recv() { 0173 if self.entries[id].children.is_some() { 0174 continue; 0175 } 0176 let mut new_entries = Vec::new(); 0177 let mut children = Vec::new(); 0178 for (r, d) in entries.into_iter().enumerate() { 0179 new_entries.push(Entry { 0180 parent: Some(id), 0181 row: r, 0182 children: None, 0183 data: d, 0184 }); 0185 children.push(self.entries.len() + r); 0186 } 0187 if new_entries.is_empty() { 0188 self.entries[id].children = Some(children); 0189 } else { 0190 self.model.begin_insert_rows( 0191 Some(id), 0192 0, 0193 new_entries.len() - 1, 0194 ); 0195 self.entries[id].children = Some(children); 0196 self.entries.append(&mut new_entries); 0197 self.model.end_insert_rows(); 0198 } 0199 } 0200 } 0201 fn get_parents(&self, id: usize) -> Vec<&T> { 0202 let mut pos = Some(id); 0203 let mut e = Vec::new(); 0204 while let Some(p) = pos { 0205 e.push(p); 0206 pos = self.entries[p].parent; 0207 } 0208 e.into_iter().rev().map(|i| &self.entries[i].data).collect() 0209 } 0210 } 0211 0212 impl<T: Item> FileSystemTreeTrait for RGeneralItemModel<T> 0213 where 0214 T: Sync + Send, 0215 { 0216 fn new(mut emit: FileSystemTreeEmitter, model: FileSystemTreeTree) -> Self { 0217 let (outgoing, thread_incoming) = channel(); 0218 let (thread_outgoing, incoming) = channel::<(usize, Vec<T>)>(); 0219 T::read_files(thread_incoming, thread_outgoing, emit.clone()); 0220 let mut tree: RGeneralItemModel<T> = RGeneralItemModel { 0221 emit, 0222 model, 0223 entries: Vec::new(), 0224 path: None, 0225 outgoing, 0226 incoming, 0227 }; 0228 tree.reset(); 0229 tree 0230 } 0231 fn emit(&mut self) -> &mut FileSystemTreeEmitter { 0232 &mut self.emit 0233 } 0234 fn path(&self) -> Option<&str> { 0235 self.path.as_ref().map(|s| &s[..]) 0236 } 0237 fn set_path(&mut self, value: Option<String>) { 0238 if self.path != value { 0239 self.path = value; 0240 self.emit.path_changed(); 0241 self.reset(); 0242 } 0243 } 0244 fn can_fetch_more(&self, index: Option<usize>) -> bool { 0245 let entry = self.get(index.unwrap_or(0)); 0246 entry.children.is_none() && entry.data.can_fetch_more() 0247 } 0248 fn fetch_more(&mut self, index: Option<usize>) { 0249 self.process_incoming(); 0250 if !self.can_fetch_more(index) { 0251 return; 0252 } 0253 self.retrieve(index.unwrap_or(0)); 0254 } 0255 fn row_count(&self, index: Option<usize>) -> usize { 0256 if self.entries.is_empty() { 0257 return 0; 0258 } 0259 if let Some(i) = index { 0260 let entry = self.get(i); 0261 if let Some(ref children) = entry.children { 0262 children.len() 0263 } else { 0264 self.retrieve(i); 0265 0 0266 } 0267 } else { 0268 1 0269 } 0270 } 0271 fn index(&self, index: Option<usize>, row: usize) -> usize { 0272 if let Some(index) = index { 0273 self.get(index).children.as_ref().unwrap()[row] 0274 } else { 0275 0 0276 } 0277 } 0278 fn parent(&self, index: usize) -> Option<usize> { 0279 self.entries[index].parent 0280 } 0281 fn row(&self, index: usize) -> usize { 0282 self.entries[index].row 0283 } 0284 fn check_row(&self, index: usize, _row: usize) -> Option<usize> { 0285 if index < self.entries.len() { 0286 Some(self.row(index)) 0287 } else { 0288 None 0289 } 0290 } 0291 fn file_name(&self, index: usize) -> String { 0292 self.get(index).data.file_name() 0293 } 0294 fn file_permissions(&self, index: usize) -> i32 { 0295 self.get(index).data.file_permissions() 0296 } 0297 #[allow(unused_variables)] 0298 fn file_icon(&self, index: usize) -> &[u8] { 0299 self.get(index).data.icon() 0300 } 0301 fn file_path(&self, index: usize) -> Option<String> { 0302 self.get(index).data.file_path() 0303 } 0304 fn file_type(&self, index: usize) -> i32 { 0305 self.get(index).data.file_type() 0306 } 0307 fn file_size(&self, index: usize) -> Option<u64> { 0308 self.get(index).data.file_size() 0309 } 0310 }