pub fn tree_remove(tree_view: &gtk::TreeView, column_file_name: i32, column_path: i32, column_color: i32, column_selection: i32, gui_data: &GuiData) {
    let text_view_errors = gui_data.text_view_errors.clone();
    let use_trash = gui_data.settings.check_button_settings_use_trash.clone().is_active();

    let model = get_list_store(tree_view);

    let mut messages: String = "".to_string();

    let mut vec_path_to_delete: Vec<(String, String)> = Vec::new();
    let mut map_with_path_to_delete: BTreeMap<String, Vec<String>> = Default::default(); // BTreeMap<Path,Vec<FileName>>

    let mut selection_rows = Vec::new();

    if let Some(iter) = model.iter_first() {
        loop {
            if model.value(&iter, column_selection).get::<bool>().unwrap() {
                // TODO, this maybe isn't required if we will be sure that any header cannot be selected
                if model.value(&iter, column_color).get::<String>().unwrap() == MAIN_ROW_COLOR {
                    selection_rows.push(model.path(&iter).unwrap());
                }
            }

            if !model.iter_next(&iter) {
                break;
            }
        }
    }

    // Save to variable paths of files, and remove it when not removing all occurrences.
    for tree_path in selection_rows.iter().rev() {
        let iter = model.iter(tree_path).unwrap();

        let file_name = model.value(&iter, column_file_name).get::<String>().unwrap();
        let path = model.value(&iter, column_path).get::<String>().unwrap();

        model.remove(&iter);

        map_with_path_to_delete.entry(path.clone()).or_insert_with(Vec::new);
        map_with_path_to_delete.get_mut(path.as_str()).unwrap().push(file_name);
    }

    // Delete duplicated entries, and remove real files
    for (path, mut vec_file_name) in map_with_path_to_delete {
        vec_file_name.sort();
        vec_file_name.dedup();
        for file_name in vec_file_name {
            if !use_trash {
                if fs::remove_file(format!("{}/{}", path.clone(), file_name.clone())).is_err() {
                    messages += format!(
                        "Failed to remove file {}/{}. It is possible that you already deleted it, because similar images shows all possible file doesn't exists or you don't have permissions.\n",
                        path, file_name
                    )
                    .as_str()
                }
            } else if trash::delete(format!("{}/{}", path.clone(), file_name.clone())).is_err() {
                messages += format!(
                    "Failed to remove file {}/{}. It is possible that you already deleted it, because similar images shows all possible file doesn't exists or you don't have permissions.\n",
                    path, file_name
                )
                .as_str()
            }

            vec_path_to_delete.push((path.clone(), file_name.clone()));
        }
    }

    // Remove only child from header
    if let Some(first_iter) = model.iter_first() {
        let mut vec_tree_path_to_delete: Vec<gtk::TreePath> = Vec::new();
        let mut current_iter = first_iter;
        if model.value(&current_iter, column_color).get::<String>().unwrap() != HEADER_ROW_COLOR {
            panic!("First deleted element, should be a header"); // First element should be header
        };

        let mut next_iter;
        let mut next_next_iter;
        'main: loop {
            if model.value(&current_iter, column_color).get::<String>().unwrap() != HEADER_ROW_COLOR {
                panic!("First deleted element, should be a header"); // First element should be header
            };

            next_iter = current_iter.clone();
            if !model.iter_next(&next_iter) {
                // There is only single header left (H1 -> END) -> (NOTHING)
                vec_tree_path_to_delete.push(model.path(&current_iter).unwrap());
                break 'main;
            }

            if model.value(&next_iter, column_color).get::<String>().unwrap() == HEADER_ROW_COLOR {
                // There are two headers each others(we remove just first) -> (H1 -> H2) -> (H2)
                vec_tree_path_to_delete.push(model.path(&current_iter).unwrap());
                current_iter = next_iter.clone();
                continue 'main;
            }

            next_next_iter = next_iter.clone();
            if !model.iter_next(&next_next_iter) {
                // There is only one child of header left, so we remove it with header (H1 -> C1 -> END) -> (NOTHING)
                vec_tree_path_to_delete.push(model.path(&current_iter).unwrap());
                vec_tree_path_to_delete.push(model.path(&next_iter).unwrap());
                break 'main;
            }

            if model.value(&next_next_iter, column_color).get::<String>().unwrap() == HEADER_ROW_COLOR {
                // One child between two headers, we can remove them  (H1 -> C1 -> H2) -> (H2)
                vec_tree_path_to_delete.push(model.path(&current_iter).unwrap());
                vec_tree_path_to_delete.push(model.path(&next_iter).unwrap());
                current_iter = next_next_iter.clone();
                continue 'main;
            }

            loop {
                // (H1 -> C1 -> C2 -> Cn -> END) -> (NO CHANGE, BECAUSE IS GOOD)
                if !model.iter_next(&next_next_iter) {
                    break 'main;
                }
                // Move to next header
                if model.value(&next_next_iter, column_color).get::<String>().unwrap() == HEADER_ROW_COLOR {
                    current_iter = next_next_iter.clone();
                    continue 'main;
                }
            }
        }
        for tree_path in vec_tree_path_to_delete.iter().rev() {
            model.remove(&model.iter(tree_path).unwrap());
        }
    }

    // Last step, remove orphan header if exists
    if let Some(iter) = model.iter_first() {
        if !model.iter_next(&iter) {
            model.clear();
        }
    }

    text_view_errors.buffer().unwrap().set_text(messages.as_str());
}
// Remove all occurrences - remove every element which have same path and name as even non selected ones
Remove all occurrences - remove every element which have same path and name as even non selected ones
Remove all occurrences - remove every element which have same path and name as even non selected ones
pub fn tree_remove(tree_view: &gtk::TreeView, column_file_name: i32, column_path: i32, column_color: i32, column_selection: i32, gui_data: &GuiData) {
    let text_view_errors = gui_data.text_view_errors.clone();
    let use_trash = gui_data.settings.check_button_settings_use_trash.clone().is_active();
    let model = get_list_store(tree_view);
    let mut messages: String = "".to_string();
    let mut vec_path_to_delete: Vec<(String, String)> = Vec::new();
    let mut map_with_path_to_delete: BTreeMap<String, Vec<String>> = Default::default(); // BTreeMap<Path,Vec<FileName>>
    let mut selection_rows = Vec::new();
    if let Some(iter) = model.iter_first() {
        loop {
            if model.value(&iter, column_selection).get::<bool>().unwrap() {
                // TODO, this maybe isn't required if we will be sure that any header cannot be selected
                if model.value(&iter, column_color).get::<String>().unwrap() == MAIN_ROW_COLOR {
                    selection_rows.push(model.path(&iter).unwrap());
                }
            }
            if !model.iter_next(&iter) {
                break;
            }
        }
    }
    // Save to variable paths of files, and remove it when not removing all occurrences.
    for tree_path in selection_rows.iter().rev() {
        let iter = model.iter(tree_path).unwrap();
        let file_name = model.value(&iter, column_file_name).get::<String>().unwrap();
        let path = model.value(&iter, column_path).get::<String>().unwrap();
        model.remove(&iter);
        map_with_path_to_delete.entry(path.clone()).or_insert_with(Vec::new);
        map_with_path_to_delete.get_mut(path.as_str()).unwrap().push(file_name);
    }
    // Delete duplicated entries, and remove real files
    for (path, mut vec_file_name) in map_with_path_to_delete {
        vec_file_name.sort();
        vec_file_name.dedup();
        for file_name in vec_file_name {
            if !use_trash {
                if fs::remove_file(format!("{}/{}", path.clone(), file_name.clone())).is_err() {
                    messages += format!(
                        "Failed to remove file {}/{}. It is possible that you already deleted it, because similar images shows all possible file doesn't exists or you don't have permissions.\n",
                        path, file_name
                    )
                    .as_str()
                }
            } else if trash::delete(format!("{}/{}", path.clone(), file_name.clone())).is_err() {
                messages += format!(
                    "Failed to remove file {}/{}. It is possible that you already deleted it, because similar images shows all possible file doesn't exists or you don't have permissions.\n",
                    path, file_name
                )
                .as_str()
            }
            vec_path_to_delete.push((path.clone(), file_name.clone()));
        }
    }
    // Remove only child from header
    if let Some(first_iter) = model.iter_first() {
        let mut vec_tree_path_to_delete: Vec<gtk::TreePath> = Vec::new();
        let mut current_iter = first_iter;
        if model.value(&current_iter, column_color).get::<String>().unwrap() != HEADER_ROW_COLOR {
            panic!("First deleted element, should be a header"); // First element should be header
        };
        let mut next_iter;
        let mut next_next_iter;
        'main: loop {
            if model.value(&current_iter, column_color).get::<String>().unwrap() != HEADER_ROW_COLOR {
                panic!("First deleted element, should be a header"); // First element should be header
            };
            next_iter = current_iter.clone();
            if !model.iter_next(&next_iter) {
                // There is only single header left (H1 -> END) -> (NOTHING)
                vec_tree_path_to_delete.push(model.path(&current_iter).unwrap());
                break 'main;
            }
            if model.value(&next_iter, column_color).get::<String>().unwrap() == HEADER_ROW_COLOR {
                // There are two headers each others(we remove just first) -> (H1 -> H2) -> (H2)
                vec_tree_path_to_delete.push(model.path(&current_iter).unwrap());
                current_iter = next_iter.clone();
                continue 'main;
            }
            next_next_iter = next_iter.clone();
            if !model.iter_next(&next_next_iter) {
                // There is only one child of header left, so we remove it with header (H1 -> C1 -> END) -> (NOTHING)
                vec_tree_path_to_delete.push(model.path(&current_iter).unwrap());
                vec_tree_path_to_delete.push(model.path(&next_iter).unwrap());
                break 'main;
            }
            if model.value(&next_next_iter, column_color).get::<String>().unwrap() == HEADER_ROW_COLOR {
                // One child between two headers, we can remove them  (H1 -> C1 -> H2) -> (H2)
                vec_tree_path_to_delete.push(model.path(&current_iter).unwrap());
                vec_tree_path_to_delete.push(model.path(&next_iter).unwrap());
                current_iter = next_next_iter.clone();
                continue 'main;
            }
            loop {
                // (H1 -> C1 -> C2 -> Cn -> END) -> (NO CHANGE, BECAUSE IS GOOD)
                if !model.iter_next(&next_next_iter) {
                    break 'main;
                }
                // Move to next header
                if model.value(&next_next_iter, column_color).get::<String>().unwrap() == HEADER_ROW_COLOR {
                    current_iter = next_next_iter.clone();
                    continue 'main;
                }
            }
        }
        for tree_path in vec_tree_path_to_delete.iter().rev() {
            model.remove(&model.iter(tree_path).unwrap());
        }
    }
    // Last step, remove orphan header if exists
    if let Some(iter) = model.iter_first() {
        if !model.iter_next(&iter) {
            model.clear();
        }
    }
    text_view_errors.buffer().unwrap().set_text(messages.as_str());
}
pub fn tree_remove ( tree_view : & gtk :: TreeView , column_file_name : i32 , column_path : i32 , column_color : i32 , column_selection : i32 , gui_data : & GuiData ) { let text_view_errors = gui_data . text_view_errors . clone ( ) ; let use_trash = gui_data . settings . check_button_settings_use_trash . clone ( ) . is_active ( ) ; let model = get_list_store ( tree_view ) ; let mut messages : String = " " . to_string ( ) ; let mut vec_path_to_delete : Vec < ( String , String ) > = Vec :: new ( ) ; let mut map_with_path_to_delete : BTreeMap < String , Vec < String > > = Default :: default ( ) ; // BTreeMap<Path,Vec<FileName>> let mut selection_rows = Vec :: new ( ) ; if let Some ( iter ) = model . iter_first ( ) { loop { if model . value ( & iter , column_selection ) . get :: < bool > ( ) . unwrap ( ) { // TODO, this maybe isn't required if we will be sure that any header cannot be selected if model . value ( & iter , column_color ) . get :: < String > ( ) . unwrap ( ) == MAIN_ROW_COLOR { selection_rows . push ( model . path ( & iter ) . unwrap ( ) ) ; } } if ! model . iter_next ( & iter ) { break ; } } } // Save to variable paths of files, and remove it when not removing all occurrences. for tree_path in selection_rows . iter ( ) . rev ( ) { let iter = model . iter ( tree_path ) . unwrap ( ) ; let file_name = model . value ( & iter , column_file_name ) . get :: < String > ( ) . unwrap ( ) ; let path = model . value ( & iter , column_path ) . get :: < String > ( ) . unwrap ( ) ; model . remove ( & iter ) ; map_with_path_to_delete . entry ( path . clone ( ) ) . or_insert_with ( Vec :: new ) ; map_with_path_to_delete . get_mut ( path . as_str ( ) ) . unwrap ( ) . push ( file_name ) ; } // Delete duplicated entries, and remove real files for ( path , mut vec_file_name ) in map_with_path_to_delete { vec_file_name . sort ( ) ; vec_file_name . dedup ( ) ; for file_name in vec_file_name { if ! use_trash { if fs :: remove_file ( format ! ( " " path clone ( ) file_name clone ( ) ) ) . is_err ( ) { messages += format ! ( " \n " path file_name ) . as_str ( ) } } else if trash :: delete ( format ! ( " " path clone ( ) file_name clone ( ) ) ) . is_err ( ) { messages += format ! ( " \n " path file_name ) . as_str ( ) } vec_path_to_delete . push ( ( path . clone ( ) , file_name . clone ( ) ) ) ; } } // Remove only child from header if let Some ( first_iter ) = model . iter_first ( ) { let mut vec_tree_path_to_delete : Vec < gtk :: TreePath > = Vec :: new ( ) ; let mut current_iter = first_iter ; if model . value ( & current_iter , column_color ) . get :: < String > ( ) . unwrap ( ) != HEADER_ROW_COLOR { panic ! ( " " ) ; // First element should be header } ; let mut next_iter ; let mut next_next_iter ; ' main : loop { if model . value ( & current_iter , column_color ) . get :: < String > ( ) . unwrap ( ) != HEADER_ROW_COLOR { panic ! ( " " ) ; // First element should be header } ; next_iter = current_iter . clone ( ) ; if ! model . iter_next ( & next_iter ) { // There is only single header left (H1 -> END) -> (NOTHING) vec_tree_path_to_delete . push ( model . path ( & current_iter ) . unwrap ( ) ) ; break ' main ; } if model . value ( & next_iter , column_color ) . get :: < String > ( ) . unwrap ( ) == HEADER_ROW_COLOR { // There are two headers each others(we remove just first) -> (H1 -> H2) -> (H2) vec_tree_path_to_delete . push ( model . path ( & current_iter ) . unwrap ( ) ) ; current_iter = next_iter . clone ( ) ; continue ' main ; } next_next_iter = next_iter . clone ( ) ; if ! model . iter_next ( & next_next_iter ) { // There is only one child of header left, so we remove it with header (H1 -> C1 -> END) -> (NOTHING) vec_tree_path_to_delete . push ( model . path ( & current_iter ) . unwrap ( ) ) ; vec_tree_path_to_delete . push ( model . path ( & next_iter ) . unwrap ( ) ) ; break ' main ; } if model . value ( & next_next_iter , column_color ) . get :: < String > ( ) . unwrap ( ) == HEADER_ROW_COLOR { // One child between two headers, we can remove them  (H1 -> C1 -> H2) -> (H2) vec_tree_path_to_delete . push ( model . path ( & current_iter ) . unwrap ( ) ) ; vec_tree_path_to_delete . push ( model . path ( & next_iter ) . unwrap ( ) ) ; current_iter = next_next_iter . clone ( ) ; continue ' main ; } loop { // (H1 -> C1 -> C2 -> Cn -> END) -> (NO CHANGE, BECAUSE IS GOOD) if ! model . iter_next ( & next_next_iter ) { break ' main ; } // Move to next header if model . value ( & next_next_iter , column_color ) . get :: < String > ( ) . unwrap ( ) == HEADER_ROW_COLOR { current_iter = next_next_iter . clone ( ) ; continue ' main ; } } } for tree_path in vec_tree_path_to_delete . iter ( ) . rev ( ) { model . remove ( & model . iter ( tree_path ) . unwrap ( ) ) ; } } // Last step, remove orphan header if exists if let Some ( iter ) = model . iter_first ( ) { if ! model . iter_next ( & iter ) { model . clear ( ) ; } } text_view_errors . buffer ( ) . unwrap ( ) . set_text ( messages . as_str ( ) ) ; }
Remove all occurrences - remove every element which have same path and name as even non selected ones
Remove all occurrences - remove every element which have same path and name as even non selected ones
tree_view
&gtk::TreeView
column_file_name
i32
column_path
i32
column_color
i32
column_selection
i32
gui_data
&GuiData
tree_view
&gtk::TreeView
column_file_name
i32
column_path
i32
column_color
i32
column_selection
i32
gui_data
&GuiData