1
0
Fork 0
mirror of synced 2024-05-03 03:52:58 +12:00

Selections

This commit is contained in:
Rafał Mikrut 2024-02-10 23:31:46 +01:00
parent 305af6a391
commit 8f202dd2ef
10 changed files with 124 additions and 19 deletions

View file

@ -1,6 +1,6 @@
use std::path::PathBuf;
use crate::{CurrentTab, ExcludedDirectoriesModel, IncludedDirectoriesModel};
use crate::{CurrentTab, ExcludedDirectoriesModel, IncludedDirectoriesModel, MainListModel, MainWindow};
use slint::{ModelRc, SharedString, VecModel};
// Remember to match updated this according to ui/main_lists.slint and connect_scan.rs files
@ -28,6 +28,24 @@ pub fn get_is_header_mode(active_tab: CurrentTab) -> bool {
}
}
pub fn get_tool_model(app: &MainWindow, tab: CurrentTab) -> ModelRc<MainListModel> {
match tab {
CurrentTab::EmptyFolders => app.get_empty_folder_model(),
CurrentTab::SimilarImages => app.get_similar_images_model(),
CurrentTab::EmptyFiles => app.get_empty_files_model(),
CurrentTab::Settings => panic!("Button should be disabled"),
}
}
pub fn set_tool_model(app: &MainWindow, tab: CurrentTab, model: ModelRc<MainListModel>) {
match tab {
CurrentTab::EmptyFolders => app.set_empty_folder_model(model),
CurrentTab::SimilarImages => app.set_similar_images_model(model),
CurrentTab::EmptyFiles => app.set_empty_files_model(model),
CurrentTab::Settings => panic!("Button should be disabled"),
}
}
// pub fn create_string_standard_list_view(items: &[String]) -> ModelRc<StandardListViewItem> {
// let new_folders_standard_list_view = items
// .iter()

View file

