Skip to main content

gtk4/
list_store.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use glib::{Type, Value, translate::*};
4use libc::c_int;
5
6use crate::{ListStore, TreeIter, TreeModel, ffi, prelude::*};
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    /// s length.
144    #[doc(alias = "gtk_list_store_reorder")]
145    #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
146    #[allow(deprecated)]
147    pub fn reorder(&self, new_order: &[u32]) {
148        unsafe {
149            let count = ffi::gtk_tree_model_iter_n_children(
150                self.upcast_ref::<TreeModel>().to_glib_none().0,
151                std::ptr::null_mut(),
152            );
153            let safe_count = count as usize == new_order.len();
154            debug_assert!(
155                safe_count,
156                "Incorrect `new_order` slice length. Expected `{count}`, found `{}`.",
157                new_order.len()
158            );
159            let safe_values = new_order.iter().max().is_none_or(|&max| {
160                let max = max as i32;
161                max >= 0 && max < count
162            });
163            debug_assert!(
164                safe_values,
165                "Some `new_order` slice values are out of range. Maximum safe value: \
166                 `{}`. The slice contents: `{new_order:?}`",
167                count - 1,
168            );
169            if safe_count && safe_values {
170                ffi::gtk_list_store_reorder(
171                    self.to_glib_none().0,
172                    mut_override(new_order.as_ptr() as *const c_int),
173                );
174            }
175        }
176    }
177
178    /// , you would write `gtk_list_store_set (store, iter,
179    /// 0, "Foo", -1)`.
180    ///
181    /// The value will be referenced by the store if it is a `G_TYPE_OBJECT`, and it
182    /// will be copied if it is a `G_TYPE_STRING` or `G_TYPE_BOXED`.
183    ///
184    /// # Deprecated since 4.10
185    ///
186    /// Use list models
187    /// ## `iter`
188    /// row iterator
189    #[doc(alias = "gtk_list_store_set")]
190    #[doc(alias = "gtk_list_store_set_valuesv")]
191    #[doc(alias = "gtk_list_store_set_valist")]
192    #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
193    #[allow(deprecated)]
194    pub fn set(&self, iter: &TreeIter, columns_and_values: &[(u32, &dyn ToValue)]) {
195        unsafe {
196            let n_columns =
197                ffi::gtk_tree_model_get_n_columns(self.upcast_ref::<TreeModel>().to_glib_none().0)
198                    as u32;
199            assert!(
200                columns_and_values.len() <= n_columns as usize,
201                "got values for {} columns but only {n_columns} columns exist",
202                columns_and_values.len(),
203            );
204            for (column, value) in columns_and_values {
205                assert!(
206                    *column < n_columns,
207                    "got column {column} which is higher than the number of columns {n_columns}",
208                );
209                let type_ = from_glib(ffi::gtk_tree_model_get_column_type(
210                    self.upcast_ref::<TreeModel>().to_glib_none().0,
211                    *column as c_int,
212                ));
213                assert!(
214                    Value::type_transformable(value.value_type(), type_),
215                    "column {column} is of type {type_} but found value of type {}",
216                    value.value_type()
217                );
218            }
219
220            let columns = columns_and_values
221                .iter()
222                .map(|(c, _)| *c)
223                .collect::<Vec<_>>();
224            let values = columns_and_values
225                .iter()
226                .map(|(_, v)| v.to_value())
227                .collect::<Vec<_>>();
228
229            ffi::gtk_list_store_set_valuesv(
230                self.to_glib_none().0,
231                mut_override(iter.to_glib_none().0),
232                mut_override(columns.as_ptr() as *const c_int),
233                mut_override(values.as_ptr() as *const glib::gobject_ffi::GValue),
234                columns.len() as c_int,
235            );
236        }
237    }
238
239    /// Sets the types of the columns of a list store.
240    ///
241    /// This function is meant primarily for objects that inherit
242    /// from [`ListStore`][crate::ListStore], and should only be used when constructing
243    /// a new instance.
244    ///
245    /// This function cannot be called after a row has been added, or
246    /// a method on the [`TreeModel`][crate::TreeModel] interface is called.
247    ///
248    /// # Deprecated since 4.10
249    ///
250    /// Use list models
251    /// ## `types`
252    /// An array length n of `GType`s
253    #[doc(alias = "gtk_list_store_set_column_types")]
254    #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
255    #[allow(deprecated)]
256    pub fn set_column_types(&self, types: &[glib::Type]) {
257        unsafe {
258            let types_ptr: Vec<glib::ffi::GType> = types.iter().map(|t| t.into_glib()).collect();
259            ffi::gtk_list_store_set_column_types(
260                self.to_glib_none().0,
261                types.len() as i32,
262                mut_override(types_ptr.as_ptr()),
263            )
264        }
265    }
266
267    /// Sets the data in the cell specified by @iter and @column.
268    /// The type of @value must be convertible to the type of the
269    /// column.
270    ///
271    /// # Deprecated since 4.10
272    ///
273    /// Use list models
274    /// ## `iter`
275    /// A valid [`TreeIter`][crate::TreeIter] for the row being modified
276    /// ## `column`
277    /// column number to modify
278    /// ## `value`
279    /// new value for the cell
280    #[doc(alias = "gtk_list_store_set_value")]
281    #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
282    #[allow(deprecated)]
283    pub fn set_value(&self, iter: &TreeIter, column: u32, value: &Value) {
284        unsafe {
285            let columns =
286                ffi::gtk_tree_model_get_n_columns(self.upcast_ref::<TreeModel>().to_glib_none().0)
287                    as u32;
288            assert!(
289                column < columns,
290                "got column {column} which is higher than the number of columns {columns}",
291            );
292
293            let type_ = from_glib(ffi::gtk_tree_model_get_column_type(
294                self.upcast_ref::<TreeModel>().to_glib_none().0,
295                column as c_int,
296            ));
297            assert!(
298                Value::type_transformable(value.type_(), type_),
299                "column {column} is of type {type_} but found value of type {}",
300                value.type_()
301            );
302
303            ffi::gtk_list_store_set_value(
304                self.to_glib_none().0,
305                mut_override(iter.to_glib_none().0),
306                column as c_int,
307                mut_override(value.to_glib_none().0),
308            );
309        }
310    }
311}