1use crate::TreeModel;
4use crate::TreeStore;
5use crate::{TreeIter, ffi};
6use glib::object::{Cast, IsA};
7use glib::translate::*;
8use glib::{Type, Value, value::ToValue};
9use libc::c_int;
10
11impl TreeStore {
12 #[doc(alias = "gtk_tree_store_newv")]
26 pub fn new(column_types: &[Type]) -> TreeStore {
27 assert_initialized_main_thread!();
28 unsafe {
29 let mut column_types = column_types
30 .iter()
31 .map(|t| t.into_glib())
32 .collect::<Vec<_>>();
33 from_glib_full(ffi::gtk_tree_store_newv(
34 column_types.len() as c_int,
35 column_types.as_mut_ptr(),
36 ))
37 }
38 }
39}
40
41pub trait TreeStoreExtManual: IsA<TreeStore> + 'static {
42 #[doc(alias = "gtk_tree_store_insert_with_valuesv")]
43 fn insert_with_values(
44 &self,
45 parent: Option<&TreeIter>,
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 {n_columns} columns exist",
61 columns_and_values.len(),
62 );
63 for (column, value) in columns_and_values {
64 assert!(
65 *column < n_columns,
66 "got column {} which is higher than the number of columns {n_columns}",
67 *column,
68 );
69 let type_ = from_glib(ffi::gtk_tree_model_get_column_type(
70 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
71 *column as c_int,
72 ));
73 assert!(
74 Value::type_transformable(value.value_type(), type_),
75 "column {} is of type {type_} but found value of type {}",
76 *column,
77 value.value_type()
78 );
79 }
80
81 let columns = columns_and_values
82 .iter()
83 .map(|(c, _)| *c)
84 .collect::<Vec<_>>();
85 let values = columns_and_values
86 .iter()
87 .map(|(_, v)| v.to_value())
88 .collect::<Vec<_>>();
89
90 let mut iter = TreeIter::uninitialized();
91 ffi::gtk_tree_store_insert_with_valuesv(
92 self.as_ref().to_glib_none().0,
93 iter.to_glib_none_mut().0,
94 mut_override(parent.to_glib_none().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_tree_store_reorder")]
114 fn reorder(&self, parent: &TreeIter, new_order: &[u32]) {
115 unsafe {
116 let count = ffi::gtk_tree_model_iter_n_children(
117 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
118 mut_override(parent.to_glib_none().0),
119 );
120 let safe_count = count as usize == new_order.len();
121 debug_assert!(
122 safe_count,
123 "Incorrect `new_order` slice length. Expected `{count}`, found `{}`.",
124 new_order.len()
125 );
126 let safe_values = new_order.iter().max().is_none_or(|&max| {
127 let max = max as i32;
128 max >= 0 && max < count
129 });
130 debug_assert!(
131 safe_values,
132 "Some `new_order` slice values are out of range. Maximum safe value: \
133 `{}`. The slice contents: `{new_order:?}`",
134 count - 1,
135 );
136 if safe_count && safe_values {
137 ffi::gtk_tree_store_reorder(
138 self.as_ref().to_glib_none().0,
139 mut_override(parent.to_glib_none().0),
140 mut_override(new_order.as_ptr() as *const c_int),
141 );
142 }
143 }
144 }
145
146 #[doc(alias = "gtk_tree_store_set")]
158 #[doc(alias = "gtk_tree_store_set_valuesv")]
159 fn set(&self, iter: &TreeIter, columns_and_values: &[(u32, &dyn ToValue)]) {
160 unsafe {
161 let n_columns = ffi::gtk_tree_model_get_n_columns(
162 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
163 ) as u32;
164 assert!(
165 columns_and_values.len() <= n_columns as usize,
166 "got values for {} columns but only {} columns exist",
167 columns_and_values.len(),
168 n_columns
169 );
170 for (column, value) in columns_and_values {
171 assert!(
172 *column < n_columns,
173 "got column {} which is higher than the number of columns {n_columns}",
174 *column,
175 );
176 let type_ = from_glib(ffi::gtk_tree_model_get_column_type(
177 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
178 *column as c_int,
179 ));
180 assert!(
181 Value::type_transformable(value.value_type(), type_),
182 "column {} is of type {type_} but found value of type {}",
183 *column,
184 value.value_type()
185 );
186 }
187
188 let columns = columns_and_values
189 .iter()
190 .map(|(c, _)| *c)
191 .collect::<Vec<_>>();
192 let values = columns_and_values
193 .iter()
194 .map(|(_, v)| v.to_value())
195 .collect::<Vec<_>>();
196
197 ffi::gtk_tree_store_set_valuesv(
198 self.as_ref().to_glib_none().0,
199 mut_override(iter.to_glib_none().0),
200 mut_override(columns.as_ptr() as *const c_int),
201 mut_override(values.as_ptr() as *const glib::gobject_ffi::GValue),
202 columns.len() as c_int,
203 );
204 }
205 }
206
207 #[doc(alias = "gtk_tree_store_set_value")]
217 fn set_value(&self, iter: &TreeIter, column: u32, value: &Value) {
218 unsafe {
219 let columns = ffi::gtk_tree_model_get_n_columns(
220 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
221 ) as u32;
222 assert!(
223 column < columns,
224 "got column {column} which is higher than the number of columns {columns}",
225 );
226
227 let type_ = from_glib(ffi::gtk_tree_model_get_column_type(
228 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
229 column as c_int,
230 ));
231 assert!(
232 Value::type_transformable(value.type_(), type_),
233 "column {column} is of type {type_} but found value of type {}",
234 value.type_()
235 );
236
237 ffi::gtk_tree_store_set_value(
238 self.as_ref().to_glib_none().0,
239 mut_override(iter.to_glib_none().0),
240 column as c_int,
241 mut_override(value.to_glib_none().0),
242 );
243 }
244 }
245}
246
247impl<O: IsA<TreeStore>> TreeStoreExtManual for O {}