1 // Copyright 2013-2016, The Gtk-rs Project Developers. 2 // See the COPYRIGHT file at the top-level directory of this distribution. 3 // Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT> 4 5 use glib::object::{Cast, IsA}; 6 use glib::translate::*; 7 use glib::{ToValue, Type, Value}; 8 use gtk_sys; 9 use libc::c_int; 10 use TreeIter; 11 use TreeModel; 12 use TreeStore; 13 14 impl TreeStore { new(column_types: &[Type]) -> TreeStore15 pub fn new(column_types: &[Type]) -> TreeStore { 16 assert_initialized_main_thread!(); 17 unsafe { 18 let mut column_types = column_types.iter().map(|t| t.to_glib()).collect::<Vec<_>>(); 19 from_glib_full(gtk_sys::gtk_tree_store_newv( 20 column_types.len() as c_int, 21 column_types.as_mut_ptr(), 22 )) 23 } 24 } 25 } 26 27 pub trait TreeStoreExtManual: 'static { insert_with_values( &self, parent: Option<&TreeIter>, position: Option<u32>, columns: &[u32], values: &[&dyn ToValue], ) -> TreeIter28 fn insert_with_values( 29 &self, 30 parent: Option<&TreeIter>, 31 position: Option<u32>, 32 columns: &[u32], 33 values: &[&dyn ToValue], 34 ) -> TreeIter; 35 reorder(&self, parent: &TreeIter, new_order: &[u32])36 fn reorder(&self, parent: &TreeIter, new_order: &[u32]); 37 set(&self, iter: &TreeIter, columns: &[u32], values: &[&dyn ToValue])38 fn set(&self, iter: &TreeIter, columns: &[u32], values: &[&dyn ToValue]); 39 set_value(&self, iter: &TreeIter, column: u32, value: &Value)40 fn set_value(&self, iter: &TreeIter, column: u32, value: &Value); 41 } 42 43 impl<O: IsA<TreeStore>> TreeStoreExtManual for O { insert_with_values( &self, parent: Option<&TreeIter>, position: Option<u32>, columns: &[u32], values: &[&dyn ToValue], ) -> TreeIter44 fn insert_with_values( 45 &self, 46 parent: Option<&TreeIter>, 47 position: Option<u32>, 48 columns: &[u32], 49 values: &[&dyn ToValue], 50 ) -> TreeIter { 51 unsafe { 52 assert!(position.unwrap_or(0) <= i32::max_value() as u32); 53 assert_eq!(columns.len(), values.len()); 54 let n_columns = gtk_sys::gtk_tree_model_get_n_columns( 55 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0, 56 ) as u32; 57 assert!(columns.len() <= n_columns as usize); 58 for (&column, value) in columns.iter().zip(values.iter()) { 59 let type_ = from_glib(gtk_sys::gtk_tree_model_get_column_type( 60 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0, 61 column as c_int, 62 )); 63 assert!(Value::type_transformable(value.to_value_type(), type_)); 64 } 65 let mut iter = TreeIter::uninitialized(); 66 gtk_sys::gtk_tree_store_insert_with_valuesv( 67 self.as_ref().to_glib_none().0, 68 iter.to_glib_none_mut().0, 69 mut_override(parent.to_glib_none().0), 70 position.map_or(-1, |n| n as c_int), 71 mut_override(columns.as_ptr() as *const c_int), 72 values.to_glib_none().0, 73 columns.len() as c_int, 74 ); 75 iter 76 } 77 } 78 reorder(&self, parent: &TreeIter, new_order: &[u32])79 fn reorder(&self, parent: &TreeIter, new_order: &[u32]) { 80 unsafe { 81 let count = gtk_sys::gtk_tree_model_iter_n_children( 82 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0, 83 mut_override(parent.to_glib_none().0), 84 ); 85 let safe_count = count as usize == new_order.len(); 86 debug_assert!( 87 safe_count, 88 "Incorrect `new_order` slice length. Expected `{}`, found `{}`.", 89 count, 90 new_order.len() 91 ); 92 let safe_values = new_order.iter().max().map_or(true, |&max| { 93 let max = max as i32; 94 max >= 0 && max < count 95 }); 96 debug_assert!( 97 safe_values, 98 "Some `new_order` slice values are out of range. Maximum safe value: \ 99 `{}`. The slice contents: `{:?}`", 100 count - 1, 101 new_order 102 ); 103 if safe_count && safe_values { 104 gtk_sys::gtk_tree_store_reorder( 105 self.as_ref().to_glib_none().0, 106 mut_override(parent.to_glib_none().0), 107 mut_override(new_order.as_ptr() as *const c_int), 108 ); 109 } 110 } 111 } 112 set(&self, iter: &TreeIter, columns: &[u32], values: &[&dyn ToValue])113 fn set(&self, iter: &TreeIter, columns: &[u32], values: &[&dyn ToValue]) { 114 unsafe { 115 assert_eq!(columns.len(), values.len()); 116 let n_columns = gtk_sys::gtk_tree_model_get_n_columns( 117 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0, 118 ) as u32; 119 assert!(columns.len() <= n_columns as usize); 120 for (&column, value) in columns.iter().zip(values.iter()) { 121 assert!(column < n_columns); 122 let type_ = from_glib(gtk_sys::gtk_tree_model_get_column_type( 123 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0, 124 column as c_int, 125 )); 126 assert!(Value::type_transformable(value.to_value_type(), type_)); 127 } 128 gtk_sys::gtk_tree_store_set_valuesv( 129 self.as_ref().to_glib_none().0, 130 mut_override(iter.to_glib_none().0), 131 mut_override(columns.as_ptr() as *const c_int), 132 values.to_glib_none().0, 133 columns.len() as c_int, 134 ); 135 } 136 } 137 set_value(&self, iter: &TreeIter, column: u32, value: &Value)138 fn set_value(&self, iter: &TreeIter, column: u32, value: &Value) { 139 unsafe { 140 let columns = gtk_sys::gtk_tree_model_get_n_columns( 141 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0, 142 ); 143 assert!(column < columns as u32); 144 let type_ = from_glib(gtk_sys::gtk_tree_model_get_column_type( 145 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0, 146 column as c_int, 147 )); 148 assert!(Value::type_transformable(value.type_(), type_)); 149 gtk_sys::gtk_tree_store_set_value( 150 self.as_ref().to_glib_none().0, 151 mut_override(iter.to_glib_none().0), 152 column as c_int, 153 mut_override(value.to_glib_none().0), 154 ); 155 } 156 } 157 } 158