gtk4/tree_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::*, TreeIter, TreeModel, TreeStore};
7
8impl TreeStore {
9 /// Creates a new tree store.
10 ///
11 /// The tree store will have @n_columns, with each column using the
12 /// corresponding type passed to this function.
13 ///
14 /// Note that only types derived from standard GObject fundamental types
15 /// are supported.
16 ///
17 /// As an example:
18 ///
19 /// **⚠️ The following code is in c ⚠️**
20 ///
21 /// ```c
22 /// gtk_tree_store_new (3, G_TYPE_INT, G_TYPE_STRING, GDK_TYPE_TEXTURE);
23 /// ```
24 ///
25 /// will create a new [`TreeStore`][crate::TreeStore] with three columns of type
26 /// `int`, `gchararray`, and [`gdk::Texture`][crate::gdk::Texture] respectively.
27 ///
28 /// # Deprecated since 4.10
29 ///
30 /// Use [`TreeListModel`][crate::TreeListModel] instead
31 ///
32 /// # Returns
33 ///
34 /// a new [`TreeStore`][crate::TreeStore]
35 #[doc(alias = "gtk_tree_store_newv")]
36 #[doc(alias = "gtk_tree_store_new")]
37 #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
38 #[allow(deprecated)]
39 pub fn new(column_types: &[Type]) -> Self {
40 assert_initialized_main_thread!();
41 unsafe {
42 let mut column_types = column_types
43 .iter()
44 .map(|t| t.into_glib())
45 .collect::<Vec<_>>();
46 from_glib_full(ffi::gtk_tree_store_newv(
47 column_types.len() as c_int,
48 column_types.as_mut_ptr(),
49 ))
50 }
51 }
52
53 /// A variant of gtk_tree_store_insert_with_values() which takes
54 /// the columns and values as two arrays, instead of varargs.
55 ///
56 /// This function is mainly intended for language bindings.
57 ///
58 /// # Deprecated since 4.10
59 ///
60 /// Use [`TreeListModel`][crate::TreeListModel] instead
61 /// ## `parent`
62 /// A valid [`TreeIter`][crate::TreeIter]
63 /// ## `position`
64 /// position to insert the new row, or -1 for last
65 /// ## `columns`
66 /// an array of column numbers
67 /// ## `values`
68 /// an array of GValues
69 ///
70 /// # Returns
71 ///
72 ///
73 /// ## `iter`
74 /// An unset [`TreeIter`][crate::TreeIter] to set the new row
75 #[doc(alias = "gtk_tree_store_insert_with_values")]
76 #[doc(alias = "gtk_tree_store_insert_with_valuesv")]
77 #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
78 #[allow(deprecated)]
79 pub fn insert_with_values(
80 &self,
81 parent: Option<&TreeIter>,
82 position: Option<u32>,
83 columns_and_values: &[(u32, &dyn ToValue)],
84 ) -> TreeIter {
85 unsafe {
86 assert!(
87 position.unwrap_or(0) <= i32::MAX as u32,
88 "can't have more than {} rows",
89 i32::MAX
90 );
91 let n_columns =
92 ffi::gtk_tree_model_get_n_columns(self.upcast_ref::<TreeModel>().to_glib_none().0)
93 as u32;
94 assert!(
95 columns_and_values.len() <= n_columns as usize,
96 "got values for {} columns but only {n_columns} columns exist",
97 columns_and_values.len(),
98 );
99 for (column, value) in columns_and_values {
100 assert!(
101 *column < n_columns,
102 "got column {column} which is higher than the number of columns {n_columns}",
103 );
104 let type_ = from_glib(ffi::gtk_tree_model_get_column_type(
105 self.upcast_ref::<TreeModel>().to_glib_none().0,
106 *column as c_int,
107 ));
108 assert!(
109 Value::type_transformable(value.value_type(), type_),
110 "column {column} is of type {} but found value of type {type_}",
111 value.value_type()
112 );
113 }
114
115 let columns = columns_and_values
116 .iter()
117 .map(|(c, _)| *c)
118 .collect::<Vec<_>>();
119 let values = columns_and_values
120 .iter()
121 .map(|(_, v)| v.to_value())
122 .collect::<Vec<_>>();
123
124 let mut iter = TreeIter::uninitialized();
125 ffi::gtk_tree_store_insert_with_valuesv(
126 self.to_glib_none().0,
127 iter.to_glib_none_mut().0,
128 mut_override(parent.to_glib_none().0),
129 position.map_or(-1, |n| n as c_int),
130 mut_override(columns.as_ptr() as *const c_int),
131 mut_override(values.as_ptr() as *const glib::gobject_ffi::GValue),
132 columns.len() as c_int,
133 );
134 iter
135 }
136 }
137
138 /// Reorders the children of @parent in @self to follow the order
139 /// indicated by @new_order.
140 ///
141 /// Note that this function only works with unsorted stores.
142 ///
143 /// # Deprecated since 4.10
144 ///
145 /// Use [`TreeListModel`][crate::TreeListModel] instead
146 /// ## `parent`
147 /// the parent of the children to re-order
148 /// ## `new_order`
149 /// an array of integers mapping the new position
150 /// of each child to its old position before the re-ordering,
151 /// i.e. `new_order[newpos] = oldpos`
152 #[doc(alias = "gtk_tree_store_reorder")]
153 #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
154 #[allow(deprecated)]
155 pub fn reorder(&self, parent: &TreeIter, new_order: &[u32]) {
156 unsafe {
157 let count = ffi::gtk_tree_model_iter_n_children(
158 self.upcast_ref::<TreeModel>().to_glib_none().0,
159 mut_override(parent.to_glib_none().0),
160 );
161 let safe_count = count as usize == new_order.len();
162 debug_assert!(
163 safe_count,
164 "Incorrect `new_order` slice length. Expected `{count}`, found `{}`.",
165 new_order.len()
166 );
167 let safe_values = new_order.iter().max().map_or(true, |&max| {
168 let max = max as i32;
169 max >= 0 && max < count
170 });
171 debug_assert!(
172 safe_values,
173 "Some `new_order` slice values are out of range. Maximum safe value: \
174 `{}`. The slice contents: `{new_order:?}`",
175 count - 1,
176 );
177 if safe_count && safe_values {
178 ffi::gtk_tree_store_reorder(
179 self.to_glib_none().0,
180 mut_override(parent.to_glib_none().0),
181 mut_override(new_order.as_ptr() as *const c_int),
182 );
183 }
184 }
185 }
186
187 /// Sets the value of one or more cells in the row referenced by @iter.
188 ///
189 /// The variable argument list should contain integer column numbers,
190 /// each column number followed by the value to be set.
191 ///
192 /// The list is terminated by a value of `-1`.
193 ///
194 /// For example, to set column 0 with type `G_TYPE_STRING` to “Foo”, you would
195 /// write
196 ///
197 /// **⚠️ The following code is in c ⚠️**
198 ///
199 /// ```c
200 /// gtk_tree_store_set (store, iter, 0, "Foo", -1);
201 /// ```
202 ///
203 /// The value will be referenced by the store if it is a `G_TYPE_OBJECT`, and it
204 /// will be copied if it is a `G_TYPE_STRING` or `G_TYPE_BOXED`.
205 ///
206 /// # Deprecated since 4.10
207 ///
208 /// Use [`TreeListModel`][crate::TreeListModel] instead
209 /// ## `iter`
210 /// A valid [`TreeIter`][crate::TreeIter] for the row being modified
211 #[doc(alias = "gtk_tree_store_set")]
212 #[doc(alias = "gtk_tree_store_set_valuesv")]
213 #[doc(alias = "gtk_tree_store_set_valist")]
214 #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
215 #[allow(deprecated)]
216 pub fn set(&self, iter: &TreeIter, columns_and_values: &[(u32, &dyn ToValue)]) {
217 unsafe {
218 let n_columns =
219 ffi::gtk_tree_model_get_n_columns(self.upcast_ref::<TreeModel>().to_glib_none().0)
220 as u32;
221 assert!(
222 columns_and_values.len() <= n_columns as usize,
223 "got values for {} columns but only {n_columns} columns exist",
224 columns_and_values.len(),
225 );
226 for (column, value) in columns_and_values {
227 assert!(
228 *column < n_columns,
229 "got column {column} which is higher than the number of columns {n_columns}",
230 );
231 let type_ = from_glib(ffi::gtk_tree_model_get_column_type(
232 self.upcast_ref::<TreeModel>().to_glib_none().0,
233 *column as c_int,
234 ));
235 assert!(
236 Value::type_transformable(value.value_type(), type_),
237 "column {column} is of type {type_} but found value of type {}",
238 value.value_type()
239 );
240 }
241
242 let columns = columns_and_values
243 .iter()
244 .map(|(c, _)| *c)
245 .collect::<Vec<_>>();
246 let values = columns_and_values
247 .iter()
248 .map(|(_, v)| v.to_value())
249 .collect::<Vec<_>>();
250
251 ffi::gtk_tree_store_set_valuesv(
252 self.to_glib_none().0,
253 mut_override(iter.to_glib_none().0),
254 mut_override(columns.as_ptr() as *const c_int),
255 mut_override(values.as_ptr() as *const glib::gobject_ffi::GValue),
256 columns.len() as c_int,
257 );
258 }
259 }
260
261 /// Sets the type of the columns in a tree store.
262 ///
263 /// This function is meant primarily for types that inherit from
264 /// [`TreeStore`][crate::TreeStore], and should only be used when constructing a new
265 /// [`TreeStore`][crate::TreeStore].
266 ///
267 /// This functions cannot be called after a row has been added,
268 /// or a method on the [`TreeModel`][crate::TreeModel] interface is called on the
269 /// tree store.
270 ///
271 /// # Deprecated since 4.10
272 ///
273 /// Use [`TreeListModel`][crate::TreeListModel] instead
274 /// ## `types`
275 /// An array of `GType` types, one for each column
276 #[doc(alias = "gtk_tree_store_set_column_types")]
277 #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
278 #[allow(deprecated)]
279 pub fn set_column_types(&self, types: &[glib::Type]) {
280 unsafe {
281 let types_ptr: Vec<glib::ffi::GType> = types.iter().map(|t| t.into_glib()).collect();
282 ffi::gtk_tree_store_set_column_types(
283 self.to_glib_none().0,
284 types.len() as i32,
285 mut_override(types_ptr.as_ptr()),
286 )
287 }
288 }
289
290 /// Sets the data in the cell specified by @iter and @column.
291 ///
292 /// The type of @value must be convertible to the type of the
293 /// column.
294 ///
295 /// # Deprecated since 4.10
296 ///
297 /// Use [`TreeListModel`][crate::TreeListModel] instead
298 /// ## `iter`
299 /// A valid [`TreeIter`][crate::TreeIter] for the row being modified
300 /// ## `column`
301 /// column number to modify
302 /// ## `value`
303 /// new value for the cell
304 #[doc(alias = "gtk_tree_store_set_value")]
305 #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
306 #[allow(deprecated)]
307 pub fn set_value(&self, iter: &TreeIter, column: u32, value: &Value) {
308 unsafe {
309 let columns =
310 ffi::gtk_tree_model_get_n_columns(self.upcast_ref::<TreeModel>().to_glib_none().0)
311 as u32;
312 assert!(
313 column < columns,
314 "got column {column} which is higher than the number of columns {columns}",
315 );
316
317 let type_ = from_glib(ffi::gtk_tree_model_get_column_type(
318 self.upcast_ref::<TreeModel>().to_glib_none().0,
319 column as c_int,
320 ));
321 assert!(
322 Value::type_transformable(value.type_(), type_),
323 "column {column} is of type {type_} but found value of type {}",
324 value.type_()
325 );
326
327 ffi::gtk_tree_store_set_value(
328 self.to_glib_none().0,
329 mut_override(iter.to_glib_none().0),
330 column as c_int,
331 mut_override(value.to_glib_none().0),
332 );
333 }
334 }
335}