1use crate::TreeIter;
4use crate::TreeModel;
5use crate::TreeStore;
6use glib::object::{Cast, IsA};
7use glib::translate::*;
8use glib::{ToValue, Type, Value};
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
41mod sealed {
42 pub trait Sealed {}
43 impl<T: glib::IsA<crate::TreeStore>> Sealed for T {}
44}
45
46pub trait TreeStoreExtManual: IsA<TreeStore> + sealed::Sealed + 'static {
47 #[doc(alias = "gtk_tree_store_insert_with_valuesv")]
48 fn insert_with_values(
49 &self,
50 parent: Option<&TreeIter>,
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 {n_columns} columns exist",
66 columns_and_values.len(),
67 );
68 for (column, value) in columns_and_values {
69 assert!(
70 *column < n_columns,
71 "got column {} which is higher than the number of columns {n_columns}",
72 *column,
73 );
74 let type_ = from_glib(ffi::gtk_tree_model_get_column_type(
75 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
76 *column as c_int,
77 ));
78 assert!(
79 Value::type_transformable(value.value_type(), type_),
80 "column {} is of type {type_} but found value of type {}",
81 *column,
82 value.value_type()
83 );
84 }
85
86 let columns = columns_and_values
87 .iter()
88 .map(|(c, _)| *c)
89 .collect::<Vec<_>>();
90 let values = columns_and_values
91 .iter()
92 .map(|(_, v)| v.to_value())
93 .collect::<Vec<_>>();
94
95 let mut iter = TreeIter::uninitialized();
96 ffi::gtk_tree_store_insert_with_valuesv(
97 self.as_ref().to_glib_none().0,
98 iter.to_glib_none_mut().0,
99 mut_override(parent.to_glib_none().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_tree_store_reorder")]
119 fn reorder(&self, parent: &TreeIter, new_order: &[u32]) {
120 unsafe {
121 let count = ffi::gtk_tree_model_iter_n_children(
122 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
123 mut_override(parent.to_glib_none().0),
124 );
125 let safe_count = count as usize == new_order.len();
126 debug_assert!(
127 safe_count,
128 "Incorrect `new_order` slice length. Expected `{count}`, found `{}`.",
129 new_order.len()
130 );
131 let safe_values = new_order.iter().max().map_or(true, |&max| {
132 let max = max as i32;
133 max >= 0 && max < count
134 });
135 debug_assert!(
136 safe_values,
137 "Some `new_order` slice values are out of range. Maximum safe value: \
138 `{}`. The slice contents: `{new_order:?}`",
139 count - 1,
140 );
141 if safe_count && safe_values {
142 ffi::gtk_tree_store_reorder(
143 self.as_ref().to_glib_none().0,
144 mut_override(parent.to_glib_none().0),
145 mut_override(new_order.as_ptr() as *const c_int),
146 );
147 }
148 }
149 }
150
151 #[doc(alias = "gtk_tree_store_set")]
163 #[doc(alias = "gtk_tree_store_set_valuesv")]
164 fn set(&self, iter: &TreeIter, columns_and_values: &[(u32, &dyn ToValue)]) {
165 unsafe {
166 let n_columns = ffi::gtk_tree_model_get_n_columns(
167 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
168 ) as u32;
169 assert!(
170 columns_and_values.len() <= n_columns as usize,
171 "got values for {} columns but only {} columns exist",
172 columns_and_values.len(),
173 n_columns
174 );
175 for (column, value) in columns_and_values {
176 assert!(
177 *column < n_columns,
178 "got column {} which is higher than the number of columns {n_columns}",
179 *column,
180 );
181 let type_ = from_glib(ffi::gtk_tree_model_get_column_type(
182 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
183 *column as c_int,
184 ));
185 assert!(
186 Value::type_transformable(value.value_type(), type_),
187 "column {} is of type {type_} but found value of type {}",
188 *column,
189 value.value_type()
190 );
191 }
192
193 let columns = columns_and_values
194 .iter()
195 .map(|(c, _)| *c)
196 .collect::<Vec<_>>();
197 let values = columns_and_values
198 .iter()
199 .map(|(_, v)| v.to_value())
200 .collect::<Vec<_>>();
201
202 ffi::gtk_tree_store_set_valuesv(
203 self.as_ref().to_glib_none().0,
204 mut_override(iter.to_glib_none().0),
205 mut_override(columns.as_ptr() as *const c_int),
206 mut_override(values.as_ptr() as *const glib::gobject_ffi::GValue),
207 columns.len() as c_int,
208 );
209 }
210 }
211
212 #[doc(alias = "gtk_tree_store_set_value")]
222 fn set_value(&self, iter: &TreeIter, column: u32, value: &Value) {
223 unsafe {
224 let columns = ffi::gtk_tree_model_get_n_columns(
225 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
226 ) as u32;
227 assert!(
228 column < columns,
229 "got column {column} which is higher than the number of columns {columns}",
230 );
231
232 let type_ = from_glib(ffi::gtk_tree_model_get_column_type(
233 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
234 column as c_int,
235 ));
236 assert!(
237 Value::type_transformable(value.type_(), type_),
238 "column {column} is of type {type_} but found value of type {}",
239 value.type_()
240 );
241
242 ffi::gtk_tree_store_set_value(
243 self.as_ref().to_glib_none().0,
244 mut_override(iter.to_glib_none().0),
245 column as c_int,
246 mut_override(value.to_glib_none().0),
247 );
248 }
249 }
250}
251
252impl<O: IsA<TreeStore>> TreeStoreExtManual for O {}