Skip to content

Commit 1d81121

Browse files
committed
Sort
1 parent a545476 commit 1d81121

File tree

2 files changed

+73
-71
lines changed

2 files changed

+73
-71
lines changed

czkawka_gui/src/connect_things/connect_popovers_sort.rs

Lines changed: 73 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -13,28 +13,35 @@ where
1313
{
1414
let model = get_list_store(tree_view);
1515

16-
if let Some(curr_iter) = model.iter_first() {
17-
assert!(model.get::<bool>(&curr_iter, column_header)); // First item should be header
18-
assert!(model.iter_next(&curr_iter)); // Must be at least two items
16+
if let Some(mut curr_iter) = model.iter_first() {
17+
assert!(model.get::<bool>(&curr_iter, column_header));
18+
assert!(model.iter_next(&curr_iter));
1919
loop {
2020
let mut iters = Vec::new();
2121
let mut all_have = false;
22+
let local_iter = curr_iter;
2223
loop {
23-
if model.get::<bool>(&curr_iter, column_header) {
24-
assert!(model.iter_next(&curr_iter), "Empty header, this should not happens");
24+
if model.get::<bool>(&local_iter, column_header) {
25+
if !model.iter_next(&local_iter) {
26+
all_have = true;
27+
}
2528
break;
2629
}
27-
iters.push(curr_iter);
28-
if !model.iter_next(&curr_iter) {
30+
iters.push(local_iter);
31+
if !model.iter_next(&local_iter) {
2932
all_have = true;
3033
break;
3134
}
3235
}
3336
if iters.len() == 1 {
34-
continue; // Can be equal 1 in reference folders
37+
curr_iter = local_iter;
38+
if all_have {
39+
break;
40+
}
41+
continue;
3542
}
36-
3743
sort_iters::<T>(&model, iters, column_sort);
44+
curr_iter = local_iter;
3845
if all_have {
3946
break;
4047
}
@@ -142,6 +149,7 @@ mod test {
142149
use glib::types::Type;
143150
use gtk4::prelude::*;
144151
use gtk4::{Popover, TreeView};
152+
use rand::random;
145153

146154
use crate::connect_things::connect_popovers_sort::{popover_sort_general, sort_iters};
147155

@@ -231,58 +239,60 @@ mod test {
231239
}
232240
}
233241

234-
// TODO - This test uncovers a bug in the code, so it is disabled for now, with sort button
235-
// #[gtk4::test]
236-
// pub(crate) fn _fuzzer_test() {
237-
// for _ in 0..10000 {
238-
// let columns_types: &[Type] = &[Type::BOOL, Type::STRING];
239-
// let list_store = gtk4::ListStore::new(columns_types);
240-
// let tree_view = TreeView::builder().model(&list_store).build();
241-
// let popover = Popover::new();
242-
//
243-
// let first_row: &[(u32, &dyn ToValue)] = &[(0, &true), (1, &"AAA")];
244-
// list_store.set(&list_store.append(), first_row);
245-
//
246-
// let mut since_last_header = 0;
247-
//
248-
// (0..(random::<u32>() % 10 + 5)).for_each(|_| {
249-
// let bool_val = if since_last_header < 2 {
250-
// since_last_header += 1;
251-
// false
252-
// } else {
253-
// since_last_header = 0;
254-
// random()
255-
// };
256-
// let string_val = rand::random::<u32>().to_string();
257-
// let a: Vec<(u32, &dyn ToValue)> = vec![(0, &bool_val), (1, &string_val)];
258-
//
259-
// list_store.set(&list_store.append(), &a);
260-
// });
261-
//
262-
// if since_last_header < 2 {
263-
// // This is invalid, and should be vec![(0, &false), (1, &"AAA")]
264-
// // but this triggers the bug
265-
// let a: Vec<(u32, &dyn ToValue)> = vec![(0, &true), (1, &"AAA")];
266-
// list_store.set(&list_store.append(), &a);
267-
// let b: Vec<(u32, &dyn ToValue)> = vec![(0, &false), (1, &"BBB")];
268-
// list_store.set(&list_store.append(), &b);
269-
// }
270-
//
271-
// print_two_items_model(&list_store);
272-
//
273-
// popover_sort_general::<String>(&popover, &tree_view, 1, 0);
274-
// }
275-
// }
276-
//
277-
// fn print_two_items_model(model: &gtk4::ListStore) {
278-
// let iter = model.iter_first().expect("Failed to get first iter");
279-
// loop {
280-
// let bool_val = model.get::<bool>(&iter, 0);
281-
// let string_val = model.get::<String>(&iter, 1);
282-
// println!("{bool_val} {string_val}");
283-
// if !model.iter_next(&iter) {
284-
// break;
285-
// }
286-
// }
287-
// }
242+
#[gtk4::test]
243+
pub(crate) fn fuzzer_test() {
244+
for _ in 0..100000 {
245+
let columns_types: &[Type] = &[Type::BOOL, Type::STRING];
246+
let list_store = gtk4::ListStore::new(columns_types);
247+
let tree_view = TreeView::builder().model(&list_store).build();
248+
let popover = Popover::new();
249+
250+
// Always start with a header
251+
let first_row: &[(u32, &dyn ToValue)] = &[(0, &true), (1, &"AAA")];
252+
list_store.set(&list_store.append(), first_row);
253+
254+
let mut since_last_header = 0;
255+
let mut need_header = false;
256+
let num_rows = (random::<u32>() % 10 + 5) as usize;
257+
let mut i = 0;
258+
while i < num_rows {
259+
if need_header {
260+
// Insert a header only if last was not a header
261+
let a: Vec<(u32, &dyn ToValue)> = vec![(0, &true), (1, &"HEADER")];
262+
list_store.set(&list_store.append(), &a);
263+
since_last_header = 0;
264+
need_header = false;
265+
i += 1;
266+
continue;
267+
}
268+
// Insert a non-header row
269+
let string_val = rand::random::<u32>().to_string();
270+
let a: Vec<(u32, &dyn ToValue)> = vec![(0, &false), (1, &string_val)];
271+
list_store.set(&list_store.append(), &a);
272+
since_last_header += 1;
273+
// After at least 2 non-header rows, randomly decide to insert a header next
274+
if since_last_header >= 2 && random::<u8>() % 3 == 0 {
275+
need_header = true;
276+
}
277+
i += 1;
278+
}
279+
280+
// Ensure at least one non-header after the last header
281+
let last_iter = list_store.iter_first().unwrap();
282+
let mut last_is_header;
283+
loop {
284+
last_is_header = list_store.get::<bool>(&last_iter, 0);
285+
if !list_store.iter_next(&last_iter) {
286+
break;
287+
}
288+
}
289+
if last_is_header {
290+
let a: Vec<(u32, &dyn ToValue)> = vec![(0, &false), (1, &"FINALROW")];
291+
list_store.set(&list_store.append(), &a);
292+
}
293+
294+
// Optionally: print_two_items_model(&list_store);
295+
popover_sort_general::<String>(&popover, &tree_view, 1, 0);
296+
}
297+
}
288298
}

czkawka_gui/src/help_functions.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -338,14 +338,6 @@ pub(crate) fn add_text_to_text_view(text_view: &TextView, string_to_append: &str
338338

339339
pub(crate) fn set_buttons(hashmap: &mut HashMap<BottomButtonsEnum, bool>, buttons_array: &[Widget], button_names: &[BottomButtonsEnum]) {
340340
for (index, button) in buttons_array.iter().enumerate() {
341-
if button_names[index] == BottomButtonsEnum::Sort {
342-
// TODO - sort button is broken, I don't have skills and time to fix it
343-
// The problem is that to speedup sorting, we operate on item iters
344-
// To fix this, we should just take entire model and sort it, which will be slow in some cases
345-
// Alternatively, just current operations on iters should be fixed(I cannot find exact problem)
346-
continue;
347-
}
348-
349341
if *hashmap.get_mut(&button_names[index]).expect("Invalid button name") {
350342
button.show();
351343
} else {

0 commit comments

Comments
 (0)