nix_query_tree_viewer/ui/stack/
tree.rs1mod columns;
2mod path;
3mod signals;
4mod store;
5
6use core::cmp::Ordering;
7use glib::clone;
8use glib::translate::ToGlibPtr;
9
10use super::super::super::ui;
11use super::super::prelude::*;
12
13fn clear(state: &ui::State) {
14 let tree_store = state.get_tree_store();
15 tree_store.clear();
16}
17
18pub fn disable(state: &ui::State) {
19 let tree_view: gtk::TreeView = state.get_tree_view();
20 tree_view.set_sensitive(false);
21}
22
23pub fn enable(state: &ui::State) {
24 let tree_view: gtk::TreeView = state.get_tree_view();
25 tree_view.set_sensitive(true);
26}
27
28fn render_nix_store_res(state: &ui::State) {
29 if let Some(res) = &*state.read_nix_store_res() {
30 let tree_store = state.get_tree_store();
31 store::insert(&tree_store, res);
32 }
33}
34
35pub fn setup(state: &ui::State) {
36 signals::connect(state);
37}
38
39#[allow(unsafe_code)]
41fn set_sort_func<O: IsA<gtk::TreeSortable>>(
42 tree_model_sort: &O,
43 sort_func: Box<
44 dyn Fn(gtk::TreeModel, gtk::TreeIter, gtk::TreeIter) -> Ordering
45 + 'static,
46 >,
47) {
48 let sort_func_data: Box<
49 Box<
50 dyn Fn(gtk::TreeModel, gtk::TreeIter, gtk::TreeIter) -> Ordering
51 + 'static,
52 >,
53 > = Box::new(sort_func);
54
55 unsafe extern "C" fn sort_func_func(
56 tree_model: *mut gtk_sys::GtkTreeModel,
57 tree_iter_a: *mut gtk_sys::GtkTreeIter,
58 tree_iter_b: *mut gtk_sys::GtkTreeIter,
59 user_data: glib_sys::gpointer,
60 ) -> i32 {
61 let tree_model: gtk::TreeModel =
62 glib::translate::from_glib_borrow(tree_model);
63 let tree_iter_a: gtk::TreeIter =
64 glib::translate::from_glib_borrow(tree_iter_a);
65 let tree_iter_b: gtk::TreeIter =
66 glib::translate::from_glib_borrow(tree_iter_b);
67 let callback: &Box<
68 dyn Fn(gtk::TreeModel, gtk::TreeIter, gtk::TreeIter) -> Ordering
69 + 'static,
70 > = &*(user_data as *mut _);
71
72 let res = callback(tree_model, tree_iter_a, tree_iter_b);
73
74 match res {
75 Ordering::Less => -1,
76 Ordering::Equal => 0,
77 Ordering::Greater => 1,
78 }
79 }
80
81 let tree_sortable: >k::TreeSortable = tree_model_sort.as_ref();
82 let gtk_tree_sortable: *mut gtk_sys::GtkTreeSortable =
83 tree_sortable.to_glib_none().0;
84
85 unsafe extern "C" fn destroy_func(data: glib_sys::gpointer) {
86 let _callback: Box<
87 Box<
88 dyn Fn(gtk::TreeModel, gtk::TreeIter, gtk::TreeIter) -> Ordering
89 + 'static,
90 >,
91 > = Box::from_raw(data as *mut _);
92 }
93
94 unsafe {
95 gtk_sys::gtk_tree_sortable_set_sort_func(
96 gtk_tree_sortable,
97 0,
98 Some(sort_func_func as _),
99 Box::into_raw(sort_func_data) as *mut std::ffi::c_void,
100 Some(
101 destroy_func as unsafe extern "C" fn(_: *mut std::ffi::c_void),
102 ),
103 );
104 }
105}
106
107pub fn change_sort_order(state: &ui::State) {
108 let tree_model_sort = state.get_tree_model_sort();
109
110 match *state.read_sort_order() {
111 ui::SortOrder::NixStoreOrigOutput => {
112 tree_model_sort.set_sort_column_id(
113 gtk::SortColumn::Default,
114 gtk::SortType::Ascending,
115 );
116 }
117 ui::SortOrder::AlphabeticalHash => {
118 set_sort_function(state);
119 tree_model_sort.set_sort_column_id(
120 gtk::SortColumn::Index(0),
121 gtk::SortType::Ascending,
122 );
123 }
124 ui::SortOrder::AlphabeticalDrvName => {
125 set_sort_function(state);
126 tree_model_sort.set_sort_column_id(
127 gtk::SortColumn::Index(0),
128 gtk::SortType::Ascending,
129 );
130 }
131 }
132}
133
134pub fn change_view_style(state: &ui::State) {
135 columns::change_view_style(state);
136}
137
138fn set_sort_func_callback(
139 state: &ui::State,
140 tree_model: gtk::TreeModel,
141 tree_model_sort_iter_a: gtk::TreeIter,
142 tree_model_sort_iter_b: gtk::TreeIter,
143) -> Ordering {
144 let sort_order = *state.read_sort_order();
145 if let Some(nix_store_res) = &*state.read_nix_store_res() {
146 let tree_store: >k::TreeStore = tree_model
147 .downcast_ref()
148 .expect("tree_model is not a tree_store");
149
150 let child_iter_a = path::GtkChildTreeIter::new(tree_model_sort_iter_a);
151 let child_iter_b = path::GtkChildTreeIter::new(tree_model_sort_iter_b);
152
153 let option_nix_query_entry_a: Option<
154 &crate::nix_query_tree::NixQueryEntry,
155 > = child_iter_a.nix_store_res_lookup(tree_store, &nix_store_res);
156 let option_nix_query_entry_b: Option<
157 &crate::nix_query_tree::NixQueryEntry,
158 > = child_iter_b.nix_store_res_lookup(tree_store, &nix_store_res);
159
160 match (option_nix_query_entry_a, option_nix_query_entry_b) {
161 (Some(nix_query_entry_a), Some(nix_query_entry_b)) => {
162 match sort_order {
163 ui::SortOrder::NixStoreOrigOutput => {
164 println!("The sort function should never be called when the sort order is NixStoreOrigOutput!!!");
165 Ordering::Equal
166 }
167 ui::SortOrder::AlphabeticalHash => {
168 nix_query_entry_a.cmp_hash(&nix_query_entry_b)
169 }
170 ui::SortOrder::AlphabeticalDrvName => {
171 nix_query_entry_a.cmp_drv_name(&nix_query_entry_b)
172 }
173 }
174 }
175 _ => panic!("Not able to get an ordering for one of the nix_query_entries. This should never happen."),
176 }
177 } else {
178 panic!("The nix_store_res in state hasn't been set yet. This should never happen.");
179 }
180}
181
182pub fn set_sort_function(state: &ui::State) {
183 let tree_model_sort = state.get_tree_model_sort();
184
185 let sort_callback = clone!(@strong state => move|tree_model, tree_model_sort_iter_a, tree_model_sort_iter_b| {
186 set_sort_func_callback(&state, tree_model, tree_model_sort_iter_a, tree_model_sort_iter_b)
187 });
188
189 set_sort_func(&tree_model_sort, Box::new(sort_callback));
190}
191
192pub fn redisplay_data(state: &ui::State) {
193 clear(state);
194 enable(state);
195
196 render_nix_store_res(state);
197
198 state
200 .get_tree_view()
201 .expand_row(>k::TreePath::new_first(), false);
202}