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