Selections
This commit is contained in:
parent
305af6a391
commit
8f202dd2ef
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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))
|
||||
}
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -44,4 +44,9 @@ export enum SelectMode {
|
|||
SelectAll,
|
||||
UnselectAll,
|
||||
InvertSelection
|
||||
}
|
||||
|
||||
export struct SelectModel {
|
||||
data: SelectMode,
|
||||
name: string
|
||||
}
|
|
@ -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"}];
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue