gtk/
tree_store.rs

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
5use glib::object::{Cast, IsA};
6use glib::translate::*;
7use glib::{ToValue, Type, Value};
8use gtk_sys;
9use libc::c_int;
10use TreeIter;
11use TreeModel;
12use TreeStore;
13
14impl TreeStore {
15    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
27pub trait TreeStoreExtManual: 'static {
28    fn insert_with_values(
29        &self,
30        parent: Option<&TreeIter>,
31        position: Option<u32>,
32        columns: &[u32],
33        values: &[&dyn ToValue],
34    ) -> TreeIter;
35
36    fn reorder(&self, parent: &TreeIter, new_order: &[u32]);
37
38    fn set(&self, iter: &TreeIter, columns: &[u32], values: &[&dyn ToValue]);
39
40    fn set_value(&self, iter: &TreeIter, column: u32, value: &Value);
41}
42
43impl<O: IsA<TreeStore>> TreeStoreExtManual for O {
44    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
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
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
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}