1use crate::ListStore;
4use crate::TreeIter;
5use crate::TreeModel;
6use glib::object::{Cast, IsA};
7use glib::translate::*;
8use glib::{ToValue, Type, Value};
9use libc::c_int;
10use std::ptr;
11
12impl ListStore {
13 #[doc(alias = "gtk_list_store_newv")]
27 pub fn new(column_types: &[Type]) -> ListStore {
28 assert_initialized_main_thread!();
29 unsafe {
30 let mut column_types = column_types
31 .iter()
32 .map(|t| t.into_glib())
33 .collect::<Vec<_>>();
34 from_glib_full(ffi::gtk_list_store_newv(
35 column_types.len() as c_int,
36 column_types.as_mut_ptr(),
37 ))
38 }
39 }
40}
41
42mod sealed {
43 pub trait Sealed {}
44 impl<T: glib::IsA<crate::ListStore>> Sealed for T {}
45}
46
47pub trait GtkListStoreExtManual: IsA<ListStore> + sealed::Sealed + 'static {
48 #[doc(alias = "gtk_list_store_insert_with_valuesv")]
49 fn insert_with_values(
50 &self,
51 position: Option<u32>,
52 columns_and_values: &[(u32, &dyn ToValue)],
53 ) -> TreeIter {
54 unsafe {
55 assert!(
56 position.unwrap_or(0) <= i32::max_value() as u32,
57 "can't have more than {} rows",
58 i32::max_value()
59 );
60 let n_columns = ffi::gtk_tree_model_get_n_columns(
61 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
62 ) as u32;
63 assert!(
64 columns_and_values.len() <= n_columns as usize,
65 "got values for {} columns but only {} columns exist",
66 columns_and_values.len(),
67 n_columns
68 );
69 for (column, value) in columns_and_values {
70 assert!(
71 *column < n_columns,
72 "got column {} which is higher than the number of columns {n_columns}",
73 *column,
74 );
75 let type_ = from_glib(ffi::gtk_tree_model_get_column_type(
76 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
77 *column as c_int,
78 ));
79 assert!(
80 Value::type_transformable(value.value_type(), type_),
81 "column {} is of type {type_} but found value of type {}",
82 *column,
83 value.value_type()
84 );
85 }
86
87 let columns = columns_and_values
88 .iter()
89 .map(|(c, _)| *c)
90 .collect::<Vec<_>>();
91 let values = columns_and_values
92 .iter()
93 .map(|(_, v)| v.to_value())
94 .collect::<Vec<_>>();
95
96 let mut iter = TreeIter::uninitialized();
97 ffi::gtk_list_store_insert_with_valuesv(
98 self.as_ref().to_glib_none().0,
99 iter.to_glib_none_mut().0,
100 position.map_or(-1, |n| n as c_int),
101 mut_override(columns.as_ptr() as *const c_int),
102 mut_override(values.as_ptr() as *const glib::gobject_ffi::GValue),
103 columns.len() as c_int,
104 );
105 iter
106 }
107 }
108
109 #[doc(alias = "gtk_list_store_reorder")]
117 fn reorder(&self, new_order: &[u32]) {
118 unsafe {
119 let count = ffi::gtk_tree_model_iter_n_children(
120 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
121 ptr::null_mut(),
122 );
123 let safe_count = count as usize == new_order.len();
124 debug_assert!(
125 safe_count,
126 "Incorrect `new_order` slice length. Expected `{count}`, found `{}`.",
127 new_order.len()
128 );
129 let safe_values = new_order.iter().max().map_or(true, |&max| {
130 let max = max as i32;
131 max >= 0 && max < count
132 });
133 debug_assert!(
134 safe_values,
135 "Some `new_order` slice values are out of range. Maximum safe value: \
136 `{}`. The slice contents: `{new_order:?}`",
137 count - 1,
138 );
139 if safe_count && safe_values {
140 ffi::gtk_list_store_reorder(
141 self.as_ref().to_glib_none().0,
142 mut_override(new_order.as_ptr() as *const c_int),
143 );
144 }
145 }
146 }
147
148 #[doc(alias = "gtk_list_store_set")]
160 #[doc(alias = "gtk_list_store_set_valuesv")]
161 fn set(&self, iter: &TreeIter, columns_and_values: &[(u32, &dyn ToValue)]) {
162 unsafe {
163 let n_columns = ffi::gtk_tree_model_get_n_columns(
164 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
165 ) as u32;
166 assert!(
167 columns_and_values.len() <= n_columns as usize,
168 "got values for {} columns but only {n_columns} columns exist",
169 columns_and_values.len(),
170 );
171 for (column, value) in columns_and_values {
172 assert!(
173 *column < n_columns,
174 "got column {} which is higher than the number of columns {n_columns}",
175 *column,
176 );
177 let type_ = from_glib(ffi::gtk_tree_model_get_column_type(
178 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
179 *column as c_int,
180 ));
181 assert!(
182 Value::type_transformable(value.value_type(), type_),
183 "column {} is of type {type_} but found value of type {}",
184 *column,
185 value.value_type()
186 );
187 }
188
189 let columns = columns_and_values
190 .iter()
191 .map(|(c, _)| *c)
192 .collect::<Vec<_>>();
193 let values = columns_and_values
194 .iter()
195 .map(|(_, v)| v.to_value())
196 .collect::<Vec<_>>();
197
198 ffi::gtk_list_store_set_valuesv(
199 self.as_ref().to_glib_none().0,
200 mut_override(iter.to_glib_none().0),
201 mut_override(columns.as_ptr() as *const c_int),
202 mut_override(values.as_ptr() as *const glib::gobject_ffi::GValue),
203 columns.len() as c_int,
204 );
205 }
206 }
207
208 #[doc(alias = "gtk_list_store_set_value")]
218 fn set_value(&self, iter: &TreeIter, column: u32, value: &Value) {
219 unsafe {
220 let columns = ffi::gtk_tree_model_get_n_columns(
221 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
222 ) as u32;
223 assert!(
224 column < columns,
225 "got column {column} which is higher than the number of columns {columns}",
226 );
227
228 let type_ = from_glib(ffi::gtk_tree_model_get_column_type(
229 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
230 column as c_int,
231 ));
232 assert!(
233 Value::type_transformable(value.type_(), type_),
234 "column {column} is of type {type_} but found value of type {}",
235 value.type_()
236 );
237
238 ffi::gtk_list_store_set_value(
239 self.as_ref().to_glib_none().0,
240 mut_override(iter.to_glib_none().0),
241 column as c_int,
242 mut_override(value.to_glib_none().0),
243 );
244 }
245 }
246}
247
248impl<O: IsA<ListStore>> GtkListStoreExtManual for O {}