Remove support for zeroed files (#461)

This commit is contained in:
Rafał Mikrut 2021-11-23 11:38:37 +01:00 committed by GitHub
parent 29129d3ec0
commit 78b49dee3d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 22 additions and 924 deletions

View File

@ -21,7 +21,6 @@
- Temporary Files - Finds temporary files
- Similar Images - Finds images which are not exactly the same (different resolution, watermarks)
- Similar Videos - Looks for similar visually videos
- Zeroed Files - Finds files which are filled with zeros (usually corrupted)
- Same Music - Searches for music with the same artist, album etc.
- Invalid Symbolic Links - Shows symbolic links which point to non-existent files/directories
- Broken Files - Finds files with an invalid extension or that are corrupted
@ -103,7 +102,6 @@ Bleachbit is a master at finding and removing temporary files, while Czkawka onl
| Big files | • | | | |
| Similar images | • | | • | |
| Similar videos | • | | | |
| Zeroed files | • | | | |
| Music duplicates(tags) | • | | • | |
| Invalid symlinks | • | • | | |
| Broken files | • | | | |

View File

@ -128,27 +128,6 @@ pub enum Commands {
#[structopt(short = "c", long, default_value = "8", parse(try_from_str = parse_image_hash_size), help="Hash size (allowed: 4, 8, 16)")]
hash_size: u8,
},
#[structopt(name = "zeroed", about = "Finds zeroed files", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka zeroed -d /home/rafal -e /home/rafal/Pulpit -f results.txt")]
ZeroedFiles {
#[structopt(flatten)]
directories: Directories,
#[structopt(flatten)]
excluded_directories: ExcludedDirectories,
#[structopt(flatten)]
excluded_items: ExcludedItems,
#[structopt(flatten)]
allowed_extensions: AllowedExtensions,
#[structopt(short = "D", long, help = "Delete found files")]
delete_files: bool,
#[structopt(flatten)]
file_to_save: FileToSave,
#[structopt(flatten)]
not_recursive: NotRecursive,
#[structopt(short, long, parse(try_from_str = parse_minimal_file_size), default_value = "8192", help = "Minimum size in bytes", long_help = "Minimum size of checked files in bytes, assigning bigger value may speed up searching")]
minimal_file_size: u64,
#[structopt(short = "i", long, parse(try_from_str = parse_maximal_file_size), default_value = "18446744073709551615", help = "Maximum size in bytes", long_help = "Maximum size of checked files in bytes, assigning lower value may speed up searching")]
maximal_file_size: u64,
},
#[structopt(name = "music", about = "Finds same music by tags", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka music -d /home/rafal -f results.txt")]
SameMusic {
#[structopt(flatten)]
@ -464,7 +443,6 @@ EXAMPLES:
{bin} empty-files -d /home/rafal /home/szczekacz -e /home/rafal/Pulpit -R -f results.txt
{bin} temp -d /home/rafal/ -E */.git */tmp* *Pulpit -f results.txt -D
{bin} image -d /home/rafal -e /home/rafal/Pulpit -f results.txt
{bin} zeroed -d /home/rafal -e /home/krzak -f results.txt"
{bin} music -d /home/rafal -e /home/rafal/Pulpit -z "artist,year, ARTISTALBUM, ALBUM___tiTlE" -f results.txt
{bin} symlinks -d /home/kicikici/ /home/szczek -e /home/kicikici/jestempsem -x jpg -f results.txt
{bin} broken -d /home/mikrut/ -e /home/mikrut/trakt -f results.txt"#;

View File

@ -18,7 +18,6 @@ use czkawka_core::{
similar_images::{return_similarity_from_similarity_preset, SimilarImages},
similar_videos::SimilarVideos,
temporary::{self, Temporary},
zeroed::{self, ZeroedFiles},
};
use std::process;
use structopt::StructOpt;
@ -243,44 +242,6 @@ fn main() {
sf.print_results();
sf.get_text_messages().print_messages();
}
Commands::ZeroedFiles {
directories,
excluded_directories,
excluded_items,
allowed_extensions,
delete_files,
file_to_save,
not_recursive,
minimal_file_size,
maximal_file_size,
} => {
let mut zf = ZeroedFiles::new();
zf.set_included_directory(directories.directories);
zf.set_excluded_directory(excluded_directories.excluded_directories);
zf.set_excluded_items(excluded_items.excluded_items);
zf.set_allowed_extensions(allowed_extensions.allowed_extensions.join(","));
zf.set_minimal_file_size(minimal_file_size);
zf.set_maximal_file_size(maximal_file_size);
zf.set_recursive_search(!not_recursive.not_recursive);
if delete_files {
zf.set_delete_method(zeroed::DeleteMethod::Delete);
}
zf.find_zeroed_files(None, None);
if let Some(file_name) = file_to_save.file_name() {
if !zf.save_results_to_file(file_name) {
zf.get_text_messages().print_messages();
process::exit(1);
}
}
#[cfg(not(debug_assertions))] // This will show too much probably unnecessary data to debug, comment line only if needed
zf.print_results();
zf.get_text_messages().print_messages();
}
Commands::SameMusic {
directories,
excluded_directories,

View File

@ -11,7 +11,6 @@ pub mod same_music;
pub mod similar_images;
pub mod similar_videos;
pub mod temporary;
pub mod zeroed;
pub mod common;
pub mod common_directory;

View File

@ -1,513 +0,0 @@
use std::fs::{File, Metadata};
use std::io::prelude::*;
use std::path::PathBuf;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use std::{fs, thread};
use crate::common::Common;
use crate::common_directory::Directories;
use crate::common_extensions::Extensions;
use crate::common_items::ExcludedItems;
use crate::common_messages::Messages;
use crate::common_traits::*;
use crossbeam_channel::Receiver;
use rayon::prelude::*;
use std::io::BufWriter;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::Arc;
use std::thread::sleep;
#[derive(Debug)]
pub struct ProgressData {
pub current_stage: u8,
pub max_stage: u8,
pub files_checked: usize,
pub files_to_check: usize,
}
#[derive(Eq, PartialEq, Clone, Debug)]
pub enum DeleteMethod {
None,
Delete,
}
#[derive(Clone)]
pub struct FileEntry {
pub path: PathBuf,
pub size: u64,
pub modified_date: u64,
}
/// Info struck with helpful information's about results
#[derive(Default)]
pub struct Info {
pub number_of_zeroed_files: usize,
pub number_of_removed_files: usize,
pub number_of_failed_to_remove_files: usize,
}
impl Info {
pub fn new() -> Self {
Default::default()
}
}
/// Struct with required information's to work
pub struct ZeroedFiles {
text_messages: Messages,
information: Info,
zeroed_files: Vec<FileEntry>,
directories: Directories,
allowed_extensions: Extensions,
excluded_items: ExcludedItems,
recursive_search: bool,
delete_method: DeleteMethod,
stopped_search: bool,
minimal_file_size: u64,
maximal_file_size: u64,
files_to_check: Vec<FileEntry>,
}
impl ZeroedFiles {
pub fn new() -> Self {
Self {
text_messages: Messages::new(),
information: Info::new(),
recursive_search: true,
allowed_extensions: Extensions::new(),
directories: Directories::new(),
excluded_items: ExcludedItems::new(),
zeroed_files: vec![],
delete_method: DeleteMethod::None,
stopped_search: false,
minimal_file_size: 8192,
maximal_file_size: u64::MAX,
files_to_check: Vec::with_capacity(1024),
}
}
pub fn find_zeroed_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) {
self.directories.optimize_directories(self.recursive_search, &mut self.text_messages);
if !self.check_files(stop_receiver, progress_sender) {
self.stopped_search = true;
return;
}
if !self.check_for_zeroed_files(stop_receiver, progress_sender) {
self.stopped_search = true;
return;
}
self.delete_files();
self.debug_print();
}
pub fn get_stopped_search(&self) -> bool {
self.stopped_search
}
pub const fn get_zeroed_files(&self) -> &Vec<FileEntry> {
&self.zeroed_files
}
pub const fn get_text_messages(&self) -> &Messages {
&self.text_messages
}
pub const fn get_information(&self) -> &Info {
&self.information
}
pub fn set_delete_method(&mut self, delete_method: DeleteMethod) {
self.delete_method = delete_method;
}
pub fn set_minimal_file_size(&mut self, minimal_file_size: u64) {
self.minimal_file_size = match minimal_file_size {
0 => 1,
t => t,
};
}
pub fn set_maximal_file_size(&mut self, maximal_file_size: u64) {
self.maximal_file_size = match maximal_file_size {
0 => 1,
t => t,
};
}
pub fn set_recursive_search(&mut self, recursive_search: bool) {
self.recursive_search = recursive_search;
}
pub fn set_included_directory(&mut self, included_directory: Vec<PathBuf>) -> bool {
self.directories.set_included_directory(included_directory, &mut self.text_messages)
}
pub fn set_excluded_directory(&mut self, excluded_directory: Vec<PathBuf>) {
self.directories.set_excluded_directory(excluded_directory, &mut self.text_messages);
}
pub fn set_allowed_extensions(&mut self, allowed_extensions: String) {
self.allowed_extensions.set_allowed_extensions(allowed_extensions, &mut self.text_messages);
}
pub fn set_excluded_items(&mut self, excluded_items: Vec<String>) {
self.excluded_items.set_excluded_items(excluded_items, &mut self.text_messages);
}
/// Check files for files which have 0
fn check_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
let start_time: SystemTime = SystemTime::now();
let mut folders_to_check: Vec<PathBuf> = Vec::with_capacity(1024 * 2); // This should be small enough too not see to big difference and big enough to store most of paths without needing to resize vector
// Add root folders for finding
for id in &self.directories.included_directories {
folders_to_check.push(id.clone());
}
//// PROGRESS THREAD START
const LOOP_DURATION: u32 = 200; //in ms
let progress_thread_run = Arc::new(AtomicBool::new(true));
let atomic_file_counter = Arc::new(AtomicUsize::new(0));
let progress_thread_handle;
if let Some(progress_sender) = progress_sender {
let progress_send = progress_sender.clone();
let progress_thread_run = progress_thread_run.clone();
let atomic_file_counter = atomic_file_counter.clone();
progress_thread_handle = thread::spawn(move || loop {
progress_send
.unbounded_send(ProgressData {
current_stage: 0,
max_stage: 1,
files_checked: atomic_file_counter.load(Ordering::Relaxed) as usize,
files_to_check: 0,
})
.unwrap();
if !progress_thread_run.load(Ordering::Relaxed) {
break;
}
sleep(Duration::from_millis(LOOP_DURATION as u64));
});
} else {
progress_thread_handle = thread::spawn(|| {});
}
//// PROGRESS THREAD END
while !folders_to_check.is_empty() {
if stop_receiver.is_some() && stop_receiver.unwrap().try_recv().is_ok() {
// End thread which send info to gui
progress_thread_run.store(false, Ordering::Relaxed);
progress_thread_handle.join().unwrap();
return false;
}
let current_folder = folders_to_check.pop().unwrap();
// Read current dir, if permission are denied just go to next
let read_dir = match fs::read_dir(&current_folder) {
Ok(t) => t,
Err(e) => {
self.text_messages.warnings.push(format!("Cannot open dir {}, reason {}", current_folder.display(), e));
continue;
} // Permissions denied
};
// Check every sub folder/file/link etc.
'dir: for entry in read_dir {
let entry_data = match entry {
Ok(t) => t,
Err(e) => {
self.text_messages.warnings.push(format!("Cannot read entry in dir {}, reason {}", current_folder.display(), e));
continue;
} //Permissions denied
};
let metadata: Metadata = match entry_data.metadata() {
Ok(t) => t,
Err(e) => {
self.text_messages.warnings.push(format!("Cannot read metadata in dir {}, reason {}", current_folder.display(), e));
continue;
} //Permissions denied
};
if metadata.is_dir() {
if !self.recursive_search {
continue;
}
let next_folder = current_folder.join(entry_data.file_name());
if self.directories.is_excluded(&next_folder) || self.excluded_items.is_excluded(&next_folder) {
continue 'dir;
}
folders_to_check.push(next_folder);
} else if metadata.is_file() {
atomic_file_counter.fetch_add(1, Ordering::Relaxed);
if metadata.len() == 0 || !(self.minimal_file_size..=self.maximal_file_size).contains(&metadata.len()) {
continue 'dir;
}
let file_name_lowercase: String = match entry_data.file_name().into_string() {
Ok(t) => t,
Err(_inspected) => {
println!("File {:?} has not valid UTF-8 name", entry_data);
continue 'dir;
}
}
.to_lowercase();
// Checking allowed extensions
if !self.allowed_extensions.file_extensions.is_empty() {
let allowed = self.allowed_extensions.file_extensions.iter().any(|e| file_name_lowercase.ends_with((".".to_string() + e.to_lowercase().as_str()).as_str()));
if !allowed {
// Not an allowed extension, ignore it.
continue 'dir;
}
}
// Checking files
let current_file_name = current_folder.join(entry_data.file_name());
if self.excluded_items.is_excluded(&current_file_name) {
continue 'dir;
}
// Creating new file entry
let fe: FileEntry = FileEntry {
path: current_file_name.clone(),
size: metadata.len(),
modified_date: match metadata.modified() {
Ok(t) => match t.duration_since(UNIX_EPOCH) {
Ok(d) => d.as_secs(),
Err(_inspected) => {
self.text_messages.warnings.push(format!("File {} seems to be modified before Unix Epoch.", current_file_name.display()));
0
}
},
Err(e) => {
self.text_messages.warnings.push(format!("Unable to get modification date from file {}, reason {}", current_file_name.display(), e));
0
} // Permissions Denied
},
};
// Adding files to Vector
self.files_to_check.push(fe);
}
}
}
// End thread which send info to gui
progress_thread_run.store(false, Ordering::Relaxed);
progress_thread_handle.join().unwrap();
Common::print_time(start_time, SystemTime::now(), "check_files".to_string());
true
}
/// Check files for files which have 0
fn check_for_zeroed_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
let start_time: SystemTime = SystemTime::now();
//// PROGRESS THREAD START
const LOOP_DURATION: u32 = 200; //in ms
let progress_thread_run = Arc::new(AtomicBool::new(true));
let atomic_file_counter = Arc::new(AtomicUsize::new(0));
let progress_thread_handle;
if let Some(progress_sender) = progress_sender {
let progress_send = progress_sender.clone();
let progress_thread_run = progress_thread_run.clone();
let atomic_file_counter = atomic_file_counter.clone();
let files_to_check = self.files_to_check.len();
progress_thread_handle = thread::spawn(move || loop {
progress_send
.unbounded_send(ProgressData {
current_stage: 1,
max_stage: 1,
files_checked: atomic_file_counter.load(Ordering::Relaxed) as usize,
files_to_check,
})
.unwrap();
if !progress_thread_run.load(Ordering::Relaxed) {
break;
}
sleep(Duration::from_millis(LOOP_DURATION as u64));
});
} else {
progress_thread_handle = thread::spawn(|| {});
}
//// PROGRESS THREAD END
self.zeroed_files = self
.files_to_check
.par_iter()
.map(|file_entry| {
atomic_file_counter.fetch_add(1, Ordering::Relaxed);
if stop_receiver.is_some() && stop_receiver.unwrap().try_recv().is_ok() {
// This will not break
return None;
}
let file_entry = file_entry.clone();
let mut n;
let mut file_handler: File = match File::open(&file_entry.path) {
Ok(t) => t,
Err(_inspected) => {
return Some(None);
}
};
// First search
let mut buffer = [0u8; 64];
n = match file_handler.read(&mut buffer) {
Ok(t) => t,
Err(_inspected) => {
return Some(None);
}
};
for i in buffer[0..n].iter() {
if *i != 0 {
return Some(None);
}
}
// Second search
loop {
let mut buffer = [0u8; 1024 * 32];
n = match file_handler.read(&mut buffer) {
Ok(t) => t,
Err(_inspected) => {
return Some(None);
}
};
for i in buffer[0..n].iter() {
if *i != 0 {
return Some(None);
}
}
if n == 0 {
break;
}
}
Some(Some(file_entry))
})
.while_some()
.filter(|file_entry| file_entry.is_some())
.map(|file_entry| file_entry.unwrap())
.collect::<Vec<_>>();
// End thread which send info to gui
progress_thread_run.store(false, Ordering::Relaxed);
progress_thread_handle.join().unwrap();
self.information.number_of_zeroed_files = self.zeroed_files.len();
Common::print_time(start_time, SystemTime::now(), "search for zeroed_files".to_string());
//Clean unused data
self.files_to_check.clear();
true
}
/// Function to delete files, from filed Vector
fn delete_files(&mut self) {
let start_time: SystemTime = SystemTime::now();
match self.delete_method {
DeleteMethod::Delete => {
for file_entry in &self.zeroed_files {
if fs::remove_file(file_entry.path.clone()).is_err() {
self.text_messages.warnings.push(file_entry.path.display().to_string());
}
}
}
DeleteMethod::None => {
//Just do nothing
}
}
Common::print_time(start_time, SystemTime::now(), "delete_files".to_string());
}
}
impl Default for ZeroedFiles {
fn default() -> Self {
Self::new()
}
}
impl DebugPrint for ZeroedFiles {
#[allow(dead_code)]
#[allow(unreachable_code)]
/// Debugging printing - only available on debug build
fn debug_print(&self) {
#[cfg(not(debug_assertions))]
{
return;
}
println!("---------------DEBUG PRINT---------------");
println!("### Information's");
println!("Errors size - {}", self.text_messages.errors.len());
println!("Warnings size - {}", self.text_messages.warnings.len());
println!("Messages size - {}", self.text_messages.messages.len());
println!("Number of removed files - {}", self.information.number_of_removed_files);
println!("Number of failed to remove files - {}", self.information.number_of_failed_to_remove_files);
println!("### Other");
println!("Zeroed list size - {}", self.zeroed_files.len());
println!("Allowed extensions - {:?}", self.allowed_extensions.file_extensions);
println!("Excluded items - {:?}", self.excluded_items.items);
println!("Included directories - {:?}", self.directories.included_directories);
println!("Excluded directories - {:?}", self.directories.excluded_directories);
println!("Recursive search - {}", self.recursive_search);
println!("Delete Method - {:?}", self.delete_method);
println!("Minimal File Size - {:?}", self.minimal_file_size);
println!("-----------------------------------------");
}
}
impl SaveResults for ZeroedFiles {
fn save_results_to_file(&mut self, file_name: &str) -> bool {
let start_time: SystemTime = SystemTime::now();
let file_name: String = match file_name {
"" => "results.txt".to_string(),
k => k.to_string(),
};
let file_handler = match File::create(&file_name) {
Ok(t) => t,
Err(e) => {
self.text_messages.errors.push(format!("Failed to create file {}, reason {}", file_name, e));
return false;
}
};
let mut writer = BufWriter::new(file_handler);
if let Err(e) = writeln!(
writer,
"Results of searching {:?} with excluded directories {:?} and excluded items {:?}",
self.directories.included_directories, self.directories.excluded_directories, self.excluded_items.items
) {
self.text_messages.errors.push(format!("Failed to save results to file {}, reason {}", file_name, e));
return false;
}
if !self.zeroed_files.is_empty() {
writeln!(writer, "Found {} zeroed files.", self.information.number_of_zeroed_files).unwrap();
for file_entry in self.zeroed_files.iter() {
writeln!(writer, "{}", file_entry.path.display()).unwrap();
}
} else {
write!(writer, "Not found any zeroed files.").unwrap();
}
Common::print_time(start_time, SystemTime::now(), "save_results_to_file".to_string());
true
}
}
impl PrintResults for ZeroedFiles {
/// Print information's about duplicated entries
/// Only needed for CLI
fn print_results(&self) {
let start_time: SystemTime = SystemTime::now();
println!("Found {} zeroed files.\n", self.information.number_of_zeroed_files);
for file_entry in self.zeroed_files.iter() {
println!("{}", file_entry.path.display());
}
Common::print_time(start_time, SystemTime::now(), "print_entries".to_string());
}
}

