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 }