[go: up one dir, main page]

gtk4/
list_store.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use glib::{translate::*, Type, Value};
4use libc::c_int;
5
6use crate::{ffi, prelude::*, ListStore, TreeIter, TreeModel};
7
8impl ListStore {
9    #[doc(alias = "gtk_list_store_newv")]
10    #[doc(alias = "gtk_list_store_new")]
11    #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
12    #[allow(deprecated)]
13    pub fn new(column_types: &[Type]) -> Self {
14        assert_initialized_main_thread!();
15        unsafe {
16            let mut column_types = column_types
17                .iter()
18                .map(|t| t.into_glib())
19                .collect::<Vec<_>>();
20            from_glib_full(ffi::gtk_list_store_newv(
21                column_types.len() as c_int,
22                column_types.as_mut_ptr(),
23            ))
24        }
25    }
26
27    #[doc(alias = "gtk_list_store_insert_with_values")]
28    #[doc(alias = "gtk_list_store_insert_with_valuesv")]
29    #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
30    #[allow(deprecated)]
31    pub fn insert_with_values(
32        &self,
33        position: Option<u32>,
34        columns_and_values: &[(u32, &dyn ToValue)],
35    ) -> TreeIter {
36        unsafe {
37            assert!(
38                position.unwrap_or(0) <= i32::MAX as u32,
39                "can't have more than {} rows",
40                i32::MAX
41            );
42            let n_columns =
43                ffi::gtk_tree_model_get_n_columns(self.upcast_ref::<TreeModel>().to_glib_none().0)
44                    as u32;
45            assert!(
46                columns_and_values.len() <= n_columns as usize,
47                "got values for {} columns but only {n_columns} columns exist",
48                columns_and_values.len(),
49            );
50            for (column, value) in columns_and_values {
51                assert!(
52                    *column < n_columns,
53                    "got column {column} which is higher than the number of columns {n_columns}",
54                );
55                let type_ = from_glib(ffi::gtk_tree_model_get_column_type(
56                    self.upcast_ref::<TreeModel>().to_glib_none().0,
57                    *column as c_int,
58                ));
59                assert!(
60                    Value::type_transformable(value.value_type(), type_),
61                    "column {column} is of type {type_} but found value of type {}",
62                    value.value_type()
63                );
64            }
65
66            let columns = columns_and_values
67                .iter()
68                .map(|(c, _)| *c)
69                .collect::<Vec<_>>();
70            let values = columns_and_values
71                .iter()
72                .map(|(_, v)| v.to_value())
73                .collect::<Vec<_>>();
74
75            let mut iter = TreeIter::uninitialized();
76            ffi::gtk_list_store_insert_with_valuesv(
77                self.to_glib_none().0,
78                iter.to_glib_none_mut().0,
79                position.map_or(-1, |n| n as c_int),
80                mut_override(columns.as_ptr() as *const c_int),
81                mut_override(values.as_ptr() as *const glib::gobject_ffi::GValue),
82                columns.len() as c_int,
83            );
84            iter
85        }
86    }
87
88    #[doc(alias = "gtk_list_store_reorder")]
89    #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
90    #[allow(deprecated)]
91    pub fn reorder(&self, new_order: &[u32]) {
92        unsafe {
93            let count = ffi::gtk_tree_model_iter_n_children(
94                self.upcast_ref::<TreeModel>().to_glib_none().0,
95                std::ptr::null_mut(),
96            );
97            let safe_count = count as usize == new_order.len();
98            debug_assert!(
99                safe_count,
100                "Incorrect `new_order` slice length. Expected `{count}`, found `{}`.",
101                new_order.len()
102            );
103            let safe_values = new_order.iter().max().is_none_or(|&max| {
104                let max = max as i32;
105                max >= 0 && max < count
106            });
107            debug_assert!(
108                safe_values,
109                "Some `new_order` slice values are out of range. Maximum safe value: \
110                 `{}`. The slice contents: `{new_order:?}`",
111                count - 1,
112            );
113            if safe_count && safe_values {
114                ffi::gtk_list_store_reorder(
115                    self.to_glib_none().0,
116                    mut_override(new_order.as_ptr() as *const c_int),
117                );
118            }
119        }
120    }
121
122    #[doc(alias = "gtk_list_store_set")]
123    #[doc(alias = "gtk_list_store_set_valuesv")]
124    #[doc(alias = "gtk_list_store_set_valist")]
125    #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
126    #[allow(deprecated)]
127    pub fn set(&self, iter: &TreeIter, columns_and_values: &[(u32, &dyn ToValue)]) {
128        unsafe {
129            let n_columns =
130                ffi::gtk_tree_model_get_n_columns(self.upcast_ref::<TreeModel>().to_glib_none().0)
131                    as u32;
132            assert!(
133                columns_and_values.len() <= n_columns as usize,
134                "got values for {} columns but only {n_columns} columns exist",
135                columns_and_values.len(),
136            );
137            for (column, value) in columns_and_values {
138                assert!(
139                    *column < n_columns,
140                    "got column {column} which is higher than the number of columns {n_columns}",
141                );
142                let type_ = from_glib(ffi::gtk_tree_model_get_column_type(
143                    self.upcast_ref::<TreeModel>().to_glib_none().0,
144                    *column as c_int,
145                ));
146                assert!(
147                    Value::type_transformable(value.value_type(), type_),
148                    "column {column} is of type {type_} but found value of type {}",
149                    value.value_type()
150                );
151            }
152
153            let columns = columns_and_values
154                .iter()
155                .map(|(c, _)| *c)
156                .collect::<Vec<_>>();
157            let values = columns_and_values
158                .iter()
159                .map(|(_, v)| v.to_value())
160                .collect::<Vec<_>>();
161
162            ffi::gtk_list_store_set_valuesv(
163                self.to_glib_none().0,
164                mut_override(iter.to_glib_none().0),
165                mut_override(columns.as_ptr() as *const c_int),
166                mut_override(values.as_ptr() as *const glib::gobject_ffi::GValue),
167                columns.len() as c_int,
168            );
169        }
170    }
171
172    #[doc(alias = "gtk_list_store_set_column_types")]
173    #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
174    #[allow(deprecated)]
175    pub fn set_column_types(&self, types: &[glib::Type]) {
176        unsafe {
177            let types_ptr: Vec<glib::ffi::GType> = types.iter().map(|t| t.into_glib()).collect();
178            ffi::gtk_list_store_set_column_types(
179                self.to_glib_none().0,
180                types.len() as i32,
181                mut_override(types_ptr.as_ptr()),
182            )
183        }
184    }
185
186    #[doc(alias = "gtk_list_store_set_value")]
187    #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
188    #[allow(deprecated)]
189    pub fn set_value(&self, iter: &TreeIter, column: u32, value: &Value) {
190        unsafe {
191            let columns =
192                ffi::gtk_tree_model_get_n_columns(self.upcast_ref::<TreeModel>().to_glib_none().0)
193                    as u32;
194            assert!(
195                column < columns,
196                "got column {column} which is higher than the number of columns {columns}",
197            );
198
199            let type_ = from_glib(ffi::gtk_tree_model_get_column_type(
200                self.upcast_ref::<TreeModel>().to_glib_none().0,
201                column as c_int,
202            ));
203            assert!(
204                Value::type_transformable(value.type_(), type_),
205                "column {column} is of type {type_} but found value of type {}",
206                value.type_()
207            );
208
209            ffi::gtk_list_store_set_value(
210                self.to_glib_none().0,
211                mut_override(iter.to_glib_none().0),
212                column as c_int,
213                mut_override(value.to_glib_none().0),
214            );
215        }
216    }
217}