Repository: qarmin/czkawka (language: rust)

Issue:
Version 5.0.0 crash on startup, GTK4 is missing?
I use Ubuntu 20.04.4.

I downloaded the `5.0.0` release but a dependency is missing:

```bash
cd /tmp/
curl --location https://github.com/qarmin/czkawka/releases/download/5.0.0/linux_czkawka_gui -o /tmp/linux_czkawka_gui
chmod +x ./linux_czkawka_gui
./linux_czkawka_gui
[…]
linux_czkawka_gui: error while loading shared libraries: libgtk-4.so.1: cannot open shared object file: No such file or directory
```

I tried to install the [dependencies](https://github.com/qarmin/czkawka/blob/master/instructions/Installation.md#ubuntudebianlinux-mint) but it didn't work:

```bash
sudo apt install libgtk-4-dev ffmpeg
Reading package lists... Done
Building dependency tree       
Reading state information... Done
E: Unable to locate package libgtk-4-dev
```

It looks like `libgtk-4-dev` only exists on Ubuntu 21.10+: https://packages.ubuntu.com/search?keywords=libgtk-4-dev

So people which use Ubuntu 21.10+ can use czkawka `5.0.0`, the others have to use `4.1.0`.


Discussion / hints:
Yes, this is expected,
As workaround to use 5.0.0 version, flatpak build is required which allows to install app on older OS(not released yet)

Thanks for your answer, we should add a note about the versions here: https://github.com/qarmin/czkawka/blob/master/instructions/Installation.md#precompiled-binaries

Fix patch:
diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml
index a4632cb5f..3eff5c503 100644
--- a/.github/workflows/mac.yml
+++ b/.github/workflows/mac.yml
@@ -44,7 +44,6 @@ jobs:
         run: cargo build --release --features heif
         env:
           CARGO_INCREMENTAL: 0
-          RUSTFLAGS: "-C debuginfo=0 -D warnings"
         if: ${{ matrix.type == 'release'}}
 
       - name: Store MacOS CLI
diff --git a/Changelog.md b/Changelog.md
index 3b54cfe85..1325d8bcd 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,3 +1,10 @@
+## Version 5.0.1 - .08.2022r
+- Fixed problem with removing ending slash with empty disk window path
+- Added to CLI bad extensions mode
+- Fixed default sorting method in CLI where finding biggest files 
+- Added tests to CI
+- Show error message when all directories are set as reference folders
+
 ## Version 5.0.0 - 28.07.2022r
 - GUI ported to use GTK 4 - [#466](https://github.com/qarmin/czkawka/pull/466)
 - Use multithreading and improved algorithm to compare image hashes - [#762](https://github.com/qarmin/czkawka/pull/762)
diff --git a/README.md b/README.md
index 3fa6456af..cf8ecb92a 100644
--- a/README.md
+++ b/README.md
@@ -27,6 +27,13 @@
 
 ![Czkawka](https://user-images.githubusercontent.com/41945903/145280350-506f7e94-4db0-4de7-a68d-6e7c26bbd2bf.gif)
 
+## Supported OS
+Linux - Ubuntu 22.04+, Fedora 36+, Alpine Linux 3.16+, Debian 12+ and a lot of more   
+Windows - 7, 8.1, 10, 11  
+MacOS - 10.15+
+
+If you are looking for older version that use GTK 3 and have support for more OS(like e.g. Ubuntu 20.04), look at [4.1.0](https://github.com/qarmin/czkawka/releases/tag/4.1.0) or older versions.
+
 ## How do I use it?
 You can find the instructions on how to use Czkawka [**here**](instructions/Instruction.md).
 
@@ -140,6 +147,7 @@ You can help by creating:
   If the change is bigger, then it's a good idea to open a new issue to discuss changes, but issues with label `PR welcome` are already checked and accepted.
 - Documentation - There is an [instruction](instructions/Instruction.md) which you can improve.
 - Translations - Instruction how to translate files is available [here](instructions/Translations.md)
+- External contributions - App use big number of external libraries like [lofty](https://github.com/Serial-ATA/lofty-rs), [image-rs](https://github.com/image-rs/image) or [symphonia](https://github.com/pdeljanov/Symphonia) so improving this libraries will automatically improve Czkawka
 
 You can also help by doing other things:
 - Creating text articles - [LinuxUprising](https://www.linuxuprising.com/2021/03/find-and-remove-duplicate-files-similar.html) or [Ubunlog](https://ubunlog.com/en/czkawka-finds-and-removes-empty-and-broken-duplicate-files/)
diff --git a/czkawka_cli/src/commands.rs b/czkawka_cli/src/commands.rs
index 7cebd0056..16791a67f 100644
--- a/czkawka_cli/src/commands.rs
+++ b/czkawka_cli/src/commands.rs
@@ -36,6 +36,8 @@ pub enum Commands {
         file_to_save: FileToSave,
         #[clap(flatten)]
         not_recursive: NotRecursive,
+        #[clap(flatten)]
+        case_sensitive_name_comparison: CaseSensitiveNameComparison,
         #[cfg(target_family = "unix")]
         #[clap(flatten)]
         exclude_other_filesystems: ExcludeOtherFilesystems,
@@ -60,7 +62,7 @@ pub enum Commands {
         #[clap(flatten)]
         exclude_other_filesystems: ExcludeOtherFilesystems,
     },
-    #[clap(name = "big", about = "Finds big files", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n    czkawka big -d /home/rafal/ /home/piszczal -e /home/rafal/Roman -n 25 -x VIDEO -f results.txt")]
+    #[clap(name = "big", about = "Finds big files", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n    czkawka big -d /home/rafal/ /home/piszczal -e /home/rafal/Roman -n 25 -J -x VIDEO -f results.txt")]
     BiggestFiles {
         #[clap(flatten)]
         directories: Directories,
@@ -78,6 +80,8 @@ pub enum Commands {
         file_to_save: FileToSave,
         #[clap(flatten)]
         not_recursive: NotRecursive,
+        #[clap(short = 'J', long, help = "Finds the smallest files instead the biggest")]
+        smallest_mode: bool,
         #[cfg(target_family = "unix")]
         #[clap(flatten)]
         exclude_other_filesystems: ExcludeOtherFilesystems,
@@ -130,7 +134,7 @@ pub enum Commands {
         minimal_file_size: u64,
         #[clap(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,
-        #[clap(short, long, default_value = "High", parse(try_from_str = parse_similar_images_similarity), help = "Similairty level (Minimal, VerySmall, Small, Medium, High, VeryHigh)", long_help = "Methods to choose similarity level of images which will be considered as duplicated.")]
+        #[clap(short, long, default_value = "High", parse(try_from_str = parse_similar_images_similarity), help = "Similairty level (Minimal, VerySmall, Small, Medium, High, VeryHigh, Original)", long_help = "Methods to choose similarity level of images which will be considered as duplicated.")]
         similarity_preset: SimilarityPreset,
         #[clap(flatten)]
         excluded_items: ExcludedItems,
@@ -143,7 +147,7 @@ pub enum Commands {
         exclude_other_filesystems: ExcludeOtherFilesystems,
         #[clap(short = 'g', long, default_value = "Gradient", parse(try_from_str = parse_similar_hash_algorithm), help = "Hash algorithm (allowed: Mean, Gradient, Blockhash, VertGradient, DoubleGradient)")]
         hash_alg: HashAlg,
-        #[clap(short = 'z', long, default_value = "Lanczos3", parse(try_from_str = parse_similar_image_filter), help = "Hash algorithm (allowed: Lanczos3, Nearest, Triangle, Faussian, Catmullrom)")]
+        #[clap(short = 'z', long, default_value = "Nearest", parse(try_from_str = parse_similar_image_filter), help = "Hash algorithm (allowed: Lanczos3, Nearest, Triangle, Faussian, Catmullrom)")]
         image_filter: FilterType,
         #[clap(short = 'c', long, default_value = "16", parse(try_from_str = parse_image_hash_size), help = "Hash size (allowed: 8, 16, 32, 64)")]
         hash_size: u8,
@@ -238,11 +242,26 @@ pub enum Commands {
         #[clap(short = 't', long, parse(try_from_str = parse_tolerance), default_value = "10", help = "Video maximium difference (allowed values <0,20>)", long_help = "Maximum difference between video frames, bigger value means that videos can looks more and more different (allowed values <0,20>)")]
         tolerance: i32,
     },
-    #[clap(name = "tester", about = "Contains various test", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n    czkawka tests -i")]
-    Tester {
-        #[clap(short = 'i', long = "test_image", help = "Test speed of hashing provided test.jpg image with different filters and methods.")]
-        test_image: bool,
+    #[clap(name = "ext", about = "Finds files with invalid extensions", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n    czkawka broken -d /home/czokolada/ -f results.txt")]
+    BadExtensions {
+        #[clap(flatten)]
+        directories: Directories,
+        #[clap(flatten)]
+        excluded_directories: ExcludedDirectories,
+        #[clap(flatten)]
+        excluded_items: ExcludedItems,
+        #[clap(flatten)]
+        allowed_extensions: AllowedExtensions,
+        #[clap(flatten)]
+        file_to_save: FileToSave,
+        #[clap(flatten)]
+        not_recursive: NotRecursive,
+        #[cfg(target_family = "unix")]
+        #[clap(flatten)]
+        exclude_other_filesystems: ExcludeOtherFilesystems,
     },
+    #[clap(name = "tester", about = "Small utility to test supported speed of ", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n    czkawka tester")]
+    Tester {},
 }
 
 #[derive(Debug, clap::StructOpt)]
@@ -317,6 +336,12 @@ pub struct AllowHardLinks {
     pub allow_hard_links: bool,
 }
 
+#[derive(Debug, clap::StructOpt)]
+pub struct CaseSensitiveNameComparison {
+    #[clap(short = 'l', long, help = "Use case sensitive name comparison")]
+    pub case_sensitive_name_comparison: bool,
+}
+
 #[derive(Debug, clap::StructOpt)]
 pub struct DryRun {
     #[clap(long, help = "Do nothing and print the operation that would happen.")]
diff --git a/czkawka_cli/src/main.rs b/czkawka_cli/src/main.rs
index 08c3f09bc..2101bdd31 100644
--- a/czkawka_cli/src/main.rs
+++ b/czkawka_cli/src/main.rs
@@ -5,17 +5,18 @@ use std::process;
 use clap::Parser;
 
 use commands::Commands;
+use czkawka_core::big_file::SearchMode;
 #[allow(unused_imports)] // It is used in release for print_results().
 use czkawka_core::common_traits::*;
 use czkawka_core::similar_images::test_image_conversion_speed;
 use czkawka_core::{
+    bad_extensions::BadExtensions,
     big_file::{self, BigFile},
     broken_files::{self, BrokenFiles},
     duplicate::DuplicateFinder,
     empty_files::{self, EmptyFiles},
     empty_folder::EmptyFolder,
-    invalid_symlinks,
-    invalid_symlinks::InvalidSymlinks,
+    invalid_symlinks::{self, InvalidSymlinks},
     same_music::SameMusic,
     similar_images::{return_similarity_from_similarity_preset, SimilarImages},
     similar_videos::SimilarVideos,
@@ -49,6 +50,7 @@ fn main() {
             exclude_other_filesystems,
             allow_hard_links,
             dryrun,
+            case_sensitive_name_comparison,
         } => {
             let mut df = DuplicateFinder::new();
 
@@ -67,6 +69,7 @@ fn main() {
             df.set_exclude_other_filesystems(exclude_other_filesystems.exclude_other_filesystems);
             df.set_ignore_hard_links(!allow_hard_links.allow_hard_links);
             df.set_dryrun(dryrun.dryrun);
+            df.set_case_sensitive_name_comparison(case_sensitive_name_comparison.case_sensitive_name_comparison);
 
             df.find_duplicates(None, None);
 
@@ -123,6 +126,7 @@ fn main() {
             #[cfg(target_family = "unix")]
             exclude_other_filesystems,
             delete_files,
+            smallest_mode,
         } => {
             let mut bf = BigFile::new();
 
@@ -137,6 +141,9 @@ fn main() {
             if delete_files {
                 bf.set_delete_method(big_file::DeleteMethod::Delete);
             }
+            if smallest_mode {
+                bf.set_search_mode(SearchMode::SmallestFiles);
+            }
 
             bf.find_big_files(None, None);
 
@@ -425,12 +432,41 @@ fn main() {
             vr.print_results();
             vr.get_text_messages().print_messages();
         }
-        Commands::Tester { test_image } => {
-            if test_image {
-                test_image_conversion_speed();
-            } else {
-                println!("At least one test should be choosen!");
+        Commands::BadExtensions {
+            directories,
+            excluded_directories,
+            excluded_items,
+            file_to_save,
+            not_recursive,
+            #[cfg(target_family = "unix")]
+            exclude_other_filesystems,
+            allowed_extensions,
+        } => {
+            let mut be = BadExtensions::new();
+
+            be.set_included_directory(directories.directories);
+            be.set_excluded_directory(excluded_directories.excluded_directories);
+            be.set_excluded_items(excluded_items.excluded_items);
+            be.set_allowed_extensions(allowed_extensions.allowed_extensions.join(","));
+            be.set_recursive_search(!not_recursive.not_recursive);
+            #[cfg(target_family = "unix")]
+            be.set_exclude_other_filesystems(exclude_other_filesystems.exclude_other_filesystems);
+
+            if let Some(file_name) = file_to_save.file_name() {
+                if !be.save_results_to_file(file_name) {
+                    be.get_text_messages().print_messages();
+                    process::exit(1);
+                }
             }
+
+            be.find_bad_extensions_files(None, None);
+
+            #[cfg(not(debug_assertions))] // This will show too much probably unnecessary data to debug, comment line only if needed
+            be.print_results();
+            be.get_text_messages().print_messages();
+        }
+        Commands::Tester {} => {
+            test_image_conversion_speed();
         }
     }
 }
diff --git a/czkawka_core/src/bad_extensions.rs b/czkawka_core/src/bad_extensions.rs
index 184f4d2df..973de9a99 100644
--- a/czkawka_core/src/bad_extensions.rs
+++ b/czkawka_core/src/bad_extensions.rs
@@ -469,7 +469,7 @@ impl BadExtensions {
 
         self.information.number_of_files_with_bad_extension = self.bad_extensions_files.len();
 
-        Common::print_time(system_time, SystemTime::now(), "sort_images - reading data from files in parallel".to_string());
+        Common::print_time(system_time, SystemTime::now(), "bad extension finding".to_string());
 
         // Clean unused data
         self.files_to_check = Default::default();
@@ -539,7 +539,7 @@ impl SaveResults for BadExtensions {
         if !self.bad_extensions_files.is_empty() {
             writeln!(writer, "Found {} files with invalid extension.", self.information.number_of_files_with_bad_extension).unwrap();
             for file_entry in self.bad_extensions_files.iter() {
-                writeln!(writer, "{}", file_entry.path.display()).unwrap();
+                writeln!(writer, "{} ----- {}", file_entry.path.display(), file_entry.proper_extensions).unwrap();
             }
         } else {
             write!(writer, "Not found any files with invalid extension.").unwrap();
@@ -556,7 +556,7 @@ impl PrintResults for BadExtensions {
         let start_time: SystemTime = SystemTime::now();
         println!("Found {} files with invalid extension.\n", self.information.number_of_files_with_bad_extension);
         for file_entry in self.bad_extensions_files.iter() {
-            println!("{}", file_entry.path.display());
+            println!("{} ----- {}", file_entry.path.display(), file_entry.proper_extensions);
         }
 
         Common::print_time(start_time, SystemTime::now(), "print_entries".to_string());
diff --git a/czkawka_core/src/big_file.rs b/czkawka_core/src/big_file.rs
index c72ebc14f..26b24a61b 100644
--- a/czkawka_core/src/big_file.rs
+++ b/czkawka_core/src/big_file.rs
@@ -464,9 +464,12 @@ impl SaveResults for BigFile {
         }
 
         if self.information.number_of_real_files != 0 {
-            write!(writer, "{} the biggest files.\n\n", self.information.number_of_real_files).unwrap();
-
-            for (size, file_entry) in self.big_files.iter().rev() {
+            if self.search_mode == SearchMode::BiggestFiles {
+                write!(writer, "{} the biggest files.\n\n", self.information.number_of_real_files).unwrap();
+            } else {
+                write!(writer, "{} the smallest files.\n\n", self.information.number_of_real_files).unwrap();
+            }
+            for (size, file_entry) in self.big_files.iter() {
                 writeln!(writer, "{} ({}) - {}", size.file_size(options::BINARY).unwrap(), size, file_entry.path.display()).unwrap();
             }
         } else {
@@ -480,9 +483,13 @@ impl SaveResults for BigFile {
 impl PrintResults for BigFile {
     fn print_results(&self) {
         let start_time: SystemTime = SystemTime::now();
-        for (size, file_entry) in self.big_files.iter().rev() {
-            // TODO Align all to same width
-            println!("{} ({} bytes) - {}", size.file_size(options::BINARY).unwrap(), size, file_entry.path.display());
+        if self.search_mode == SearchMode::BiggestFiles {
+            println!("{} the biggest files.\n\n", self.information.number_of_real_files);
+        } else {
+            println!("{} the smallest files.\n\n", self.information.number_of_real_files);
+        }
+        for (size, file_entry) in self.big_files.iter() {
+            println!("{} ({}) - {}", size.file_size(options::BINARY).unwrap(), size, file_entry.path.display());
         }
         Common::print_time(start_time, SystemTime::now(), "print_entries".to_string());
     }
diff --git a/czkawka_core/src/similar_images.rs b/czkawka_core/src/similar_images.rs
index c9d59c9cd..60a21893e 100644
--- a/czkawka_core/src/similar_images.rs
+++ b/czkawka_core/src/similar_images.rs
@@ -32,7 +32,7 @@ use crate::flc;
 use crate::localizer_core::generate_translation_hashmap;
 
 pub const SIMILAR_VALUES: [[u32; 6]; 4] = [
-    [0, 2, 5, 7, 14, 20],    // 8
+    [1, 2, 5, 7, 14, 20],    // 8
     [2, 5, 15, 30, 40, 40],  // 16
     [4, 10, 20, 40, 40, 40], // 32
     [6, 20, 40, 40, 40, 40], // 64
@@ -59,6 +59,7 @@ pub struct FileEntry {
 /// Used by CLI tool when we cannot use directly values
 #[derive(Clone, Debug)]
 pub enum SimilarityPreset {
+    Original,
     VeryHigh,
     High,
     Medium,
@@ -1283,6 +1284,7 @@ pub fn return_similarity_from_similarity_preset(similarity_preset: &SimilarityPr
         _ => panic!(),
     };
     match similarity_preset {
+        SimilarityPreset::Original => 0,
         SimilarityPreset::VeryHigh => SIMILAR_VALUES[index_preset][0],
         SimilarityPreset::High => SIMILAR_VALUES[index_preset][1],
         SimilarityPreset::Medium => SIMILAR_VALUES[index_preset][2],
diff --git a/czkawka_gui/i18n/en/czkawka_gui.ftl b/czkawka_gui/i18n/en/czkawka_gui.ftl
index 5b89c8746..7879711c4 100644
--- a/czkawka_gui/i18n/en/czkawka_gui.ftl
+++ b/czkawka_gui/i18n/en/czkawka_gui.ftl
@@ -463,6 +463,7 @@ invalid_symlink_infinite_recursion = Infinite recursion
 invalid_symlink_non_existent_destination = Non-existent destination file
 
 # Other
+selected_all_reference_folders = Cannot start search, when all directories are set as reference folders
 searching_for_data = Searching data, it may take a while, please wait...
 text_view_messages = MESSAGES
 text_view_warnings = WARNINGS
diff --git a/czkawka_gui/src/connect_things/connect_button_search.rs b/czkawka_gui/src/connect_things/connect_button_search.rs
index fc874106c..c7a46c0a4 100644
--- a/czkawka_gui/src/connect_things/connect_button_search.rs
+++ b/czkawka_gui/src/connect_things/connect_button_search.rs
@@ -117,6 +117,13 @@ pub fn connect_button_search(
     let check_button_settings_save_also_json = gui_data.settings.check_button_settings_save_also_json.clone();
 
     buttons_search_clone.connect_clicked(move |_| {
+        // Check if user selected all referenced folders
+        let list_store_included_directories = get_list_store(&tree_view_included_directories);
+        if check_if_list_store_column_have_all_same_values(&list_store_included_directories, ColumnsIncludedDirectory::ReferenceButton as i32, true) {
+            entry_info.set_text(&flg!("selected_all_reference_folders"));
+            return;
+        }
+
         let included_directories = get_path_buf_from_vector_of_strings(get_string_from_list_store(&tree_view_included_directories, ColumnsIncludedDirectory::Path as i32, None));
         let excluded_directories = get_path_buf_from_vector_of_strings(get_string_from_list_store(&tree_view_excluded_directories, ColumnsExcludedDirectory::Path as i32, None));
         let reference_directories = get_path_buf_from_vector_of_strings(get_string_from_list_store(
diff --git a/czkawka_gui/src/connect_things/connect_selection_of_directories.rs b/czkawka_gui/src/connect_things/connect_selection_of_directories.rs
index 3829982eb..1ad1782e8 100644
--- a/czkawka_gui/src/connect_things/connect_selection_of_directories.rs
+++ b/czkawka_gui/src/connect_things/connect_selection_of_directories.rs
@@ -184,6 +184,7 @@ fn add_manually_directories(window_main: &Window, tree_view: &TreeView, excluded
         dialog.close();
     });
 }
+
 fn remove_ending_slashes(original_string: &mut String) {
     let mut windows_disk_path: bool = false;
     let mut chars = original_string.chars();
@@ -202,6 +203,7 @@ fn remove_ending_slashes(original_string: &mut String) {
         original_string.pop();
     }
 }
+
 #[test]
 pub fn test_remove_ending_slashes() {
     let mut original = "/home/rafal".to_string();
@@ -248,6 +250,14 @@ pub fn test_remove_ending_slashes() {
     remove_ending_slashes(&mut original);
     assert_eq!(&original, "C:/");
 
+    let mut original = "C:/roman/function/".to_string();
+    remove_ending_slashes(&mut original);
+    assert_eq!(&original, "C:/roman/function");
+
+    let mut original = "C:/staszek/without".to_string();
+    remove_ending_slashes(&mut original);
+    assert_eq!(&original, "C:/staszek/without");
+
     let mut original = "C:\\\\\\\\\\".to_string();
     remove_ending_slashes(&mut original);
     assert_eq!(&original, "C:\\");
diff --git a/czkawka_gui/src/help_functions.rs b/czkawka_gui/src/help_functions.rs
index ccfb2b12c..bdcef1475 100644
--- a/czkawka_gui/src/help_functions.rs
+++ b/czkawka_gui/src/help_functions.rs
@@ -743,6 +743,24 @@ pub fn check_if_value_is_in_list_store(list_store: &ListStore, column: i32, valu
     false
 }
 
+pub fn check_if_list_store_column_have_all_same_values(list_store: &ListStore, column: i32, value: bool) -> bool {
+    if let Some(iter) = list_store.iter_first() {
+        loop {
+            let list_store_value: bool = list_store.get::<bool>(&iter, column as i32);
+
+            if value != list_store_value {
+                return false;
+            }
+
+            if !list_store.iter_next(&iter) {
+                break;
+            }
+        }
+        return true;
+    }
+    false
+}
+
 #[cfg(test)]
 mod test {
     use gtk4::prelude::*;
@@ -750,9 +768,44 @@ mod test {
     use image::DynamicImage;
 
     use crate::help_functions::{
-        change_dimension_to_krotka, check_if_value_is_in_list_store, get_all_boxes_from_widget, get_all_direct_children, get_max_file_name, get_pixbuf_from_dynamic_image,
+        change_dimension_to_krotka, check_if_list_store_column_have_all_same_values, check_if_value_is_in_list_store, get_all_boxes_from_widget, get_all_direct_children,
+        get_max_file_name, get_pixbuf_from_dynamic_image,
     };
 
+    #[gtk4::test]
+    fn test_check_if_list_store_column_have_all_same_values() {
+        let columns_types: &[glib::types::Type] = &[glib::types::Type::BOOL];
+        let list_store = gtk4::ListStore::new(columns_types);
+
+        list_store.clear();
+        let values_to_add: &[(u32, &dyn ToValue)] = &[(0, &true), (0, &true), (0, &false)];
+        for i in values_to_add {
+            list_store.set(&list_store.append(), &[*i]);
+        }
+        assert!(!check_if_list_store_column_have_all_same_values(&list_store, 0, true));
+        assert!(!check_if_list_store_column_have_all_same_values(&list_store, 0, false));
+
+        list_store.clear();
+        let values_to_add: &[(u32, &dyn ToValue)] = &[(0, &true), (0, &true), (0, &true)];
+        for i in values_to_add {
+            list_store.set(&list_store.append(), &[*i]);
+        }
+        assert!(check_if_list_store_column_have_all_same_values(&list_store, 0, true));
+        assert!(!check_if_list_store_column_have_all_same_values(&list_store, 0, false));
+
+        list_store.clear();
+        let values_to_add: &[(u32, &dyn ToValue)] = &[(0, &false)];
+        for i in values_to_add {
+            list_store.set(&list_store.append(), &[*i]);
+        }
+        assert!(!check_if_list_store_column_have_all_same_values(&list_store, 0, true));
+        assert!(check_if_list_store_column_have_all_same_values(&list_store, 0, false));
+
+        list_store.clear();
+        assert!(!check_if_list_store_column_have_all_same_values(&list_store, 0, true));
+        assert!(!check_if_list_store_column_have_all_same_values(&list_store, 0, false));
+    }
+
     #[gtk4::test]
     fn test_check_if_value_is_in_list_store() {
         let columns_types: &[glib::types::Type] = &[glib::types::Type::STRING];
@@ -808,6 +861,7 @@ mod test {
         get_pixbuf_from_dynamic_image(&dynamic_image).unwrap();
         get_pixbuf_from_dynamic_image(&dynamic_image).unwrap();
     }
+
     #[test]
     fn test_change_dimension_to_krotka() {
         assert_eq!(change_dimension_to_krotka("50x50".to_string()), (50, 50));
diff --git a/czkawka_gui/ui/settings.ui b/czkawka_gui/ui/settings.ui
index 60987dd5c..cbce0c907 100644
--- a/czkawka_gui/ui/settings.ui
+++ b/czkawka_gui/ui/settings.ui
@@ -153,7 +153,7 @@
                       <object class="GtkCheckButton" id="check_button_settings_hide_hard_links">
                         <property name="active">1</property>
                         <property name="focusable">1</property>
-                        <property name="label" translatable="yes">Hide hard links(only Linux and MacOS)</property>
+                        <property name="label" translatable="yes">Hide hard links(only Linux and macOS)</property>
                       </object>
                     </child>
                     <child>
diff --git a/data/com.github.qarmin.czkawka.metainfo.xml b/data/com.github.qarmin.czkawka.metainfo.xml
index 005bf9849..e11364f7f 100644
--- a/data/com.github.qarmin.czkawka.metainfo.xml
+++ b/data/com.github.qarmin.czkawka.metainfo.xml
@@ -19,7 +19,7 @@
     </screenshot>
   </screenshots>
   <releases>
-    <release version="5.0.0" date="2021-07-28"/>
+    <release version="5.0.0" date="2022-07-28"/>
   </releases>
   <content_rating type="oars-1.0"/>
   <developer_name>Rafał Mikrut</developer_name>
diff --git a/instructions/Compilation.md b/instructions/Compilation.md
index 62244dc3a..22b6cb1f2 100644
--- a/instructions/Compilation.md
+++ b/instructions/Compilation.md
@@ -11,8 +11,8 @@ Support for heif images is optional and require to install libheif library.
 
 | Program | Min  | What for                                                                      |
 |---------|------|-------------------------------------------------------------------------------|
-| Rust    | 1.60 | Czkawka, aims to support the latest available version of Rust on Ubuntu 20.04 |
-| GTK     | 3.24 | Only for the `GTK` backend                                                    |
+| Rust    | 1.60 | Czkawka, aims to support the latest available version of Rust on Ubuntu 22.04 |
+| GTK     | 4.6  | Only for the `GTK` backend                                                    |
 
 #### Debian / Ubuntu
 ```shell
@@ -24,11 +24,11 @@ sudo apt install -y libgtk-4-dev
 #### Fedora / CentOS / Rocky Linux
 ```shell
 curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # Download the latest stable Rust
-sudo yum install gtk3-devel glib2-devel
+sudo yum install gtk4-devel glib2-devel
 ```
 
 #### macOS
-You need to install Rust via Homebrew, GTK Libraries and optionally heif library(to have support for heic files, which are quite popular on mac)
+You need to install Rust via Homebrew, GTK Libraries and optionally heif library(to have support for heic files, which are quite popular on Mac)
 ```shell
 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
 brew install rustup
@@ -88,10 +88,9 @@ target/release/czkawka_gui
 ```
 
 ## Additional features
-For now, finding broken audio files is temporarily disabled by default, because app crashes when audio libraries are not found on the computer.  
-I'm waiting for ability to disable audio playback feature, so after that I will be able to re-enable by default this feature (https://github.com/RustAudio/rodio/issues/349)
+Currently, the only additional dependence is heif image support.
 
-To enable checking for broken audio files, just add ` --all-features`
+To enable checking for heif images, just add ` --all-features` or `--features heif`
 ```
-cargo run --all-features --bin czkawka_cli -- broken  -d /home/rafal/ -f "results.txt"
+cargo run --features heif --bin czkawka_cli -- image  -d /home/rafal/ -f "results.txt"
 ```
diff --git a/instructions/Installation.md b/instructions/Installation.md
index 05416b131..013e49e76 100644
--- a/instructions/Installation.md
+++ b/instructions/Installation.md
@@ -7,13 +7,16 @@ For Czkawka GUI the lowest supported version of GTK is `3.24` which is the only
 In app exists Similar Video tool which require `FFmpeg` to work, but is completelly optional and without it, only warning would be printed when trying to use this tool without installed ffmpeg.  
 Broken files finder by default don't check for music files, but it is possible to enable this feature and that require to have alsa lib installed(on Ubuntu this is `libasound2-dev` package)
 
+**Warning**
+Main Czkawka GUI dependency - GTK 4 is only available on newer systems like e.g. Ubuntu 22.04, so if you have problems with running app on older systems, you may like to use older Czkawka versions, upgrade OS or install flatpak package which use its own set of dependencies.
+
 #### Ubuntu/Debian/Linux Mint
 ```
 sudo apt install libgtk-4-dev ffmpeg
 ```
 #### Fedora/Rocky Linux
 ```
-sudo yum install gtk3-devel glib2-devel
+sudo yum install gtk4-devel glib2-devel
 sudo dnf -y install https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm
 sudo dnf -y install https://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm
 sudo dnf -y install ffmpeg
@@ -43,7 +46,7 @@ At the end execute it:
 **Warning**  
 Prebuilt binaries are available only for x86_64, so if you use ARM machine like e.g. Mac M1, you need to compile manually app.  
 
-There is also a way to use x86_64 binaries on ARM, but this require to install special version of required libraries probably via:
+There is also a way to use x86_64 binaries on ARM, but this requires to install special version of required libraries probably via:
 ```shell
 arch -x86_64 /usr/local/bin/brew install gtk4 adwaita-icon-theme ffmpeg librsvg libheif
 ```


Test patch: