Fixes random things (#1160)
* AB * More simple * Optimize even more code * Delete info * Common * Randoms * Included * ProfData * Upgrade
This commit is contained in:
parent
bf78fc8b57
commit
0defcbd253
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -17,4 +17,5 @@ ci_tester/target
|
||||||
ci_tester/Cargo.lock
|
ci_tester/Cargo.lock
|
||||||
krokiet/Cargo.lock
|
krokiet/Cargo.lock
|
||||||
krokiet/target
|
krokiet/target
|
||||||
*.json
|
*.json
|
||||||
|
*.mm_profdata
|
847
Cargo.lock
generated
847
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,8 @@
|
||||||
## Version 7.0.0 - ?
|
## Version 7.0.0 - ?
|
||||||
|
### BREAKING CHANGES
|
||||||
|
- Reducing size of cache files, made old cache files incompatible with new version
|
||||||
|
- `-C` in CLI now saves as compact json
|
||||||
|
|
||||||
### GTK GUI
|
### GTK GUI
|
||||||
- Added drag&drop support for included/excluded folders - [#1106](https://github.com/qarmin/czkawka/pull/1106)
|
- Added drag&drop support for included/excluded folders - [#1106](https://github.com/qarmin/czkawka/pull/1106)
|
||||||
- Added information where are saved scan results - [#1102](https://github.com/qarmin/czkawka/pull/1102)
|
- Added information where are saved scan results - [#1102](https://github.com/qarmin/czkawka/pull/1102)
|
||||||
|
@ -23,6 +27,7 @@
|
||||||
- Fixed recognizing not accessible folders as non-empty - [#1152](https://github.com/qarmin/czkawka/pull/1152)
|
- Fixed recognizing not accessible folders as non-empty - [#1152](https://github.com/qarmin/czkawka/pull/1152)
|
||||||
- Unifying code for collecting files to scan - [#1159](https://github.com/qarmin/czkawka/pull/1159)
|
- Unifying code for collecting files to scan - [#1159](https://github.com/qarmin/czkawka/pull/1159)
|
||||||
- Decrease memory usage when collecting files by removing unused fields in custom file entries structs - [#1159](https://github.com/qarmin/czkawka/pull/1159)
|
- Decrease memory usage when collecting files by removing unused fields in custom file entries structs - [#1159](https://github.com/qarmin/czkawka/pull/1159)
|
||||||
|
- Decrease a little size of cache by few percents and improve loading/saving speed - [#1159](https://github.com/qarmin/czkawka/pull/1159)
|
||||||
|
|
||||||
## Version 6.1.0 - 15.10.2023r
|
## Version 6.1.0 - 15.10.2023r
|
||||||
- BREAKING CHANGE - Changed cache saving method, deduplicated, optimized and simplified procedure(all files needs to be hashed again) - [#1072](https://github.com/qarmin/czkawka/pull/1072), [#1086](https://github.com/qarmin/czkawka/pull/1086)
|
- BREAKING CHANGE - Changed cache saving method, deduplicated, optimized and simplified procedure(all files needs to be hashed again) - [#1072](https://github.com/qarmin/czkawka/pull/1072), [#1086](https://github.com/qarmin/czkawka/pull/1086)
|
||||||
|
@ -171,7 +176,7 @@
|
||||||
## Version 3.2.0 - 07.08.2021r
|
## Version 3.2.0 - 07.08.2021r
|
||||||
- Use checkbox instead selection to select files [#392](https://github.com/qarmin/czkawka/pull/392)
|
- Use checkbox instead selection to select files [#392](https://github.com/qarmin/czkawka/pull/392)
|
||||||
- Re-enable hardlink on windows - [#410](https://github.com/qarmin/czkawka/pull/410)
|
- Re-enable hardlink on windows - [#410](https://github.com/qarmin/czkawka/pull/410)
|
||||||
- Fix symlink and harlink creating - [#409](https://github.com/qarmin/czkawka/pull/409)
|
- Fix symlink and hardlink creating - [#409](https://github.com/qarmin/czkawka/pull/409)
|
||||||
- Add image preview to duplicate finder [#408](https://github.com/qarmin/czkawka/pull/408)
|
- Add image preview to duplicate finder [#408](https://github.com/qarmin/czkawka/pull/408)
|
||||||
- Add setting maximum file size [#407](https://github.com/qarmin/czkawka/pull/407)
|
- Add setting maximum file size [#407](https://github.com/qarmin/czkawka/pull/407)
|
||||||
- Add new grouping algorithm to similar images [#405](https://github.com/qarmin/czkawka/pull/405)
|
- Add new grouping algorithm to similar images [#405](https://github.com/qarmin/czkawka/pull/405)
|
||||||
|
|
|
@ -26,7 +26,7 @@ hamming = "0.1"
|
||||||
|
|
||||||
# Needed by same music
|
# Needed by same music
|
||||||
bitflags = "2.4"
|
bitflags = "2.4"
|
||||||
lofty = "0.17"
|
lofty = "0.18"
|
||||||
|
|
||||||
# Needed by broken files
|
# Needed by broken files
|
||||||
zip = { version = "0.6", features = ["aes-crypto", "bzip2", "deflate", "time"], default-features = false }
|
zip = { version = "0.6", features = ["aes-crypto", "bzip2", "deflate", "time"], default-features = false }
|
||||||
|
@ -42,7 +42,7 @@ blake3 = "1.5"
|
||||||
crc32fast = "1.3"
|
crc32fast = "1.3"
|
||||||
xxhash-rust = { version = "0.8", features = ["xxh3"] }
|
xxhash-rust = { version = "0.8", features = ["xxh3"] }
|
||||||
|
|
||||||
tempfile = "3.8"
|
tempfile = "3.9"
|
||||||
|
|
||||||
# Video Duplicates
|
# Video Duplicates
|
||||||
vid_dup_finder_lib = "0.1"
|
vid_dup_finder_lib = "0.1"
|
||||||
|
@ -56,7 +56,7 @@ serde_json = "1.0"
|
||||||
# Language
|
# Language
|
||||||
i18n-embed = { version = "0.14", features = ["fluent-system", "desktop-requester"] }
|
i18n-embed = { version = "0.14", features = ["fluent-system", "desktop-requester"] }
|
||||||
i18n-embed-fl = "0.7"
|
i18n-embed-fl = "0.7"
|
||||||
rust-embed = { version = "8.1", features = ["debug-embed"] }
|
rust-embed = { version = "8.2", features = ["debug-embed"] }
|
||||||
once_cell = "1.19"
|
once_cell = "1.19"
|
||||||
|
|
||||||
# Raw image files
|
# Raw image files
|
||||||
|
|
|
@ -331,40 +331,21 @@ pub fn split_path(path: &Path) -> (String, String) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn split_path_compare(path_a: &Path, path_b: &Path) -> Ordering {
|
pub fn split_path_compare(path_a: &Path, path_b: &Path) -> Ordering {
|
||||||
let parent_dir_a = path_a.parent();
|
match path_a.parent().cmp(&path_b.parent()) {
|
||||||
let parent_dir_b = path_b.parent();
|
Ordering::Equal => path_a.file_name().cmp(&path_b.file_name()),
|
||||||
if parent_dir_a.is_none() || parent_dir_b.is_none() {
|
other => other,
|
||||||
let file_name_a = path_a.file_name();
|
|
||||||
let file_name_b = path_b.file_name();
|
|
||||||
if file_name_a.is_none() || file_name_b.is_none() {
|
|
||||||
return Ordering::Equal;
|
|
||||||
}
|
|
||||||
|
|
||||||
return if file_name_a > file_name_b { Ordering::Greater } else { Ordering::Less };
|
|
||||||
}
|
|
||||||
if parent_dir_a > parent_dir_b {
|
|
||||||
Ordering::Greater
|
|
||||||
} else {
|
|
||||||
Ordering::Less
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_crash_message(library_name: &str, file_path: &str, home_library_url: &str) -> String {
|
pub fn create_crash_message(library_name: &str, file_path: &str, home_library_url: &str) -> String {
|
||||||
format!("{library_name} library crashed when opening \"{file_path}\", please check if this is fixed with the latest version of {library_name} (e.g. with https://github.com/qarmin/crates_tester) and if it is not fixed, please report bug here - {home_library_url}")
|
format!("{library_name} library crashed when opening \"{file_path}\", please check if this is fixed with the latest version of {library_name} and if it is not fixed, please report bug here - {home_library_url}")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn regex_check(expression_item: &SingleExcludedItem, directory: impl AsRef<Path>) -> bool {
|
pub fn regex_check(expression_item: &SingleExcludedItem, directory_name: &str) -> bool {
|
||||||
if expression_item.expression == "*" {
|
if expression_item.expression_splits.is_empty() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if expression_item.expression_splits.is_empty() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get rid of non unicode characters
|
|
||||||
let directory_name = directory.as_ref().to_string_lossy();
|
|
||||||
|
|
||||||
// Early checking if directory contains all parts needed by expression
|
// Early checking if directory contains all parts needed by expression
|
||||||
for split in &expression_item.unique_extensions_splits {
|
for split in &expression_item.unique_extensions_splits {
|
||||||
if !directory_name.contains(split) {
|
if !directory_name.contains(split) {
|
||||||
|
@ -481,7 +462,7 @@ where
|
||||||
infos.push(format!(
|
infos.push(format!(
|
||||||
"dry_run - would create hardlink from {:?} to {:?}",
|
"dry_run - would create hardlink from {:?} to {:?}",
|
||||||
original_file.get_path(),
|
original_file.get_path(),
|
||||||
original_file.get_path()
|
file_entry.get_path()
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
if dry_run {
|
if dry_run {
|
||||||
|
@ -519,7 +500,7 @@ where
|
||||||
if dry_run {
|
if dry_run {
|
||||||
infos.push(format!("dry_run - would delete file: {:?}", i.get_path()));
|
infos.push(format!("dry_run - would delete file: {:?}", i.get_path()));
|
||||||
} else {
|
} else {
|
||||||
if let Err(e) = std::fs::remove_file(i.get_path()) {
|
if let Err(e) = fs::remove_file(i.get_path()) {
|
||||||
errors.push(format!("Cannot delete file: {:?} - {e}", i.get_path()));
|
errors.push(format!("Cannot delete file: {:?} - {e}", i.get_path()));
|
||||||
failed_to_remove_files += 1;
|
failed_to_remove_files += 1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -661,6 +642,7 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_regex() {
|
fn test_regex() {
|
||||||
|
assert!(regex_check(&new_excluded_item("*"), "/home/rafal"));
|
||||||
assert!(regex_check(&new_excluded_item("*home*"), "/home/rafal"));
|
assert!(regex_check(&new_excluded_item("*home*"), "/home/rafal"));
|
||||||
assert!(regex_check(&new_excluded_item("*home"), "/home"));
|
assert!(regex_check(&new_excluded_item("*home"), "/home"));
|
||||||
assert!(regex_check(&new_excluded_item("*home/"), "/home/"));
|
assert!(regex_check(&new_excluded_item("*home/"), "/home/"));
|
||||||
|
|
|
@ -12,33 +12,34 @@ use serde::{Deserialize, Serialize};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::io::{BufReader, BufWriter};
|
use std::io::{BufReader, BufWriter};
|
||||||
|
|
||||||
|
const CACHE_VERSION: &str = "70";
|
||||||
|
|
||||||
pub fn get_broken_files_cache_file() -> String {
|
pub fn get_broken_files_cache_file() -> String {
|
||||||
"cache_broken_files_61.bin".to_string()
|
format!("cache_broken_files_{CACHE_VERSION}.bin")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_similar_images_cache_file(hash_size: &u8, hash_alg: &HashAlg, image_filter: &FilterType) -> String {
|
pub fn get_similar_images_cache_file(hash_size: &u8, hash_alg: &HashAlg, image_filter: &FilterType) -> String {
|
||||||
format!(
|
format!(
|
||||||
"cache_similar_images_{}_{}_{}_61.bin",
|
"cache_similar_images_{hash_size}_{}_{}_{CACHE_VERSION}.bin",
|
||||||
hash_size,
|
|
||||||
convert_algorithm_to_string(hash_alg),
|
convert_algorithm_to_string(hash_alg),
|
||||||
convert_filters_to_string(image_filter),
|
convert_filters_to_string(image_filter),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_similar_videos_cache_file() -> String {
|
pub fn get_similar_videos_cache_file() -> String {
|
||||||
"cache_similar_videos_61.bin".to_string()
|
format!("cache_similar_videos_{CACHE_VERSION}.bin")
|
||||||
}
|
}
|
||||||
pub fn get_similar_music_cache_file(checking_tags: bool) -> &'static str {
|
pub fn get_similar_music_cache_file(checking_tags: bool) -> String {
|
||||||
if checking_tags {
|
if checking_tags {
|
||||||
"cache_same_music_tags_61.bin"
|
format!("cache_same_music_tags_{CACHE_VERSION}.bin")
|
||||||
} else {
|
} else {
|
||||||
"cache_same_music_fingerprints_61.bin"
|
format!("cache_same_music_fingerprints_{CACHE_VERSION}.bin")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_duplicate_cache_file(type_of_hash: &HashType, is_prehash: bool) -> String {
|
pub fn get_duplicate_cache_file(type_of_hash: &HashType, is_prehash: bool) -> String {
|
||||||
let prehash_str = if is_prehash { "_prehash" } else { "" };
|
let prehash_str = if is_prehash { "_prehash" } else { "" };
|
||||||
format!("cache_duplicates_{type_of_hash:?}{prehash_str}_61.bin")
|
format!("cache_duplicates_{type_of_hash:?}{prehash_str}_{CACHE_VERSION}.bin")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[fun_time(message = "save_cache_to_file_generalized", level = "debug")]
|
#[fun_time(message = "save_cache_to_file_generalized", level = "debug")]
|
||||||
|
|
|
@ -305,8 +305,7 @@ impl Directories {
|
||||||
self.reference_directories.iter().any(|e| path.starts_with(e))
|
self.reference_directories.iter().any(|e| path.starts_with(e))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_excluded(&self, path: impl AsRef<Path>) -> bool {
|
pub fn is_excluded(&self, path: &Path) -> bool {
|
||||||
let path = path.as_ref();
|
|
||||||
#[cfg(target_family = "windows")]
|
#[cfg(target_family = "windows")]
|
||||||
let path = normalize_windows_path(path);
|
let path = normalize_windows_path(path);
|
||||||
// We're assuming that `excluded_directories` are already normalized
|
// We're assuming that `excluded_directories` are already normalized
|
||||||
|
|
|
@ -85,15 +85,17 @@ impl ExcludedItems {
|
||||||
pub fn get_excluded_items(&self) -> &Vec<String> {
|
pub fn get_excluded_items(&self) -> &Vec<String> {
|
||||||
&self.expressions
|
&self.expressions
|
||||||
}
|
}
|
||||||
pub fn is_excluded(&self, path: impl AsRef<Path>) -> bool {
|
pub fn is_excluded(&self, path: &Path) -> bool {
|
||||||
if self.connected_expressions.is_empty() {
|
if self.connected_expressions.is_empty() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#[cfg(target_family = "windows")]
|
#[cfg(target_family = "windows")]
|
||||||
let path = normalize_windows_path(path);
|
let path = normalize_windows_path(path);
|
||||||
|
|
||||||
|
let path_str = path.to_string_lossy();
|
||||||
|
|
||||||
for expression in &self.connected_expressions {
|
for expression in &self.connected_expressions {
|
||||||
if regex_check(expression, &path) {
|
if regex_check(expression, &path_str) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,6 +109,7 @@ pub fn new_excluded_item(expression: &str) -> SingleExcludedItem {
|
||||||
let mut unique_extensions_splits = expression_splits.clone();
|
let mut unique_extensions_splits = expression_splits.clone();
|
||||||
unique_extensions_splits.sort();
|
unique_extensions_splits.sort();
|
||||||
unique_extensions_splits.dedup();
|
unique_extensions_splits.dedup();
|
||||||
|
unique_extensions_splits.sort_by_key(|b| std::cmp::Reverse(b.len()));
|
||||||
SingleExcludedItem {
|
SingleExcludedItem {
|
||||||
expression,
|
expression,
|
||||||
expression_splits,
|
expression_splits,
|
||||||
|
|
|
@ -222,7 +222,7 @@ impl SameMusic {
|
||||||
|
|
||||||
if self.common_data.use_cache {
|
if self.common_data.use_cache {
|
||||||
let (messages, loaded_items) =
|
let (messages, loaded_items) =
|
||||||
load_cache_from_file_generalized_by_path::<MusicEntry>(get_similar_music_cache_file(checking_tags), self.get_delete_outdated_cache(), &self.music_to_check);
|
load_cache_from_file_generalized_by_path::<MusicEntry>(&get_similar_music_cache_file(checking_tags), self.get_delete_outdated_cache(), &self.music_to_check);
|
||||||
self.get_text_messages_mut().extend_with_another_messages(messages);
|
self.get_text_messages_mut().extend_with_another_messages(messages);
|
||||||
loaded_hash_map = loaded_items.unwrap_or_default();
|
loaded_hash_map = loaded_items.unwrap_or_default();
|
||||||
|
|
||||||
|
@ -260,7 +260,7 @@ impl SameMusic {
|
||||||
all_results.insert(file_entry.path.to_string_lossy().to_string(), file_entry);
|
all_results.insert(file_entry.path.to_string_lossy().to_string(), file_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
let messages = save_cache_to_file_generalized(get_similar_music_cache_file(checking_tags), &all_results, self.common_data.save_also_as_json, 0);
|
let messages = save_cache_to_file_generalized(&get_similar_music_cache_file(checking_tags), &all_results, self.common_data.save_also_as_json, 0);
|
||||||
self.get_text_messages_mut().extend_with_another_messages(messages);
|
self.get_text_messages_mut().extend_with_another_messages(messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ regex = "1.10"
|
||||||
image_hasher = "1.2"
|
image_hasher = "1.2"
|
||||||
|
|
||||||
# Move files to trash
|
# Move files to trash
|
||||||
trash = "3.1"
|
trash = "3.2"
|
||||||
|
|
||||||
# For moving files(why std::fs doesn't have such features?)
|
# For moving files(why std::fs doesn't have such features?)
|
||||||
fs_extra = "1.3"
|
fs_extra = "1.3"
|
||||||
|
@ -44,7 +44,7 @@ fs_extra = "1.3"
|
||||||
# Language
|
# Language
|
||||||
i18n-embed = { version = "0.14", features = ["fluent-system", "desktop-requester"] }
|
i18n-embed = { version = "0.14", features = ["fluent-system", "desktop-requester"] }
|
||||||
i18n-embed-fl = "0.7"
|
i18n-embed-fl = "0.7"
|
||||||
rust-embed = { version = "8.1", features = ["debug-embed"] }
|
rust-embed = { version = "8.2", features = ["debug-embed"] }
|
||||||
once_cell = "1.19"
|
once_cell = "1.19"
|
||||||
|
|
||||||
log = "0.4.20"
|
log = "0.4.20"
|
||||||
|
|
|
@ -450,7 +450,7 @@ fn popover_custom_select_unselect(
|
||||||
need_to_change_thing = true;
|
need_to_change_thing = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if regex_check(&name_wildcard_lowercase_excluded, name.to_lowercase()) {
|
if regex_check(&name_wildcard_lowercase_excluded, &name.to_lowercase()) {
|
||||||
need_to_change_thing = true;
|
need_to_change_thing = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -461,7 +461,7 @@ fn popover_custom_select_unselect(
|
||||||
need_to_change_thing = true;
|
need_to_change_thing = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if regex_check(&path_wildcard_lowercase_excluded, path.to_lowercase()) {
|
if regex_check(&path_wildcard_lowercase_excluded, &path.to_lowercase()) {
|
||||||
need_to_change_thing = true;
|
need_to_change_thing = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,15 +11,6 @@ repository = "https://github.com/qarmin/czkawka"
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# Try to use only needed features from https://github.com/slint-ui/slint/blob/master/api/rs/slint/Cargo.toml#L23-L31
|
|
||||||
#slint = { path = "/home/rafal/test/slint/api/rs/slint/", default-features = false, features = ["std",
|
|
||||||
#slint = { git = "https://github.com/slint-ui/slint.git", default-features = false, features = [
|
|
||||||
slint = { version = "1.3", default-features = false, features = [
|
|
||||||
"std",
|
|
||||||
"backend-winit",
|
|
||||||
"compat-1-2"
|
|
||||||
] }
|
|
||||||
|
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
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"
|
||||||
|
@ -40,13 +31,21 @@ rayon = "1.8.0"
|
||||||
# Translations
|
# Translations
|
||||||
i18n-embed = { version = "0.14", features = ["fluent-system", "desktop-requester"] }
|
i18n-embed = { version = "0.14", features = ["fluent-system", "desktop-requester"] }
|
||||||
i18n-embed-fl = "0.7"
|
i18n-embed-fl = "0.7"
|
||||||
rust-embed = { version = "8.1", features = ["debug-embed"] }
|
rust-embed = { version = "8.2", features = ["debug-embed"] }
|
||||||
once_cell = "1.19"
|
once_cell = "1.19"
|
||||||
|
|
||||||
|
# Try to use only needed features from https://github.com/slint-ui/slint/blob/master/api/rs/slint/Cargo.toml#L23-L31
|
||||||
|
#slint = { path = "/home/rafal/test/slint/api/rs/slint/", default-features = false, features = ["std",
|
||||||
|
slint = { git = "https://github.com/slint-ui/slint.git", default-features = false, features = [
|
||||||
|
# slint = { version = "1.3", default-features = false, features = [
|
||||||
|
"std",
|
||||||
|
"backend-winit",
|
||||||
|
"compat-1-2"
|
||||||
|
] }
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
slint-build = "1.3"
|
|
||||||
#slint-build = { git = "https://github.com/slint-ui/slint.git" }
|
|
||||||
#slint-build = { path = "/home/rafal/test/slint/api/rs/build/"}
|
#slint-build = { path = "/home/rafal/test/slint/api/rs/build/"}
|
||||||
|
slint-build = { git = "https://github.com/slint-ui/slint.git" }
|
||||||
|
# slint-build = "1.3"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["winit_femtovg", "winit_software"]
|
default = ["winit_femtovg", "winit_software"]
|
||||||
|
|
|
@ -3,7 +3,6 @@ use slint::{ComponentHandle, Model, ModelRc, VecModel};
|
||||||
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};
|
||||||
use crate::{Callabler, CurrentTab, GuiState, MainListModel, MainWindow};
|
use crate::{Callabler, CurrentTab, GuiState, MainListModel, MainWindow};
|
||||||
use czkawka_core::common::{remove_folder_if_contains_only_empty_folders, CHARACTER};
|
use czkawka_core::common::{remove_folder_if_contains_only_empty_folders, CHARACTER};
|
||||||
use log::info;
|
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
|
||||||
pub fn connect_delete_button(app: &MainWindow) {
|
pub fn connect_delete_button(app: &MainWindow) {
|
||||||
|
@ -64,7 +63,6 @@ fn remove_selected_items(items: Vec<MainListModel>, active_tab: CurrentTab) {
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
info!("Removing items: {:?} {:?}", items_to_remove, active_tab);
|
|
||||||
// Iterate over empty folders and not delete them if they are not empty
|
// Iterate over empty folders and not delete them if they are not empty
|
||||||
if active_tab == CurrentTab::EmptyFolders {
|
if active_tab == CurrentTab::EmptyFolders {
|
||||||
items_to_remove.into_par_iter().for_each(|item| {
|
items_to_remove.into_par_iter().for_each(|item| {
|
||||||
|
|
|
@ -259,7 +259,7 @@ pub fn save_base_settings_to_file(app: &MainWindow) {
|
||||||
|
|
||||||
pub fn save_custom_settings_to_file(app: &MainWindow) {
|
pub fn save_custom_settings_to_file(app: &MainWindow) {
|
||||||
let current_item = app.global::<Settings>().get_settings_preset_idx();
|
let current_item = app.global::<Settings>().get_settings_preset_idx();
|
||||||
let result = save_data_to_file(get_config_file(current_item), &collect_settings(app));
|
let result = save_data_to_file(get_config_file(current_item + 1), &collect_settings(app));
|
||||||
|
|
||||||
if let Err(e) = result {
|
if let Err(e) = result {
|
||||||
error!("{e}");
|
error!("{e}");
|
||||||
|
@ -279,14 +279,18 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = match std::fs::read_to_string(&config_file) {
|
let result = match std::fs::read_to_string(&config_file) {
|
||||||
Ok(serialized) => match serde_json::from_str(&serialized) {
|
Ok(serialized) => {
|
||||||
Ok(custom_settings) => Ok(custom_settings),
|
debug!("Loading data from file {:?} took {:?}", config_file, current_time.elapsed());
|
||||||
Err(e) => Err(format!("Cannot deserialize settings: {e}")),
|
|
||||||
},
|
match serde_json::from_str(&serialized) {
|
||||||
|
Ok(custom_settings) => Ok(custom_settings),
|
||||||
|
Err(e) => Err(format!("Cannot deserialize settings: {e}")),
|
||||||
|
}
|
||||||
|
}
|
||||||
Err(e) => Err(format!("Cannot read config file: {e}")),
|
Err(e) => Err(format!("Cannot read config file: {e}")),
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!("Loading data from file {:?} took {:?}", config_file, current_time.elapsed());
|
debug!("Loading and converting data from file {:?} took {:?}", config_file, current_time.elapsed());
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
101
krokiet/ui/included_directories.slint
Normal file
101
krokiet/ui/included_directories.slint
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
|
||||||
|
import {Button, StandardListView, VerticalBox, ListView, ScrollView, TextEdit, CheckBox} from "std-widgets.slint";
|
||||||
|
import {Callabler} from "callabler.slint";
|
||||||
|
|
||||||
|
export struct IncludedDirectoriesModel {
|
||||||
|
path: string,
|
||||||
|
referended_folder: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
export component InlcudedDirectories {
|
||||||
|
in-out property <[IncludedDirectoriesModel]> model: [{path: "/home/path", referended_folder: false}];
|
||||||
|
in-out property <int> current_index: -1;
|
||||||
|
|
||||||
|
in-out property <length> size_referenced_folder: 40px;
|
||||||
|
|
||||||
|
min-width: 50px;
|
||||||
|
VerticalLayout {
|
||||||
|
HorizontalLayout {
|
||||||
|
spacing: 5px;
|
||||||
|
Text {
|
||||||
|
text: "Referenced folder";
|
||||||
|
width: size_referenced_folder;
|
||||||
|
}
|
||||||
|
Text{
|
||||||
|
horizontal-stretch: 1.0;
|
||||||
|
text: "Path";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ListView {
|
||||||
|
for data in model : Rectangle {
|
||||||
|
height: 30px;
|
||||||
|
border_radius: 5px;
|
||||||
|
width: parent.width;
|
||||||
|
HorizontalLayout {
|
||||||
|
spacing: 5px;
|
||||||
|
width: parent.width;
|
||||||
|
|
||||||
|
CheckBox {
|
||||||
|
checked: data.referended_folder;
|
||||||
|
width: size_referenced_folder;
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
horizontal-stretch: 1.0;
|
||||||
|
text: data.path;
|
||||||
|
vertical-alignment: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export component ExcludeDirectories {
|
||||||
|
in-out property <[string]> model: ["/home/path"];
|
||||||
|
in-out property <int> current_index: -1;
|
||||||
|
private property <PointerEvent> event;
|
||||||
|
|
||||||
|
min-width: 50px;
|
||||||
|
VerticalLayout {
|
||||||
|
HorizontalLayout {
|
||||||
|
spacing: 5px;
|
||||||
|
Text {
|
||||||
|
text: "Path";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ListView {
|
||||||
|
for data[idx] in model : Rectangle {
|
||||||
|
height: 30px;
|
||||||
|
border_radius: 5px;
|
||||||
|
width: parent.width;
|
||||||
|
|
||||||
|
touch_area := TouchArea {
|
||||||
|
clicked => {
|
||||||
|
if (current_index == -1) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
double-clicked => {
|
||||||
|
if (event.button == PointerEventButton.middle && event.kind == PointerEventKind.up) {
|
||||||
|
Callabler.item_opened(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pointer-event(event) => {
|
||||||
|
root.event = event;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HorizontalLayout {
|
||||||
|
spacing: 5px;
|
||||||
|
width: parent.width;
|
||||||
|
|
||||||
|
Text {
|
||||||
|
horizontal-stretch: 1.0;
|
||||||
|
text: data;
|
||||||
|
vertical-alignment: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -108,7 +108,7 @@ export component LeftSidePanel {
|
||||||
HorizontalLayout {
|
HorizontalLayout {
|
||||||
alignment: start;
|
alignment: start;
|
||||||
Button {
|
Button {
|
||||||
enabled: GuiState.active_tab != CurrentTab.Settings && GuiState.available_subsettings;
|
visible: GuiState.active_tab != CurrentTab.Settings && GuiState.available_subsettings;
|
||||||
min-width: 20px;
|
min-width: 20px;
|
||||||
min-height: 20px;
|
min-height: 20px;
|
||||||
max-height: self.width;
|
max-height: self.width;
|
||||||
|
@ -122,7 +122,7 @@ export component LeftSidePanel {
|
||||||
HorizontalLayout {
|
HorizontalLayout {
|
||||||
alignment: end;
|
alignment: end;
|
||||||
Button {
|
Button {
|
||||||
enabled: GuiState.active_tab != CurrentTab.Settings;
|
visible: GuiState.active_tab != CurrentTab.Settings;
|
||||||
min-width: 20px;
|
min-width: 20px;
|
||||||
min-height: 20px;
|
min-height: 20px;
|
||||||
max-height: self.width;
|
max-height: self.width;
|
||||||
|
|
|
@ -75,17 +75,16 @@ export component SelectableTableView inherits Rectangle {
|
||||||
height: 20px;
|
height: 20px;
|
||||||
background: r.header-row ? ColorPalette.list_view_normal_header_color : (touch-area.has-hover ? (r.selected_row ? ColorPalette.list-view-normal-selected-header : ColorPalette.list_view_normal_color) : (r.selected_row ? ColorPalette.list-view-normal-selected-header : ColorPalette.list_view_normal_color));
|
background: r.header-row ? ColorPalette.list_view_normal_header_color : (touch-area.has-hover ? (r.selected_row ? ColorPalette.list-view-normal-selected-header : ColorPalette.list_view_normal_color) : (r.selected_row ? ColorPalette.list-view-normal-selected-header : ColorPalette.list_view_normal_color));
|
||||||
touch_area := TouchArea {
|
touch_area := TouchArea {
|
||||||
clicked => {
|
function clicked_manual() {
|
||||||
if (!r.header_row) {
|
if (!r.header_row) {
|
||||||
r.selected_row = !r.selected_row;
|
|
||||||
if (root.selected-item == -1) {
|
if (root.selected-item == -1) {
|
||||||
|
r.selected_row = !r.selected_row;
|
||||||
root.selected-item = idx;
|
root.selected-item = idx;
|
||||||
} else {
|
} else {
|
||||||
if (r.selected_row == true) {
|
if (!r.selected_row && root.selected-item != idx) {
|
||||||
|
r.selected_row = !r.selected_row;
|
||||||
root.values[root.selected-item].selected_row = false;
|
root.values[root.selected-item].selected_row = false;
|
||||||
root.selected-item = idx;
|
root.selected-item = idx;
|
||||||
} else {
|
|
||||||
root.selected-item = -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,13 +95,19 @@ export component SelectableTableView inherits Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
double-clicked => {
|
||||||
|
Callabler.item_opened(r.val[root.parentPathIdx - 1] + "/" + r.val[root.fileNameIdx - 1])
|
||||||
|
}
|
||||||
pointer-event(event) => {
|
pointer-event(event) => {
|
||||||
// TODO this should be clicked by double-click
|
// TODO this should be clicked by double-click - https://github.com/slint-ui/slint/issues/4235
|
||||||
if (event.button == PointerEventButton.right && event.kind == PointerEventKind.up) {
|
if (event.button == PointerEventButton.right && event.kind == PointerEventKind.up) {
|
||||||
Callabler.item_opened(r.val[root.parentPathIdx - 1])
|
Callabler.item_opened(r.val[root.parentPathIdx - 1])
|
||||||
} else if (event.button == PointerEventButton.middle && event.kind == PointerEventKind.up) {
|
} else if (event.button == PointerEventButton.left && event.kind == PointerEventKind.up) {
|
||||||
Callabler.item_opened(r.val[root.parentPathIdx - 1] + "/" + r.val[root.fileNameIdx - 1])
|
clicked_manual();
|
||||||
}
|
}
|
||||||
|
//else if (event.button == PointerEventButton.middle && event.kind == PointerEventKind.up) {
|
||||||
|
// Callabler.item_opened(r.val[root.parentPathIdx - 1] + "/" + r.val[root.fileNameIdx - 1])
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { Preview } from "preview.slint";
|
||||||
import {PopupNewDirectories} from "popup_new_directories.slint";
|
import {PopupNewDirectories} from "popup_new_directories.slint";
|
||||||
import { PopupSelect } from "popup_select.slint";
|
import { PopupSelect } from "popup_select.slint";
|
||||||
|
|
||||||
component ComboBoxWrapper inherits HorizontalLayout {
|
component ComboBoxWrapper inherits HorizontalLayout {
|
||||||
in-out property <string> text;
|
in-out property <string> text;
|
||||||
in-out property <[string]> model;
|
in-out property <[string]> model;
|
||||||
in-out property <int> current_index;
|
in-out property <int> current_index;
|
||||||
|
|
Loading…
Reference in a new issue