View File

@ -21,7 +21,6 @@ pub fn connect_button_delete(gui_data: &GuiData) {
let tree_view_temporary_files_finder = gui_data.main_notebook.tree_view_temporary_files_finder.clone();
let tree_view_similar_images_finder = gui_data.main_notebook.tree_view_similar_images_finder.clone();
let tree_view_similar_videos_finder = gui_data.main_notebook.tree_view_similar_videos_finder.clone();
let tree_view_zeroed_files_finder = gui_data.main_notebook.tree_view_zeroed_files_finder.clone();
let tree_view_same_music_finder = gui_data.main_notebook.tree_view_same_music_finder.clone();
let tree_view_invalid_symlinks = gui_data.main_notebook.tree_view_invalid_symlinks.clone();
let tree_view_broken_files = gui_data.main_notebook.tree_view_broken_files.clone();
@ -126,15 +125,6 @@ pub fn connect_button_delete(gui_data: &GuiData) {
);
}
}
NotebookMainEnum::Zeroed => {
basic_remove(
&tree_view_zeroed_files_finder.clone(),
ColumnsZeroedFiles::Name as i32,
ColumnsZeroedFiles::Path as i32,
ColumnsZeroedFiles::ActiveSelectButton as i32,
&gui_data,
);
}
NotebookMainEnum::SameMusic => {
if !check_button_settings_confirm_group_deletion.is_active()
|| !check_if_deleting_all_files_in_group(

View File

@ -16,7 +16,6 @@ pub fn connect_button_move(gui_data: &GuiData) {
let tree_view_empty_files_finder = gui_data.main_notebook.tree_view_empty_files_finder.clone();
let tree_view_temporary_files_finder = gui_data.main_notebook.tree_view_temporary_files_finder.clone();
let tree_view_similar_images_finder = gui_data.main_notebook.tree_view_similar_images_finder.clone();
let tree_view_zeroed_files_finder = gui_data.main_notebook.tree_view_zeroed_files_finder.clone();
let tree_view_same_music_finder = gui_data.main_notebook.tree_view_same_music_finder.clone();
let tree_view_invalid_symlinks = gui_data.main_notebook.tree_view_invalid_symlinks.clone();
let tree_view_broken_files = gui_data.main_notebook.tree_view_broken_files.clone();
@ -75,16 +74,6 @@ pub fn connect_button_move(gui_data: &GuiData) {
&gui_data,
);
}
NotebookMainEnum::Zeroed => {
move_things(
tree_view_zeroed_files_finder.clone(),
ColumnsZeroedFiles::Name as i32,
ColumnsZeroedFiles::Path as i32,
None,
ColumnsZeroedFiles::ActiveSelectButton as i32,
&gui_data,
);
}
NotebookMainEnum::BrokenFiles => {
move_things(
tree_view_broken_files.clone(),

View File

@ -14,7 +14,6 @@ pub fn connect_button_save(gui_data: &GuiData) {
let shared_similar_images_state = gui_data.shared_similar_images_state.clone();
let shared_similar_videos_state = gui_data.shared_similar_videos_state.clone();
let shared_same_music_state = gui_data.shared_same_music_state.clone();
let shared_zeroed_files_state = gui_data.shared_zeroed_files_state.clone();
let shared_same_invalid_symlinks = gui_data.shared_same_invalid_symlinks.clone();
let shared_broken_files_state = gui_data.shared_broken_files_state.clone();
let notebook_main = gui_data.main_notebook.notebook_main.clone();
@ -57,11 +56,6 @@ pub fn connect_button_save(gui_data: &GuiData) {
shared_similar_videos_state.borrow_mut().save_results_to_file(file_name);
}
NotebookMainEnum::Zeroed => {
file_name = "results_zeroed_files.txt";
shared_zeroed_files_state.borrow_mut().save_results_to_file(file_name);
}
NotebookMainEnum::SameMusic => {
file_name = "results_same_music.txt";

View File

@ -13,7 +13,6 @@ use czkawka_core::same_music::{MusicSimilarity, SameMusic};
use czkawka_core::similar_images::SimilarImages;
use czkawka_core::similar_videos::SimilarVideos;
use czkawka_core::temporary::Temporary;
use czkawka_core::zeroed::ZeroedFiles;
use glib::Sender;
use gtk::prelude::*;
use gtk::WindowPosition;
@ -36,7 +35,6 @@ pub fn connect_button_search(
futures_sender_similar_images: futures::channel::mpsc::UnboundedSender<similar_images::ProgressData>,
futures_sender_similar_videos: futures::channel::mpsc::UnboundedSender<similar_videos::ProgressData>,
futures_sender_temporary: futures::channel::mpsc::UnboundedSender<temporary::ProgressData>,
futures_sender_zeroed: futures::channel::mpsc::UnboundedSender<zeroed::ProgressData>,
futures_sender_invalid_symlinks: futures::channel::mpsc::UnboundedSender<invalid_symlinks::ProgressData>,
futures_sender_broken_files: futures::channel::mpsc::UnboundedSender<broken_files::ProgressData>,
) {
@ -80,7 +78,6 @@ pub fn connect_button_search(
let tree_view_same_music_finder = gui_data.main_notebook.tree_view_same_music_finder.clone();
let tree_view_similar_images_finder = gui_data.main_notebook.tree_view_similar_images_finder.clone();
let tree_view_similar_videos_finder = gui_data.main_notebook.tree_view_similar_videos_finder.clone();
let tree_view_zeroed_files_finder = gui_data.main_notebook.tree_view_zeroed_files_finder.clone();
let tree_view_invalid_symlinks = gui_data.main_notebook.tree_view_invalid_symlinks.clone();
let tree_view_broken_files = gui_data.main_notebook.tree_view_broken_files.clone();
let text_view_errors = gui_data.text_view_errors.clone();
@ -382,27 +379,6 @@ pub fn connect_button_search(
let _ = glib_stop_sender.send(Message::SimilarVideos(sf));
});
}
NotebookMainEnum::Zeroed => {
label_stage.show();
grid_progress_stages.show_all();
window_progress.resize(1, 1);
get_list_store(&tree_view_zeroed_files_finder).clear();
let futures_sender_zeroed = futures_sender_zeroed.clone();
// Find zeroed files
thread::spawn(move || {
let mut zf = ZeroedFiles::new();
zf.set_included_directory(included_directories);
zf.set_excluded_directory(excluded_directories);
zf.set_recursive_search(recursive_search);
zf.set_excluded_items(excluded_items);
zf.set_allowed_extensions(allowed_extensions);
zf.find_zeroed_files(Some(&stop_receiver), Some(&futures_sender_zeroed));
let _ = glib_stop_sender.send(Message::ZeroedFiles(zf));
});
}
NotebookMainEnum::SameMusic => {
label_stage.show();
grid_progress_stages.show_all();

View File

@ -17,6 +17,7 @@ pub fn connect_button_select(gui_data: &GuiData) {
{
// Remember to update connect_popovers file, because this data are connected to each others
hashmap.insert(NotebookMainEnum::SimilarImages, vec!["all", "image_size", "reverse", "custom", "date"]);
hashmap.insert(NotebookMainEnum::SimilarVideos, vec!["all", "reverse", "custom", "date"]);
hashmap.insert(NotebookMainEnum::Duplicate, vec!["all", "reverse", "custom", "date"]);
hashmap.insert(NotebookMainEnum::SameMusic, vec!["all", "reverse", "custom", "date"]);
@ -24,7 +25,6 @@ pub fn connect_button_select(gui_data: &GuiData) {
hashmap.insert(NotebookMainEnum::EmptyDirectories, vec!["all", "reverse", "custom"]);
hashmap.insert(NotebookMainEnum::BigFiles, vec!["all", "reverse", "custom"]);
hashmap.insert(NotebookMainEnum::Symlinks, vec!["all", "reverse", "custom"]);
hashmap.insert(NotebookMainEnum::Zeroed, vec!["all", "reverse", "custom"]);
hashmap.insert(NotebookMainEnum::Temporary, vec!["all", "reverse", "custom"]);
hashmap.insert(NotebookMainEnum::BrokenFiles, vec!["all", "reverse", "custom"]);
}

View File

@ -24,7 +24,6 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
let text_view_errors = gui_data.text_view_errors.clone();
let shared_duplication_state = gui_data.shared_duplication_state.clone();
let shared_buttons = gui_data.shared_buttons.clone();
let tree_view_zeroed_files_finder = gui_data.main_notebook.tree_view_zeroed_files_finder.clone();
let shared_empty_folders_state = gui_data.shared_empty_folders_state.clone();
let shared_empty_files_state = gui_data.shared_empty_files_state.clone();
let shared_broken_files_state = gui_data.shared_broken_files_state.clone();
@ -37,7 +36,6 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
let shared_temporary_files_state = gui_data.shared_temporary_files_state.clone();
let shared_similar_images_state = gui_data.shared_similar_images_state.clone();
let shared_similar_videos_state = gui_data.shared_similar_videos_state.clone();
let shared_zeroed_files_state = gui_data.shared_zeroed_files_state.clone();
let tree_view_same_music_finder = gui_data.main_notebook.tree_view_same_music_finder.clone();
let shared_same_music_state = gui_data.shared_same_music_state.clone();
let buttons_names = gui_data.bottom_buttons.buttons_names.clone();
@ -679,64 +677,6 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
}
}
}
Message::ZeroedFiles(zf) => {
if zf.get_stopped_search() {
entry_info.set_text("Searching for zeroed files was stopped by user");
} else {
let information = zf.get_information();
let text_messages = zf.get_text_messages();
let zeroed_files_number: usize = information.number_of_zeroed_files;
entry_info.set_text(format!("Found {} zeroed files.", zeroed_files_number).as_str());
// Create GUI
{
let list_store = get_list_store(&tree_view_zeroed_files_finder);
let vector = zf.get_zeroed_files();
// Sort
let mut vector = vector.clone();
vector.sort_by_key(|e| {
let t = split_path(e.path.as_path());
(t.0, t.1)
});
for file_entry in vector {
let (directory, file) = split_path(&file_entry.path);
let values: [(u32, &dyn ToValue); 6] = [
(0, &false),
(1, &(file_entry.size.file_size(options::BINARY).unwrap())),
(2, &(file_entry.size)),
(3, &file),
(4, &directory),
(5, &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string())),
];
list_store.set(&list_store.append(), &values);
}
print_text_messages_to_text_view(text_messages, &text_view_errors);
}
// Set state
{
*shared_zeroed_files_state.borrow_mut() = zf;
if zeroed_files_number > 0 {
*shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Zeroed).unwrap().get_mut("save").unwrap() = true;
*shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Zeroed).unwrap().get_mut("delete").unwrap() = true;
*shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Zeroed).unwrap().get_mut("select").unwrap() = true;
*shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Zeroed).unwrap().get_mut("move").unwrap() = true;
} else {
*shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Zeroed).unwrap().get_mut("save").unwrap() = false;
*shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Zeroed).unwrap().get_mut("delete").unwrap() = false;
*shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Zeroed).unwrap().get_mut("select").unwrap() = false;
*shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Zeroed).unwrap().get_mut("move").unwrap() = false;
}
set_buttons(&mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Zeroed).unwrap(), &buttons_array, &buttons_names);
}
}
}
Message::SameMusic(mf) => {
if mf.get_stopped_search() {
entry_info.set_text("Searching for same music was stopped by user");

View File

@ -699,6 +699,19 @@ pub fn connect_popovers(gui_data: &GuiData) {
column_size_as_bytes: Some(ColumnsSimilarImages::SizeAsBytes as i32),
column_modification_as_secs: Some(ColumnsSimilarImages::ModificationAsSecs as i32),
},
PopoverObject {
notebook_type: NotebookMainEnum::SimilarVideos,
available_modes: vec!["all", "reverse", "custom", "date"].iter().map(|e| e.to_string()).collect(),
tree_view: gui_data.main_notebook.tree_view_similar_videos_finder.clone(),
column_path: ColumnsSimilarVideos::Path as i32,
column_name: ColumnsSimilarVideos::Name as i32,
column_selection: ColumnsSimilarVideos::ActiveSelectButton as u32,
column_color: Some(ColumnsSimilarVideos::Color as i32),
column_dimensions: None,
column_size: Some(ColumnsSimilarVideos::Size as i32),
column_size_as_bytes: Some(ColumnsSimilarVideos::SizeAsBytes as i32),
column_modification_as_secs: Some(ColumnsSimilarVideos::ModificationAsSecs as i32),
},
PopoverObject {
notebook_type: NotebookMainEnum::EmptyDirectories,
available_modes: vec!["all", "reverse", "custom"].iter().map(|e| e.to_string()).collect(),
@ -751,19 +764,6 @@ pub fn connect_popovers(gui_data: &GuiData) {
column_size_as_bytes: None,
column_modification_as_secs: None,
},
PopoverObject {
notebook_type: NotebookMainEnum::Zeroed,
available_modes: vec!["all", "reverse", "custom"].iter().map(|e| e.to_string()).collect(),
tree_view: gui_data.main_notebook.tree_view_zeroed_files_finder.clone(),
column_path: ColumnsZeroedFiles::Path as i32,
column_name: ColumnsZeroedFiles::Name as i32,
column_selection: ColumnsZeroedFiles::ActiveSelectButton as u32,
column_color: None,
column_dimensions: None,
column_size: None,
column_size_as_bytes: Some(ColumnsZeroedFiles::SizeAsBytes as i32),
column_modification_as_secs: None,
},
PopoverObject {
notebook_type: NotebookMainEnum::BrokenFiles,
available_modes: vec!["all", "reverse", "custom"].iter().map(|e| e.to_string()).collect(),

View File

@ -1,7 +1,7 @@
use crate::gui_data::GuiData;
use crate::taskbar_progress::tbp_flags::TBPF_INDETERMINATE;
use czkawka_core::{big_file, broken_files, duplicate, empty_files, empty_folder, invalid_symlinks, same_music, similar_images, similar_videos, temporary, zeroed};
use czkawka_core::{big_file, broken_files, duplicate, empty_files, empty_folder, invalid_symlinks, same_music, similar_images, similar_videos, temporary};
use futures::StreamExt;
@ -18,7 +18,6 @@ pub fn connect_progress_window(
mut futures_receiver_similar_images: futures::channel::mpsc::UnboundedReceiver<similar_images::ProgressData>,
mut futures_receiver_similar_videos: futures::channel::mpsc::UnboundedReceiver<similar_videos::ProgressData>,
mut futures_receiver_temporary: futures::channel::mpsc::UnboundedReceiver<temporary::ProgressData>,
mut futures_receiver_zeroed: futures::channel::mpsc::UnboundedReceiver<zeroed::ProgressData>,
mut futures_receiver_invalid_symlinks: futures::channel::mpsc::UnboundedReceiver<invalid_symlinks::ProgressData>,
mut futures_receiver_broken_files: futures::channel::mpsc::UnboundedReceiver<broken_files::ProgressData>,
) {
@ -279,41 +278,6 @@ pub fn connect_progress_window(
};
main_context.spawn_local(future);
}
{
// Zeroed Files
let label_stage = gui_data.progress_window.label_stage.clone();
let progress_bar_current_stage = gui_data.progress_window.progress_bar_current_stage.clone();
let progress_bar_all_stages = gui_data.progress_window.progress_bar_all_stages.clone();
let taskbar_state = gui_data.taskbar_state.clone();
let future = async move {
while let Some(item) = futures_receiver_zeroed.next().await {
match item.current_stage {
0 => {
progress_bar_current_stage.hide();
label_stage.set_text(format!("Scanned {} files", item.files_checked).as_str());
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
}
1 => {
progress_bar_current_stage.show();
if item.files_to_check != 0 {
progress_bar_all_stages.set_fraction((1f64 + (item.files_checked) as f64 / item.files_to_check as f64) / (item.max_stage + 1) as f64);
progress_bar_current_stage.set_fraction((item.files_checked) as f64 / item.files_to_check as f64);
taskbar_state.borrow().set_progress_value((item.files_to_check + item.files_checked) as u64, item.files_to_check as u64 * (item.max_stage + 1) as u64);
} else {
progress_bar_all_stages.set_fraction((1f64) / (item.max_stage + 1) as f64);
progress_bar_current_stage.set_fraction(0f64);
taskbar_state.borrow().set_progress_value(1, (item.max_stage + 1) as u64);
}
label_stage.set_text(format!("Checking {}/{} file", item.files_checked, item.files_to_check).as_str());
}
_ => {
panic!();
}
}
}
};
main_context.spawn_local(future);
}
{
// Invalid Symlinks
let label_stage = gui_data.progress_window.label_stage.clone();

View File

@ -439,65 +439,6 @@ pub fn create_tree_view_directories(tree_view: &mut gtk::TreeView) {
tree_view.set_headers_visible(false);
}
pub fn create_tree_view_zeroed_files(tree_view: &mut gtk::TreeView) {
let model = get_list_store(tree_view);
let renderer = gtk::CellRendererToggle::new();
renderer.connect_toggled(move |_r, path| {
let iter = model.iter(&path).unwrap();
let mut fixed = model
.value(&iter, ColumnsZeroedFiles::ActiveSelectButton as i32)
.get::<bool>()
.unwrap_or_else(|err| panic!("ListStore value missing at path {}: {}", path, err));
fixed = !fixed;
model.set_value(&iter, ColumnsZeroedFiles::ActiveSelectButton as u32, &fixed.to_value());
});
let column = gtk::TreeViewColumn::new();
column.pack_start(&renderer, true);
column.set_resizable(false);
column.set_fixed_width(30);
column.add_attribute(&renderer, "active", ColumnsZeroedFiles::ActiveSelectButton as i32);
tree_view.append_column(&column);
let renderer = gtk::CellRendererText::new();
let column: gtk::TreeViewColumn = TreeViewColumn::new();
column.pack_start(&renderer, true);
column.set_title("Size");
column.set_resizable(true);
column.set_min_width(50);
column.add_attribute(&renderer, "text", ColumnsZeroedFiles::Size as i32);
tree_view.append_column(&column);
let renderer = gtk::CellRendererText::new();
let column: gtk::TreeViewColumn = TreeViewColumn::new();
column.pack_start(&renderer, true);
column.set_title("File Name");
column.set_resizable(true);
column.set_min_width(50);
column.add_attribute(&renderer, "text", ColumnsZeroedFiles::Name as i32);
tree_view.append_column(&column);
let renderer = gtk::CellRendererText::new();
let column: gtk::TreeViewColumn = TreeViewColumn::new();
column.pack_start(&renderer, true);
column.set_title("Path");
column.set_resizable(true);
column.set_min_width(50);
column.add_attribute(&renderer, "text", ColumnsZeroedFiles::Path as i32);
tree_view.append_column(&column);
let renderer = gtk::CellRendererText::new();
let column: gtk::TreeViewColumn = TreeViewColumn::new();
column.pack_start(&renderer, true);
column.set_title("Modification Date");
column.set_resizable(true);
column.set_min_width(50);
column.add_attribute(&renderer, "text", ColumnsZeroedFiles::Modification as i32);
tree_view.append_column(&column);
tree_view.set_vexpand(true);
}
pub fn create_tree_view_same_music(tree_view: &mut gtk::TreeView) {
let model = get_list_store(tree_view);

View File

@ -66,18 +66,6 @@ pub fn opening_enter_function_big_files(tree_view: &gtk::TreeView, event: &gdk::
handle_tree_keypress(tree_view, event, ColumnsBigFiles::Name as u32, ColumnsBigFiles::Path as u32, ColumnsBigFiles::ActiveSelectButton as u32)
}
pub fn opening_double_click_function_zeroed_files(tree_view: &gtk::TreeView, event: &gdk::EventButton) -> gtk::Inhibit {
if event.event_type() == gdk::EventType::DoubleButtonPress && event.button() == 1 {
common_open_function(tree_view, ColumnsZeroedFiles::Name as i32, ColumnsZeroedFiles::Path as i32, OpenMode::PathAndName);
} else if event.event_type() == gdk::EventType::DoubleButtonPress && event.button() == 3 {
common_open_function(tree_view, ColumnsZeroedFiles::Name as i32, ColumnsZeroedFiles::Path as i32, OpenMode::OnlyPath);
}
gtk::Inhibit(false)
}
pub fn opening_enter_function_zeroed_files(tree_view: &gtk::TreeView, event: &gdk::EventKey) -> gtk::Inhibit {
handle_tree_keypress(tree_view, event, ColumnsZeroedFiles::Name as u32, ColumnsZeroedFiles::Path as u32, ColumnsZeroedFiles::ActiveSelectButton as u32)
}
pub fn opening_double_click_function_same_music(tree_view: &gtk::TreeView, event: &gdk::EventButton) -> gtk::Inhibit {
if event.event_type() == gdk::EventType::DoubleButtonPress && event.button() == 1 {
common_open_function(tree_view, ColumnsSameMusic::Name as i32, ColumnsSameMusic::Path as i32, OpenMode::PathAndName);

View File

@ -19,7 +19,6 @@ use czkawka_core::same_music::SameMusic;
use czkawka_core::similar_images::SimilarImages;
use czkawka_core::similar_videos::SimilarVideos;
use czkawka_core::temporary::Temporary;
use czkawka_core::zeroed::ZeroedFiles;
use gtk::prelude::*;
use gtk::{Builder, WindowPosition};
use std::cell::RefCell;
@ -61,7 +60,6 @@ pub struct GuiData {
pub shared_big_files_state: Rc<RefCell<BigFile>>,
pub shared_similar_images_state: Rc<RefCell<SimilarImages>>,
pub shared_similar_videos_state: Rc<RefCell<SimilarVideos>>,
pub shared_zeroed_files_state: Rc<RefCell<ZeroedFiles>>,
pub shared_same_music_state: Rc<RefCell<SameMusic>>,
pub shared_same_invalid_symlinks: Rc<RefCell<InvalidSymlinks>>,
pub shared_broken_files_state: Rc<RefCell<BrokenFiles>>,
@ -142,7 +140,6 @@ impl GuiData {
let shared_big_files_state: Rc<RefCell<_>> = Rc::new(RefCell::new(BigFile::new()));
let shared_similar_images_state: Rc<RefCell<_>> = Rc::new(RefCell::new(SimilarImages::new()));
let shared_similar_videos_state: Rc<RefCell<_>> = Rc::new(RefCell::new(SimilarVideos::new()));
let shared_zeroed_files_state: Rc<RefCell<_>> = Rc::new(RefCell::new(ZeroedFiles::new()));
let shared_same_music_state: Rc<RefCell<_>> = Rc::new(RefCell::new(SameMusic::new()));
let shared_same_invalid_symlinks: Rc<RefCell<_>> = Rc::new(RefCell::new(InvalidSymlinks::new()));
let shared_broken_files_state: Rc<RefCell<_>> = Rc::new(RefCell::new(BrokenFiles::new()));
@ -180,7 +177,6 @@ impl GuiData {
shared_big_files_state,
shared_similar_images_state,
shared_similar_videos_state,
shared_zeroed_files_state,
shared_same_music_state,
shared_same_invalid_symlinks,
shared_broken_files_state,

View File

@ -12,7 +12,6 @@ pub struct GuiMainNotebook {
pub scrolled_window_big_files_finder: gtk::ScrolledWindow,
pub scrolled_window_similar_images_finder: gtk::ScrolledWindow,
pub scrolled_window_similar_videos_finder: gtk::ScrolledWindow,
pub scrolled_window_zeroed_files_finder: gtk::ScrolledWindow,
pub scrolled_window_same_music_finder: gtk::ScrolledWindow,
pub scrolled_window_invalid_symlinks: gtk::ScrolledWindow,
pub scrolled_window_broken_files: gtk::ScrolledWindow,
@ -24,7 +23,6 @@ pub struct GuiMainNotebook {
pub tree_view_big_files_finder: gtk::TreeView,
pub tree_view_similar_images_finder: gtk::TreeView,
pub tree_view_similar_videos_finder: gtk::TreeView,
pub tree_view_zeroed_files_finder: gtk::TreeView,
pub tree_view_same_music_finder: gtk::TreeView,
pub tree_view_invalid_symlinks: gtk::TreeView,
pub tree_view_broken_files: gtk::TreeView,
@ -92,7 +90,6 @@ impl GuiMainNotebook {
let scrolled_window_big_files_finder: gtk::ScrolledWindow = builder.object("scrolled_window_big_files_finder").unwrap();
let scrolled_window_similar_images_finder: gtk::ScrolledWindow = builder.object("scrolled_window_similar_images_finder").unwrap();
let scrolled_window_similar_videos_finder: gtk::ScrolledWindow = builder.object("scrolled_window_similar_videos_finder").unwrap();
let scrolled_window_zeroed_files_finder: gtk::ScrolledWindow = builder.object("scrolled_window_zeroed_files_finder").unwrap();
let scrolled_window_same_music_finder: gtk::ScrolledWindow = builder.object("scrolled_window_same_music_finder").unwrap();
let scrolled_window_invalid_symlinks: gtk::ScrolledWindow = builder.object("scrolled_window_invalid_symlinks").unwrap();
let scrolled_window_broken_files: gtk::ScrolledWindow = builder.object("scrolled_window_broken_files").unwrap();
@ -104,7 +101,6 @@ impl GuiMainNotebook {
let tree_view_big_files_finder: gtk::TreeView = TreeView::new();
let tree_view_similar_images_finder: gtk::TreeView = TreeView::new();
let tree_view_similar_videos_finder: gtk::TreeView = TreeView::new();
let tree_view_zeroed_files_finder: gtk::TreeView = TreeView::new();
let tree_view_same_music_finder: gtk::TreeView = TreeView::new();
let tree_view_invalid_symlinks: gtk::TreeView = TreeView::new();
let tree_view_broken_files: gtk::TreeView = TreeView::new();
@ -168,7 +164,6 @@ impl GuiMainNotebook {
scrolled_window_big_files_finder,
scrolled_window_similar_images_finder,
scrolled_window_similar_videos_finder,
scrolled_window_zeroed_files_finder,
scrolled_window_same_music_finder,
scrolled_window_invalid_symlinks,
scrolled_window_broken_files,
@ -179,7 +174,6 @@ impl GuiMainNotebook {
tree_view_big_files_finder,
tree_view_similar_images_finder,
tree_view_similar_videos_finder,
tree_view_zeroed_files_finder,
tree_view_same_music_finder,
tree_view_invalid_symlinks,
tree_view_broken_files,

View File

@ -10,7 +10,6 @@ use czkawka_core::same_music::SameMusic;
use czkawka_core::similar_images::SimilarImages;
use czkawka_core::similar_videos::SimilarVideos;
use czkawka_core::temporary::Temporary;
use czkawka_core::zeroed::ZeroedFiles;
use gtk::prelude::*;
use gtk::{ListStore, TextView};
use std::collections::HashMap;
@ -24,7 +23,6 @@ pub enum Message {
Temporary(Temporary),
SimilarImages(SimilarImages),
SimilarVideos(SimilarVideos),
ZeroedFiles(ZeroedFiles),
SameMusic(SameMusic),
InvalidSymlinks(InvalidSymlinks),
BrokenFiles(BrokenFiles),
@ -100,14 +98,6 @@ pub enum ColumnsSimilarVideos {
Color,
TextColor,
}
pub enum ColumnsZeroedFiles {
ActiveSelectButton = 0,
Size,
SizeAsBytes,
Name,
Path,
Modification,
}
pub enum ColumnsSameMusic {
ActivatableSelectButton = 0,
ActiveSelectButton,

View File

@ -46,7 +46,6 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
let scrolled_window_similar_videos_finder = gui_data.main_notebook.scrolled_window_similar_videos_finder.clone();
let scrolled_window_same_music_finder = gui_data.main_notebook.scrolled_window_same_music_finder.clone();
let scrolled_window_invalid_symlinks = gui_data.main_notebook.scrolled_window_invalid_symlinks.clone();
let scrolled_window_zeroed_files_finder = gui_data.main_notebook.scrolled_window_zeroed_files_finder.clone();
let scrolled_window_broken_files = gui_data.main_notebook.scrolled_window_broken_files.clone();
let image_preview_similar_images = gui_data.main_notebook.image_preview_similar_images.clone();
@ -438,42 +437,6 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
gtk::Inhibit(false)
});
}
// Zeroed Files
{
let col_types: [glib::types::Type; 6] = [
glib::types::Type::BOOL,
glib::types::Type::STRING,
glib::types::Type::U64,
glib::types::Type::STRING,
glib::types::Type::STRING,
glib::types::Type::STRING,
];
let list_store: gtk::ListStore = gtk::ListStore::new(&col_types);
let mut tree_view: gtk::TreeView = TreeView::with_model(&list_store);
tree_view.selection().set_mode(SelectionMode::Multiple);
create_tree_view_zeroed_files(&mut tree_view);
tree_view.connect_button_press_event(opening_double_click_function_zeroed_files);
tree_view.connect_key_press_event(opening_enter_function_zeroed_files);
gui_data.main_notebook.tree_view_zeroed_files_finder = tree_view.clone();
scrolled_window_zeroed_files_finder.add(&tree_view);
scrolled_window_zeroed_files_finder.show_all();
let gui_data = gui_data.clone();
tree_view.connect_key_release_event(move |tree_view, e| {
if let Some(button_number) = e.keycode() {
// Handle delete button
if button_number == 119 {
basic_remove(tree_view, ColumnsZeroedFiles::Name as i32, ColumnsZeroedFiles::Path as i32, ColumnsZeroedFiles::ActiveSelectButton as i32, &gui_data);
}
}
gtk::Inhibit(false)
});
}
// Same Music
{
let col_types: [glib::types::Type; 15] = [

View File

@ -102,7 +102,6 @@ fn main() {
let (futures_sender_similar_videos, futures_receiver_similar_videos): (futures::channel::mpsc::UnboundedSender<similar_videos::ProgressData>, futures::channel::mpsc::UnboundedReceiver<similar_videos::ProgressData>) =
futures::channel::mpsc::unbounded();
let (futures_sender_temporary, futures_receiver_temporary): (futures::channel::mpsc::UnboundedSender<temporary::ProgressData>, futures::channel::mpsc::UnboundedReceiver<temporary::ProgressData>) = futures::channel::mpsc::unbounded();
let (futures_sender_zeroed, futures_receiver_zeroed): (futures::channel::mpsc::UnboundedSender<zeroed::ProgressData>, futures::channel::mpsc::UnboundedReceiver<zeroed::ProgressData>) = futures::channel::mpsc::unbounded();
let (futures_sender_invalid_symlinks, futures_receiver_invalid_symlinks): (futures::channel::mpsc::UnboundedSender<invalid_symlinks::ProgressData>, futures::channel::mpsc::UnboundedReceiver<invalid_symlinks::ProgressData>) =
futures::channel::mpsc::unbounded();
let (futures_sender_broken_files, futures_receiver_broken_files): (futures::channel::mpsc::UnboundedSender<broken_files::ProgressData>, futures::channel::mpsc::UnboundedReceiver<broken_files::ProgressData>) = futures::channel::mpsc::unbounded();
@ -124,7 +123,6 @@ fn main() {
futures_sender_similar_images,
futures_sender_similar_videos,
futures_sender_temporary,
futures_sender_zeroed,
futures_sender_invalid_symlinks,
futures_sender_broken_files,
);
@ -147,7 +145,6 @@ fn main() {
futures_receiver_similar_images,
futures_receiver_similar_videos,
futures_receiver_temporary,
futures_receiver_zeroed,
futures_receiver_invalid_symlinks,
futures_receiver_broken_files,
);

View File

@ -1,4 +1,4 @@
pub const NUMBER_OF_NOTEBOOK_MAIN_TABS: usize = 11;
pub const NUMBER_OF_NOTEBOOK_MAIN_TABS: usize = 10;
pub const NUMBER_OF_NOTEBOOK_UPPER_TABS: usize = 4;
// Needs to be updated when changed order of notebook tabs
@ -12,7 +12,6 @@ pub enum NotebookMainEnum {
SimilarImages,
SimilarVideos,
SameMusic,
Zeroed,
Symlinks,
BrokenFiles,
}
@ -26,9 +25,8 @@ pub fn to_notebook_main_enum(notebook_number: u32) -> NotebookMainEnum {
5 => NotebookMainEnum::SimilarImages,
6 => NotebookMainEnum::SimilarVideos,
7 => NotebookMainEnum::SameMusic,
8 => NotebookMainEnum::Zeroed,
9 => NotebookMainEnum::Symlinks,
10 => NotebookMainEnum::BrokenFiles,
8 => NotebookMainEnum::Symlinks,
9 => NotebookMainEnum::BrokenFiles,
_ => panic!("Invalid Notebook Tab"),
}
}
@ -44,7 +42,6 @@ pub fn get_all_main_tabs() -> [NotebookMainEnum; NUMBER_OF_NOTEBOOK_MAIN_TABS] {
to_notebook_main_enum(7),
to_notebook_main_enum(8),
to_notebook_main_enum(9),
to_notebook_main_enum(10),
]
}

View File

@ -1926,42 +1926,6 @@ Author: Rafał Mikrut
<property name="tab-fill">False</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkScrolledWindow" id="scrolled_window_zeroed_files_finder">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="shadow-type">in</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="position">8</property>
</packing>
</child>
<child type="tab">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Zeroed Files</property>
</object>
<packing>
<property name="position">8</property>
<property name="tab-fill">False</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolled_window_invalid_symlinks">
<property name="visible">True</property>
@ -1972,7 +1936,7 @@ Author: Rafał Mikrut
</child>
</object>
<packing>
<property name="position">9</property>
<property name="position">8</property>
</packing>
</child>
<child type="tab">
@ -1982,7 +1946,7 @@ Author: Rafał Mikrut
<property name="label" translatable="yes">Invalid Symlinks</property>
</object>
<packing>
<property name="position">9</property>
<property name="position">8</property>
<property name="tab-fill">False</property>
</packing>
</child>
@ -1996,7 +1960,7 @@ Author: Rafał Mikrut
</child>
</object>
<packing>
<property name="position">10</property>
<property name="position">9</property>
</packing>
</child>
<child type="tab">
@ -2006,7 +1970,7 @@ Author: Rafał Mikrut
<property name="label" translatable="yes">Broken Files</property>
</object>
<packing>
<property name="position">10</property>
<property name="position">9</property>
<property name="tab-fill">False</property>
</packing>
</child>

View File

@ -169,14 +169,6 @@ Currently files with these extensions are considered temporary files -
This only removes the most basic temporary files, for more I suggest to use BleachBit.
### Zeroed Files
Zeroed files very often are results of e.g. incorrect file downloads.
Their search consists of 3 steps:
- Collecting a list of all files with a size greater than 0
- At start, 64 bytes of each file are checked to discard the vast majority of non-zero files without major performance losses.
- The next step is to check the rest of the file with bigger parts(32KB)
### Invalid Symlinks
To find invalid symlinks we must first find symlnks.