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