More
This commit is contained in:
parent
1e9b055964
commit
6567bc7d8f
|
@ -9,7 +9,7 @@ pub fn get_str_path_idx(active_tab: CurrentTab) -> usize {
|
|||
CurrentTab::EmptyFolders => 1,
|
||||
CurrentTab::EmptyFiles => 1,
|
||||
CurrentTab::SimilarImages => 4,
|
||||
CurrentTab::Settings => panic!("Button should be disabled"),
|
||||
CurrentTab::Settings | CurrentTab::About => panic!("Button should be disabled"),
|
||||
}
|
||||
}
|
||||
pub fn get_str_name_idx(active_tab: CurrentTab) -> usize {
|
||||
|
@ -17,7 +17,7 @@ pub fn get_str_name_idx(active_tab: CurrentTab) -> usize {
|
|||
CurrentTab::EmptyFolders => 0,
|
||||
CurrentTab::EmptyFiles => 0,
|
||||
CurrentTab::SimilarImages => 3,
|
||||
CurrentTab::Settings => panic!("Button should be disabled"),
|
||||
CurrentTab::Settings | CurrentTab::About => panic!("Button should be disabled"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,14 +26,14 @@ pub fn get_int_modification_date_idx(active_tab: CurrentTab) -> usize {
|
|||
CurrentTab::EmptyFiles => 0,
|
||||
CurrentTab::SimilarImages => 0,
|
||||
CurrentTab::EmptyFolders => 0,
|
||||
CurrentTab::Settings => panic!("Button should be disabled"),
|
||||
CurrentTab::Settings | CurrentTab::About => panic!("Button should be disabled"),
|
||||
}
|
||||
}
|
||||
pub fn get_int_size_idx(active_tab: CurrentTab) -> usize {
|
||||
match active_tab {
|
||||
CurrentTab::EmptyFiles => 2,
|
||||
CurrentTab::SimilarImages => 2,
|
||||
CurrentTab::Settings => panic!("Button should be disabled"),
|
||||
CurrentTab::Settings | CurrentTab::About => panic!("Button should be disabled"),
|
||||
CurrentTab::EmptyFolders => panic!("Unable to get size from this tab"),
|
||||
}
|
||||
}
|
||||
|
@ -41,14 +41,14 @@ pub fn get_int_size_idx(active_tab: CurrentTab) -> usize {
|
|||
pub fn get_int_width_idx(active_tab: CurrentTab) -> usize {
|
||||
match active_tab {
|
||||
CurrentTab::SimilarImages => 4,
|
||||
CurrentTab::Settings => panic!("Button should be disabled"),
|
||||
CurrentTab::Settings | CurrentTab::About => panic!("Button should be disabled"),
|
||||
_ => panic!("Unable to get height from this tab"),
|
||||
}
|
||||
}
|
||||
pub fn get_int_height_idx(active_tab: CurrentTab) -> usize {
|
||||
match active_tab {
|
||||
CurrentTab::SimilarImages => 5,
|
||||
CurrentTab::Settings => panic!("Button should be disabled"),
|
||||
CurrentTab::Settings | CurrentTab::About => panic!("Button should be disabled"),
|
||||
_ => panic!("Unable to get height from this tab"),
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ pub fn get_is_header_mode(active_tab: CurrentTab) -> bool {
|
|||
match active_tab {
|
||||
CurrentTab::EmptyFolders | CurrentTab::EmptyFiles => false,
|
||||
CurrentTab::SimilarImages => true,
|
||||
CurrentTab::Settings => panic!("Button should be disabled"),
|
||||
CurrentTab::Settings | CurrentTab::About => panic!("Button should be disabled"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ pub fn get_tool_model(app: &MainWindow, tab: CurrentTab) -> ModelRc<MainListMode
|
|||
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"),
|
||||
CurrentTab::Settings | CurrentTab::About => panic!("Button should be disabled"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ pub fn set_tool_model(app: &MainWindow, tab: CurrentTab, model: ModelRc<MainList
|
|||
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"),
|
||||
CurrentTab::Settings | CurrentTab::About => panic!("Button should be disabled"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ use czkawka_core::common_messages::Messages;
|
|||
|
||||
use crate::common::{get_is_header_mode, get_tool_model, set_tool_model};
|
||||
use crate::model_operations::{collect_full_path_from_model, deselect_all_items, filter_out_checked_items};
|
||||
use crate::{Callabler, CurrentTab, GuiState, MainListModel, MainWindow};
|
||||
use crate::{Callabler, CurrentTab, GuiState, MainListModel, MainWindow, Settings};
|
||||
|
||||
pub fn connect_delete_button(app: &MainWindow) {
|
||||
let a = app.as_weak();
|
||||
|
@ -17,9 +17,9 @@ pub fn connect_delete_button(app: &MainWindow) {
|
|||
|
||||
let model = get_tool_model(&app, active_tab);
|
||||
|
||||
let remove_to_trash = false;
|
||||
let settings = app.global::<Settings>();
|
||||
|
||||
let (errors, new_model) = handle_delete_items(&model, active_tab, remove_to_trash);
|
||||
let (errors, new_model) = handle_delete_items(&app, &model, active_tab, settings.get_move_to_trash());
|
||||
|
||||
if let Some(new_model) = new_model {
|
||||
set_tool_model(&app, active_tab, new_model);
|
||||
|
@ -31,13 +31,14 @@ pub fn connect_delete_button(app: &MainWindow) {
|
|||
});
|
||||
}
|
||||
|
||||
fn handle_delete_items(items: &ModelRc<MainListModel>, active_tab: CurrentTab, remove_to_trash: bool) -> (Vec<String>, Option<ModelRc<MainListModel>>) {
|
||||
fn handle_delete_items(app: &MainWindow, items: &ModelRc<MainListModel>, active_tab: CurrentTab, remove_to_trash: bool) -> (Vec<String>, Option<ModelRc<MainListModel>>) {
|
||||
let (entries_to_delete, mut entries_left) = filter_out_checked_items(items, get_is_header_mode(active_tab));
|
||||
|
||||
if !entries_to_delete.is_empty() {
|
||||
let vec_items_to_remove = collect_full_path_from_model(&entries_to_delete, active_tab);
|
||||
let errors = remove_selected_items(vec_items_to_remove, active_tab, remove_to_trash);
|
||||
deselect_all_items(&mut entries_left);
|
||||
app.set_text_summary_text(format!("Deleted {} items, failed to remove {} items", entries_to_delete.len() - errors.len(), errors.len()).into());
|
||||
|
||||
let r = ModelRc::new(VecModel::from(entries_left)); // TODO here maybe should also stay old model if entries cannot be removed
|
||||
return (errors, Some(r));
|
||||
|
@ -48,7 +49,6 @@ fn handle_delete_items(items: &ModelRc<MainListModel>, active_tab: CurrentTab, r
|
|||
// TODO delete in parallel items, consider to add progress bar
|
||||
// For empty folders double check if folders are really empty - this function probably should be run in thread
|
||||
// and at the end should be send signal to main thread to update model
|
||||
// TODO handle also situations where cannot delete file/folder
|
||||
fn remove_selected_items(items_to_remove: Vec<String>, active_tab: CurrentTab, remove_to_trash: bool) -> Vec<String> {
|
||||
// Iterate over empty folders and not delete them if they are not empty
|
||||
if active_tab == CurrentTab::EmptyFolders {
|
||||
|
|
|
@ -37,4 +37,13 @@ pub fn connect_open_items(app: &MainWindow) {
|
|||
error!("Failed to open cache folder {:?}: {e}", cache_folder);
|
||||
}
|
||||
});
|
||||
|
||||
app.global::<Callabler>().on_open_link(move |link| {
|
||||
match open::that(link.as_str()) {
|
||||
Ok(()) => {}
|
||||
Err(e) => {
|
||||
eprintln!("Failed to open link: {e}");
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ pub fn connect_scan_button(app: &MainWindow, progress_sender: Sender<ProgressDat
|
|||
CurrentTab::SimilarImages => {
|
||||
scan_similar_images(a, progress_sender, stop_receiver, custom_settings);
|
||||
}
|
||||
CurrentTab::Settings => panic!("Button should be disabled"),
|
||||
CurrentTab::Settings | CurrentTab::About => panic!("Button should be disabled"),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -58,12 +58,12 @@ fn scan_similar_images(a: Weak<MainWindow>, progress_sender: Sender<ProgressData
|
|||
let mut finder = SimilarImages::new();
|
||||
set_common_settings(&mut finder, &custom_settings);
|
||||
finder.set_hash_size(custom_settings.similar_images_sub_hash_size);
|
||||
let resize_algortithm = ALLOWED_RESIZE_ALGORITHM_VALUES
|
||||
let resize_algorithm = ALLOWED_RESIZE_ALGORITHM_VALUES
|
||||
.iter()
|
||||
.find(|(setting_name, _gui_name, _resize_alg)| setting_name == &custom_settings.similar_images_sub_resize_algorithm)
|
||||
.expect("Resize algorithm not found")
|
||||
.2;
|
||||
finder.set_image_filter(resize_algortithm);
|
||||
finder.set_image_filter(resize_algorithm);
|
||||
let hash_type = ALLOWED_HASH_TYPE_VALUES
|
||||
.iter()
|
||||
.find(|(setting_name, _gui_name, _resize_alg)| setting_name == &custom_settings.similar_images_sub_hash_type)
|
||||
|
|
|
@ -64,10 +64,6 @@ fn main() {
|
|||
let (progress_sender, progress_receiver): (Sender<ProgressData>, Receiver<ProgressData>) = unbounded();
|
||||
let (stop_sender, stop_receiver): (Sender<()>, Receiver<()>) = unbounded();
|
||||
|
||||
// to_remove_debug(&app);
|
||||
|
||||
// Slint files may already contains data in models, so clear them before starting - todo,
|
||||
// check if non zeroed models are useful
|
||||
zeroing_all_models(&app);
|
||||
|
||||
set_initial_gui_infos(&app);
|
||||
|
@ -98,56 +94,3 @@ pub fn zeroing_all_models(app: &MainWindow) {
|
|||
app.set_empty_files_model(Rc::new(VecModel::default()).into());
|
||||
app.set_similar_images_model(Rc::new(VecModel::default()).into());
|
||||
}
|
||||
|
||||
// // TODO remove this after debugging - or leave commented
|
||||
// pub fn to_remove_debug(app: &MainWindow) {
|
||||
// app.set_empty_folder_model(to_remove_create_without_header("@@").into());
|
||||
// app.set_empty_files_model(to_remove_create_without_header("%%").into());
|
||||
// app.set_similar_images_model(to_remove_create_with_header().into());
|
||||
// }
|
||||
|
||||
// fn to_remove_create_with_header() -> Rc<VecModel<MainListModel>> {
|
||||
// let header_row_data: Rc<VecModel<MainListModel>> = Rc::new(VecModel::default());
|
||||
// for r in 0..10_000 {
|
||||
// let items = VecModel::default();
|
||||
//
|
||||
// for c in 0..3 {
|
||||
// items.push(slint::format!("Item {r}.{c}"));
|
||||
// }
|
||||
//
|
||||
// let is_header = r % 3 == 0;
|
||||
// let is_checked = (r % 2 == 0) && !is_header;
|
||||
//
|
||||
// let item = MainListModel {
|
||||
// checked: is_checked,
|
||||
// header_row: is_header,
|
||||
// selected_row: false,
|
||||
// val: ModelRc::new(items),
|
||||
// };
|
||||
//
|
||||
// header_row_data.push(item);
|
||||
// }
|
||||
// header_row_data
|
||||
// }
|
||||
// fn to_remove_create_without_header(s: &str) -> Rc<VecModel<MainListModel>> {
|
||||
// let non_header_row_data: Rc<VecModel<MainListModel>> = Rc::new(VecModel::default());
|
||||
// for r in 0..100_000 {
|
||||
// let items = VecModel::default();
|
||||
//
|
||||
// for c in 0..3 {
|
||||
// items.push(slint::format!("Item {r}.{c}.{s}"));
|
||||
// }
|
||||
//
|
||||
// let is_checked = r % 2 == 0;
|
||||
//
|
||||
// let item = MainListModel {
|
||||
// checked: is_checked,
|
||||
// header_row: false,
|
||||
// selected_row: false,
|
||||
// val: ModelRc::new(items),
|
||||
// };
|
||||
//
|
||||
// non_header_row_data.push(item);
|
||||
// }
|
||||
// non_header_row_data
|
||||
// }
|
||||
|
|
|
@ -199,7 +199,7 @@ pub fn create_default_settings_files() {
|
|||
}
|
||||
}
|
||||
|
||||
for i in 1..=10 {
|
||||
for i in 0..10 {
|
||||
let config_file = get_config_file(i);
|
||||
if let Some(config_file) = config_file {
|
||||
if !config_file.is_file() {
|
||||
|
|
|
@ -23,10 +23,10 @@ export component ActionButtons inherits HorizontalLayout {
|
|||
callback show_select_popup(length, length);
|
||||
callback show_remove_popup();
|
||||
callback request_folder_to_move();
|
||||
in-out property <BottomPanelVisibility> bottom_panel_visibility: BottomPanelVisibility.Directories;
|
||||
in-out property <BottomPanelVisibility> bottom_panel_visibility <=> GuiState.bottom_panel_visibility;
|
||||
in-out property <bool> stop_requested: false;
|
||||
in-out property <bool> scanning;
|
||||
in-out property <bool> lists_enabled: GuiState.active_tab != CurrentTab.Settings;
|
||||
in-out property <bool> lists_enabled: GuiState.is_tool_tab_active;
|
||||
out property <int> name;
|
||||
height: 30px;
|
||||
spacing: 4px;
|
||||
|
|
|
@ -32,4 +32,6 @@ export global Callabler {
|
|||
|
||||
callback open_config_folder();
|
||||
callback open_cache_folder();
|
||||
|
||||
callback open_link(string);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,8 @@ export enum CurrentTab {
|
|||
EmptyFolders,
|
||||
EmptyFiles,
|
||||
SimilarImages,
|
||||
Settings
|
||||
Settings,
|
||||
About
|
||||
}
|
||||
|
||||
export enum TypeOfOpenedItem {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {CurrentTab} from "common.slint";
|
||||
import {SelectModel, SelectMode} from "common.slint";
|
||||
import {SelectModel, SelectMode, BottomPanelVisibility} from "common.slint";
|
||||
|
||||
// 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
|
||||
|
@ -19,5 +19,8 @@ export global GuiState {
|
|||
|
||||
in-out property <bool> available_subsettings: active_tab == CurrentTab.SimilarImages;
|
||||
in-out property <CurrentTab> active_tab: CurrentTab.EmptyFiles;
|
||||
in-out property <bool> is_tool_tab_active: active_tab != CurrentTab.Settings && active_tab != CurrentTab.About;
|
||||
in-out property <[SelectModel]> select_results_list: [{data: SelectMode.SelectAll, name: "Select All"}, {data: SelectMode.UnselectAll, name: "Deselect All"}, {data: SelectMode.SelectTheSmallestResolution, name: "Select the smallest resolution"}];
|
||||
|
||||
in-out property <BottomPanelVisibility> bottom_panel_visibility: BottomPanelVisibility.Directories;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Button, VerticalBox , HorizontalBox, TabWidget, ListView, StandardListView, StandardTableView, CheckBox} from "std-widgets.slint";
|
||||
import {CurrentTab} from "common.slint";
|
||||
import {CurrentTab, BottomPanelVisibility} from "common.slint";
|
||||
import {ColorPalette} from "color_palette.slint";
|
||||
import {GuiState} from "gui_state.slint";
|
||||
import {Callabler} from "callabler.slint";
|
||||
|
@ -70,11 +70,20 @@ export component LeftSidePanel {
|
|||
VerticalLayout {
|
||||
spacing: 20px;
|
||||
Rectangle {
|
||||
visible: GuiState.active_tab != CurrentTab.About;
|
||||
height: 100px;
|
||||
Image {
|
||||
width: root.width;
|
||||
source: @image-url("../icons/logo.png");
|
||||
}
|
||||
touch_area := TouchArea {
|
||||
clicked => {
|
||||
GuiState.active_tab = CurrentTab.About;
|
||||
Callabler.tab_changed();
|
||||
root.changed_current_tab();
|
||||
GuiState.bottom_panel_visibility = BottomPanelVisibility.NotVisible;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VerticalLayout {
|
||||
|
@ -110,7 +119,7 @@ export component LeftSidePanel {
|
|||
HorizontalLayout {
|
||||
alignment: start;
|
||||
Button {
|
||||
visible: GuiState.active_tab != CurrentTab.Settings && GuiState.available_subsettings;
|
||||
visible: GuiState.available_subsettings;
|
||||
min-width: 20px;
|
||||
min-height: 20px;
|
||||
max-height: self.width;
|
||||
|
|
|
@ -5,6 +5,7 @@ import {CurrentTab, TypeOfOpenedItem} from "common.slint";
|
|||
import {MainListModel} from "common.slint";
|
||||
import {SettingsList} from "settings_list.slint";
|
||||
import {GuiState} from "gui_state.slint";
|
||||
import {About} from "about.slint";
|
||||
|
||||
export component MainList {
|
||||
in-out property <[MainListModel]> empty_folder_model: [
|
||||
|
@ -55,6 +56,10 @@ export component MainList {
|
|||
visible: GuiState.active_tab == CurrentTab.Settings;
|
||||
}
|
||||
|
||||
about_app := About {
|
||||
visible: GuiState.active_tab == CurrentTab.About;
|
||||
}
|
||||
|
||||
focus_item := FocusScope {
|
||||
width: 0px; // Hack to not steal first click from other components - https://github.com/slint-ui/slint/issues/3503
|
||||
// Hack not works https://github.com/slint-ui/slint/issues/3503#issuecomment-1817809834 because disables key-released event
|
||||
|
|
|
@ -83,7 +83,7 @@ export component MainWindow inherits Window {
|
|||
similar_images_model <=> root.similar_images_model;
|
||||
}
|
||||
preview_or_tool_settings := Rectangle {
|
||||
visible: (GuiState.preview_visible || tool_settings.visible) && GuiState.active_tab != CurrentTab.Settings;
|
||||
visible: (GuiState.preview_visible || tool_settings.visible) && GuiState.is_tool_tab_active;
|
||||
height: parent.height;
|
||||
x: parent.width / 2;
|
||||
width: self.visible ? parent.width / 2 : 0;
|
||||
|
@ -134,9 +134,17 @@ export component MainWindow inherits Window {
|
|||
}
|
||||
}
|
||||
|
||||
text_summary := LineEdit {
|
||||
text: text_summary_text;
|
||||
read-only: true;
|
||||
HorizontalLayout {
|
||||
spacing: 5px;
|
||||
text_summary := LineEdit {
|
||||
text: text_summary_text;
|
||||
read-only: true;
|
||||
}
|
||||
Text {
|
||||
text: "Krokiet\n7.0.0";
|
||||
vertical-alignment: center;
|
||||
horizontal-alignment: center;
|
||||
}
|
||||
}
|
||||
|
||||
bottom_panel := BottomPanel {
|
||||
|
|
|
@ -84,10 +84,6 @@ export component PopupMoveFolders inherits Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
init => {
|
||||
show_popup();
|
||||
}
|
||||
|
||||
show_popup() => {
|
||||
popup_window.show();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue