mirror of
https://github.com/qarmin/czkawka
synced 2024-11-10 07:10:40 +00:00
Added popup delete
This commit is contained in:
parent
dfb89b2f5e
commit
04dba35c33
@ -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"),
|
||||
|
@ -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,
|
||||
// },
|
||||
// ]))
|
||||
// }
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
73
krokiet/ui/popup_delete.slint
Normal file
73
krokiet/ui/popup_delete.slint
Normal 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();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user