@ -4,7 +4,7 @@ use std::path::MAIN_SEPARATOR;
use czkawka_core::common::remove_folder_if_contains_only_empty_folders;
use crate::common::{get_is_header_mode, get_name_idx, get_path_idx};
use crate::common::{get_is_header_mode, get_name_idx, get_path_idx, get_tool_model, set_tool_model};
use crate::{Callabler, CurrentTab, GuiState, MainListModel, MainWindow};
pub fn connect_delete_button(app: &MainWindow) {
@ -14,22 +14,12 @@ pub fn connect_delete_button(app: &MainWindow) {
let active_tab = app.global::<GuiState>().get_active_tab();
let model = match active_tab {
CurrentTab::EmptyFolders => app.get_empty_folder_model(),
CurrentTab::SimilarImages => app.get_similar_images_model(),
CurrentTab::EmptyFiles => app.get_empty_files_model(),
CurrentTab::Settings => panic!("Button should be disabled"),
};
let model = get_tool_model(&app, active_tab);
let new_model = handle_delete_items(&model, active_tab);
if let Some(new_model) = new_model {
match active_tab {
CurrentTab::EmptyFolders => app.set_empty_folder_model(new_model),
CurrentTab::SimilarImages => app.set_similar_images_model(new_model),
CurrentTab::EmptyFiles => app.set_empty_files_model(new_model),
CurrentTab::Settings => panic!("Button should be disabled"),
}
set_tool_model(&app, active_tab, new_model);
}
app.global::<GuiState>().set_preview_visible(false);

View file

@ -0,0 +1,82 @@
use crate::common::{get_tool_model, set_tool_model};
use crate::{Callabler, GuiState, MainListModel, MainWindow, SelectMode};
use crate::{CurrentTab, SelectModel};
use slint::{ComponentHandle, Model, ModelRc, VecModel};
// TODO optimize this, not sure if it is possible to not copy entire model to just select item
// https://github.com/slint-ui/slint/discussions/4595
pub fn connect_select(app: &MainWindow) {
let a = app.as_weak();
app.global::<Callabler>().on_select_items(move |select_mode| {
let app = a.upgrade().unwrap();
let active_tab = app.global::<GuiState>().get_active_tab();
let current_model = get_tool_model(&app, active_tab);
let new_model = match select_mode {
SelectMode::SelectAll => select_all(current_model),
SelectMode::UnselectAll => deselect_all(current_model),
SelectMode::InvertSelection => invert_selection(current_model),
};
set_tool_model(&app, active_tab, new_model);
});
}
pub fn connect_showing_proper_select_buttons(app: &MainWindow) {
set_select_buttons(&app);
let a = app.as_weak();
app.global::<Callabler>().on_tab_changed(move || {
let app = a.upgrade().unwrap();
set_select_buttons(&app);
});
}
fn set_select_buttons(app: &MainWindow) {
// let active_tab = app.global::<GuiState>().get_active_tab();
let base_buttons = vec![SelectMode::SelectAll, SelectMode::UnselectAll, SelectMode::InvertSelection];
// TODO Here needs to be put logic to set custom buttons depending on tab
let new_select_model = base_buttons
.into_iter()
.map(|e| SelectModel {
name: translate_select_mode(e).into(),
data: e,
})
.collect::<Vec<_>>();
app.global::<GuiState>().set_select_results_list(ModelRc::new(VecModel::from(new_select_model)));
}
fn translate_select_mode(select_mode: SelectMode) -> String {
match select_mode {
SelectMode::SelectAll => "Select all".into(),
SelectMode::UnselectAll => "Unselect all".into(),
SelectMode::InvertSelection => "Invert selection".into(),
}
}
fn select_all(model: ModelRc<MainListModel>) -> ModelRc<MainListModel> {
let mut old_data = model.iter().collect::<Vec<_>>();
old_data.iter_mut().for_each(|x| {
if !x.header_row {
x.checked = true
}
});
ModelRc::new(VecModel::from(old_data))
}
fn deselect_all(model: ModelRc<MainListModel>) -> ModelRc<MainListModel> {
let mut old_data = model.iter().collect::<Vec<_>>();
old_data.iter_mut().for_each(|x| x.checked = false);
ModelRc::new(VecModel::from(old_data))
}
fn invert_selection(model: ModelRc<MainListModel>) -> ModelRc<MainListModel> {
let mut old_data = model.iter().collect::<Vec<_>>();
old_data.iter_mut().for_each(|x| {
if !x.header_row {
x.checked = !x.checked
}
});
ModelRc::new(VecModel::from(old_data))
}

View file

@ -30,6 +30,7 @@ use crate::connect_directories_changes::connect_add_remove_directories;
use crate::connect_open::connect_open_items;
use crate::connect_progress_receiver::connect_progress_gathering;
use crate::connect_scan::connect_scan_button;
use crate::connect_select::{connect_select, connect_showing_proper_select_buttons};
use crate::connect_show_preview::connect_show_preview;
use crate::connect_stop::connect_stop_button;
use crate::connect_translation::connect_translations;
@ -84,6 +85,8 @@ fn main() {
connect_show_preview(&app);
connect_translations(&app);
connect_changing_settings_preset(&app);
connect_select(&app);
connect_showing_proper_select_buttons(&app);
app.run().unwrap();

View file

@ -5,7 +5,6 @@ import {CurrentTab} from "common.slint";
import {BottomPanelVisibility} from "common.slint";
import {Callabler} from "callabler.slint";
import {GuiState} from "gui_state.slint";
import { ContextMenu } from "widgets/context_menu.slint";
export component VisibilityButton inherits Button {
in-out property <BottomPanelVisibility> button_visibility;

View file

@ -20,6 +20,8 @@ export global Callabler {
callback load_current_preset();
callback reset_current_preset();
callback tab_changed();
// Translations
pure callback translate(string, [{key: string, value: string}]) -> string;

View file

@ -44,4 +44,9 @@ export enum SelectMode {
SelectAll,
UnselectAll,
InvertSelection
}
export struct SelectModel {
data: SelectMode,
name: string
}

View file

@ -1,6 +1,8 @@
import {CurrentTab} from "common.slint";
import {SelectModel, SelectMode} from "common.slint";
// State to show
// State Gui state that shows the current state of the GUI
// It extends Settings global state with settings that are not saved to the settings file
export global GuiState {
in-out property <length> app_width;
in-out property <length> app_height;
@ -17,4 +19,5 @@ export global GuiState {
in-out property <bool> available_subsettings: active_tab == CurrentTab.SimilarImages;
in-out property <CurrentTab> active_tab: CurrentTab.EmptyFiles;
in-out property <[SelectModel]> select_results_list: [{data: SelectMode.SelectAll, name: "Select All"}, {data: SelectMode.UnselectAll, name: "Deselect All"}];
}

View file

@ -2,6 +2,7 @@ import { Button, VerticalBox , HorizontalBox, TabWidget, ListView, StandardListV
import {CurrentTab} from "common.slint";
import {ColorPalette} from "color_palette.slint";
import {GuiState} from "gui_state.slint";
import {Callabler} from "callabler.slint";
component TabItem {
in property <bool> scanning;
@ -19,6 +20,7 @@ component TabItem {
return;
}
GuiState.active_tab = root.curr-tab;
Callabler.tab_changed();
changed_current_tab();
}
}
@ -130,6 +132,7 @@ export component LeftSidePanel {
icon: @image-url("../icons/settings.svg");
clicked => {
GuiState.active_tab = CurrentTab.Settings;
Callabler.tab_changed();
root.changed_current_tab();
}
}

View file

@ -5,7 +5,7 @@ import {MainList} from "main_lists.slint";
import {CurrentTab, ProgressToSend} from "common.slint";
import { ActionButtons } from "action_buttons.slint";
import { Progress } from "progress.slint";
import {MainListModel} from "common.slint";
import {MainListModel, SelectMode, SelectModel} from "common.slint";
import {Settings} from "settings.slint";
import {Callabler} from "callabler.slint";
import { BottomPanel } from "bottom_panel.slint";
@ -15,7 +15,7 @@ import { Preview } from "preview.slint";
export component PopupSelectResults inherits Rectangle {
callback show_popup();
property <[{data: string, name: string}]> model: [{data: "SELECT_ALL", name: "Select All"}, {data: "DESELECT_ALL", name: "Deselect All"}, {data: "INVERT_SELECTION", name: "Invert Selection"}];
property <[SelectModel]> model: GuiState.select_results_list;
property <length> item_height: 30px;
property <length> item_width: 140px;
out property <length> all_items_height: item_height * model.length;
@ -38,7 +38,7 @@ export component PopupSelectResults inherits Rectangle {
width: item_width;
clicked => {
debug(i.data);
Callabler.select_items(i.data);
popup_window.close();
}
}