diff --git a/common-rust/src/implementation.rs b/common-rust/src/implementation.rs index 478a7c4..d0c3156 100644 --- a/common-rust/src/implementation.rs +++ b/common-rust/src/implementation.rs @@ -1,6 +1,9 @@ use interface::*; use types::*; use libc::{c_int}; +use std::fs::read_dir; +use std::path::PathBuf; +use std::ffi::OsString; pub struct Hello { emit: HelloEmitter, @@ -28,30 +31,91 @@ impl Drop for Hello { } } +struct DirEntry { + name: OsString, + parent: usize, + children: Option> +} + pub struct RItemModel { emit: RItemModelEmitter, -// string: String + entries: Vec +} + +impl RItemModel { + fn get(&mut self, index: &QModelIndex) -> usize { + let p = if index.is_valid() { + let row = index.row() as usize; + self.entries[index.id() as usize].children.as_ref().unwrap()[row] + } else { + 1 + }; + if self.entries[p].children.is_none() { + self.read_dir(p); + } + p + } + fn get_path(&self, id: usize) -> PathBuf { + let mut pos = id; + let mut e = Vec::new(); + while pos > 0 { + e.push(pos); + pos = self.entries[pos].parent; + } + let mut path = PathBuf::new(); + for i in e.into_iter().rev() { + path.push(&self.entries[i].name); + } + path + } + fn read_dir(&mut self, id: usize) { + let mut v = Vec::new(); + if let Ok(it) = read_dir(self.get_path(id)) { + for i in it.filter_map(|v|v.ok()) { + let de = DirEntry { + name: i.file_name(), + parent: id, + children: None + }; + v.push(self.entries.len()); + self.entries.push(de); + } + } + self.entries[id].children = Some(v); + } } impl RItemModelTrait for RItemModel { fn create(emit: RItemModelEmitter) -> Self { + let none = DirEntry { name: OsString::new(), parent: 0, children: None }; + let root = DirEntry { name: OsString::from("/"), parent: 0, children: None }; RItemModel { - emit: emit + emit: emit, + entries: vec![none, root] } } - fn column_count(&self, parent: QModelIndex) -> c_int { - if parent.is_valid() { 0 } else { 2 } + fn column_count(&mut self, parent: QModelIndex) -> c_int { + 1 } - fn row_count(&self, parent: QModelIndex) -> c_int { - if parent.is_valid() { 0 } else { 2 } + fn row_count(&mut self, parent: QModelIndex) -> c_int { + let i = self.get(&parent); + self.entries[i].children.as_ref().unwrap().len() as i32 } - fn index(&self, row: i32, column: i32, parent: QModelIndex) -> QModelIndex { - QModelIndex::flat(row, column) + fn index(&mut self, row: i32, column: i32, parent: QModelIndex) -> QModelIndex { + QModelIndex::create(row, column, self.get(&parent)) } fn parent(&self, index: QModelIndex) -> QModelIndex { - QModelIndex::invalid() + if !index.is_valid() || index.id() == 1 { + return QModelIndex::invalid(); + } + let parentid = self.entries[index.id()].parent; + let ref e = self.entries[parentid]; + let mut i = e.children.as_ref().unwrap().iter(); + let row = i.position(|v|*v==index.id()).unwrap() as i32; + QModelIndex::create(row, 0, e.parent) } - fn data<'a>(&'a self, index: QModelIndex, role: c_int) -> Variant<'a> { - Variant::from("hello") + fn data<'a>(&'a mut self, index: QModelIndex, role: c_int) -> Variant<'a> { + let i = self.get(&index); + return Variant::from(self.entries[i].name.to_string_lossy().to_string()); } } diff --git a/common-rust/src/interface.rs b/common-rust/src/interface.rs index fc4351a..971fbd7 100644 --- a/common-rust/src/interface.rs +++ b/common-rust/src/interface.rs @@ -65,11 +65,11 @@ impl RItemModelEmitter { pub trait RItemModelTrait { fn create(emit: RItemModelEmitter) -> Self; - fn column_count(&self, parent: QModelIndex) -> c_int; - fn row_count(&self, parent: QModelIndex) -> c_int; - fn index(&self, row: c_int, column: c_int, parent: QModelIndex) -> QModelIndex; + fn column_count(&mut self, parent: QModelIndex) -> c_int; + fn row_count(&mut self, parent: QModelIndex) -> c_int; + fn index(&mut self, row: c_int, column: c_int, parent: QModelIndex) -> QModelIndex; fn parent(&self, index: QModelIndex) -> QModelIndex; - fn data<'a>(&'a self, index: QModelIndex, role: c_int) -> Variant<'a>; + fn data<'a>(&'a mut self, index: QModelIndex, role: c_int) -> Variant<'a>; } #[no_mangle] @@ -88,20 +88,20 @@ pub extern fn ritemmodel_free(ptr: *mut RItemModel) { } #[no_mangle] -pub extern fn ritemmodel_column_count(ptr: *const RItemModel, parent: QModelIndex) -> i32 { - let ritemmodel = unsafe { &*ptr }; +pub extern fn ritemmodel_column_count(ptr: *mut RItemModel, parent: QModelIndex) -> i32 { + let ritemmodel = unsafe { &mut *ptr }; ritemmodel.column_count(parent) } #[no_mangle] -pub extern fn ritemmodel_row_count(ptr: *const RItemModel, parent: QModelIndex) -> i32 { - let ritemmodel = unsafe { &*ptr }; +pub extern fn ritemmodel_row_count(ptr: *mut RItemModel, parent: QModelIndex) -> i32 { + let ritemmodel = unsafe { &mut *ptr }; ritemmodel.row_count(parent) } #[no_mangle] -pub extern fn ritemmodel_index(ptr: *const RItemModel, row: i32, column: i32, parent: QModelIndex) -> QModelIndex { - let ritemmodel = unsafe { &*ptr }; +pub extern fn ritemmodel_index(ptr: *mut RItemModel, row: i32, column: i32, parent: QModelIndex) -> QModelIndex { + let ritemmodel = unsafe { &mut *ptr }; ritemmodel.index(row, column, parent) } @@ -112,8 +112,8 @@ pub extern fn ritemmodel_parent(ptr: *const RItemModel, index: QModelIndex) -> Q } #[no_mangle] -pub extern fn ritemmodel_data(ptr: *const RItemModel, index: QModelIndex, role: c_int, d: *mut c_void, set: fn (*mut c_void, &QVariant)) { - let ritemmodel = unsafe { &*ptr }; +pub extern fn ritemmodel_data(ptr: *mut RItemModel, index: QModelIndex, role: c_int, d: *mut c_void, set: fn (*mut c_void, &QVariant)) { + let ritemmodel = unsafe { &mut *ptr }; let data = ritemmodel.data(index, role); set(d, &QVariant::from(&data)); } diff --git a/common-rust/src/types.rs b/common-rust/src/types.rs index 231faa8..8bb24bd 100644 --- a/common-rust/src/types.rs +++ b/common-rust/src/types.rs @@ -21,7 +21,7 @@ pub enum Variant<'a> { None, Bool(bool), String(String), - str(&'a str) + Str(&'a str) } impl<'a> From for Variant<'a> { @@ -38,7 +38,7 @@ impl<'a> From for Variant<'a> { impl<'a> From<&'a str> for Variant<'a> { fn from(value: &'a str) -> Variant { - Variant::str(value) + Variant::Str(value) } } @@ -87,7 +87,7 @@ impl<'a> From<&'a Variant<'a>> for QVariant<'a> { type_: VariantType::String as c_uint, phantom: PhantomData }, - &Variant::str(ref v) => QVariant { + &Variant::Str(ref v) => QVariant { data: v.as_ptr(), len: v.len() as c_int, type_: VariantType::String as c_uint, @@ -112,6 +112,13 @@ impl QModelIndex { internal_id: 0 } } + pub fn create(row: c_int, column: c_int, id: usize) -> QModelIndex { + QModelIndex { + row: row, + column: column, + internal_id: id + } + } pub fn flat(row: c_int, column: c_int) -> QModelIndex { QModelIndex { row: row, @@ -122,4 +129,13 @@ impl QModelIndex { pub fn is_valid(&self) -> bool { self.internal_id != 0 && self.row >= 0 && self.column >= 0 } + pub fn row(&self) -> c_int { + self.row + } + pub fn column(&self) -> c_int { + self.column + } + pub fn id(&self) -> usize { + self.internal_id + } }