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