2
0
mirror of https://github.com/qarmin/czkawka synced 2024-11-10 07:10:40 +00:00

Added popup delete

This commit is contained in:
Rafał Mikrut 2024-02-11 11:54:48 +01:00
parent dfb89b2f5e
commit 04dba35c33
5 changed files with 182 additions and 96 deletions

View File

@ -38,14 +38,14 @@ pub fn get_int_size_idx(active_tab: CurrentTab) -> usize {
}
}
pub fn get_width_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"),
_ => panic!("Unable to get height from this tab"),
}
}
pub fn get_height_idx(active_tab: CurrentTab) -> usize {
pub fn get_int_height_idx(active_tab: CurrentTab) -> usize {
match active_tab {
CurrentTab::SimilarImages => 5,
CurrentTab::Settings => panic!("Button should be disabled"),

View File

@ -1,4 +1,6 @@
use crate::common::{connect_i32_into_u64, get_int_size_idx, get_is_header_mode, get_tool_model, set_tool_model};
use crate::common::{
connect_i32_into_u64, get_int_height_idx, get_int_modification_date_idx, get_int_size_idx, get_int_width_idx, get_is_header_mode, get_tool_model, set_tool_model,
};
use crate::{Callabler, GuiState, MainListModel, MainWindow, SelectMode};
use crate::{CurrentTab, SelectModel};
use slint::{ComponentHandle, Model, ModelRc, VecModel};
@ -16,9 +18,12 @@ pub fn connect_select(app: &MainWindow) {
SelectMode::SelectAll => select_all(current_model),
SelectMode::UnselectAll => deselect_all(current_model),
SelectMode::InvertSelection => invert_selection(current_model),
SelectMode::SelectTheBiggestSize => select_the_biggest_size(current_model, active_tab),
SelectMode::SelectTheSmallestSize => select_the_small_size(current_model, active_tab),
_ => unimplemented!(),
SelectMode::SelectTheBiggestSize => select_by_size_date(current_model, active_tab, true, true),
SelectMode::SelectTheSmallestSize => select_by_size_date(current_model, active_tab, false, true),
SelectMode::SelectTheBiggestResolution => select_by_resolution(current_model, active_tab, true),
SelectMode::SelectTheSmallestResolution => select_by_resolution(current_model, active_tab, false),
SelectMode::SelectNewest => select_by_size_date(current_model, active_tab, true, false),
SelectMode::SelectOldest => select_by_size_date(current_model, active_tab, false, false),
};
set_tool_model(&app, active_tab, new_model);
});
@ -77,51 +82,93 @@ fn translate_select_mode(select_mode: SelectMode) -> String {
}
}
fn select_the_biggest_size(model: ModelRc<MainListModel>, active_tab: CurrentTab) -> ModelRc<MainListModel> {
// TODO, when model will be able to contain i64 instead two i32, this function could be merged with select_by_size_date
fn select_by_resolution(model: ModelRc<MainListModel>, active_tab: CurrentTab, biggest: bool) -> ModelRc<MainListModel> {
let is_header_mode = get_is_header_mode(active_tab);
assert!(is_header_mode); // non header modes not really have reasont to use this function
assert!(is_header_mode); // non header modes not really have reason to use this function
let mut old_data = model.iter().collect::<Vec<_>>();
let headers_idx = find_header_idx_and_deselect_all(&mut old_data);
let size_idx = get_int_size_idx(active_tab);
let width_idx = get_int_width_idx(active_tab);
let height_idx = get_int_height_idx(active_tab);
for i in 0..(headers_idx.len() - 1) {
let mut max_size = 0;
let mut max_size_idx = 0;
for j in (headers_idx[i] + 1)..headers_idx[i + 1] {
let int_data = old_data[j].val_int.iter().collect::<Vec<_>>();
let size = connect_i32_into_u64(int_data[size_idx], int_data[size_idx + 1]);
if size > max_size {
max_size = size;
max_size_idx = j;
if biggest {
for i in 0..(headers_idx.len() - 1) {
let mut max_item = 0;
let mut max_item_idx = 0;
#[allow(clippy::needless_range_loop)]
for j in (headers_idx[i] + 1)..headers_idx[i + 1] {
let int_data = old_data[j].val_int.iter().collect::<Vec<_>>();
let item = int_data[width_idx] * int_data[height_idx];
if item > max_item {
max_item = item;
max_item_idx = j;
}
}
old_data[max_item_idx].checked = true;
}
} else {
for i in 0..(headers_idx.len() - 1) {
let mut min_item = u64::MAX;
let mut min_item_idx = 0;
#[allow(clippy::needless_range_loop)]
for j in (headers_idx[i] + 1)..headers_idx[i + 1] {
let int_data = old_data[j].val_int.iter().collect::<Vec<_>>();
let item = (int_data[width_idx] * int_data[height_idx]) as u64;
if item < min_item {
min_item = item;
min_item_idx = j;
}
}
old_data[min_item_idx].checked = true;
}
old_data[max_size_idx].checked = true;
}
ModelRc::new(VecModel::from(old_data))
}
fn select_the_small_size(model: ModelRc<MainListModel>, active_tab: CurrentTab) -> ModelRc<MainListModel> {
fn select_by_size_date(model: ModelRc<MainListModel>, active_tab: CurrentTab, biggest_newest: bool, size: bool) -> ModelRc<MainListModel> {
let is_header_mode = get_is_header_mode(active_tab);
assert!(is_header_mode); // non header modes not really have reasont to use this function
assert!(is_header_mode); // non header modes not really have reason to use this function
let mut old_data = model.iter().collect::<Vec<_>>();
let headers_idx = find_header_idx_and_deselect_all(&mut old_data);
let size_idx = get_int_size_idx(active_tab);
let item_idx = if size {
get_int_size_idx(active_tab)
} else {
get_int_modification_date_idx(active_tab)
};
for i in 0..(headers_idx.len() - 1) {
let mut min_size = u64::MAX;
let mut min_size_idx = 0;
for j in (headers_idx[i] + 1)..headers_idx[i + 1] {
let int_data = old_data[j].val_int.iter().collect::<Vec<_>>();
let size = connect_i32_into_u64(int_data[size_idx], int_data[size_idx + 1]);
if size < min_size {
min_size = size;
min_size_idx = j;
if biggest_newest {
for i in 0..(headers_idx.len() - 1) {
let mut max_item = 0;
let mut max_item_idx = 0;
#[allow(clippy::needless_range_loop)]
for j in (headers_idx[i] + 1)..headers_idx[i + 1] {
let int_data = old_data[j].val_int.iter().collect::<Vec<_>>();
let item = connect_i32_into_u64(int_data[item_idx], int_data[item_idx + 1]);
if item > max_item {
max_item = item;
max_item_idx = j;
}
}
old_data[max_item_idx].checked = true;
}
} else {
for i in 0..(headers_idx.len() - 1) {
let mut min_item = u64::MAX;
let mut min_item_idx = 0;
#[allow(clippy::needless_range_loop)]
for j in (headers_idx[i] + 1)..headers_idx[i + 1] {
let int_data = old_data[j].val_int.iter().collect::<Vec<_>>();
let item = connect_i32_into_u64(int_data[item_idx], int_data[item_idx + 1]);
if item < min_item {
min_item = item;
min_item_idx = j;
}
}
old_data[min_item_idx].checked = true;
}
old_data[min_size_idx].checked = true;
}
ModelRc::new(VecModel::from(old_data))
@ -129,11 +176,11 @@ fn select_the_small_size(model: ModelRc<MainListModel>, active_tab: CurrentTab)
fn select_all(model: ModelRc<MainListModel>) -> ModelRc<MainListModel> {
let mut old_data = model.iter().collect::<Vec<_>>();
old_data.iter_mut().for_each(|x| {
for x in &mut old_data {
if !x.header_row {
x.checked = true
x.checked = true;
}
});
}
ModelRc::new(VecModel::from(old_data))
}
@ -145,15 +192,15 @@ fn deselect_all(model: ModelRc<MainListModel>) -> ModelRc<MainListModel> {
fn invert_selection(model: ModelRc<MainListModel>) -> ModelRc<MainListModel> {
let mut old_data = model.iter().collect::<Vec<_>>();
old_data.iter_mut().for_each(|x| {
for x in &mut old_data {
if !x.header_row {
x.checked = !x.checked
x.checked = !x.checked;
}
});
}
ModelRc::new(VecModel::from(old_data))
}
fn find_header_idx_and_deselect_all(old_data: &mut Vec<MainListModel>) -> Vec<usize> {
fn find_header_idx_and_deselect_all(old_data: &mut [MainListModel]) -> Vec<usize> {
let mut header_idx = old_data
.iter()
.enumerate()
@ -161,55 +208,10 @@ fn find_header_idx_and_deselect_all(old_data: &mut Vec<MainListModel>) -> Vec<us
.collect::<Vec<_>>();
header_idx.push(old_data.len());
old_data.iter_mut().for_each(|x| {
for x in old_data.iter_mut() {
if !x.header_row {
x.checked = false;
}
});
}
header_idx
}
#[cfg(test)]
mod test {
use crate::{MainListModel, SelectMode};
use slint::ModelRc;
// #[test]
// pub fn test_select_all() {
// let model = ModelRc::new(VecModel::from(vec![SelectModel {
// name: "test".into(),
// data: SelectMode::SelectAll,
// }]));
// let new_model = select_all(model);
// let new_data = new_model.iter().collect::<Vec<_>>();
// assert_eq!(new_data[0].checked, true);
// }
//
// fn prepare_simple_model() -> ModelRc<MainListModel> {
// ModelRc::new(VecModel::from(vec![
// MainListModel {
// header_row: false,
// checked: false,
// selected_row: false,
// val_str: [],
// val_int: [0, 0, 0, 0, 0, 0],
// },
// MainListModel {
// header_row: false,
// checked: true,
// text: "test".into(),
// size: 0,
// resolution: (0, 0),
// date: 0,
// },
// MainListModel {
// header_row: false,
// checked: false,
// text: "test".into(),
// size: 0,
// resolution: (0, 0),
// date: 0,
// },
// ]))
// }
}

View File

@ -21,6 +21,7 @@ export component ActionButtons inherits HorizontalLayout {
callback scan_stopping;
callback scan_starting(CurrentTab);
callback show_select_popup(length, length);
callback show_remove_popup();
in-out property <BottomPanelVisibility> bottom_panel_visibility: BottomPanelVisibility.Directories;
in-out property <bool> stop_requested: false;
in-out property <bool> scanning;
@ -57,16 +58,6 @@ export component ActionButtons inherits HorizontalLayout {
horizontal-stretch: 0.5;
}
delete_button := Button {
height: parent.height;
enabled: !scanning && lists_enabled;
text: "Delete";
clicked => {
Callabler.delete_selected_items();
}
}
select_button := Button {
height: parent.height;
enabled: !scanning && lists_enabled;
@ -76,6 +67,15 @@ export component ActionButtons inherits HorizontalLayout {
}
}
delete_button := Button {
height: parent.height;
enabled: !scanning && lists_enabled;
text: "Delete";
clicked => {
show_remove_popup();
}
}
Rectangle {
horizontal-stretch: 0.5;
}

View File

@ -13,6 +13,7 @@ import {ColorPalette} from "color_palette.slint";
import {GuiState} from "gui_state.slint";
import { Preview } from "preview.slint";
import {PopupNewDirectories} from "popup_new_directories.slint";
import {PopupDelete} from "popup_delete.slint";
import { PopupSelectResults } from "popup_select_results.slint";
import { ToolSettings } from "tool_settings.slint";
@ -122,6 +123,9 @@ export component MainWindow inherits Window {
select_popup_window.y_offset = y_offset;
select_popup_window.show_popup();
}
show_remove_popup => {
delete_popup_window.show_popup();
}
}
text_summary := LineEdit {
@ -158,6 +162,13 @@ export component MainWindow inherits Window {
width: root.width;
}
delete_popup_window := PopupDelete {
height: root.height;
width: root.width;
x: parent.x + (root.width - self.popup_width) / 2.0;
y: parent.y + (parent.height - self.popup_height) / 2.0;
}
scan_ended(scan_text) => {
text_summary_text = scan_text;

View File

@ -0,0 +1,73 @@
import { Button, VerticalBox ,TextEdit, HorizontalBox, TabWidget, ListView, StandardListView, StandardTableView, CheckBox, LineEdit} from "std-widgets.slint";
import {SelectableTableView} from "selectable_tree_view.slint";
import {LeftSidePanel} from "left_side_panel.slint";
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, SelectMode, SelectModel} from "common.slint";
import {Settings} from "settings.slint";
import {Callabler} from "callabler.slint";
import { BottomPanel } from "bottom_panel.slint";
import {ColorPalette} from "color_palette.slint";
import {GuiState} from "gui_state.slint";
import { Preview } from "preview.slint";
export component PopupDelete inherits Rectangle {
out property <length> popup_width: 350px;
out property <length> popup_height: 150px;
callback show_popup();
popup_window := PopupWindow {
width: popup_width;
height: popup_height;
close-on-click: true;
Rectangle {
width: parent.width;
height: parent.height;
border-radius: 5px;
background: ColorPalette.popup_background;
VerticalLayout {
Text {
vertical-stretch: 0.0;
text: "Delete items";
vertical-alignment: center;
horizontal-alignment: center;
font-size: 13px;
padding: 10px;
}
Text {
vertical-stretch: 1.0;
text: "Are you sure you want to delete the selected items?";
vertical-alignment: center;
horizontal-alignment: center;
font-size: 13px;
padding: 10px;
}
HorizontalLayout {
Button {
text: "Yes";
clicked => {
popup_window.close();
Callabler.delete_selected_items();
}
}
Rectangle {
}
Button {
text: "No";
clicked => {
popup_window.close();
}
}
}
}
}
}
show_popup() => {
popup_window.show();
}
}