gtk/
list_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 std::ptr;
11use ListStore;
12use TreeIter;
13use TreeModel;
14
15impl ListStore {
16    pub fn new(column_types: &[Type]) -> ListStore {
17        assert_initialized_main_thread!();
18        unsafe {
19            let mut column_types = column_types.iter().map(|t| t.to_glib()).collect::<Vec<_>>();
20            from_glib_full(gtk_sys::gtk_list_store_newv(
21                column_types.len() as c_int,
22                column_types.as_mut_ptr(),
23            ))
24        }
25    }
26}
27
28pub trait GtkListStoreExtManual: 'static {
29    fn insert_with_values(
30        &self,
31        position: Option<u32>,
32        columns: &[u32],
33        values: &[&dyn ToValue],
34    ) -> TreeIter;
35
36    fn reorder(&self, 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<ListStore>> GtkListStoreExtManual for O {
44    fn insert_with_values(
45        &self,
46        position: Option<u32>,
47        columns: &[u32],
48        values: &[&dyn ToValue],
49    ) -> TreeIter {
50        unsafe {
51            assert!(position.unwrap_or(0) <= i32::max_value() as u32);
52            assert_eq!(columns.len(), values.len());
53            let n_columns = gtk_sys::gtk_tree_model_get_n_columns(
54                self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
55            ) as u32;
56            assert!(columns.len() <= n_columns as usize);
57            for (&column, value) in columns.iter().zip(values.iter()) {
58                assert!(column < n_columns);
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_list_store_insert_with_valuesv(
67                self.as_ref().to_glib_none().0,
68                iter.to_glib_none_mut().0,
69                position.map_or(-1, |n| n as c_int),
70                mut_override(columns.as_ptr() as *const c_int),
71                values.to_glib_none().0,
72                columns.len() as c_int,
73            );
74            iter
75        }
76    }
77
78    fn reorder(&self, new_order: &[u32]) {
79        unsafe {
80            let count = gtk_sys::gtk_tree_model_iter_n_children(
81                self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
82                ptr::null_mut(),
83            );
84            let safe_count = count as usize == new_order.len();
85            debug_assert!(
86                safe_count,
87                "Incorrect `new_order` slice length. Expected `{}`, found `{}`.",
88                count,
89                new_order.len()
90            );
91            let safe_values = new_order.iter().max().map_or(true, |&max| {
92                let max = max as i32;
93                max >= 0 && max < count
94            });
95            debug_assert!(
96                safe_values,
97                "Some `new_order` slice values are out of range. Maximum safe value: \
98                 `{}`. The slice contents: `{:?}`",
99                count - 1,
100                new_order
101            );
102            if safe_count && safe_values {
103                gtk_sys::gtk_list_store_reorder(
104                    self.as_ref().to_glib_none().0,
105                    mut_override(new_order.as_ptr() as *const c_int),
106                );
107            }
108        }
109    }
110
111    fn set(&self, iter: &TreeIter, columns: &[u32], values: &[&dyn ToValue]) {
112        unsafe {
113            assert_eq!(columns.len(), values.len());
114            let n_columns = gtk_sys::gtk_tree_model_get_n_columns(
115                self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
116            ) as u32;
117            assert!(columns.len() <= n_columns as usize);
118            for (&column, value) in columns.iter().zip(values.iter()) {
119                assert!(column < n_columns);
120                let type_ = from_glib(gtk_sys::gtk_tree_model_get_column_type(
121                    self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
122                    column as c_int,
123                ));
124                assert!(Value::type_transformable(value.to_value_type(), type_));
125            }
126            gtk_sys::gtk_list_store_set_valuesv(
127                self.as_ref().to_glib_none().0,
128                mut_override(iter.to_glib_none().0),
129                mut_override(columns.as_ptr() as *const c_int),
130                values.to_glib_none().0,
131                columns.len() as c_int,
132            );
133        }
134    }
135
136    fn set_value(&self, iter: &TreeIter, column: u32, value: &Value) {
137        unsafe {
138            let columns = gtk_sys::gtk_tree_model_get_n_columns(
139                self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
140            );
141            assert!(column < columns as u32);
142            let type_ = from_glib(gtk_sys::gtk_tree_model_get_column_type(
143                self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
144                column as c_int,
145            ));
146            assert!(Value::type_transformable(value.type_(), type_));
147            gtk_sys::gtk_list_store_set_value(
148                self.as_ref().to_glib_none().0,
149                mut_override(iter.to_glib_none().0),
150                column as c_int,
151                mut_override(value.to_glib_none().0),
152            );
153        }
154    }
155}