1
0
Fork 0
mirror of synced 2024-06-02 02:24:44 +12:00
This commit is contained in:
Rafał Mikrut 2023-10-22 22:12:59 +02:00
parent e859c777a4
commit 6d8fe135ce
9 changed files with 109 additions and 19 deletions

1
Cargo.lock generated
View file

@ -1328,6 +1328,7 @@ name = "czkawka_slint"
version = "6.1.0" version = "6.1.0"
dependencies = [ dependencies = [
"chrono", "chrono",
"crossbeam-channel",
"czkawka_core", "czkawka_core",
"open", "open",
"rand", "rand",

View file

@ -17,6 +17,7 @@ rand = "0.8.5"
czkawka_core = { version = "6.1.0", path = "../czkawka_core" } czkawka_core = { version = "6.1.0", path = "../czkawka_core" }
chrono = "0.4.31" chrono = "0.4.31"
open="5.0.0" open="5.0.0"
crossbeam-channel = "0.5.8"
[build-dependencies] [build-dependencies]
#slint-build = "1.2.2" #slint-build = "1.2.2"

View file

@ -0,0 +1,39 @@
use crate::{MainWindow, ProgressToSend};
use crossbeam_channel::Receiver;
use czkawka_core::common_dir_traversal::ProgressData;
use slint::{ComponentHandle, SharedString};
use std::thread;
pub fn connect_progress_gathering(app: &MainWindow, progress_receiver: Receiver<ProgressData>) {
let a = app.as_weak();
thread::spawn(move || loop {
let progress_data = progress_receiver.recv().unwrap();
a.upgrade_in_event_loop(move |app| {
let (all_stages, current_stage) = common_get_data(&progress_data);
let to_send = ProgressToSend {
all_progress: (all_stages * 100.0) as i32,
current_progress: (current_stage * 100.0) as i32,
step_name: SharedString::from(format!("Checked {} folders", progress_data.entries_checked)),
};
app.set_progress_datas(to_send);
})
.unwrap();
});
}
fn common_get_data(item: &ProgressData) -> (f64, f64) {
if item.entries_to_check != 0 {
let all_stages = (item.current_stage as f64 + (item.entries_checked) as f64 / item.entries_to_check as f64) / (item.max_stage + 1) as f64;
let all_stages = if all_stages > 0.99 { 0.99 } else { all_stages };
let current_stage = (item.entries_checked) as f64 / item.entries_to_check as f64;
let current_stage = if current_stage > 0.99 { 0.99 } else { current_stage };
(all_stages, current_stage)
} else {
let all_stages = (item.current_stage as f64) / (item.max_stage + 1) as f64;
let all_stages = if all_stages > 0.99 { 0.99 } else { all_stages };
(all_stages, 0f64)
}
}

View file

@ -1,5 +1,7 @@
use crate::{split_path, CurrentTab, MainWindow}; use crate::{split_path, CurrentTab, MainWindow, ProgressToSend};
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
use crossbeam_channel::Sender;
use czkawka_core::common_dir_traversal::ProgressData;
use czkawka_core::common_tool::CommonData; use czkawka_core::common_tool::CommonData;
use czkawka_core::empty_folder::EmptyFolder; use czkawka_core::empty_folder::EmptyFolder;
use slint::{ComponentHandle, ModelRc, SharedString, VecModel, Weak}; use slint::{ComponentHandle, ModelRc, SharedString, VecModel, Weak};
@ -7,27 +9,32 @@ use std::path::PathBuf;
use std::rc::Rc; use std::rc::Rc;
use std::thread; use std::thread;
pub fn connect_scan_button(app: &MainWindow) { pub fn connect_scan_button(app: &MainWindow, progress_sender: Sender<ProgressData>) {
let a = app.as_weak(); let a = app.as_weak();
app.on_scanned(move |active_tab| { app.on_scanned(move |active_tab| {
let app = a.upgrade().unwrap(); let app = a.upgrade().unwrap();
app.set_scanning(true); app.set_scanning(true);
app.set_progress_datas(ProgressToSend {
all_progress: 0,
current_progress: 0,
step_name: SharedString::from(""),
});
let a = app.as_weak(); let a = app.as_weak();
match active_tab { match active_tab {
CurrentTab::EmptyFolders => { CurrentTab::EmptyFolders => {
scan_empty_folders(a); scan_empty_folders(a, &progress_sender);
} }
_ => panic!(), _ => panic!(),
} }
}); });
} }
fn scan_empty_folders(a: Weak<MainWindow>) { fn scan_empty_folders(a: Weak<MainWindow>, progress_sender: &Sender<ProgressData>) {
thread::spawn(move || { thread::spawn(move || {
let mut ef = EmptyFolder::new(); let mut ef = EmptyFolder::new();
ef.set_included_directory(vec![PathBuf::from("/home/rafal/Desktop")]); ef.set_included_directory(vec![PathBuf::from("/home/rafal/Desktop")]);
ef.find_empty_folders(None, None); ef.find_empty_folders(None, Some(progress_sender));
ef.get_empty_folder_list(); ef.get_empty_folder_list();

View file

@ -1,7 +1,9 @@
mod connect_delete; mod connect_delete;
mod connect_open; mod connect_open;
mod connect_progress_receiver;
mod connect_scan; mod connect_scan;
use crossbeam_channel::{unbounded, Receiver, Sender};
use std::path::Path; use std::path::Path;
use std::rc::Rc; use std::rc::Rc;
@ -9,17 +11,22 @@ use crate::connect_delete::connect_delete_button;
use crate::connect_open::connect_open_items; use crate::connect_open::connect_open_items;
use crate::connect_scan::connect_scan_button; use crate::connect_scan::connect_scan_button;
use crate::connect_progress_receiver::connect_progress_gathering;
use czkawka_core::common_dir_traversal::ProgressData;
use slint::{ModelRc, SharedString, VecModel}; use slint::{ModelRc, SharedString, VecModel};
slint::include_modules!(); slint::include_modules!();
fn main() { fn main() {
let app = MainWindow::new().unwrap(); //.run().unwrap(); let app = MainWindow::new().unwrap(); //.run().unwrap();
let (progress_sender, progress_receiver): (Sender<ProgressData>, Receiver<ProgressData>) = unbounded();
// Fills model at start, don't really needed too much after testing
to_remove_debug(&app); to_remove_debug(&app);
connect_delete_button(&app); connect_delete_button(&app);
connect_scan_button(&app); connect_scan_button(&app, progress_sender);
connect_open_items(&app); connect_open_items(&app);
connect_progress_gathering(&app, progress_receiver);
app.run().unwrap(); app.run().unwrap();
} }
@ -29,7 +36,7 @@ type ModelType = VecModel<(bool, bool, bool, ModelRc<SharedString>)>;
pub fn to_remove_debug(app: &MainWindow) { pub fn to_remove_debug(app: &MainWindow) {
let row_data: Rc<ModelType> = Rc::new(VecModel::default()); let row_data: Rc<ModelType> = Rc::new(VecModel::default());
for r in 0..100_000 { for r in 0..1_000_000 {
let items = VecModel::default(); let items = VecModel::default();
for c in 0..3 { for c in 0..3 {

View file

@ -1,5 +1,4 @@
import { Button, VerticalBox , HorizontalBox, TabWidget, ListView, StandardListView, StandardTableView, CheckBox} from "std-widgets.slint"; import { Button, VerticalBox , HorizontalBox, TabWidget, ListView, StandardListView, StandardTableView, CheckBox} from "std-widgets.slint";
import {SelectableTableView} from "selectable_tree_view.slint";
import {LeftSidePanel} from "left_side_panel.slint"; import {LeftSidePanel} from "left_side_panel.slint";
import {MainList} from "main_lists.slint"; import {MainList} from "main_lists.slint";
import {CurrentTab} from "common.slint"; import {CurrentTab} from "common.slint";

View file

@ -7,4 +7,10 @@ export enum CurrentTab {
export enum TypeOfOpenedItem { export enum TypeOfOpenedItem {
CurrentItem, CurrentItem,
ParentItem, ParentItem,
}
export struct ProgressToSend {
current_progress: int,
all_progress: int,
step_name: string,
} }

View file

@ -2,19 +2,26 @@ import { Button, VerticalBox , HorizontalBox, TabWidget, ListView, StandardListV
import {SelectableTableView} from "selectable_tree_view.slint"; import {SelectableTableView} from "selectable_tree_view.slint";
import {LeftSidePanel} from "left_side_panel.slint"; import {LeftSidePanel} from "left_side_panel.slint";
import {MainList} from "main_lists.slint"; import {MainList} from "main_lists.slint";
import {CurrentTab} from "common.slint"; import {CurrentTab, ProgressToSend} from "common.slint";
import { ActionButtons } from "action_buttons.slint"; import { ActionButtons } from "action_buttons.slint";
import { Progress } from "progress.slint";
export component MainWindow inherits Window { export component MainWindow inherits Window {
callback deleted; callback deleted;
callback scanned(CurrentTab); callback scanned(CurrentTab);
callback item_opened(string); callback item_opened(string);
min-width: 300px; min-width: 300px;
preferred-width: 1024px; preferred-width: 1024px;
min-height: 300px; min-height: 300px;
preferred-height: 600px; preferred-height: 600px;
in-out property <bool> scanning: false; in-out property <bool> scanning: false;
in-out property <ProgressToSend> progress_datas : {
current_progress: 15,
all_progress: 20,
step_name: "Cache",
};
in-out property <CurrentTab> active-tab: CurrentTab.EmptyFolders; in-out property <CurrentTab> active-tab: CurrentTab.EmptyFolders;
in-out property <[{checked: bool, header_row: bool, selected_row: bool, val:[string]}]> empty_folder_model: [ in-out property <[{checked: bool, header_row: bool, selected_row: bool, val:[string]}]> empty_folder_model: [
@ -63,14 +70,21 @@ export component MainWindow inherits Window {
active-tab <=> root.active-tab; active-tab <=> root.active-tab;
} }
MainList { VerticalLayout {
horizontal-stretch: 1.0; horizontal-stretch: 1.0;
active-tab <=> root.active-tab; MainList {
empty_folder_model <=> root.empty_folder_model; vertical-stretch: 1.0;
empty_files_model <=> root.empty_files_model; active-tab <=> root.active-tab;
similar_images_model <=> root.similar_images_model; empty_folder_model <=> root.empty_folder_model;
empty_files_model <=> root.empty_files_model;
item_opened(item) => {item_opened(item)} similar_images_model <=> root.similar_images_model;
item_opened(item) => {item_opened(item)}
}
Progress {
horizontal-stretch: 0.0;
progress_datas <=> root.progress_datas;
}
} }
} }
ActionButtons { ActionButtons {

View file

@ -18,9 +18,18 @@ export component SelectableTableView inherits Rectangle {
in-out property <int> selected_item: -1; in-out property <int> selected_item: -1;
forward-focus: focus_item;
focus_item := FocusScope {
key-released(event) => {
debug(event);
accept
}
}
VerticalBox { VerticalBox {
padding: 5px; padding: 5px;
// Widgets forward-focus: focus-item;
HorizontalLayout { HorizontalLayout {
padding: 5px; padding: 5px;
spacing: 5px; spacing: 5px;
@ -32,11 +41,13 @@ export component SelectableTableView inherits Rectangle {
Rectangle { Rectangle {
width: 1px; width: 1px;
background: gray; background: gray;
forward-focus: focus-item;
TouchArea { TouchArea {
width: 5px; width: 5px;
x: (parent.width - self.width) / 2; x: (parent.width - self.width) / 2;
property <length> cached; property <length> cached;
forward-focus: focus-item;
pointer-event(event) => { pointer-event(event) => {
if (event.button == PointerEventButton.left && event.kind == PointerEventKind.down) { if (event.button == PointerEventButton.left && event.kind == PointerEventKind.down) {
self.cached = root.column_sizes[idx]; self.cached = root.column_sizes[idx];
@ -58,14 +69,17 @@ export component SelectableTableView inherits Rectangle {
} }
list_view := ListView { list_view := ListView {
min-width: 100px; min-width: 100px;
forward-focus: focus-item;
for r[idx] in root.values : Rectangle { for r[idx] in root.values : Rectangle {
forward-focus: focus-item;
height: 30px; height: 30px;
// TODO move this into singleton // TODO move this into singleton
background: r.header-row ? #888888 : (touch-area.has-hover ? (r.selected_row ? #cccccc : #dddddd) : (r.selected_row ? #cccccc: #dddddd)); background: r.header-row ? #888888 : (touch-area.has-hover ? (r.selected_row ? #cccccc : #dddddd) : (r.selected_row ? #cccccc: #dddddd));
// background: touch-area.has-hover ? (selected ? #333333 : #222222) : (selected ? #333333: #222222); // background: touch-area.has-hover ? (selected ? #333333 : #222222) : (selected ? #333333: #222222);
touch_area:= TouchArea { touch_area:= TouchArea {
forward-focus: focus-item;
clicked => { clicked => {
if (!r.header_row) { if (!r.header_row) {
r.selected_row = !r.selected_row; r.selected_row = !r.selected_row;
@ -82,6 +96,7 @@ export component SelectableTableView inherits Rectangle {
} }
} }
pointer-event(event) => { pointer-event(event) => {
debug(event);
// TODO this should be clicked by double-click // TODO this should be clicked by double-click
if (event.button == PointerEventButton.right && event.kind == PointerEventKind.up) { if (event.button == PointerEventButton.right && event.kind == PointerEventKind.up) {
root.item_opened(r.val[root.parentPathIdx - 1]) root.item_opened(r.val[root.parentPathIdx - 1])
@ -94,16 +109,16 @@ export component SelectableTableView inherits Rectangle {
HorizontalLayout { HorizontalLayout {
padding: 5px; padding: 5px;
spacing: 5px; spacing: 5px;
forward-focus: focus-item;
CheckBox { CheckBox {
//min-width: 200px;
visible: !r.header-row; visible: !r.header-row;
checked: r.checked && !r.header-row; checked: r.checked && !r.header-row;
width: root.column-sizes[0]; width: root.column-sizes[0];
forward-focus: focus-item;
toggled => { toggled => {
r.checked = self.checked; r.checked = self.checked;
} }
// preferred-width: root.column-sizes[0];
} }
HorizontalLayout { HorizontalLayout {
@ -112,6 +127,7 @@ export component SelectableTableView inherits Rectangle {
width: root.column-sizes[idx + 1]; width: root.column-sizes[idx + 1];
text: f; text: f;
font-size: 12px; font-size: 12px;
forward-focus: focus-item;
vertical-alignment: center; vertical-alignment: center;