gtk4/
tree_sortable.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{fmt, mem};
4
5use glib::translate::*;
6
7use crate::{ffi, prelude::*, Ordering, SortType, TreeIter, TreeModel, TreeSortable};
8
9#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
10#[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
11#[allow(deprecated)]
12pub enum SortColumn {
13    #[doc(alias = "GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID")]
14    Default,
15    Index(u32),
16}
17
18#[doc(hidden)]
19impl IntoGlib for SortColumn {
20    type GlibType = i32;
21
22    #[inline]
23    fn into_glib(self) -> i32 {
24        match self {
25            SortColumn::Default => ffi::GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
26            SortColumn::Index(x) => {
27                assert!(x <= i32::MAX as u32, "column index is too big");
28                x as i32
29            }
30        }
31    }
32}
33
34#[doc(hidden)]
35impl FromGlib<i32> for SortColumn {
36    #[inline]
37    unsafe fn from_glib(val: i32) -> Self {
38        skip_assert_initialized!();
39        match val {
40            ffi::GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID => Self::Default,
41            x => {
42                assert!(x >= 0, "invalid column index");
43                Self::Index(x as u32)
44            }
45        }
46    }
47}
48
49impl fmt::Display for SortColumn {
50    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
51        write!(
52            f,
53            "SortColumn::{}",
54            match *self {
55                SortColumn::Default => "Default",
56                SortColumn::Index(_) => "Index",
57            }
58        )
59    }
60}
61
62mod sealed {
63    pub trait Sealed {}
64    impl<T: super::IsA<super::TreeSortable>> Sealed for T {}
65}
66
67// rustdoc-stripper-ignore-next
68/// Trait containing manually implemented methods of
69/// [`TreeSortable`](crate::TreeSortable).
70#[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
71#[allow(deprecated)]
72pub trait TreeSortableExtManual: sealed::Sealed + IsA<TreeSortable> + 'static {
73    /// Sets the default comparison function used when sorting to be @sort_func.
74    /// If the current sort column id of @self is
75    /// `GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID`, then the model will sort using
76    /// this function.
77    ///
78    /// If @sort_func is [`None`], then there will be no default comparison function.
79    /// This means that once the model  has been sorted, it can’t go back to the
80    /// default state. In this case, when the current sort column id of @self
81    /// is `GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID`, the model will be unsorted.
82    ///
83    /// # Deprecated since 4.10
84    ///
85    /// ## `sort_func`
86    /// The comparison function
87    #[doc(alias = "gtk_tree_sortable_set_default_sort_func")]
88    fn set_default_sort_func<F>(&self, sort_func: F)
89    where
90        F: Fn(&Self, &TreeIter, &TreeIter) -> Ordering + 'static,
91    {
92        unsafe {
93            ffi::gtk_tree_sortable_set_default_sort_func(
94                self.as_ref().to_glib_none().0,
95                Some(trampoline::<Self, F>),
96                into_raw(sort_func),
97                Some(destroy_closure::<Self, F>),
98            )
99        }
100    }
101    /// Sets the comparison function used when sorting to be @sort_func. If the
102    /// current sort column id of @self is the same as @sort_column_id, then
103    /// the model will sort using this function.
104    ///
105    /// # Deprecated since 4.10
106    ///
107    /// ## `sort_column_id`
108    /// the sort column id to set the function for
109    /// ## `sort_func`
110    /// The comparison function
111    #[doc(alias = "gtk_tree_sortable_set_sort_func")]
112    fn set_sort_func<F>(&self, sort_column_id: SortColumn, sort_func: F)
113    where
114        F: Fn(&Self, &TreeIter, &TreeIter) -> Ordering + 'static,
115    {
116        unsafe {
117            ffi::gtk_tree_sortable_set_sort_func(
118                self.as_ref().to_glib_none().0,
119                sort_column_id.into_glib(),
120                Some(trampoline::<Self, F>),
121                into_raw(sort_func),
122                Some(destroy_closure::<Self, F>),
123            )
124        }
125    }
126    /// Fills in @sort_column_id and @order with the current sort column and the
127    /// order. It returns [`true`] unless the @sort_column_id is
128    /// `GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID` or
129    /// `GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID`.
130    ///
131    /// # Deprecated since 4.10
132    ///
133    ///
134    /// # Returns
135    ///
136    /// [`true`] if the sort column is not one of the special sort
137    ///   column ids.
138    ///
139    /// ## `sort_column_id`
140    /// The sort column id to be filled in
141    ///
142    /// ## `order`
143    /// The [`SortType`][crate::SortType] to be filled in
144    #[doc(alias = "gtk_tree_sortable_get_sort_column_id")]
145    #[doc(alias = "get_sort_column_id")]
146    fn sort_column_id(&self) -> Option<(SortColumn, SortType)> {
147        unsafe {
148            let mut sort_column_id = mem::MaybeUninit::uninit();
149            let mut order = mem::MaybeUninit::uninit();
150            ffi::gtk_tree_sortable_get_sort_column_id(
151                self.as_ref().to_glib_none().0,
152                sort_column_id.as_mut_ptr(),
153                order.as_mut_ptr(),
154            );
155            let sort_column_id = sort_column_id.assume_init();
156            if sort_column_id != ffi::GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID {
157                Some((from_glib(sort_column_id), from_glib(order.assume_init())))
158            } else {
159                None
160            }
161        }
162    }
163    /// Sets the current sort column to be @sort_column_id. The @self will
164    /// resort itself to reflect this change, after emitting a
165    /// `GtkTreeSortable::sort-column-changed` signal. @sort_column_id may either be
166    /// a regular column id, or one of the following special values:
167    ///
168    /// - `GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID`: the default sort function
169    ///   will be used, if it is set
170    ///
171    /// - `GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID`: no sorting will occur
172    ///
173    /// # Deprecated since 4.10
174    ///
175    /// ## `sort_column_id`
176    /// the sort column id to set
177    /// ## `order`
178    /// The sort order of the column
179    #[doc(alias = "gtk_tree_sortable_set_sort_column_id")]
180    fn set_sort_column_id(&self, sort_column_id: SortColumn, order: SortType) {
181        unsafe {
182            ffi::gtk_tree_sortable_set_sort_column_id(
183                self.as_ref().to_glib_none().0,
184                sort_column_id.into_glib(),
185                order.into_glib(),
186            );
187        }
188    }
189    #[doc(alias = "gtk_tree_sortable_set_sort_column_id")]
190    fn set_unsorted(&self) {
191        unsafe {
192            ffi::gtk_tree_sortable_set_sort_column_id(
193                self.as_ref().to_glib_none().0,
194                ffi::GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID,
195                SortType::Ascending.into_glib(),
196            );
197        }
198    }
199}
200
201unsafe extern "C" fn trampoline<T, F: Fn(&T, &TreeIter, &TreeIter) -> Ordering>(
202    this: *mut ffi::GtkTreeModel,
203    iter: *mut ffi::GtkTreeIter,
204    iter2: *mut ffi::GtkTreeIter,
205    f: glib::ffi::gpointer,
206) -> i32
207where
208    T: IsA<TreeSortable>,
209{
210    let f: &F = &*(f as *const F);
211    f(
212        &TreeModel::from_glib_none(this).unsafe_cast(),
213        &from_glib_borrow(iter),
214        &from_glib_borrow(iter2),
215    )
216    .into_glib()
217}
218
219unsafe extern "C" fn destroy_closure<T, F: Fn(&T, &TreeIter, &TreeIter) -> Ordering>(
220    ptr: glib::ffi::gpointer,
221) {
222    let _ = Box::<F>::from_raw(ptr as *mut _);
223}
224
225fn into_raw<F, T>(func: F) -> glib::ffi::gpointer
226where
227    F: Fn(&T, &TreeIter, &TreeIter) -> Ordering + 'static,
228{
229    skip_assert_initialized!();
230    let func: Box<F> = Box::new(func);
231    Box::into_raw(func) as glib::ffi::gpointer
232}
233
234impl<O: IsA<TreeSortable>> TreeSortableExtManual for O {}