From 82cfdde155df5d9921ca64a0dd17a907c662808e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mikrut?= <41945903+qarmin@users.noreply.github.com> Date: Thu, 26 Sep 2024 11:13:24 +0200 Subject: [PATCH] Add new mode, replace unwraps, change sending progress data (#1354) --- .github/workflows/linux_cli.yml | 2 +- .github/workflows/linux_cli_eyra.yml | 2 +- .github/workflows/linux_gui.yml | 6 +- .github/workflows/mac.yml | 49 +- Cargo.lock | 3204 ++++++++++------- Changelog.md | 295 +- ci_tester/src/main.rs | 19 +- czkawka_cli/Cargo.toml | 6 +- czkawka_cli/README.md | 28 +- czkawka_cli/src/commands.rs | 58 +- czkawka_cli/src/main.rs | 133 +- czkawka_cli/src/progress.rs | 66 +- czkawka_core/Cargo.toml | 28 +- czkawka_core/src/bad_extensions.rs | 44 +- czkawka_core/src/big_file.rs | 59 +- czkawka_core/src/broken_files.rs | 55 +- czkawka_core/src/common.rs | 80 +- czkawka_core/src/common_cache.rs | 4 +- czkawka_core/src/common_dir_traversal.rs | 32 +- czkawka_core/src/common_extensions.rs | 1 + czkawka_core/src/common_tool.rs | 12 +- czkawka_core/src/common_traits.rs | 5 +- czkawka_core/src/duplicate.rs | 261 +- czkawka_core/src/empty_files.rs | 3 +- czkawka_core/src/empty_folder.rs | 16 +- czkawka_core/src/invalid_symlinks.rs | 7 +- czkawka_core/src/lib.rs | 2 + czkawka_core/src/progress_data.rs | 232 ++ czkawka_core/src/same_music.rs | 353 +- czkawka_core/src/similar_images.rs | 395 +- czkawka_core/src/similar_videos.rs | 78 +- czkawka_core/src/temporary.rs | 5 +- czkawka_gui/Cargo.toml | 28 +- czkawka_gui/README.md | 2 +- czkawka_gui/src/compute_results.rs | 161 +- .../connect_things/connect_button_compare.rs | 114 +- .../connect_things/connect_button_delete.rs | 18 +- .../connect_things/connect_button_hardlink.rs | 21 +- .../src/connect_things/connect_button_move.rs | 6 +- .../src/connect_things/connect_button_save.rs | 37 +- .../connect_things/connect_button_search.rs | 158 +- .../connect_things/connect_button_select.rs | 6 +- .../src/connect_things/connect_button_sort.rs | 6 +- .../src/connect_things/connect_button_stop.rs | 2 +- .../connect_things/connect_change_language.rs | 4 +- .../connect_things/connect_notebook_tabs.rs | 2 +- .../connect_things/connect_popovers_select.rs | 43 +- .../connect_things/connect_popovers_sort.rs | 44 +- .../connect_things/connect_progress_window.rs | 162 +- .../connect_same_music_mode_changed.rs | 13 +- .../connect_selection_of_directories.rs | 10 +- .../src/connect_things/connect_settings.rs | 9 +- .../connect_similar_image_size_change.rs | 2 +- czkawka_gui/src/create_tree_view.rs | 2 +- czkawka_gui/src/gui_structs/gui_about.rs | 2 +- .../src/gui_structs/gui_bottom_buttons.rs | 30 +- .../src/gui_structs/gui_compare_images.rs | 18 +- czkawka_gui/src/gui_structs/gui_data.rs | 62 +- czkawka_gui/src/gui_structs/gui_header.rs | 4 +- .../src/gui_structs/gui_main_notebook.rs | 214 +- .../src/gui_structs/gui_popovers_select.rs | 41 +- .../src/gui_structs/gui_popovers_sort.rs | 12 +- .../src/gui_structs/gui_progress_dialog.rs | 16 +- czkawka_gui/src/gui_structs/gui_settings.rs | 79 +- .../src/gui_structs/gui_upper_notebook.rs | 46 +- czkawka_gui/src/help_combo_box.rs | 8 +- czkawka_gui/src/help_functions.rs | 45 +- czkawka_gui/src/initialize_gui.rs | 24 +- czkawka_gui/src/main.rs | 3 +- czkawka_gui/src/notebook_info.rs | 2 + czkawka_gui/src/opening_selecting_records.rs | 54 +- czkawka_gui/src/saving_loading.rs | 26 +- czkawka_gui/src/taskbar_progress_dummy.rs | 1 + czkawka_gui/ui/about_dialog.ui | 9 +- czkawka_gui/ui/compare_images.ui | 2 +- czkawka_gui/ui/czkawka.cmb | 648 ++-- czkawka_gui/ui/main_window.ui | 8 +- czkawka_gui/ui/popover_right_click.ui | 2 +- czkawka_gui/ui/popover_select.ui | 2 +- czkawka_gui/ui/popover_sort.ui | 2 +- czkawka_gui/ui/progress.ui | 2 +- czkawka_gui/ui/settings.ui | 2 +- instructions/Compilation.md | 2 +- justfile | 59 + krokiet/Cargo.toml | 28 +- krokiet/build.rs | 4 +- krokiet/src/connect_delete.rs | 2 +- krokiet/src/connect_directories_changes.rs | 6 +- krokiet/src/connect_move.rs | 4 +- krokiet/src/connect_progress_receiver.rs | 83 +- krokiet/src/connect_scan.rs | 328 +- krokiet/src/connect_select.rs | 4 +- krokiet/src/connect_show_preview.rs | 2 +- krokiet/src/connect_stop.rs | 2 +- krokiet/src/main.rs | 6 +- krokiet/src/model_operations.rs | 20 +- krokiet/src/settings.rs | 32 +- krokiet/ui/color_palette.slint | 15 +- krokiet/ui/settings.slint | 5 +- krokiet/ui/settings_list.slint | 8 + krokiet/ui/tool_settings.slint | 5 +- 101 files changed, 4768 insertions(+), 3601 deletions(-) create mode 100644 czkawka_core/src/progress_data.rs create mode 100644 justfile diff --git a/.github/workflows/linux_cli.yml b/.github/workflows/linux_cli.yml index 8bc3bffc5..3360f2847 100644 --- a/.github/workflows/linux_cli.yml +++ b/.github/workflows/linux_cli.yml @@ -12,7 +12,7 @@ jobs: linux-cli: strategy: matrix: - toolchain: [ stable, 1.75.0 ] + toolchain: [ stable, 1.79.0 ] type: [ release ] runs-on: ubuntu-20.04 steps: diff --git a/.github/workflows/linux_cli_eyra.yml b/.github/workflows/linux_cli_eyra.yml index c78dc9701..b70a4b927 100644 --- a/.github/workflows/linux_cli_eyra.yml +++ b/.github/workflows/linux_cli_eyra.yml @@ -23,7 +23,7 @@ jobs: # New versions of nightly rust may call new unimplemented in eyra functions, so use const version - name: Setup rust version - run: rustup default nightly-2024-02-06 + run: rustup default nightly-2024-09-25 - name: Add eyra run: | diff --git a/.github/workflows/linux_gui.yml b/.github/workflows/linux_gui.yml index 81a3edba2..5d9e19367 100644 --- a/.github/workflows/linux_gui.yml +++ b/.github/workflows/linux_gui.yml @@ -12,7 +12,7 @@ jobs: linux-krokiet-gui: strategy: matrix: - toolchain: [ stable, 1.75.0 ] + toolchain: [ stable, 1.79.0 ] type: [ release ] runs-on: ubuntu-20.04 steps: @@ -39,7 +39,7 @@ jobs: linux-krokiet-gui-heif: strategy: matrix: - toolchain: [ stable, 1.75.0 ] + toolchain: [ stable, 1.79.0 ] type: [ release ] runs-on: ubuntu-22.04 steps: @@ -69,7 +69,7 @@ jobs: linux-gui: strategy: matrix: - toolchain: [ stable, 1.75.0 ] + toolchain: [ stable, 1.79.0 ] type: [ release ] runs-on: ubuntu-22.04 steps: diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index 143195d9f..90093c435 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -59,27 +59,28 @@ jobs: path: target/release/krokiet if: ${{ matrix.type == 'release' }} - - name: Build Release Heif - run: cargo build --release --features heif - if: ${{ matrix.type == 'release'}} - - - name: Store MacOS CLI Heif - uses: actions/upload-artifact@v4 - with: - name: czkawka_cli-${{ runner.os }}-${{ matrix.toolchain }}-heif - path: target/release/czkawka_cli - if: ${{ matrix.type == 'release' }} - - - name: Store MacOS GUI Heif - uses: actions/upload-artifact@v4 - with: - name: czkawka_gui-${{ runner.os }}-${{ matrix.toolchain }}-heif - path: target/release/czkawka_gui - if: ${{ matrix.type == 'release' }} - - - name: Store MacOS Krokiet Heif - uses: actions/upload-artifact@v4 - with: - name: krokiet-${{ runner.os }}-${{ matrix.toolchain }}-heif - path: target/release/krokiet - if: ${{ matrix.type == 'release' }} \ No newline at end of file +# TODO - compilation is broken, not sure why +# - name: Build Release Heif +# run: cargo build --release --features heif +# if: ${{ matrix.type == 'release'}} +# +# - name: Store MacOS CLI Heif +# uses: actions/upload-artifact@v4 +# with: +# name: czkawka_cli-${{ runner.os }}-${{ matrix.toolchain }}-heif +# path: target/release/czkawka_cli +# if: ${{ matrix.type == 'release' }} +# +# - name: Store MacOS GUI Heif +# uses: actions/upload-artifact@v4 +# with: +# name: czkawka_gui-${{ runner.os }}-${{ matrix.toolchain }}-heif +# path: target/release/czkawka_gui +# if: ${{ matrix.type == 'release' }} +# +# - name: Store MacOS Krokiet Heif +# uses: actions/upload-artifact@v4 +# with: +# name: krokiet-${{ runner.os }}-${{ matrix.toolchain }}-heif +# path: target/release/krokiet +# if: ${{ matrix.type == 'release' }} \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index f2133d5db..56a2a7cee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "ab_glyph" -version = "0.2.23" +version = "0.2.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80179d7dd5d7e8c285d67c4a1e652972a92de7475beddfb92028c76463b13225" +checksum = "79faae4620f45232f599d9bc7b290f88247a0834162c4495ab2f02d60004adfb" dependencies = [ "ab_glyph_rasterizer", "owned_ttf_parser", @@ -24,6 +24,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "adler32" version = "1.2.0" @@ -43,9 +49,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.9" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d713b3834d76b85304d4d525563c1276e2e30dc97cc67bfb4585a4a29fc2c89f" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", "getrandom", @@ -56,27 +62,33 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] +[[package]] +name = "aligned-vec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" + [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "android-activity" -version = "0.5.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee91c0c2905bae44f84bfa4e044536541df26b7703fd0888deeb9060fcc44289" +checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" dependencies = [ "android-properties", - "bitflags 2.4.2", + "bitflags 2.6.0", "cc", "cesu8", "jni", @@ -113,47 +125,48 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.12" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b09b5178381e0874812a9b157f7fe84982617e48f71f4e3235482775e5b540" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -161,27 +174,47 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.80" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" + +[[package]] +name = "arbitrary" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +dependencies = [ + "derive_arbitrary", +] [[package]] name = "arc-swap" -version = "1.6.0" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" + +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] [[package]] name = "arrayref" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "as-raw-xcb-connection" @@ -200,9 +233,9 @@ dependencies = [ [[package]] name = "ashpd" -version = "0.8.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b22517ee647547c01a687cf9b76074e1c91334032a4324f7243c6ee0f949390" +checksum = "bfe7e0dd0ac5a401dc116ed9f9119cf9decc625600474cb41f0fc0a0050abc9a" dependencies = [ "async-fs", "async-net", @@ -210,44 +243,46 @@ dependencies = [ "futures-channel", "futures-util", "rand", + "raw-window-handle 0.6.2", "serde", "serde_repr", "url", + "wayland-backend", + "wayland-client", + "wayland-protocols", "zbus", ] [[package]] name = "async-broadcast" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258b52a1aa741b9f09783b2d86cf0aeeb617bbf847f6933340a39644227acbdb" +checksum = "20cd0e2e25ea8e5f7e9df04578dc6cf5c83577fd09b1a46aaf5c85e1c33f2a7e" dependencies = [ - "event-listener 5.1.0", - "event-listener-strategy 0.5.0", + "event-listener", + "event-listener-strategy", "futures-core", "pin-project-lite", ] [[package]] name = "async-channel" -version = "2.2.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" dependencies = [ "concurrent-queue", - "event-listener 5.1.0", - "event-listener-strategy 0.5.0", + "event-listener-strategy", "futures-core", "pin-project-lite", ] [[package]] name = "async-executor" -version = "1.8.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c" +checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" dependencies = [ - "async-lock 3.3.0", "async-task", "concurrent-queue", "fastrand", @@ -257,22 +292,22 @@ dependencies = [ [[package]] name = "async-fs" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc19683171f287921f2405677dd2ed2549c3b3bda697a563ebc3a121ace2aba1" +checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a" dependencies = [ - "async-lock 3.3.0", + "async-lock", "blocking", "futures-lite", ] [[package]] name = "async-io" -version = "2.3.1" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f97ab0c5b00a7cdbe5a371b9a782ee7be1316095885c8a4ea1daf490eb0ef65" +checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" dependencies = [ - "async-lock 3.3.0", + "async-lock", "cfg-if", "concurrent-queue", "futures-io", @@ -282,26 +317,17 @@ dependencies = [ "rustix", "slab", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "async-lock" -version = "2.8.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ - "event-listener 2.5.3", -] - -[[package]] -name = "async-lock" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" -dependencies = [ - "event-listener 4.0.3", - "event-listener-strategy 0.4.0", + "event-listener", + "event-listener-strategy", "pin-project-lite", ] @@ -318,41 +344,42 @@ dependencies = [ [[package]] name = "async-process" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451e3cf68011bd56771c79db04a9e333095ab6349f7e47592b788e9b98720cc8" +checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" dependencies = [ "async-channel", "async-io", - "async-lock 3.3.0", + "async-lock", "async-signal", + "async-task", "blocking", "cfg-if", - "event-listener 5.1.0", + "event-listener", "futures-lite", "rustix", - "windows-sys 0.52.0", + "tracing", ] [[package]] name = "async-recursion" -version = "1.0.5" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "async-signal" -version = "0.2.5" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5" +checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" dependencies = [ "async-io", - "async-lock 2.8.0", + "async-lock", "atomic-waker", "cfg-if", "futures-core", @@ -360,24 +387,24 @@ dependencies = [ "rustix", "signal-hook-registry", "slab", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "async-task" -version = "4.7.0" +version = "4.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.77" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] @@ -397,33 +424,59 @@ dependencies = [ [[package]] name = "auto_enums" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1899bfcfd9340ceea3533ea157360ba8fa864354eccbceab58e1006ecab35393" +checksum = "459b77b7e855f875fd15f101064825cd79eb83185a961d66e6298560126facfb" dependencies = [ "derive_utils", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "av1-grain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6678909d8c5d46a42abcf571271e15fdbc0a225e3646cf23762cd415046c78bf" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "876c75a42f6364451a033496a14c44bffe41f5f4a8236f697391f11024e596d2" +dependencies = [ + "arrayvec", +] [[package]] name = "base64" -version = "0.21.7" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] -name = "base64ct" -version = "1.6.0" +name = "basic-toml" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +checksum = "823388e228f614e9558c6804262db37960ec8821856535f5c3f59913140558f8" +dependencies = [ + "serde", +] [[package]] name = "bincode" @@ -440,7 +493,7 @@ version = "0.69.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "cexpr", "clang-sys", "itertools 0.12.1", @@ -453,7 +506,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.50", + "syn 2.0.77", "which", ] @@ -471,9 +524,15 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bitstream-io" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "b81e1519b0d82120d2fd469d5bfb2919a9361c48b02d82d04befc1cdd2002452" [[package]] name = "bk-tree" @@ -487,15 +546,15 @@ dependencies = [ [[package]] name = "blake3" -version = "1.5.0" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87" +checksum = "d82033247fd8e890df8f740e407ad4d038debb9eb1f40533fffb32e7d17dc6f7" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", - "constant_time_eq 0.3.0", + "constant_time_eq", ] [[package]] @@ -522,71 +581,73 @@ dependencies = [ "generic-array", ] -[[package]] -name = "block-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae85a0696e7ea3b835a453750bf002770776609115e6d25c6d2ff28a8200f7e7" -dependencies = [ - "objc-sys", -] - [[package]] name = "block2" -version = "0.3.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15b55663a85f33501257357e6421bb33e769d5c9ffb5ba0921c975a123e35e68" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" dependencies = [ - "block-sys", "objc2", ] [[package]] name = "blocking" -version = "1.5.1" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" dependencies = [ "async-channel", - "async-lock 3.3.0", "async-task", - "fastrand", "futures-io", "futures-lite", "piper", - "tracing", ] +[[package]] +name = "borsh" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6362ed55def622cddc70a4746a68554d7b687713770de539e59a739b249f8ed" +dependencies = [ + "cfg_aliases", +] + +[[package]] +name = "built" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "236e6289eda5a812bc6b53c3b024039382a2895fbbeef2d748b2931546d392c4" + [[package]] name = "bumpalo" -version = "3.15.2" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3b1be7772ee4501dba05acbe66bb1e8760f6a6c474a36035631638e4415f130" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "by_address" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf8dba2868114ed769a1f2590fc9ae5eb331175b44313b6c9b922f8f7ca813d0" +checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" [[package]] name = "bytemuck" -version = "1.14.3" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f" +checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.5.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" +checksum = "0cc8b54b395f2fcfbb3d90c47b01c7f444d94d05bdeb775811dec868ac3bbc26" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] @@ -595,11 +656,17 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + [[package]] name = "bytes" -version = "1.5.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "bzip2" @@ -624,35 +691,34 @@ dependencies = [ [[package]] name = "cairo-rs" -version = "0.19.2" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2650f66005301bd33cc486dec076e1293c4cecf768bc7ba9bf5d2b1be339b99c" +checksum = "e8a0ea147c94108c9613235388f540e4d14c327f7081c9e471fc8ee8a2533e69" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "cairo-sys-rs", "glib", "libc", - "thiserror", ] [[package]] name = "cairo-sys-rs" -version = "0.19.2" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3bb3119664efbd78b5e6c93957447944f16bdbced84c17a9f41c7829b81e64" +checksum = "428290f914b9b86089f60f5d8a9f6e440508e1bcff23b25afd51502b0a2da88f" dependencies = [ "glib-sys", "libc", - "system-deps", + "system-deps 7.0.3", ] [[package]] name = "calloop" -version = "0.12.4" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fba7adb4dd5aa98e5553510223000e7148f621165ec5f9acd7113f6ca4995298" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "log", "polling", "rustix", @@ -660,13 +726,26 @@ dependencies = [ "thiserror", ] +[[package]] +name = "calloop" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ead1e1514bce44c0f40e027899fbc595907fc112635bed21b3b5d975c0a5e7" +dependencies = [ + "bitflags 2.6.0", + "polling", + "rustix", + "slab", + "tracing", +] + [[package]] name = "calloop-wayland-source" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f0ea9b9476c7fad82841a8dbb380e2eae480c21910feba80725b46931ed8f02" +checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" dependencies = [ - "calloop", + "calloop 0.13.0", "rustix", "wayland-backend", "wayland-client", @@ -683,11 +762,13 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.86" +version = "1.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9fa1897e4325be0d68d48df6aa1a71ac2ed4d27723887e7754192705350730" +checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" dependencies = [ + "jobserver", "libc", + "shlex", ] [[package]] @@ -718,31 +799,35 @@ dependencies = [ [[package]] name = "cfg-expr" -version = "0.15.7" +version = "0.15.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa50868b64a9a6fda9d593ce778849ea8715cd2a3d2cc17ffdb4a2f2f2f1961d" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" dependencies = [ "smallvec", "target-lexicon", ] [[package]] -name = "cfg-if" -version = "1.0.0" +name = "cfg-expr" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "d0890061c4d3223e7267f3bad2ec40b997d64faac1c2815a4a9d95018e2b9e9c" +dependencies = [ + "smallvec", + "target-lexicon", +] [[package]] -name = "cfg_aliases" -version = "0.1.1" +name = "cfg-if" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cfg_aliases" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77e53693616d3075149f4ead59bdeecd204ac6b8192d8969757601b74bddf00f" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "cgl" @@ -755,16 +840,16 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.34" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", - "windows-targets 0.52.2", + "windows-targets 0.52.6", ] [[package]] @@ -779,20 +864,20 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", - "libloading 0.8.1", + "libloading 0.8.5", ] [[package]] name = "clap" -version = "4.5.1" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" +checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3" dependencies = [ "clap_builder", "clap_derive", @@ -800,33 +885,33 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.1" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" +checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b" dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.11.0", + "strsim 0.11.1", ] [[package]] name = "clap_derive" -version = "4.5.0" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "clipboard-win" @@ -840,9 +925,9 @@ dependencies = [ [[package]] name = "clru" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8191fa7302e03607ff0e237d4246cc043ff5b3cb9409d995172ba3bea16b807" +checksum = "cbd0f76e066e64fdc5631e3bb46381254deab9ef1158292f27c8c57e3bf3fe59" [[package]] name = "cocoa" @@ -853,8 +938,8 @@ dependencies = [ "bitflags 1.3.2", "block", "cocoa-foundation", - "core-foundation", - "core-graphics", + "core-foundation 0.9.4", + "core-graphics 0.23.2", "foreign-types", "libc", "objc", @@ -868,8 +953,8 @@ checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" dependencies = [ "bitflags 1.3.2", "block", - "core-foundation", - "core-graphics-types", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", "libc", "objc", ] @@ -898,15 +983,15 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "combine" -version = "4.6.6" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" dependencies = [ "bytes", "memchr", @@ -914,9 +999,9 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ "crossbeam-utils", ] @@ -936,9 +1021,9 @@ dependencies = [ [[package]] name = "const-field-offset" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee299fd3deaafe475c5265e87273a98ce753148e79abe7ba4c0c6f90652e1a17" +checksum = "91fcde4ca1211b5a94b573083c472ee19e86b19a441913f66e1cc5c41daf0255" dependencies = [ "const-field-offset-macro", "field-offset", @@ -946,32 +1031,26 @@ dependencies = [ [[package]] name = "const-field-offset-macro" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c1f041b3982b9d56ee85931d60106643188e04385b7ec3eeeca546247eb18c" +checksum = "5387f5bbc9e9e6c96436ea125afa12614cebf8ac67f49abc08c1e7a891466c90" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "const_fn" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935" - -[[package]] -name = "constant_time_eq" -version = "0.1.5" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +checksum = "373e9fafaa20882876db20562275ff58d50e0caa2590077fe7ce7bef90211d0d" [[package]] name = "constant_time_eq" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" [[package]] name = "convert_case" @@ -1003,21 +1082,44 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core-graphics" -version = "0.23.1" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "970a29baf4110c26fedbc7f82107d42c23f7e88e404c4577ed73fe99ff85a212" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" dependencies = [ "bitflags 1.3.2", - "core-foundation", - "core-graphics-types", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.10.0", + "core-graphics-types 0.2.0", "foreign-types", "libc", ] @@ -1029,7 +1131,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.10.0", "libc", ] @@ -1039,8 +1152,8 @@ version = "20.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9d2790b5c08465d49f8dc05c8bcae9fea467855947db39b0f8145c091aaced5" dependencies = [ - "core-foundation", - "core-graphics", + "core-foundation 0.9.4", + "core-graphics 0.23.2", "foreign-types", "libc", ] @@ -1062,33 +1175,33 @@ checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] [[package]] name = "critical-section" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" +checksum = "f64009896348fc5af4222e9cf7d7d82a95a256c634ebcf61c53e4ea461422242" [[package]] name = "crossbeam-channel" -version = "0.5.11" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ "crossbeam-utils", ] @@ -1123,9 +1236,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crunchy" @@ -1144,32 +1257,19 @@ dependencies = [ ] [[package]] -name = "css-color-parser2" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf8ed1639f4b56ec6f31d007ff66ce4a13099dce5a9995d48368a30d62bf04bd" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "ctor" -version = "0.2.6" +name = "ctor-lite" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d2b3721e861707777e3195b0158f950ae6dc4a27e4d02ff9f67e3eb3de199e" -dependencies = [ - "quote", - "syn 2.0.50", -] +checksum = "1f791803201ab277ace03903de1594460708d2d54df6053f2d9e82f592b19e3b" [[package]] name = "ctrlc" -version = "3.4.2" +version = "3.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b467862cc8610ca6fc9a1532d7777cee0804e678ab45410897b9396495994a0b" +checksum = "90eeab0aa92f3f9b4e87f258c72b139c207d251f9cbc1080a0086b86a8870dd3" dependencies = [ - "nix 0.27.1", - "windows-sys 0.52.0", + "nix", + "windows-sys 0.59.0", ] [[package]] @@ -1200,7 +1300,7 @@ dependencies = [ "anyhow", "audio_checker", "bincode", - "bitflags 2.4.2", + "bitflags 2.6.0", "bk-tree", "blake3", "crc32fast", @@ -1213,7 +1313,7 @@ dependencies = [ "humansize", "i18n-embed", "i18n-embed-fl", - "image", + "image 0.25.2", "image_hasher", "imagepipe", "infer", @@ -1259,7 +1359,7 @@ dependencies = [ "humansize", "i18n-embed", "i18n-embed-fl", - "image", + "image 0.25.2", "image_hasher", "log", "once_cell", @@ -1314,12 +1414,13 @@ checksum = "7762d17f1241643615821a8455a0b2c3e803784b058693d990b11f2dce25a0ca" [[package]] name = "dashmap" -version = "5.5.3" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" dependencies = [ "cfg-if", - "hashbrown 0.14.3", + "crossbeam-utils", + "hashbrown 0.14.5", "lock_api", "once_cell", "parking_lot_core", @@ -1327,9 +1428,9 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" [[package]] name = "data-url" @@ -1376,38 +1477,38 @@ dependencies = [ ] [[package]] -name = "derivative" -version = "2.2.0" +name = "derive_arbitrary" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.77", ] [[package]] name = "derive_more" -version = "0.99.17" +version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "convert_case", "proc-macro2", "quote", "rustc_version", - "syn 1.0.109", + "syn 2.0.77", ] [[package]] name = "derive_utils" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61bb5a1014ce6dfc2a378578509abe775a5aa06bff584a547555d9efdb81b926" +checksum = "65f152f4b8559c4da5d574bafc7af85454d706b4c5fe8b530d508cacbb6807ea" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] @@ -1450,13 +1551,13 @@ checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" [[package]] name = "displaydoc" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] @@ -1465,7 +1566,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" dependencies = [ - "libloading 0.8.1", + "libloading 0.8.5", ] [[package]] @@ -1476,53 +1577,36 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "downcast-rs" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" [[package]] -name = "drm" -version = "0.9.0" +name = "dpi" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edf9159ef4bcecd0c5e4cbeb573b8d0037493403d542780dba5d840bbf9df56f" -dependencies = [ - "bitflags 1.3.2", - "bytemuck", - "drm-ffi 0.5.0", - "drm-fourcc", - "nix 0.26.4", -] +checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53" [[package]] name = "drm" -version = "0.11.1" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0f8a69e60d75ae7dab4ef26a59ca99f2a89d4c142089b537775ae0c198bdcde" +checksum = "98888c4bbd601524c11a7ed63f814b8825f420514f78e96f752c437ae9cbb5d1" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "bytemuck", - "drm-ffi 0.7.1", + "drm-ffi", "drm-fourcc", "rustix", ] [[package]] name = "drm-ffi" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1352481b7b90e27a8a1bf8ef6b33cf18b98dba7c410e75c24bb3eef2f0d8d525" -dependencies = [ - "drm-sys 0.4.0", - "nix 0.26.4", -] - -[[package]] -name = "drm-ffi" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41334f8405792483e32ad05fbb9c5680ff4e84491883d2947a4757dc54cb2ac6" +checksum = "97c98727e48b7ccb4f4aea8cfe881e5b07f702d17b7875991881b41af7278d53" dependencies = [ - "drm-sys 0.6.1", + "drm-sys", "rustix", ] @@ -1534,28 +1618,19 @@ checksum = "0aafbcdb8afc29c1a7ee5fbe53b5d62f4565b35a042a662ca9fecd0b54dae6f4" [[package]] name = "drm-sys" -version = "0.4.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1369f1679d6b706d234c4c1e0613c415c2c74b598a09ad28080ba2474b72e42d" +checksum = "fd39dde40b6e196c2e8763f23d119ddb1a8714534bf7d77fa97a65b0feda3986" dependencies = [ "libc", -] - -[[package]] -name = "drm-sys" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d09ff881f92f118b11105ba5e34ff8f4adf27b30dae8f12e28c193af1c83176" -dependencies = [ - "libc", - "linux-raw-sys 0.6.4", + "linux-raw-sys 0.6.5", ] [[package]] name = "dwrote" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439a1c2ba5611ad3ed731280541d36d2e9c4ac5e7fb818a27b604bdc5a6aa65b" +checksum = "2da3498378ed373237bdef1eddcc64e7be2d3ba4841f4c22a998e81cadeea83c" dependencies = [ "lazy_static", "libc", @@ -1567,9 +1642,9 @@ dependencies = [ [[package]] name = "either" -version = "1.10.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "encode_unicode" @@ -1579,9 +1654,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if", ] @@ -1594,9 +1669,9 @@ checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" [[package]] name = "enumflags2" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3278c9d5fb675e0a51dabcf4c0d355f692b064171535ba72361be1528a9d8e8d" +checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d" dependencies = [ "enumflags2_derive", "serde", @@ -1604,24 +1679,24 @@ dependencies = [ [[package]] name = "enumflags2_derive" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4" +checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "enumn" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fd000fd6988e73bbe993ea3db9b1aa64906ab88766d654973924340c8cddb42" +checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] @@ -1632,9 +1707,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -1642,35 +1717,18 @@ dependencies = [ [[package]] name = "euclid" -version = "0.22.9" +version = "0.22.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f253bc5c813ca05792837a0ff4b3a580336b224512d48f7eda1d7dd9210787" +checksum = "ad9cdb4b747e485a12abb0e6566612956c7a1bafa3bdb8d682c5b6d403589e48" dependencies = [ "num-traits", ] [[package]] name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - -[[package]] -name = "event-listener" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener" -version = "5.1.0" +version = "5.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7ad6fd685ce13acd6d9541a30f6db6567a7a24c9ffd4ba2955d29e3f22c8b27" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" dependencies = [ "concurrent-queue", "parking", @@ -1679,21 +1737,11 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" -dependencies = [ - "event-listener 4.0.3", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feedafcaa9b749175d5ac357452a9d41ea2911da598fde46ce1fe02c37751291" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" dependencies = [ - "event-listener 5.1.0", + "event-listener", "pin-project-lite", ] @@ -1707,23 +1755,29 @@ dependencies = [ "flume", "half", "lebe", - "miniz_oxide", + "miniz_oxide 0.7.4", "rayon-core", "smallvec", "zune-inflate", ] +[[package]] +name = "extended" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af9673d8203fcb076b19dfd17e38b3d4ae9f44959416ea532ce72415a6020365" + [[package]] name = "fastrand" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "fax" -version = "0.2.0" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2cec1797683c06c2f3de5edb3fde4d99c70e96f3204f6aaff944078353e5c55" +checksum = "b03e33ad0e71af414ef9d2b0a94d23ff59115bb068e6a6a06c0952f2c22ffd77" dependencies = [ "fax_derive", ] @@ -1741,29 +1795,29 @@ dependencies = [ [[package]] name = "fdeflate" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +checksum = "d8090f921a24b04994d9929e204f50b498a33ea6ba559ffaa05e04f7ee7fb5ab" dependencies = [ "simd-adler32", ] [[package]] name = "femtovg" -version = "0.8.2" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18ab822e58e8bc2b89840dc5dde49afe39302e129c60d39c8520200c085404a7" +checksum = "47921d14afc4daad9bedc926099bc6edcaa23e37a957448f86cdefcbafe2f632" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "fnv", - "generational-arena", "glow", - "image", + "image 0.25.2", "imgref", "log", "lru", "rgb", - "rustybuzz 0.11.0", + "rustybuzz", + "slotmap", "unicode-bidi", "unicode-segmentation", "wasm-bindgen", @@ -1776,7 +1830,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4465342596fe680b4670e2f235066aaa123e44a0149fecb86378f288b32c83db" dependencies = [ - "image", + "image 0.24.9", "rayon", "serde", "serde_json", @@ -1790,20 +1844,20 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" dependencies = [ - "memoffset 0.9.0", + "memoffset", "rustc_version", ] [[package]] name = "filetime" -version = "0.2.23" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", - "windows-sys 0.52.0", + "libredox 0.1.3", + "windows-sys 0.59.0", ] [[package]] @@ -1815,20 +1869,14 @@ dependencies = [ "toml 0.5.11", ] -[[package]] -name = "finl_unicode" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" - [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.8.0", ] [[package]] @@ -1839,9 +1887,9 @@ checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" [[package]] name = "fluent" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61f69378194459db76abd2ce3952b790db103ceb003008d3d50d97c41ff847a7" +checksum = "bb74634707bebd0ce645a981148e8fb8c7bccd4c33c652aeffd28bf2f96d555a" dependencies = [ "fluent-bundle", "unic-langid", @@ -1849,9 +1897,9 @@ dependencies = [ [[package]] name = "fluent-bundle" -version = "0.15.2" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e242c601dec9711505f6d5bbff5bedd4b61b2469f2e8bb8e57ee7c9747a87ffd" +checksum = "7fe0a21ee80050c678013f82edf4b705fe2f26f1f9877593d13198612503f493" dependencies = [ "fluent-langneg", "fluent-syntax", @@ -1874,9 +1922,9 @@ dependencies = [ [[package]] name = "fluent-syntax" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0abed97648395c902868fee9026de96483933faa54ea3b40d652f7dfe61ca78" +checksum = "2a530c4694a6a8d528794ee9bbd8ba0122e779629ac908d15ad5a7ae7763a33d" dependencies = [ "thiserror", ] @@ -1898,35 +1946,36 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "fontconfig-parser" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a595cb550439a117696039dfc69830492058211b771a2a165379f2a1a53d84d" +checksum = "c1fcfcd44ca6e90c921fee9fa665d530b21ef1327a4c1a6c5250ea44b776ada7" dependencies = [ "roxmltree", ] [[package]] name = "fontdb" -version = "0.16.2" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0299020c3ef3f60f526a4f64ab4a3d4ce116b1acbf24cdd22da0068e5d81dc3" +checksum = "e32eac81c1135c1df01d4e6d4233c47ba11f6a6d07f33e0bba09d18797077770" dependencies = [ "fontconfig-parser", "log", - "memmap2 0.9.4", + "memmap2", "slotmap", "tinyvec", - "ttf-parser", + "ttf-parser 0.21.1", ] [[package]] name = "fontdue" -version = "0.8.0" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9099a2f86b8e674b75d03ff154b3fe4c5208ed249ced8d69cc313a9fa40bb488" +checksum = "efe23d02309319171d00d794c9ff48d4f903c0e481375b1b04b017470838af04" dependencies = [ - "hashbrown 0.14.3", - "ttf-parser", + "hashbrown 0.14.5", + "rayon", + "ttf-parser 0.21.1", ] [[package]] @@ -1947,7 +1996,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] @@ -2034,9 +2083,9 @@ checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-lite" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445ba825b27408685aaecefd65178908c36c6e96aaf6d8599419d46e624192ba" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" dependencies = [ "fastrand", "futures-core", @@ -2053,7 +2102,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] @@ -2087,12 +2136,12 @@ dependencies = [ [[package]] name = "gbm" -version = "0.12.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ec389cda876966cf824111bf6e533fb934c711d473498279964a990853b3c6" +checksum = "45bf55ba6dd53ad0ac115046ff999c5324c283444ee6e0be82454c4e8eb2f36a" dependencies = [ - "bitflags 1.3.2", - "drm 0.9.0", + "bitflags 2.6.0", + "drm", "drm-fourcc", "gbm-sys", "libc", @@ -2100,18 +2149,18 @@ dependencies = [ [[package]] name = "gbm-sys" -version = "0.2.2" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b63eba9b9b7a231514482deb08759301c9f9f049ac6869403f381834ebfeaf67" +checksum = "6fd2d6bf7c0143b38beece05f9a5c4c851a49a8434f62bf58ff28da92b0ddc58" dependencies = [ "libc", ] [[package]] name = "gdk-pixbuf" -version = "0.19.2" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6a23f8a0b5090494fd04924662d463f8386cc678dd3915015a838c1a3679b92" +checksum = "8730751991b97419fc3f0c2dca2c9e45b48edf46e48e0f965964ecf33889812f" dependencies = [ "gdk-pixbuf-sys", "gio", @@ -2121,22 +2170,22 @@ dependencies = [ [[package]] name = "gdk-pixbuf-sys" -version = "0.19.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcbd04c1b2c4834cc008b4828bc917d062483b88d26effde6342e5622028f96" +checksum = "1ffbf649fd5b1c8c0f0feeb015b7533c3ef92da2887fb95ddd338bc2b1644a7c" dependencies = [ "gio-sys", "glib-sys", "gobject-sys", "libc", - "system-deps", + "system-deps 7.0.3", ] [[package]] name = "gdk4" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6771942f85a2beaa220c64739395e4401b9fab4a52aba9b503fa1e6ed4d4d806" +checksum = "4b7d7237c1487ed4b300aac7744efcbf1319e12d60d7afcd6f505414bd5b5dea" dependencies = [ "cairo-rs", "gdk-pixbuf", @@ -2149,9 +2198,9 @@ dependencies = [ [[package]] name = "gdk4-sys" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1eb95854fab65072023a7814434f003db571d6e45c287c0b0c540c1c78bdf6ae" +checksum = "a67576c8ec012156d7f680e201a807b4432a77babb3157e0555e990ab6bcd878" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", @@ -2161,16 +2210,7 @@ dependencies = [ "libc", "pango-sys", "pkg-config", - "system-deps", -] - -[[package]] -name = "generational-arena" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877e94aff08e743b651baaea359664321055749b398adff8740a7399af7796e7" -dependencies = [ - "cfg-if", + "system-deps 7.0.3", ] [[package]] @@ -2196,16 +2236,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "gethostname" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb65d4ba3173c56a500b555b532f72c42e8d1fe64962b518897f8959fae2c177" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "gethostname" version = "0.4.3" @@ -2218,9 +2248,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -2229,9 +2259,9 @@ dependencies = [ [[package]] name = "gif" -version = "0.12.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045" +checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" dependencies = [ "color_quant", "weezl", @@ -2239,9 +2269,9 @@ dependencies = [ [[package]] name = "gio" -version = "0.19.2" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eae10b27b6dd27e22ed0d812c6387deba295e6fc004a8b379e459b663b05a02" +checksum = "dcacaa37401cad0a95aadd266bc39c72a131d454fc012f6dfd217f891d76cc52" dependencies = [ "futures-channel", "futures-core", @@ -2252,19 +2282,18 @@ dependencies = [ "libc", "pin-project-lite", "smallvec", - "thiserror", ] [[package]] name = "gio-sys" -version = "0.19.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf8e1d9219bb294636753d307b030c1e8a032062cba74f493c431a5c8b81ce4" +checksum = "5237611e97e9b86ab5768adc3eef853ae713ea797aa3835404acdfacffc9fb38" dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps", + "system-deps 7.0.3", "windows-sys 0.52.0", ] @@ -2281,11 +2310,11 @@ dependencies = [ [[package]] name = "glib" -version = "0.19.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab9e86540b5d8402e905ad4ce7d6aa544092131ab564f3102175af176b90a053" +checksum = "95648aac01b75503000bb3bcaa5ec7a7a2dd61e43636b8b1814854de94dd80e4" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "futures-channel", "futures-core", "futures-executor", @@ -2298,30 +2327,29 @@ dependencies = [ "libc", "memchr", "smallvec", - "thiserror", ] [[package]] name = "glib-macros" -version = "0.19.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f5897ca27a83e4cdc7b4666850bade0a2e73e17689aabafcc9acddad9d823b8" +checksum = "302f1d633c9cdef4350330e7b68fd8016e2834bb106c93fdf9789fcde753c1ab" dependencies = [ - "heck", - "proc-macro-crate 3.1.0", + "heck 0.5.0", + "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "glib-sys" -version = "0.19.0" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630f097773d7c7a0bb3258df4e8157b47dc98bbfa0e60ad9ab56174813feced4" +checksum = "92eee4531c1c9abba945d19378b205031b5890e1f99c319ba0503b6e0c06a163" dependencies = [ "libc", - "system-deps", + "system-deps 7.0.3", ] [[package]] @@ -2332,12 +2360,13 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globalcache" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccd40efe5b4f0021ca3c36a140cb365563be3c579653b573a5a8ac69bd6f9028" +checksum = "240a3059d86f2ba6859ac79f95ff94e65606abc775c1bc0ecf9b6590fb35dc04" dependencies = [ "async-trait", "tuple", + "web-time", ] [[package]] @@ -2354,55 +2383,56 @@ dependencies = [ [[package]] name = "glutin" -version = "0.31.3" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fcd4ae4e86d991ad1300b8f57166e5be0c95ef1f63f3f5b827f8a164548746" +checksum = "ec69412a0bf07ea7607e638b415447857a808846c2b685a43c8aa18bc6d5e499" dependencies = [ - "bitflags 2.4.2", - "cfg_aliases 0.1.1", + "bitflags 2.6.0", + "cfg_aliases", "cgl", - "core-foundation", + "core-foundation 0.9.4", "dispatch", "glutin_egl_sys", "glutin_glx_sys", "glutin_wgl_sys", - "icrate", - "libloading 0.8.1", + "libloading 0.8.5", "objc2", + "objc2-app-kit", + "objc2-foundation", "once_cell", - "raw-window-handle 0.5.2", + "raw-window-handle 0.6.2", "wayland-sys", - "windows-sys 0.48.0", + "windows-sys 0.52.0", "x11-dl", ] [[package]] name = "glutin-winit" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebcdfba24f73b8412c5181e56f092b5eff16671c514ce896b258a0a64bd7735" +checksum = "85edca7075f8fc728f28cb8fbb111a96c3b89e930574369e3e9c27eb75d3788f" dependencies = [ - "cfg_aliases 0.1.1", + "cfg_aliases", "glutin", - "raw-window-handle 0.5.2", + "raw-window-handle 0.6.2", "winit", ] [[package]] name = "glutin_egl_sys" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77cc5623f5309ef433c3dd4ca1223195347fe62c413da8e2fdd0eb76db2d9bcd" +checksum = "cae99fff4d2850dbe6fb8c1fa8e4fead5525bab715beaacfccf3fb994e01c827" dependencies = [ "gl_generator", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "glutin_glx_sys" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a165fd686c10dcc2d45380b35796e577eacfd43d4660ee741ec8ebe2201b3b4f" +checksum = "9c2b2d3918e76e18e08796b55eb64e8fe6ec67d5a6b2e2a7e2edce224ad24c63" dependencies = [ "gl_generator", "x11-dl", @@ -2410,29 +2440,29 @@ dependencies = [ [[package]] name = "glutin_wgl_sys" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8098adac955faa2d31079b65dc48841251f69efd3ac25477903fc424362ead" +checksum = "0a4e1951bbd9434a81aa496fe59ccc2235af3820d27b85f9314e279609211e2c" dependencies = [ "gl_generator", ] [[package]] name = "gobject-sys" -version = "0.19.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e2b1080b9418dd0c58b498da3a5c826030343e0ef07bde6a955d28de54979" +checksum = "fa3d1dcd8a1eb2e7c22be3d5e792b14b186f3524f79b25631730f9a8c169d49a" dependencies = [ "glib-sys", "libc", - "system-deps", + "system-deps 7.0.3", ] [[package]] name = "graphene-rs" -version = "0.19.2" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e4d388e96c5f29e2b2f67045d229ddf826d0a8d6d282f94ed3b34452222c91" +checksum = "80aac87f74e81c0e13433e892a047237abdc37945c86887f5eed905038356e69" dependencies = [ "glib", "graphene-sys", @@ -2441,21 +2471,21 @@ dependencies = [ [[package]] name = "graphene-sys" -version = "0.19.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "236ed66cc9b18d8adf233716f75de803d0bf6fc806f60d14d948974a12e240d0" +checksum = "cc2f91ecd32989efad60326cc20a8fb252bd2852239a08e4e70cde8c100de9ca" dependencies = [ "glib-sys", "libc", "pkg-config", - "system-deps", + "system-deps 7.0.3", ] [[package]] name = "gsk4" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e8ce8dee0fd87a11002214b1204ff18c9272fbd530408f0884a0f9b25dc31de" +checksum = "1f3cf2091e1af185b347b3450817d93dea6fe435df7abd4c2cd7fb5bcb4cfda8" dependencies = [ "cairo-rs", "gdk4", @@ -2468,9 +2498,9 @@ dependencies = [ [[package]] name = "gsk4-sys" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2660a652da5b662d43924df19ba40d73f015ed427329ef51d2b1360a4e0dc0e4" +checksum = "6aa69614a26d8760c186c3690f1b0fbb917572ca23ef83137445770ceddf8cde" dependencies = [ "cairo-sys-rs", "gdk4-sys", @@ -2479,14 +2509,14 @@ dependencies = [ "graphene-sys", "libc", "pango-sys", - "system-deps", + "system-deps 7.0.3", ] [[package]] name = "gtk4" -version = "0.8.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d26ffa3ec6316ccaa1df62d3e7f5bae1637c0acbb43f250fabef38319f73c64" +checksum = "f4fe572bf318e5dbc6f5a2f8a25d853f1ae3f42768c0b08af6ca20a18f4057e1" dependencies = [ "cairo-rs", "field-offset", @@ -2505,23 +2535,21 @@ dependencies = [ [[package]] name = "gtk4-macros" -version = "0.8.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8b86439e9896f6f3f47c3d8077c5c8205174078760afdabd9098a8e9e937d97" +checksum = "e9e7b362c8fccd2712297903717d65d30defdab2b509bc9d209cbe5ffb9fabaf" dependencies = [ - "anyhow", - "proc-macro-crate 3.1.0", - "proc-macro-error", + "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.77", ] [[package]] name = "gtk4-sys" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2abc0a6d356d59a3806021829ce6ed3e70bba3509b41a535fedcb09fae13fbc0" +checksum = "1114a207af8ada02cf4658a76692f4190f06f093380d5be07e3ca8b43aa7c666" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", @@ -2533,14 +2561,14 @@ dependencies = [ "gsk4-sys", "libc", "pango-sys", - "system-deps", + "system-deps 7.0.3", ] [[package]] name = "half" -version = "2.3.1" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc52e53916c08643f1b56ec082790d1e86a32e58dc5268f897f313fbae7b4872" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" dependencies = [ "bytemuck", "cfg-if", @@ -2573,21 +2601,13 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" -dependencies = [ - "ahash", -] - -[[package]] -name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", "allocator-api2", + "rayon", ] [[package]] @@ -2596,11 +2616,23 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" -version = "0.3.6" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hermit-abi" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" [[package]] name = "hex" @@ -2637,12 +2669,13 @@ dependencies = [ [[package]] name = "i-slint-backend-linuxkms" -version = "1.4.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fff24de728432445a94f890093bd852a7c3fd01ae282e40ae0eab6ea629a66d" +checksum = "ab8f782e541bb2c856e388a63a409215a4f22876e68a5582f00032145fc08f9f" dependencies = [ - "calloop", - "drm 0.9.0", + "bytemuck", + "calloop 0.14.1", + "drm", "gbm", "glutin", "i-slint-common", @@ -2650,17 +2683,18 @@ dependencies = [ "i-slint-renderer-femtovg", "i-slint-renderer-skia", "input", - "nix 0.27.1", - "raw-window-handle 0.5.2", + "memmap2", + "nix", + "raw-window-handle 0.6.2", "vulkano", "xkbcommon", ] [[package]] name = "i-slint-backend-selector" -version = "1.4.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1953f792a394a7ad26932b4989646719fb126910029006f7cef40ffd189633d0" +checksum = "350b9375a979856a3655a9905174b055726e85b9c4b6bd315f1d36f6529dbc33" dependencies = [ "cfg-if", "i-slint-backend-linuxkms", @@ -2672,13 +2706,13 @@ dependencies = [ [[package]] name = "i-slint-backend-winit" -version = "1.4.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138c36c5c9e12f22fe07f280200cedb5d31e07641e40e3b45376fe2112ead303" +checksum = "4831644094018b8533264d601ab54f585ba6cc834068e8eae77e571d4cc5b70e" dependencies = [ "bytemuck", "cfg-if", - "cfg_aliases 0.2.0", + "cfg_aliases", "cocoa", "const-field-offset", "copypasta", @@ -2694,12 +2728,11 @@ dependencies = [ "lyon_path", "once_cell", "pin-weak", - "raw-window-handle 0.5.2", + "raw-window-handle 0.6.2", "rgb", "scoped-tls-hkt", "scopeguard", "softbuffer", - "vtable", "wasm-bindgen", "web-sys", "winit", @@ -2707,31 +2740,30 @@ dependencies = [ [[package]] name = "i-slint-common" -version = "1.4.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "550e9282fda488b76ce057a728168d1aef947c758f3221b92ae904b167ab008c" +checksum = "bdd025e9a8c1bb6f2132ab453a0f552408050115552134200a7edea2247cccce" dependencies = [ "cfg-if", "derive_more", "fontdb", - "libloading 0.8.1", + "libloading 0.8.5", ] [[package]] name = "i-slint-compiler" -version = "1.4.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa2c3525ea761b3e9251f7869e64dce5f483f7ea1a5e04fe7b9a3fb5780dd6" +checksum = "5c3d2bb25fc20cbd999e3c812cae181206d0280e6e73e7ead2fd4598412d93d8" dependencies = [ "by_address", "codemap", "codemap-diagnostic", - "css-color-parser2", "derive_more", "fontdue", "i-slint-common", - "image", - "itertools 0.12.1", + "image 0.24.9", + "itertools 0.13.0", "linked_hash_set", "lyon_extra", "lyon_path", @@ -2741,7 +2773,7 @@ dependencies = [ "quote", "resvg", "rowan", - "smol_str", + "smol_str 0.3.1", "strum", "thiserror", "url", @@ -2749,13 +2781,15 @@ dependencies = [ [[package]] name = "i-slint-core" -version = "1.4.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d40990f7ed42c76799edc0e8cae9a8ffcc77569506a94e86eef81626c7387a7" +checksum = "6d2757683b3377730a67966479a88d6c9f27f7b50b379e3a31c7fbf954e4a661" dependencies = [ "auto_enums", + "bitflags 2.6.0", "bytemuck", "cfg-if", + "chrono", "clru", "const-field-offset", "derive_more", @@ -2763,7 +2797,7 @@ dependencies = [ "fontdue", "i-slint-common", "i-slint-core-macros", - "image", + "image 0.24.9", "integer-sqrt", "lyon_algorithms", "lyon_extra", @@ -2774,9 +2808,10 @@ dependencies = [ "pin-project", "pin-weak", "portable-atomic", + "raw-window-handle 0.6.2", "resvg", "rgb", - "rustybuzz 0.12.1", + "rustybuzz", "scoped-tls-hkt", "scopeguard", "slab", @@ -2788,28 +2823,28 @@ dependencies = [ "vtable", "wasm-bindgen", "web-sys", - "web-time 1.0.0", + "web-time", ] [[package]] name = "i-slint-core-macros" -version = "1.4.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2a4e4c21ed660181abe101b6f141d920e838fec4bc1ff20f7440dc03fb5ad8" +checksum = "17c4f06e2ccbf6e7381abd64e8716767e97b5fdf15280decf8f08f8d58cde25c" dependencies = [ "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "i-slint-renderer-femtovg" -version = "1.4.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "337e6ec928bde01baa27d3fdeddd5a33665952aead4d0d9be9818f573a41344c" +checksum = "9a450bd34e9493cb8694dbe5998346a84f180fae14ad26ae7d8c385fa0c039f4" dependencies = [ "cfg-if", "const-field-offset", - "core-foundation", + "core-foundation 0.9.4", "core-text", "derive_more", "dwrote", @@ -2822,13 +2857,11 @@ dependencies = [ "lyon_path", "once_cell", "pin-weak", - "raw-window-handle 0.5.2", "rgb", "scoped-tls-hkt", - "ttf-parser", + "ttf-parser 0.21.1", "unicode-script", "unicode-segmentation", - "vtable", "wasm-bindgen", "web-sys", "winapi", @@ -2836,18 +2869,18 @@ dependencies = [ [[package]] name = "i-slint-renderer-skia" -version = "1.4.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1189ac65d7e31129407e2cfef4009cdea500040a73d8f87505949f82af0939db" +checksum = "51d6e478f22705e017db15416434d5dec7b138b6a1853baacdb489b8b558c1eb" dependencies = [ "ash", "bytemuck", "cfg-if", - "cfg_aliases 0.2.0", + "cfg_aliases", "cocoa", "const-field-offset", - "core-foundation", - "core-graphics-types", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", "derive_more", "foreign-types", "glow", @@ -2860,35 +2893,36 @@ dependencies = [ "objc", "once_cell", "pin-weak", - "raw-window-handle 0.5.2", + "raw-window-handle 0.6.2", + "raw-window-metal", "scoped-tls-hkt", "skia-safe", "softbuffer", "unicode-segmentation", "vtable", "vulkano", - "windows 0.52.0", + "windows 0.58.0", ] [[package]] name = "i18n-config" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c9ce3c48cbc21fd5b22b9331f32b5b51f6ad85d969b99e793427332e76e7640" +checksum = "8e88074831c0be5b89181b05e6748c4915f77769ecc9a4c372f88b169a8509c9" dependencies = [ + "basic-toml", "log", "serde", "serde_derive", "thiserror", - "toml 0.8.10", "unic-langid", ] [[package]] name = "i18n-embed" -version = "0.14.1" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94205d95764f5bb9db9ea98fa77f89653365ca748e27161f5bbea2ffd50e459c" +checksum = "e901c87176ac0b615033c81dbe927c230f74700abfd60ed953a6f547c87bbe6d" dependencies = [ "arc-swap", "fluent", @@ -2908,9 +2942,9 @@ dependencies = [ [[package]] name = "i18n-embed-fl" -version = "0.8.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8241a781f49e923415e106fcd1f89c3fab92cc9f699a521c56e95dee273903d3" +checksum = "d73fe51b9655599147183495551696628b335f75b2dbfa225196b16d69d7288e" dependencies = [ "dashmap", "find-crate", @@ -2922,8 +2956,8 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "strsim 0.10.0", - "syn 2.0.50", + "strsim 0.11.1", + "syn 2.0.77", "unic-langid", ] @@ -2937,21 +2971,21 @@ dependencies = [ "i18n-config", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core", + "windows-core 0.52.0", ] [[package]] @@ -2963,17 +2997,6 @@ dependencies = [ "cc", ] -[[package]] -name = "icrate" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d3aaff8a54577104bafdf686ff18565c3b6903ca5782a2026ef06e2c7aa319" -dependencies = [ - "block2", - "dispatch", - "objc2", -] - [[package]] name = "ident_case" version = "1.0.1" @@ -2992,9 +3015,9 @@ dependencies = [ [[package]] name = "image" -version = "0.24.8" +version = "0.24.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "034bbe799d1909622a74d1193aa50147769440040ff36cb2baa947609b0a4e23" +checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" dependencies = [ "bytemuck", "byteorder", @@ -3008,14 +3031,47 @@ dependencies = [ "tiff", ] +[[package]] +name = "image" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99314c8a2152b8ddb211f924cdae532d8c5e4c8bb54728e12fff1b0cd5963a10" +dependencies = [ + "bytemuck", + "byteorder-lite", + "color_quant", + "exr", + "gif", + "image-webp", + "num-traits", + "png", + "qoi", + "ravif", + "rayon", + "rgb", + "tiff", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "image-webp" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f79afb8cbee2ef20f59ccd477a218c12a93943d075b492015ecb1bb81f8ee904" +dependencies = [ + "byteorder-lite", + "quick-error", +] + [[package]] name = "image_hasher" -version = "1.2.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f9e64a8c472ea9f81ac448e3b488fd82dcdfce6434cf880882bf36bfb5c268a" +checksum = "9481465fe767d92494987319b0b447a5829edf57f09c52bf8639396abaaeaf78" dependencies = [ "base64", - "image", + "image 0.25.2", "rustdct 0.7.1", "serde", "transpose", @@ -3029,7 +3085,7 @@ checksum = "7af2d89e882e4be2e9b1ef50454aaa8da2c58924960e24521145f16ea4f7fd1c" dependencies = [ "bincode", "blake3", - "image", + "image 0.24.9", "lazy_static", "log", "multicache", @@ -3065,12 +3121,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.3" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -3088,9 +3144,9 @@ dependencies = [ [[package]] name = "infer" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb33622da908807a06f9513c19b3c1ad50fab3e4137d82a78107d502075aa199" +checksum = "bc150e5ce2330295b8616ce0e3f53250e53af31759a9dbedad1621ba29151847" dependencies = [ "cfb", ] @@ -3107,11 +3163,11 @@ dependencies = [ [[package]] name = "input" -version = "0.8.3" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e74cd82cedcd66db78742a8337bdc48f188c4d2c12742cbc5cd85113f0b059" +checksum = "7911ce3db9c10c5ab4a35c49af778a5f9a827bd0f7371d9be56175d8dd2740d0" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "input-sys", "io-lifetimes", "libc", @@ -3127,9 +3183,9 @@ checksum = "bd4f5b4d1c00331c5245163aacfe5f20be75b564c7112d45893d4ae038119eb0" [[package]] name = "instant" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if", ] @@ -3143,11 +3199,22 @@ dependencies = [ "num-traits", ] +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + [[package]] name = "intl-memoizer" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c310433e4a310918d6ed9243542a6b83ec1183df95dff8f23f87bb88a264a66f" +checksum = "fe22e020fce238ae18a6d5d8c502ee76a52a6e880d99477657e6acc30ec57bda" dependencies = [ "type-map", "unic-langid", @@ -3168,7 +3235,7 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", "windows-sys 0.48.0", ] @@ -3192,6 +3259,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "istring" version = "0.3.4" @@ -3219,11 +3292,20 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jni" @@ -3247,6 +3329,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + [[package]] name = "jpeg-decoder" version = "0.3.1" @@ -3258,9 +3349,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.68" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ "wasm-bindgen", ] @@ -3285,7 +3376,7 @@ dependencies = [ "humansize", "i18n-embed", "i18n-embed-fl", - "image", + "image 0.25.2", "image_hasher", "log", "once_cell", @@ -3303,11 +3394,12 @@ dependencies = [ [[package]] name = "kurbo" -version = "0.9.5" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd85a5776cd9500c2e2059c8c76c3b01528566b7fcbaf8098b55a33fc298849b" +checksum = "89234b2cc610a7dd927ebde6b41dd1a5d4214cffaef4cf1fb2195d592f92518f" dependencies = [ "arrayvec", + "smallvec", ] [[package]] @@ -3318,9 +3410,9 @@ checksum = "10257499f089cd156ad82d0a9cd57d9501fa2c989068992a97eb3c27836f206b" [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "lazycell" @@ -3336,15 +3428,15 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libflate" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7d5654ae1795afc7ff76f4365c2c8791b0feb18e8996a96adad8ffd7c3b2bf" +checksum = "45d9dfdc14ea4ef0900c1cddbc8dcd553fbaacd8a4a282cf4018ae9dd04fb21e" dependencies = [ "adler32", "core2", @@ -3355,15 +3447,26 @@ dependencies = [ [[package]] name = "libflate_lz77" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be5f52fb8c451576ec6b79d3f4deb327398bc05bbdbd99021a6e77a4c855d524" +checksum = "e6e0d73b369f386f1c44abd9c570d5318f55ccde816ff4b562fa452e5182863d" dependencies = [ "core2", - "hashbrown 0.13.2", + "hashbrown 0.14.5", "rle-decode-fast", ] +[[package]] +name = "libfuzzer-sys" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7" +dependencies = [ + "arbitrary", + "cc", + "once_cell", +] + [[package]] name = "libheif-rs" version = "0.18.0" @@ -3396,12 +3499,12 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.1" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "windows-sys 0.48.0", + "windows-targets 0.52.6", ] [[package]] @@ -3431,24 +3534,24 @@ dependencies = [ [[package]] name = "libredox" -version = "0.0.1" +version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "libc", "redox_syscall 0.4.1", ] [[package]] name = "libredox" -version = "0.0.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "libc", - "redox_syscall 0.4.1", + "redox_syscall 0.5.6", ] [[package]] @@ -3478,15 +3581,15 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "linux-raw-sys" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0b5399f6804fbab912acbd8878ed3532d506b7c951b8f9f164ef90fef39e3f4" +checksum = "2a385b1be4e5c3e362ad2ffa73c392e53f031eaa5b7d648e64cd87f27f6063d7" [[package]] name = "locale_config" @@ -3503,19 +3606,25 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", ] +[[package]] +name = "lockfree-object-pool" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" + [[package]] name = "lofty" -version = "0.18.2" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f75066eb1d25a7047fb2667edb410ae2592439ed81546f95c28b0a1c7d7d3818" +checksum = "c8bc4717ff10833a623b009e9254ae8667c7a59edc3cfb01c37aeeef4b6d54a7" dependencies = [ "byteorder", "data-encoding", @@ -3528,20 +3637,20 @@ dependencies = [ [[package]] name = "lofty_attr" -version = "0.9.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "764b60e1ddd07e5665a6a17636a95cd7d8f3b86c73503a69c32979d05f72f3cf" +checksum = "28bd4b9d8a5af74808932492521cdd272019b056f75fcc70056bd2c09fceb550" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "log" -version = "0.4.20" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "loom" @@ -3558,11 +3667,20 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] + [[package]] name = "lru" -version = "0.12.2" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2c024b41519440580066ba82aab04092b333e09066a5eb86c7c4890df31f22" +checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" [[package]] name = "lyon_algorithms" @@ -3576,11 +3694,12 @@ dependencies = [ [[package]] name = "lyon_extra" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ce2ae38f2480094ec1f0d5df51a75581fa84f0e8f32a0edb1d264630c99f3b" +checksum = "8c4a243ce61e7e5f3ae6c72a88d8fb081b6c69f13500c15e99cfd1159a833b20" dependencies = [ "lyon_path", + "thiserror", ] [[package]] @@ -3596,9 +3715,9 @@ dependencies = [ [[package]] name = "lyon_path" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca507745ba7ccbc76e5c44e7b63b1a29d2b0d6126f375806a5bbaf657c7d6c45" +checksum = "9c08a606c7a59638d6c6aa18ac91a06aa9fb5f765a7efb27e6a4da58700740d7" dependencies = [ "lyon_geom", "num-traits", @@ -3622,6 +3741,15 @@ dependencies = [ "regex-automata 0.1.10", ] +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", +] + [[package]] name = "md5" version = "0.7.0" @@ -3630,42 +3758,24 @@ checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a5a03cefb0d953ec0be133036f14e109412fa594edc2f77227249db66cc3ed" -dependencies = [ - "libc", -] - -[[package]] -name = "memmap2" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" dependencies = [ "libc", ] [[package]] name = "memoffset" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg", -] - -[[package]] -name = "memoffset" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" dependencies = [ "autocfg", ] @@ -3676,9 +3786,9 @@ version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c43f73953f8cbe511f021b58f18c3ce1c3d1ae13fe953293e13345bf83217f25" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "block", - "core-graphics-types", + "core-graphics-types 0.1.3", "foreign-types", "log", "objc", @@ -3693,9 +3803,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" dependencies = [ "mime", "unicase", @@ -3709,14 +3819,23 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", "simd-adler32", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "multicache" version = "0.6.1" @@ -3728,16 +3847,16 @@ dependencies = [ [[package]] name = "ndk" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "jni-sys", "log", "ndk-sys", "num_enum", - "raw-window-handle 0.5.2", + "raw-window-handle 0.6.2", "thiserror", ] @@ -3749,35 +3868,30 @@ checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" [[package]] name = "ndk-sys" -version = "0.5.0+25.2.9519653" +version = "0.6.0+11769913" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" dependencies = [ "jni-sys", ] [[package]] -name = "nix" -version = "0.26.4" +name = "new_debug_unreachable" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", - "memoffset 0.7.1", -] +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] name = "nix" -version = "0.27.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "cfg-if", + "cfg_aliases", "libc", - "memoffset 0.9.0", + "memoffset", ] [[package]] @@ -3790,6 +3904,12 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -3800,6 +3920,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + [[package]] name = "num-complex" version = "0.3.1" @@ -3811,9 +3941,9 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", ] @@ -3824,6 +3954,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + [[package]] name = "num-integer" version = "0.1.46" @@ -3833,11 +3974,22 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", @@ -3845,23 +3997,23 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ - "proc-macro-crate 3.1.0", + "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] @@ -3902,25 +4054,206 @@ dependencies = [ [[package]] name = "objc-sys" -version = "0.3.2" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7c71324e4180d0899963fc83d9d241ac39e699609fc1025a850aadac8257459" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" [[package]] name = "objc2" -version = "0.4.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "559c5a40fdd30eb5e344fbceacf7595a81e242529fb4e21cf5f43fb4f11ff98d" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" dependencies = [ "objc-sys", "objc2-encode", ] +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.6.0", + "block2", + "libc", + "objc2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation", + "objc2-quartz-core", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2", + "objc2", + "objc2-contacts", + "objc2-foundation", +] + [[package]] name = "objc2-encode" -version = "3.0.0" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7891e71393cd1f227313c9379a26a584ff3d7e6e7159e988851f0934c993f0f8" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.6.0", + "block2", + "dispatch", + "libc", + "objc2", +] + +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2", + "objc2", + "objc2-app-kit", + "objc2-foundation", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "objc2-symbols" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-image", + "objc2-core-location", + "objc2-foundation", + "objc2-link-presentation", + "objc2-quartz-core", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-uniform-type-identifiers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", +] [[package]] name = "objc_exception" @@ -3942,9 +4275,9 @@ dependencies = [ [[package]] name = "ogg_pager" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c949d63b387b25c332f6e39d1762dd4b405008289dd7681f02c258b1294653ca" +checksum = "87b0bef808533c5890ab77279538212efdbbbd9aa4ef1ccdfcfbf77a42f7e6fa" dependencies = [ "byteorder", ] @@ -3961,9 +4294,9 @@ dependencies = [ [[package]] name = "open" -version = "5.0.1" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90878fb664448b54c4e592455ad02831e23a3f7e157374a8b95654731aac7349" +checksum = "61a877bf6abd716642a53ef1b89fb498923a4afca5c754f9050b4d081c05c4b3" dependencies = [ "is-wsl", "libc", @@ -3991,12 +4324,12 @@ dependencies = [ [[package]] name = "os_info" -version = "3.7.0" +version = "3.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "006e42d5b888366f1880eda20371fedde764ed2213dc8496f49622fa0c99cd5e" +checksum = "ae99c7fa6dd38c7cafe1ec085e804f8f555a2f8659b0dbe03f1f9963a9b51092" dependencies = [ "log", - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -4007,18 +4340,18 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "owned_ttf_parser" -version = "0.20.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4586edfe4c648c71797a74c84bacb32b52b212eff5dfe2bb9f2c599844023e7" +checksum = "490d3a563d3122bf7c911a59b0add9389e5ec0f5f0c3ac6b91ff235a0e6a7f90" dependencies = [ - "ttf-parser", + "ttf-parser 0.24.1", ] [[package]] name = "pango" -version = "0.19.2" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7809e8af4df8d024a066106b72ca6bc7253a484ae3867041a96103ef8a13188d" +checksum = "5764e5a174a5a0ec054fe5962ce6d4fc7052e2d0dcc23bbc77202b40a4a403d3" dependencies = [ "gio", "glib", @@ -4028,27 +4361,27 @@ dependencies = [ [[package]] name = "pango-sys" -version = "0.19.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52ef6a881c19fbfe3b1484df5cad411acaaba29dbec843941c3110d19f340ea" +checksum = "fd317e1de76b14b3d3efe05518c08b360327f1ab7fec150473a89ffcad4b072d" dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps", + "system-deps 7.0.3", ] [[package]] name = "parking" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -4056,33 +4389,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", + "redox_syscall 0.5.6", "smallvec", - "windows-targets 0.48.5", -] - -[[package]] -name = "password-hash" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" -dependencies = [ - "base64ct", - "rand_core", - "subtle", + "windows-targets 0.52.6", ] [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pathdiff" @@ -4092,14 +4414,12 @@ checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" [[package]] name = "pbkdf2" -version = "0.11.0" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" dependencies = [ "digest", "hmac", - "password-hash", - "sha2", ] [[package]] @@ -4115,7 +4435,7 @@ dependencies = [ "deflate", "fax", "globalcache", - "indexmap 2.2.3", + "indexmap 2.5.0", "istring", "itertools 0.10.5", "jpeg-decoder", @@ -4155,29 +4475,29 @@ checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" [[package]] name = "pin-project" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -4193,9 +4513,9 @@ checksum = "b330c9d1b92dfe68442ca20b009c717d5f0b1e3cf4965e62f704c3c6e95a1305" [[package]] name = "piper" -version = "0.2.1" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", "fastrand", @@ -4204,9 +4524,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "png" @@ -4218,21 +4538,22 @@ dependencies = [ "crc32fast", "fdeflate", "flate2", - "miniz_oxide", + "miniz_oxide 0.7.4", ] [[package]] name = "polling" -version = "3.5.0" +version = "3.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24f040dee2588b4963afb4e420540439d126f73fdacf4a9c486a96d840bac3c9" +checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" dependencies = [ "cfg-if", "concurrent-queue", + "hermit-abi 0.4.0", "pin-project-lite", "rustix", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4243,9 +4564,9 @@ checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" [[package]] name = "portable-atomic" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" +checksum = "d30538d42559de6b034bc76fd6dd4c38961b1ee5c6c56e3808c50128fdbc22ce" dependencies = [ "critical-section", ] @@ -4258,46 +4579,39 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "prettyplease" -version = "0.2.16" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" +checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" dependencies = [ "proc-macro2", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "primal-check" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9df7f93fd637f083201473dab4fee2db4c429d32e55e3299980ab3957ab916a0" +checksum = "dc0d895b311e3af9902528fbb8f928688abbd95872819320517cc24ca6b2bd08" dependencies = [ "num-integer", ] [[package]] name = "proc-macro-crate" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" -dependencies = [ - "once_cell", - "toml_edit 0.19.15", -] - -[[package]] -name = "proc-macro-crate" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" dependencies = [ - "toml_edit 0.21.1", + "toml_edit", ] [[package]] @@ -4326,13 +4640,32 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] +[[package]] +name = "profiling" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd" +dependencies = [ + "quote", + "syn 2.0.77", +] + [[package]] name = "qoi" version = "0.4.1" @@ -4342,20 +4675,26 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + [[package]] name = "quick-xml" -version = "0.31.0" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" +checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" dependencies = [ "memchr", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -4390,6 +4729,55 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rav1e" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" +dependencies = [ + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools 0.12.1", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "once_cell", + "paste", + "profiling", + "rand", + "rand_chacha", + "simd_helpers", + "system-deps 6.2.2", + "thiserror", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.11.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f0bfd976333248de2078d350bfdf182ff96e168a24d23d2436cef320dd4bdd" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rgb", +] + [[package]] name = "raw-window-handle" version = "0.5.2" @@ -4398,9 +4786,20 @@ checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" [[package]] name = "raw-window-handle" -version = "0.6.0" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "raw-window-metal" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42a9830a0e1b9fb145ebb365b8bc4ccd75f290f98c0247deafbbe2c75cefb544" +checksum = "b2000e45d7daa9b6d946e88dfa1d7ae330424a81918a6545741821c989eb80a9" +dependencies = [ + "objc2", + "objc2-foundation", + "objc2-quartz-core", +] [[package]] name = "rawloader" @@ -4419,9 +4818,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.8.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -4448,43 +4847,43 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "355ae415ccd3a04315d3f8246e86d67689ea74d88d915576e1589a351062a13b" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", ] [[package]] name = "redox_users" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", - "libredox 0.0.1", + "libredox 0.1.3", "thiserror", ] [[package]] name = "regex" -version = "1.10.3" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.5", - "regex-syntax 0.8.2", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", ] [[package]] @@ -4498,13 +4897,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax 0.8.4", ] [[package]] @@ -4515,15 +4914,15 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "resvg" -version = "0.38.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c34501046959e06470ba62a2dc7f31c15f94ac250d842a45f9e012f4ee40c1e" +checksum = "944d052815156ac8fa77eaac055220e95ba0b01fa8887108ca710c03805d9051" dependencies = [ "log", "pico-args", @@ -4535,20 +4934,19 @@ dependencies = [ [[package]] name = "rfd" -version = "0.14.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373d2fc6310e2d14943d4e66ebed5b774a2b6b3b1610e7377edf124fb2760d6b" +checksum = "8af382a047821a08aa6bfc09ab0d80ff48d45d8726f7cd8e44891f7cb4a4278e" dependencies = [ "ashpd", - "block", - "dispatch", + "block2", "js-sys", "log", - "objc", - "objc-foundation", - "objc_id", + "objc2", + "objc2-app-kit", + "objc2-foundation", "pollster", - "raw-window-handle 0.6.0", + "raw-window-handle 0.6.2", "urlencoding", "wasm-bindgen", "wasm-bindgen-futures", @@ -4558,9 +4956,9 @@ dependencies = [ [[package]] name = "rgb" -version = "0.8.37" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" dependencies = [ "bytemuck", ] @@ -4573,22 +4971,21 @@ checksum = "3582f63211428f83597b51b2ddb88e2a91a9d52d12831f9d08f5e624e8977422" [[package]] name = "rowan" -version = "0.15.15" +version = "0.15.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a58fa8a7ccff2aec4f39cc45bf5f985cec7125ab271cf681c279fd00192b49" +checksum = "0a542b0253fa46e632d27a1dc5cf7b930de4df8659dc6e720b647fc72147ae3d" dependencies = [ "countme", - "hashbrown 0.14.3", - "memoffset 0.9.0", + "hashbrown 0.14.5", "rustc-hash", "text-size", ] [[package]] name = "roxmltree" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cd14fd5e3b777a7422cca79358c57a8f6e3a703d9ac187448d0daf220c2407f" +checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" [[package]] name = "rubato" @@ -4596,7 +4993,7 @@ version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6dd52e80cfc21894deadf554a5673002938ae4625f7a283e536f9cf7c17b0d5" dependencies = [ - "num-complex 0.4.5", + "num-complex 0.4.6", "num-integer", "num-traits", "realfft", @@ -4604,9 +5001,9 @@ dependencies = [ [[package]] name = "rust-embed" -version = "8.2.0" +version = "8.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82c0bbc10308ed323529fd3c1dce8badda635aa319a5ff0e6466f33b8101e3f" +checksum = "fa66af4a4fdd5e7ebc276f115e895611a34739a9c1c01028383d612d550953c0" dependencies = [ "rust-embed-impl", "rust-embed-utils", @@ -4615,22 +5012,22 @@ dependencies = [ [[package]] name = "rust-embed-impl" -version = "8.2.0" +version = "8.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6227c01b1783cdfee1bcf844eb44594cd16ec71c35305bf1c9fb5aade2735e16" +checksum = "6125dbc8867951125eec87294137f4e9c2c96566e61bf72c45095a7c77761478" dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.50", + "syn 2.0.77", "walkdir", ] [[package]] name = "rust-embed-utils" -version = "8.2.0" +version = "8.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cb0a25bfbb2d4b4402179c2cf030387d9990857ce08a32592c6238db9fa8665" +checksum = "2e5347777e9aacb56039b0e1f28785929a8a3b709e87482e7442c72e7c12529d" dependencies = [ "sha2", "walkdir", @@ -4644,9 +5041,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] @@ -4689,7 +5086,7 @@ version = "6.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43806561bc506d0c5d160643ad742e3161049ac01027b5e6d7524091fd401d86" dependencies = [ - "num-complex 0.4.5", + "num-complex 0.4.6", "num-integer", "num-traits", "primal-check", @@ -4700,22 +5097,22 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.31" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "errno", "libc", - "linux-raw-sys 0.4.13", + "linux-raw-sys 0.4.14", "windows-sys 0.52.0", ] [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "rusty-chromaprint" @@ -4729,30 +5126,14 @@ dependencies = [ [[package]] name = "rustybuzz" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ee8fe2a8461a0854a37101fe7a1b13998d0cfa987e43248e81d2a5f4570f6fa" -dependencies = [ - "bitflags 1.3.2", - "bytemuck", - "smallvec", - "ttf-parser", - "unicode-bidi-mirroring", - "unicode-ccc", - "unicode-properties", - "unicode-script", -] - -[[package]] -name = "rustybuzz" -version = "0.12.1" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0ae5692c5beaad6a9e22830deeed7874eae8a4e3ba4076fb48e12c56856222c" +checksum = "cfb9cf8877777222e4a3bc7eb247e398b56baba500c38c1c46842431adc8b55c" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "bytemuck", "smallvec", - "ttf-parser", + "ttf-parser 0.21.1", "unicode-bidi-mirroring", "unicode-ccc", "unicode-properties", @@ -4761,9 +5142,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -4782,9 +5163,9 @@ checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "scoped-tls-hkt" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ddc765d3410d9f6c6ca071bf0b67f6b01e3ec4595dc3892f02677e75819dddc" +checksum = "e9603871ffe5df3ac39cb624790c296dbd47a400d202f56bf3e414045099524d" [[package]] name = "scopeguard" @@ -4794,13 +5175,13 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sctk-adwaita" -version = "0.8.1" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b2eaf3a5b264a521b988b2e73042e742df700c4f962cde845d1541adb46550" +checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" dependencies = [ "ab_glyph", "log", - "memmap2 0.9.4", + "memmap2", "smithay-client-toolkit", "tiny-skia", ] @@ -4811,68 +5192,69 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e14e4d63b804dc0c7ec4a1e52bcb63f02c7ac94476755aa579edac21e01f915d" dependencies = [ - "self_cell 1.0.3", + "self_cell 1.0.4", ] [[package]] name = "self_cell" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58bf37232d3bb9a2c4e641ca2a11d83b5062066f88df7fed36c28772046d65ba" +checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "serde_repr" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "serde_spanned" -version = "0.6.5" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -4928,9 +5310,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -4941,6 +5323,15 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + [[package]] name = "simplecss" version = "0.2.1" @@ -4952,37 +5343,37 @@ dependencies = [ [[package]] name = "siphasher" -version = "0.3.11" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "skia-bindings" -version = "0.70.0" +version = "0.78.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bc61a106126a429bb4775ce5fbe23b2bcaa74d1a9c484997f4700de31480b44" +checksum = "a5ac1da945f92ee2c5ae7999bc679d682fd976ef524b09cc80b5aae971d3e557" dependencies = [ "bindgen", "cc", "flate2", - "heck", + "heck 0.5.0", "lazy_static", "regex", "serde_json", "tar", - "toml 0.8.10", + "toml 0.8.19", ] [[package]] name = "skia-safe" -version = "0.70.0" +version = "0.78.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3201eba92bca1f83864f5c3a48309bcfee7e0590bebd7826e7ab0a49aa24a750" +checksum = "80a2993ab98e8f01c874fc35cfec9a8d216d968b80f7e9b1cb9ac1bf4f6a2f3a" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "lazy_static", "skia-bindings", - "windows 0.52.0", + "windows 0.58.0", ] [[package]] @@ -4996,9 +5387,9 @@ dependencies = [ [[package]] name = "slint" -version = "1.4.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d51a972e5c6f22793f9b334eeb537121337fbf66ed73e978475fca031fd367a" +checksum = "c4ec667df21d0bf4a5eb49735ab476c809a625ba2fa9a59a2405bc9edf0977ce" dependencies = [ "const-field-offset", "i-slint-backend-selector", @@ -5013,21 +5404,21 @@ dependencies = [ [[package]] name = "slint-build" -version = "1.4.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebf98969a520e19ec675435b8c21b883d4a06489947e137bbd30859b50ad0c36" +checksum = "ec068281021ccd3a69dbe36a0caf207d88aa5b50945ced9000f17a5d2b139003" dependencies = [ "i-slint-compiler", "spin_on", "thiserror", - "toml_edit 0.21.1", + "toml_edit", ] [[package]] name = "slint-macros" -version = "1.4.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "564b2a25cc34007aa9cd73630394efa972b956fee86538caa5d09808b3ba0c05" +checksum = "9f79eb3465efc8fb2f1939fd7473cbdfc75aa2d4eef3d2b3964b60595e357a2f" dependencies = [ "i-slint-compiler", "proc-macro2", @@ -5046,23 +5437,23 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smithay-client-toolkit" -version = "0.18.1" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "922fd3eeab3bd820d76537ce8f582b1cf951eceb5475c28500c7457d9d17f53a" +checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" dependencies = [ - "bitflags 2.4.2", - "calloop", + "bitflags 2.6.0", + "calloop 0.13.0", "calloop-wayland-source", "cursor-icon", "libc", "log", - "memmap2 0.9.4", + "memmap2", "rustix", "thiserror", "wayland-backend", @@ -5077,9 +5468,9 @@ dependencies = [ [[package]] name = "smithay-clipboard" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c091e7354ea8059d6ad99eace06dd13ddeedbb0ac72d40a9a6e7ff790525882d" +checksum = "cc8216eec463674a0e90f29e0ae41a4db573ec5b56b1c6c1c71615d249b6d846" dependencies = [ "libc", "smithay-client-toolkit", @@ -5088,10 +5479,20 @@ dependencies = [ [[package]] name = "smol_str" -version = "0.2.1" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" +dependencies = [ + "serde", +] + +[[package]] +name = "smol_str" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6845563ada680337a52d43bb0b29f396f2d911616f6573012645b9e3d048a49" +checksum = "66eaf762c5af19db3108300515c8aa7a50efc90ff745f4c62288052ebf9fdd25" dependencies = [ + "borsh", "serde", ] @@ -5111,7 +5512,7 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "990079665f075b699031e9c08fd3ab99be5029b96f3b78dc0709e8f77e4efebf" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "syn 1.0.109", @@ -5119,24 +5520,25 @@ dependencies = [ [[package]] name = "softbuffer" -version = "0.3.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f266ce2aa23eaaaa4e758ed44495d505d00fb79f359d46f6c1900cb053123b62" +checksum = "18051cdd562e792cad055119e0cdb2cfc137e44e3987532e0f9659a77931bb08" dependencies = [ "as-raw-xcb-connection", "bytemuck", - "cfg_aliases 0.1.1", - "cocoa", - "core-graphics", - "drm 0.11.1", + "cfg_aliases", + "core-graphics 0.24.0", + "drm", "fastrand", "foreign-types", "js-sys", "log", - "memmap2 0.9.4", - "objc", - "raw-window-handle 0.5.2", - "redox_syscall 0.4.1", + "memmap2", + "objc2", + "objc2-foundation", + "objc2-quartz-core", + "raw-window-handle 0.6.2", + "redox_syscall 0.5.6", "rustix", "tiny-xlib", "wasm-bindgen", @@ -5144,8 +5546,8 @@ dependencies = [ "wayland-client", "wayland-sys", "web-sys", - "windows-sys 0.48.0", - "x11rb 0.12.0", + "windows-sys 0.59.0", + "x11rb", ] [[package]] @@ -5204,13 +5606,13 @@ dependencies = [ [[package]] name = "stringprep" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" dependencies = [ - "finl_unicode", "unicode-bidi", "unicode-normalization", + "unicode-properties", ] [[package]] @@ -5221,43 +5623,43 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "strsim" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" -version = "0.26.1" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "723b93e8addf9aa965ebe2d11da6d7540fa2283fcea14b3371ff055f7ba13f5f" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" -version = "0.26.1" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a3417fc93d76740d974a01654a09777cb500428cc874ca9f45edfe0c4d4cd18" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", "rustversion", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "svgtypes" -version = "0.13.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e44e288cd960318917cbd540340968b90becc8bc81f171345d706e7a89d9d70" +checksum = "794de53cc48eaabeed0ab6a3404a65f40b3e38c067e4435883a65d2aa4ca000e" dependencies = [ "kurbo", "siphasher", @@ -5265,9 +5667,9 @@ dependencies = [ [[package]] name = "symphonia" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62e48dba70095f265fdb269b99619b95d04c89e619538138383e63310b14d941" +checksum = "815c942ae7ee74737bb00f965fa5b5a2ac2ce7b6c01c0cc169bbeaf7abd5f5a9" dependencies = [ "lazy_static", "symphonia-bundle-flac", @@ -5278,18 +5680,19 @@ dependencies = [ "symphonia-codec-pcm", "symphonia-codec-vorbis", "symphonia-core", + "symphonia-format-caf", "symphonia-format-isomp4", "symphonia-format-mkv", "symphonia-format-ogg", - "symphonia-format-wav", + "symphonia-format-riff", "symphonia-metadata", ] [[package]] name = "symphonia-bundle-flac" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f23b0482a7cb18fcdf9981ab0b78df800ef0080187d294650023c462439058d" +checksum = "72e34f34298a7308d4397a6c7fbf5b84c5d491231ce3dd379707ba673ab3bd97" dependencies = [ "log", "symphonia-core", @@ -5299,11 +5702,10 @@ dependencies = [ [[package]] name = "symphonia-bundle-mp3" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f31d7fece546f1e6973011a9eceae948133bbd18fd3d52f6073b1e38ae6368a" +checksum = "c01c2aae70f0f1fb096b6f0ff112a930b1fb3626178fba3ae68b09dce71706d4" dependencies = [ - "bitflags 1.3.2", "lazy_static", "log", "symphonia-core", @@ -5312,9 +5714,9 @@ dependencies = [ [[package]] name = "symphonia-codec-aac" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68bdd75b25ce4b84b12a4bd20bfea2460c2dbd7fc1d227ef5533504d3168109d" +checksum = "cdbf25b545ad0d3ee3e891ea643ad115aff4ca92f6aec472086b957a58522f70" dependencies = [ "lazy_static", "log", @@ -5323,9 +5725,9 @@ dependencies = [ [[package]] name = "symphonia-codec-adpcm" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "870e7dc1865d818c7b6318879d060553a73a3b2a3b8443dff90910f10ac41150" +checksum = "c94e1feac3327cd616e973d5be69ad36b3945f16b06f19c6773fc3ac0b426a0f" dependencies = [ "log", "symphonia-core", @@ -5333,9 +5735,9 @@ dependencies = [ [[package]] name = "symphonia-codec-alac" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a27e8763d1c9eff666faf903e73a99d4de2f7a93fca4e3c214c1d68432903b9" +checksum = "2d8a6666649a08412906476a8b0efd9b9733e241180189e9f92b09c08d0e38f3" dependencies = [ "log", "symphonia-core", @@ -5343,9 +5745,9 @@ dependencies = [ [[package]] name = "symphonia-codec-pcm" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47f1fbd220a06a641c8ce2ddad10f5ef6ee5cc0c54d9044d25d43b0d3119deaa" +checksum = "f395a67057c2ebc5e84d7bb1be71cce1a7ba99f64e0f0f0e303a03f79116f89b" dependencies = [ "log", "symphonia-core", @@ -5353,9 +5755,9 @@ dependencies = [ [[package]] name = "symphonia-codec-vorbis" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3953397e3506aa01350c4205817e4f95b58d476877a42f0458d07b665749e203" +checksum = "5a98765fb46a0a6732b007f7e2870c2129b6f78d87db7987e6533c8f164a9f30" dependencies = [ "log", "symphonia-core", @@ -5364,9 +5766,9 @@ dependencies = [ [[package]] name = "symphonia-core" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c73eb88fee79705268cc7b742c7bc93a7b76e092ab751d0833866970754142" +checksum = "798306779e3dc7d5231bd5691f5a813496dc79d3f56bf82e25789f2094e022c3" dependencies = [ "arrayvec", "bitflags 1.3.2", @@ -5375,11 +5777,22 @@ dependencies = [ "log", ] +[[package]] +name = "symphonia-format-caf" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e43c99c696a388295a29fe71b133079f5d8b18041cf734c5459c35ad9097af50" +dependencies = [ + "log", + "symphonia-core", + "symphonia-metadata", +] + [[package]] name = "symphonia-format-isomp4" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf14bae5cf352032416bc64151e5d6242d29d33cbf3238513b44d4427a1efb" +checksum = "abfdf178d697e50ce1e5d9b982ba1b94c47218e03ec35022d9f0e071a16dc844" dependencies = [ "encoding_rs", "log", @@ -5390,9 +5803,9 @@ dependencies = [ [[package]] name = "symphonia-format-mkv" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5c61dfc851ad25d4043d8c231d8617e8f7cd02a6cc0edad21ade21848d58895" +checksum = "1bb43471a100f7882dc9937395bd5ebee8329298e766250b15b3875652fe3d6f" dependencies = [ "lazy_static", "log", @@ -5403,9 +5816,9 @@ dependencies = [ [[package]] name = "symphonia-format-ogg" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bf1a00ccd11452d44048a0368828040f778ae650418dbd9d8765b7ee2574c8d" +checksum = "ada3505789516bcf00fc1157c67729eded428b455c27ca370e41f4d785bfa931" dependencies = [ "log", "symphonia-core", @@ -5414,11 +5827,12 @@ dependencies = [ ] [[package]] -name = "symphonia-format-wav" -version = "0.5.3" +name = "symphonia-format-riff" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da76614728fa27c003bdcdfbac51396bd8fcbf94c95fe8e62f1d2bac58ef03a4" +checksum = "05f7be232f962f937f4b7115cbe62c330929345434c834359425e043bfd15f50" dependencies = [ + "extended", "log", "symphonia-core", "symphonia-metadata", @@ -5426,9 +5840,9 @@ dependencies = [ [[package]] name = "symphonia-metadata" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89c3e1937e31d0e068bbe829f66b2f2bfaa28d056365279e0ef897172c3320c0" +checksum = "bc622b9841a10089c5b18e99eb904f4341615d5aa55bbf4eedde1be721a4023c" dependencies = [ "encoding_rs", "lazy_static", @@ -5438,9 +5852,9 @@ dependencies = [ [[package]] name = "symphonia-utils-xiph" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a450ca645b80d69aff8b35576cbfdc7f20940b29998202aab910045714c951f8" +checksum = "484472580fa49991afda5f6550ece662237b00c6f562c7d9638d1b086ed010fe" dependencies = [ "symphonia-core", "symphonia-metadata", @@ -5459,9 +5873,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.50" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -5470,22 +5884,35 @@ dependencies = [ [[package]] name = "system-deps" -version = "6.2.0" +version = "6.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +dependencies = [ + "cfg-expr 0.15.8", + "heck 0.5.0", + "pkg-config", + "toml 0.8.19", + "version-compare", +] + +[[package]] +name = "system-deps" +version = "7.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2d580ff6a20c55dfb86be5f9c238f67835d0e81cbdea8bf5680e0897320331" +checksum = "66d23aaf9f331227789a99e8de4c91bf46703add012bdfd45fdecdfb2975a005" dependencies = [ - "cfg-expr", - "heck", + "cfg-expr 0.17.0", + "heck 0.5.0", "pkg-config", - "toml 0.8.10", + "toml 0.8.19", "version-compare", ] [[package]] name = "tar" -version = "0.4.40" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" +checksum = "4ff6c40d3aedb5e06b57c6f669ad17ab063dd1e63d977c6a88e7f4dfa4f04020" dependencies = [ "filetime", "libc", @@ -5494,20 +5921,21 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.14" +version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tempfile" -version = "3.10.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", "fastrand", + "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5527,22 +5955,22 @@ checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233" [[package]] name = "thiserror" -version = "1.0.57" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.57" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] @@ -5568,9 +5996,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.34" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", @@ -5591,9 +6019,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ "num-conv", "time-core", @@ -5627,30 +6055,31 @@ dependencies = [ [[package]] name = "tiny-xlib" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4098d49269baa034a8d1eae9bd63e9fa532148d772121dace3bcd6a6c98eb6d" +checksum = "1d52f22673960ad13af14ff4025997312def1223bfa7c8e4949d099e6b3d5d1c" dependencies = [ "as-raw-xcb-connection", - "ctor", - "libloading 0.8.1", + "ctor-lite", + "libloading 0.8.5", + "pkg-config", "tracing", ] [[package]] name = "tinystr" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c02bf3c538ab32ba913408224323915f4ef9a6d61c0e85d493f355921c0ece" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" dependencies = [ "displaydoc", ] [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -5672,58 +6101,36 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.10" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.6", + "toml_edit", ] [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.19.15" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.2.3", - "toml_datetime", - "winnow 0.5.40", -] - -[[package]] -name = "toml_edit" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" -dependencies = [ - "indexmap 2.2.3", - "toml_datetime", - "winnow 0.5.40", -] - -[[package]] -name = "toml_edit" -version = "0.22.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1b5fd4128cc8d3e0cb74d4ed9a9cc7c7284becd4df68f5f940e1ad123606f6" -dependencies = [ - "indexmap 2.2.3", + "indexmap 2.5.0", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.2", + "winnow", ] [[package]] @@ -5732,6 +6139,7 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -5745,7 +6153,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] @@ -5799,18 +6207,19 @@ dependencies = [ [[package]] name = "trash" -version = "3.3.1" +version = "5.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c658458d46d9d5a153a3b5cdd88d8579ad50d4fb85d53961e4526c8fc7c55a57" +checksum = "33caf2a9be1812a263a4bfce74d2de225fcde12ee7b77001361abd2b34ffdcc4" dependencies = [ "chrono", "libc", "log", - "objc", + "objc2", + "objc2-foundation", "once_cell", "scopeguard", - "url", - "windows 0.44.0", + "urlencoding", + "windows 0.56.0", ] [[package]] @@ -5821,9 +6230,15 @@ checksum = "622b09ce2fe2df4618636fb92176d205662f59803f39e70d1c333393082de96c" [[package]] name = "ttf-parser" -version = "0.20.0" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c591d83f69777866b9126b24c6dd9a18351f177e49d625920d19f989fd31cf8" + +[[package]] +name = "ttf-parser" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4" +checksum = "5be21190ff5d38e8b4a2d3b6a3ae57f612cc39c96e83cedeaf7abc338a8bac4a" [[package]] name = "tuple" @@ -5837,9 +6252,9 @@ dependencies = [ [[package]] name = "type-map" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d3364c5e96cb2ad1603037ab253ddd34d7fb72a58bdddf4b7350760fc69a46" +checksum = "deb68604048ff8fa93347f02441e4487594adc20bb8a084f9e564d2b827a0a9f" dependencies = [ "rustc-hash", ] @@ -5861,10 +6276,11 @@ dependencies = [ [[package]] name = "udev" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebdbbd670373442a12fe9ef7aeb53aec4147a5a27a00bbc3ab639f08f48191a" +checksum = "50051c6e22be28ee6f217d50014f3bc29e81c20dc66ff7ca0d5c5226e1dcc5a1" dependencies = [ + "io-lifetimes", "libc", "libudev-sys", "pkg-config", @@ -5876,25 +6292,25 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" dependencies = [ - "memoffset 0.9.0", + "memoffset", "tempfile", "winapi", ] [[package]] name = "unic-langid" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "238722e6d794ed130f91f4ea33e01fcff4f188d92337a21297892521c72df516" +checksum = "23dd9d1e72a73b25e07123a80776aae3e7b0ec461ef94f9151eed6ec88005a44" dependencies = [ "unic-langid-impl", ] [[package]] name = "unic-langid-impl" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bd55a2063fdea4ef1f8633243a7b0524cbeef1905ae04c31a1c9b9775c55bc6" +checksum = "0a5422c1f65949306c99240b81de9f3f15929f5a8bfe05bb44b034cc8bf593e5" dependencies = [ "serde", "tinystr", @@ -5917,21 +6333,21 @@ checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-bidi-mirroring" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56d12260fb92d52f9008be7e4bca09f584780eb2266dc8fecc6a192bec561694" +checksum = "23cb788ffebc92c5948d0e997106233eeb1d8b9512f93f41651f52b6c5f5af86" [[package]] name = "unicode-ccc" -version = "0.1.2" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2520efa644f8268dce4dcd3050eaa7fc044fca03961e9998ac7e2e92b77cf1" +checksum = "1df77b101bcc4ea3d78dafc5ad7e4f58ceffe0b2b16bf446aeb50b6cb4157656" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-linebreak" @@ -5941,30 +6357,30 @@ checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" [[package]] name = "unicode-normalization" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] name = "unicode-properties" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291" +checksum = "52ea75f83c0137a9b98608359a5f1af8144876eb67bcb1ce837368e906a9f524" [[package]] name = "unicode-script" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad8d71f5726e5f285a935e9fe8edfd53f0491eb6e9a5774097fdabee7cd8c9cd" +checksum = "9fb421b350c9aff471779e262955939f565ec18b86c15364e6bdf0d662ca7c1f" [[package]] name = "unicode-segmentation" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-vo" @@ -5974,15 +6390,15 @@ checksum = "b1d386ff53b415b7fe27b50bb44679e2cc4660272694b7b6f3326d8480823a94" [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "url" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", @@ -5998,75 +6414,53 @@ checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" [[package]] name = "usvg" -version = "0.38.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "377f62b4a3c173de8654c1aa80ab1dac1154e6f13a779a9943e53780120d1625" +checksum = "b84ea542ae85c715f07b082438a4231c3760539d902e11d093847a0b22963032" dependencies = [ "base64", - "log", - "pico-args", - "usvg-parser", - "usvg-text-layout", - "usvg-tree", - "xmlwriter", -] - -[[package]] -name = "usvg-parser" -version = "0.38.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "351a05e6f2023d6b4e946f734240a3927aefdcf930d7d42587a2c8a8869814b0" -dependencies = [ "data-url", "flate2", + "fontdb", "imagesize", "kurbo", "log", + "pico-args", "roxmltree", + "rustybuzz", "simplecss", "siphasher", + "strict-num", "svgtypes", - "usvg-tree", -] - -[[package]] -name = "usvg-text-layout" -version = "0.38.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c41888b9d5cf431fe852eaf9d047bbde83251b98f1749c2f08b1071e6db46e2" -dependencies = [ - "fontdb", - "kurbo", - "log", - "rustybuzz 0.12.1", + "tiny-skia-path", "unicode-bidi", "unicode-script", "unicode-vo", - "usvg-tree", + "xmlwriter", ] [[package]] -name = "usvg-tree" -version = "0.38.0" +name = "utf8parse" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18863e0404ed153d6e56362c5b1146db9f4f262a3244e3cf2dbe7d8a85909f05" -dependencies = [ - "strict-num", - "svgtypes", - "tiny-skia-path", -] +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] -name = "utf8parse" -version = "0.2.1" +name = "uuid" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" [[package]] -name = "uuid" -version = "1.7.0" +name = "v_frame" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] [[package]] name = "valuable" @@ -6076,15 +6470,15 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "version-compare" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" +checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "vid_dup_finder_lib" @@ -6093,7 +6487,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6aeb8f9a4a0c8aeb3963a0db7ecd80c92353576c807949faeae08a7b259b0a2" dependencies = [ "ffmpeg_cmdline_utils", - "image", + "image 0.24.9", "rand", "rayon", "rustdct 0.6.0", @@ -6114,9 +6508,9 @@ dependencies = [ [[package]] name = "vtable" -version = "0.1.11" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f4c7506238561777a1861d3dc3c0001877c475187e7bc4392ea87ebf631fd9c" +checksum = "379cd4a9d99f35bcf1687282268b94b59f14b098cba210632605f39709230963" dependencies = [ "const-field-offset", "portable-atomic", @@ -6126,13 +6520,13 @@ dependencies = [ [[package]] name = "vtable-macro" -version = "0.1.10" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b2b8eecdb8e4284adf5546fc518f048f6dc33e7203dbe36fa93a4add39b31f6" +checksum = "68c1b85ec843d3bc60e9d65fa7e00ce6549416a25c267b5ea93e6c81e3aa66e5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] @@ -6144,12 +6538,12 @@ dependencies = [ "ahash", "ash", "bytemuck", - "core-graphics-types", + "core-graphics-types 0.1.3", "crossbeam-queue", "half", - "heck", - "indexmap 2.2.3", - "libloading 0.8.1", + "heck 0.4.1", + "indexmap 2.5.0", + "libloading 0.8.5", "objc", "once_cell", "parking_lot", @@ -6166,9 +6560,9 @@ dependencies = [ [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -6182,34 +6576,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.91" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.91" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.41" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" dependencies = [ "cfg-if", "js-sys", @@ -6219,9 +6614,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.91" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -6229,28 +6624,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.91" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.91" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "wayland-backend" -version = "0.3.3" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d50fa61ce90d76474c87f5fc002828d81b32677340112b4ef08079a9d459a40" +checksum = "056535ced7a150d45159d3a8dc30f91a2e2d588ca0b23f70e56033622b8016f6" dependencies = [ "cc", "downcast-rs", @@ -6262,11 +6657,11 @@ dependencies = [ [[package]] name = "wayland-client" -version = "0.31.2" +version = "0.31.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82fb96ee935c2cea6668ccb470fb7771f6215d1691746c2d896b447a00ad3f1f" +checksum = "e3f45d1222915ef1fd2057220c1d9d9624b7654443ea35c3877f7a52bd0a5a2d" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "rustix", "wayland-backend", "wayland-scanner", @@ -6278,16 +6673,16 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "cursor-icon", "wayland-backend", ] [[package]] name = "wayland-cursor" -version = "0.31.1" +version = "0.31.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71ce5fa868dd13d11a0d04c5e2e65726d0897be8de247c0c5a65886e283231ba" +checksum = "3a94697e66e76c85923b0d28a0c251e8f0666f58fc47d316c0f4da6da75d37cb" dependencies = [ "rustix", "wayland-client", @@ -6296,11 +6691,11 @@ dependencies = [ [[package]] name = "wayland-protocols" -version = "0.31.2" +version = "0.32.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4" +checksum = "2b5755d77ae9040bb872a25026555ce4cb0ae75fd923e90d25fba07d81057de0" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "wayland-backend", "wayland-client", "wayland-scanner", @@ -6308,11 +6703,11 @@ dependencies = [ [[package]] name = "wayland-protocols-plasma" -version = "0.2.0" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23803551115ff9ea9bce586860c5c5a971e360825a0309264102a9495a5ff479" +checksum = "8a0a41a6875e585172495f7a96dfa42ca7e0213868f4f15c313f7c33221a7eff" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -6321,11 +6716,11 @@ dependencies = [ [[package]] name = "wayland-protocols-wlr" -version = "0.2.0" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" +checksum = "dad87b5fd1b1d3ca2f792df8f686a2a11e3fe1077b71096f7a175ab699f89109" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -6334,9 +6729,9 @@ dependencies = [ [[package]] name = "wayland-scanner" -version = "0.31.1" +version = "0.31.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63b3a62929287001986fb58c789dce9b67604a397c15c611ad9f747300b6c283" +checksum = "597f2001b2e5fc1121e3d5b9791d3e78f05ba6bfa4641053846248e3a13661c3" dependencies = [ "proc-macro2", "quick-xml", @@ -6345,9 +6740,9 @@ dependencies = [ [[package]] name = "wayland-sys" -version = "0.31.1" +version = "0.31.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15a0c8eaff5216d07f226cb7a549159267f3467b289d9a2e52fd3ef5aae2b7af" +checksum = "efa8ac0d8e8ed3e3b5c9fc92c7881406a268e11555abe36493efabe649a29e09" dependencies = [ "dlib", "log", @@ -6357,19 +6752,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "web-time" -version = "0.2.4" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa30049b1c872b72c89866d458eae9f20380ab280ffd1b1e18df2d3e2d98cfe0" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" dependencies = [ "js-sys", "wasm-bindgen", @@ -6377,9 +6762,9 @@ dependencies = [ [[package]] name = "web-time" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ee269d72cc29bf77a2c4bc689cc750fb39f5cbd493d2205bbb3f5c7779cf7b0" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ "js-sys", "wasm-bindgen", @@ -6421,20 +6806,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-wsapoll" -version = "0.1.1" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "winapi", + "windows-sys 0.59.0", ] [[package]] @@ -6445,30 +6821,31 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.44.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets 0.42.2", + "windows-targets 0.48.5", ] [[package]] name = "windows" -version = "0.48.0" +version = "0.56.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132" dependencies = [ - "windows-targets 0.48.5", + "windows-core 0.56.0", + "windows-targets 0.52.6", ] [[package]] name = "windows" -version = "0.52.0" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" dependencies = [ - "windows-core", - "windows-targets 0.52.2", + "windows-core 0.58.0", + "windows-targets 0.52.6", ] [[package]] @@ -6477,7 +6854,104 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.2", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6" +dependencies = [ + "windows-implement 0.56.0", + "windows-interface 0.56.0", + "windows-result 0.1.2", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement 0.58.0", + "windows-interface 0.58.0", + "windows-result 0.2.0", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "windows-interface" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result 0.2.0", + "windows-targets 0.52.6", ] [[package]] @@ -6504,7 +6978,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.2", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -6539,17 +7022,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98532992affa02e52709d5b4d145a3668ae10d9081eea4a7f26f719a8476f71" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.1", - "windows_aarch64_msvc 0.52.1", - "windows_i686_gnu 0.52.1", - "windows_i686_msvc 0.52.1", - "windows_x86_64_gnu 0.52.1", - "windows_x86_64_gnullvm 0.52.1", - "windows_x86_64_msvc 0.52.1", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -6566,9 +7050,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7269c1442e75af9fa59290383f7665b828efc76c429cc0b7f2ecb33cf51ebae" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -6584,9 +7068,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f70ab2cebf332b7ecbdd98900c2da5298a8c862472fb35c75fc297eabb9d89b8" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -6602,9 +7086,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.1" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "679f235acf6b1639408c0f6db295697a19d103b0cdc88146aa1b992c580c647d" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -6620,9 +7110,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3480ac194b55ae274a7e135c21645656825da4a7f5b6e9286291b2113c94a78b" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -6638,9 +7128,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42c46bab241c121402d1cb47d028ea3680ee2f359dcc287482dcf7fdddc73363" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -6656,9 +7146,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc885a4332ee1afb9a1bacf11514801011725570d35675abc229ce7e3afe4d20" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -6674,43 +7164,47 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e440c60457f84b0bee09208e62acc7ade264b38c4453f6312b8c9ab1613e73c" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winit" -version = "0.29.10" +version = "0.30.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c824f11941eeae66ec71111cc2674373c772f482b58939bb4066b642aa2ffcf" +checksum = "0be9e76a1f1077e04a411f0b989cbd3c93339e1771cb41e71ac4aee95bfd2c67" dependencies = [ "ahash", "android-activity", "atomic-waker", - "bitflags 2.4.2", + "bitflags 2.6.0", + "block2", "bytemuck", - "calloop", - "cfg_aliases 0.1.1", - "core-foundation", - "core-graphics", + "calloop 0.13.0", + "cfg_aliases", + "concurrent-queue", + "core-foundation 0.9.4", + "core-graphics 0.23.2", "cursor-icon", - "icrate", + "dpi", "js-sys", "libc", - "log", - "memmap2 0.9.4", + "memmap2", "ndk", - "ndk-sys", "objc2", - "once_cell", + "objc2-app-kit", + "objc2-foundation", + "objc2-ui-kit", "orbclient", "percent-encoding", - "raw-window-handle 0.5.2", - "redox_syscall 0.3.5", + "pin-project", + "raw-window-handle 0.6.2", + "redox_syscall 0.4.1", "rustix", "sctk-adwaita", "smithay-client-toolkit", - "smol_str", + "smol_str 0.2.2", + "tracing", "unicode-segmentation", "wasm-bindgen", "wasm-bindgen-futures", @@ -6719,27 +7213,18 @@ dependencies = [ "wayland-protocols", "wayland-protocols-plasma", "web-sys", - "web-time 0.2.4", - "windows-sys 0.48.0", + "web-time", + "windows-sys 0.52.0", "x11-dl", - "x11rb 0.13.0", + "x11rb", "xkbcommon-dl", ] [[package]] name = "winnow" -version = "0.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] - -[[package]] -name = "winnow" -version = "0.6.2" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a4191c47f15cc3ec71fcb4913cb83d58def65dd3787610213c649283b5ce178" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] @@ -6755,12 +7240,12 @@ dependencies = [ [[package]] name = "x11-clipboard" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613c2be3e772af2bbb57c5a94413675f5ec668bac00a71ada2ced28c420ef087" +checksum = "b98785a09322d7446e28a13203d2cae1059a0dd3dfb32cb06d0a225f023d8286" dependencies = [ "libc", - "x11rb 0.13.0", + "x11rb", ] [[package]] @@ -6776,50 +7261,24 @@ dependencies = [ [[package]] name = "x11rb" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1641b26d4dec61337c35a1b1aaf9e3cba8f46f0b43636c609ab0291a648040a" -dependencies = [ - "as-raw-xcb-connection", - "gethostname 0.3.0", - "libc", - "libloading 0.7.4", - "nix 0.26.4", - "once_cell", - "winapi", - "winapi-wsapoll", - "x11rb-protocol 0.12.0", -] - -[[package]] -name = "x11rb" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8f25ead8c7e4cba123243a6367da5d3990e0d3affa708ea19dce96356bd9f1a" +checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" dependencies = [ "as-raw-xcb-connection", - "gethostname 0.4.3", + "gethostname", "libc", - "libloading 0.8.1", + "libloading 0.8.5", "once_cell", "rustix", - "x11rb-protocol 0.13.0", -] - -[[package]] -name = "x11rb-protocol" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d6c3f9a0fb6701fab8f6cea9b0c0bd5d6876f1f89f7fada07e558077c344bc" -dependencies = [ - "nix 0.26.4", + "x11rb-protocol", ] [[package]] name = "x11rb-protocol" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e63e71c4b8bd9ffec2c963173a4dc4cbde9ee96961d4fcb4429db9929b606c34" +checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" [[package]] name = "xattr" @@ -6828,34 +7287,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" dependencies = [ "libc", - "linux-raw-sys 0.4.13", + "linux-raw-sys 0.4.14", "rustix", ] [[package]] name = "xcursor" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a0ccd7b4a5345edfcd0c3535718a4e9ff7798ffc536bb5b5a0e26ff84732911" +checksum = "0ef33da6b1660b4ddbfb3aef0ade110c8b8a781a3b6382fa5f2b5b040fd55f61" [[package]] name = "xdg-home" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e5a325c3cb8398ad6cf859c1135b25dd29e186679cf2da7581d9679f63b38e" +checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" dependencies = [ "libc", - "winapi", + "windows-sys 0.59.0", ] [[package]] name = "xkbcommon" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13867d259930edc7091a6c41b4ce6eee464328c6ff9659b7e4c668ca20d4c91e" +checksum = "8d66ca9352cbd4eecbbc40871d8a11b4ac8107cfc528a6e14d7c19c69d0e1ac9" dependencies = [ "libc", - "memmap2 0.8.0", + "memmap2", "xkeysym", ] @@ -6865,7 +7324,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "dlib", "log", "once_cell", @@ -6874,15 +7333,15 @@ dependencies = [ [[package]] name = "xkeysym" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "054a8e68b76250b253f671d1268cb7f1ae089ec35e195b2efb2a4e9a836d0621" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" [[package]] name = "xml-rs" -version = "0.8.19" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" +checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26" [[package]] name = "xmlwriter" @@ -6892,9 +7351,9 @@ checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" [[package]] name = "xxhash-rust" -version = "0.8.10" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927da81e25be1e1a2901d59b81b37dd2efd1fc9c9345a55007f09bf5a2d3ee03" +checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984" [[package]] name = "yaml-rust" @@ -6907,28 +7366,27 @@ dependencies = [ [[package]] name = "zbus" -version = "4.0.1" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b8e3d6ae3342792a6cc2340e4394334c7402f3d793b390d2c5494a4032b3030" +checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725" dependencies = [ "async-broadcast", "async-executor", "async-fs", "async-io", - "async-lock 3.3.0", + "async-lock", "async-process", "async-recursion", "async-task", "async-trait", "blocking", - "derivative", "enumflags2", - "event-listener 5.1.0", + "event-listener", "futures-core", "futures-sink", "futures-util", "hex", - "nix 0.27.1", + "nix", "ordered-stream", "rand", "serde", @@ -6946,15 +7404,14 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "4.0.1" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7a3e850ff1e7217a3b7a07eba90d37fe9bb9e89a310f718afcde5885ca9b6d7" +checksum = "267db9407081e90bbfa46d841d3cbc60f59c0351838c4bc65199ecd79ab1983e" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", - "regex", - "syn 1.0.109", + "syn 2.0.77", "zvariant_utils", ] @@ -6971,43 +7428,91 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.77", ] [[package]] name = "zip" -version = "0.6.6" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +checksum = "dc5e4288ea4057ae23afc69a4472434a87a2495cafce6632fd1c4ec9f5cf3494" dependencies = [ "aes", - "byteorder", + "arbitrary", "bzip2", - "constant_time_eq 0.1.5", + "constant_time_eq", "crc32fast", "crossbeam-utils", + "displaydoc", "flate2", "hmac", + "indexmap 2.5.0", + "memchr", "pbkdf2", + "rand", "sha1", + "thiserror", "time", + "zeroize", + "zopfli", +] + +[[package]] +name = "zopfli" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5019f391bac5cf252e93bbcc53d039ffd62c7bfb7c150414d61369afe57e946" +dependencies = [ + "bumpalo", + "crc32fast", + "lockfree-object-pool", + "log", + "once_cell", + "simd-adler32", ] +[[package]] +name = "zune-core" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" + [[package]] name = "zune-inflate" version = "0.2.54" @@ -7017,11 +7522,20 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "zune-jpeg" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16099418600b4d8f028622f73ff6e3deaabdff330fb9a2a131dea781ee8b0768" +dependencies = [ + "zune-core", +] + [[package]] name = "zvariant" -version = "4.0.0" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e09e8be97d44eeab994d752f341e67b3b0d80512a8b315a0671d47232ef1b65" +checksum = "2084290ab9a1c471c38fc524945837734fbf124487e105daec2bb57fd48c81fe" dependencies = [ "endi", "enumflags2", @@ -7033,24 +7547,24 @@ dependencies = [ [[package]] name = "zvariant_derive" -version = "4.0.0" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72a5857e2856435331636a9fbb415b09243df4521a267c5bedcd5289b4d5799e" +checksum = "73e2ba546bda683a90652bac4a279bc146adad1386f25379cf73200d2002c449" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.77", "zvariant_utils", ] [[package]] name = "zvariant_utils" -version = "1.1.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00bedb16a193cc12451873fee2a1bc6550225acece0e36f333e68326c73c8172" +checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.77", ] diff --git a/Changelog.md b/Changelog.md index c270b7129..d476bf87b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,116 +1,187 @@ +## Version 8.0.0 - ? + +### Core + +- Removed some unnecessary panics +- Simplified usage of structures when sending/receiving progress information +- Added Median hash algorithm +- Fixed compilation with Rust >=1.80 +- Extracted tool input parameters, that helped to find not used parameters +- Added new mod to find similar music only in groups with similar title tag + +### Krokiet + +- Fixed invalid default hash size in similar images +- Fixed and added more input parameters to the application + +### GTK GUI + +- Fixed and added more input parameters to the application + +### CLI + +- Fixed and added more input parameters to the application + ## Version 7.0.0 - 19.02.2024r + ### 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 + - 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) ### CLI -- Providing full static rust binary with [Eyra](https://github.com/sunfishcode/eyra) - [#1102](https://github.com/qarmin/czkawka/pull/1102) -- Fixed duplicated `-c` argument, now saving as compact json is handled via `-C` - [#1153](https://github.com/qarmin/czkawka/pull/1153) + +- Providing full static rust binary + with [Eyra](https://github.com/sunfishcode/eyra) - [#1102](https://github.com/qarmin/czkawka/pull/1102) +- Fixed duplicated `-c` argument, now saving as compact json is handled via + `-C` - [#1153](https://github.com/qarmin/czkawka/pull/1153) - Added scan progress bar - [#1183](https://github.com/qarmin/czkawka/pull/1183) - Clean and safe cancelling of scan - [#1183](https://github.com/qarmin/czkawka/pull/1183) - Unification of CLI arguments - [#1183](https://github.com/qarmin/czkawka/pull/1183) - Hardlink support for similar images/videos - [#1201](https://github.com/qarmin/czkawka/pull/1201) ### Krokiet GUI + - Initial release of new gui - [#1102](https://github.com/qarmin/czkawka/pull/1102) ### Core -- Using normal crossbeam channels instead of asyncio tokio channel - [#1102](https://github.com/qarmin/czkawka/pull/1102) + +- Using normal crossbeam channels instead of asyncio tokio + channel - [#1102](https://github.com/qarmin/czkawka/pull/1102) - Fixed tool type when using progress of empty directories - [#1102](https://github.com/qarmin/czkawka/pull/1102) -- Fixed missing json support when saving size and name duplicate results - [#1102](https://github.com/qarmin/czkawka/pull/1102) +- Fixed missing json support when saving size and name duplicate + results - [#1102](https://github.com/qarmin/czkawka/pull/1102) - Fix cross-compiled debug windows build - [#1102](https://github.com/qarmin/czkawka/pull/1102) -- Added bigger stack size by default(fixes stack overflow in some musl apps) - [#1102](https://github.com/qarmin/czkawka/pull/1102) -- Added optional libraw dependency(better single-core performance and support more raw files) - [#1102](https://github.com/qarmin/czkawka/pull/1102) -- Speedup checking for wildcards and fix invalid recognizing long excluded items - [#1152](https://github.com/qarmin/czkawka/pull/1152) -- Big speedup when searching for empty folders(especially with multithreading + cached FS schema) - [#1152](https://github.com/qarmin/czkawka/pull/1152) -- Collecting files for scan can be a lot of faster due lazy file metadata gathering - [#1152](https://github.com/qarmin/czkawka/pull/1152) +- Added bigger stack size by default(fixes stack overflow in some musl + apps) - [#1102](https://github.com/qarmin/czkawka/pull/1102) +- Added optional libraw dependency(better single-core performance and support more raw + files) - [#1102](https://github.com/qarmin/czkawka/pull/1102) +- Speedup checking for wildcards and fix invalid recognizing long excluded + items - [#1152](https://github.com/qarmin/czkawka/pull/1152) +- Big speedup when searching for empty folders(especially with multithreading + cached FS + schema) - [#1152](https://github.com/qarmin/czkawka/pull/1152) +- Collecting files for scan can be a lot of faster due lazy file metadata + gathering - [#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) -- 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) -- Added ability to remove from scan files with excluded extensions - [#1184](https://github.com/qarmin/czkawka/pull/1102) -- Fixed not showing in similar images results, files with same hashes when using reference folders - [#1184](https://github.com/qarmin/czkawka/pull/1102) -- Optimize release binaries with LTO(~25/50% smaller, ~5/10% faster) - [#1184](https://github.com/qarmin/czkawka/pull/1102) +- 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) +- Added ability to remove from scan files with excluded + extensions - [#1184](https://github.com/qarmin/czkawka/pull/1102) +- Fixed not showing in similar images results, files with same hashes when using reference + folders - [#1184](https://github.com/qarmin/czkawka/pull/1102) +- Optimize release binaries with LTO(~25/50% smaller, ~5/10% + faster) - [#1184](https://github.com/qarmin/czkawka/pull/1102) ## 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) - Remove up to 340ms of delay when waiting for results - [#1070](https://github.com/qarmin/czkawka/pull/1070) -- Added logger with useful info when debugging app (level can be adjusted via e.g. `RUST_LOG=debug` env) - [#1072](https://github.com/qarmin/czkawka/pull/1072), [#1070](https://github.com/qarmin/czkawka/pull/1070) -- Core code cleanup - [#1072](https://github.com/qarmin/czkawka/pull/1072), [#1070](https://github.com/qarmin/czkawka/pull/1070), [#1082](https://github.com/qarmin/czkawka/pull/1082) -- Updated list of bad extensions and support for finding invalid jar files - [#1070](https://github.com/qarmin/czkawka/pull/1070) +- Added logger with useful info when debugging app (level can be adjusted via e.g. `RUST_LOG=debug` + env) - [#1072](https://github.com/qarmin/czkawka/pull/1072), [#1070](https://github.com/qarmin/czkawka/pull/1070) +- Core code + cleanup - [#1072](https://github.com/qarmin/czkawka/pull/1072), [#1070](https://github.com/qarmin/czkawka/pull/1070), [#1082](https://github.com/qarmin/czkawka/pull/1082) +- Updated list of bad extensions and support for finding invalid jar + files - [#1070](https://github.com/qarmin/czkawka/pull/1070) - More default excluded items on Windows(like pagefile) - [#1074](https://github.com/qarmin/czkawka/pull/1074) -- Unified printing/saving method to files/terminal and fixed some differences/bugs - [#1082](https://github.com/qarmin/czkawka/pull/1082) +- Unified printing/saving method to files/terminal and fixed some + differences/bugs - [#1082](https://github.com/qarmin/czkawka/pull/1082) - Uses fun_time library to print how much functions take time - [#1082](https://github.com/qarmin/czkawka/pull/1082) - Added exporting results into json file format - [#1083](https://github.com/qarmin/czkawka/pull/1083) - Added new test/regression suite for CI - [#1083](https://github.com/qarmin/czkawka/pull/1083) - Added ability to use relative paths - [#1083](https://github.com/qarmin/czkawka/pull/1083) - Allowed removing similar images/videos/music from cli - [#1087](https://github.com/qarmin/czkawka/pull/1087) -- Added info about saving/loading items to cache in duplicate and music mode - [#1091](https://github.com/qarmin/czkawka/pull/1091) +- Added info about saving/loading items to cache in duplicate and music + mode - [#1091](https://github.com/qarmin/czkawka/pull/1091) - Fixed number of files to check in duplicate mode - [#1091](https://github.com/qarmin/czkawka/pull/1091) -- Added support for qoi image format(without preview yet) - [e92a](https://github.com/qarmin/czkawka/commit/e92a8a65de9bd1250be482dbce06959125554849) +- Added support for qoi image format(without preview + yet) - [e92a](https://github.com/qarmin/czkawka/commit/e92a8a65de9bd1250be482dbce06959125554849) - Fixed stability problem, that could remove invalid file in CLI - [#1083](https://github.com/qarmin/czkawka/pull/1083) - Fix Windows gui crashes by using gtk 4.6 instead 4.8 or 4.10 - [#992](https://github.com/qarmin/czkawka/pull/992) - Fixed printing info about duplicated music files - [#1016](https://github.com/qarmin/czkawka/pull/1016) - Fixed printing info about duplicated video files - [#1017](https://github.com/qarmin/czkawka/pull/1017) ## Version 6.0.0 - 11.06.2023r + - Add finding similar audio files by content - [#970](https://github.com/qarmin/czkawka/pull/970) - Allow to find duplicates by name/size at once - [#956](https://github.com/qarmin/czkawka/pull/956) - Fix, simplify and speed up finding similar images - [#983](https://github.com/qarmin/czkawka/pull/956) - Fixed bug when cache for music tags not worked - [#970](https://github.com/qarmin/czkawka/pull/970) - Allow to set number of threads from CLI - [#972](https://github.com/qarmin/czkawka/pull/972) - Fix problem with invalid item sorting in bad extensions mode - [#972](https://github.com/qarmin/czkawka/pull/972) -- Big refactor/cleaning of code - [#956](https://github.com/qarmin/czkawka/pull/956)/[#970](https://github.com/qarmin/czkawka/pull/970)/[#972](https://github.com/qarmin/czkawka/pull/972) +- Big refactor/cleaning of + code - [#956](https://github.com/qarmin/czkawka/pull/956)/[#970](https://github.com/qarmin/czkawka/pull/970)/[#972](https://github.com/qarmin/czkawka/pull/972) - Use builtin gtk webp loader for previews - [#923](https://github.com/qarmin/czkawka/pull/923) - Fixed docker build - [#947](https://github.com/qarmin/czkawka/pull/947) - Restore snap builds broken since GTk 4 port - [#965](https://github.com/qarmin/czkawka/pull/947) -- Instruction how to build native ARM64 binaries on Mac - [#945](https://github.com/qarmin/czkawka/pull/945)/[#971](https://github.com/qarmin/czkawka/pull/971) +- Instruction how to build native ARM64 binaries on + Mac - [#945](https://github.com/qarmin/czkawka/pull/945)/[#971](https://github.com/qarmin/czkawka/pull/971) ## Version 5.1.0 - 19.02.2023r + - Added sort button - [#894](https://github.com/qarmin/czkawka/pull/894) - Allow to set number of thread used to scan - [#839](https://github.com/qarmin/czkawka/pull/839) - Faster similar images comparing with reference folders - [#826](https://github.com/qarmin/czkawka/pull/826) - Update to clap 4 - [#878](https://github.com/qarmin/czkawka/pull/878) - Use FileChooserNative instead FileChooserDialog - [#894](https://github.com/qarmin/czkawka/pull/894) -- Fix invalid music tags in music files when using reference folders - [#894](https://github.com/qarmin/czkawka/pull/894) -- Updated pdf dependency(a lot of less amount of broken pdf false positives) - [#894](https://github.com/qarmin/czkawka/pull/894) +- Fix invalid music tags in music files when using reference + folders - [#894](https://github.com/qarmin/czkawka/pull/894) +- Updated pdf dependency(a lot of less amount of broken pdf false + positives) - [#894](https://github.com/qarmin/czkawka/pull/894) - Changed strange PDF error message - "Try at" - [#894](https://github.com/qarmin/czkawka/pull/894) - Treat extensions Mp4 and m4v as identical - [#834](https://github.com/qarmin/czkawka/pull/834) - Improve thumbnail quality - [#895](https://github.com/qarmin/czkawka/pull/895) -- Verify if hardlinking works, and if not, disable button with proper message - [#881](https://github.com/qarmin/czkawka/pull/881) +- Verify if hardlinking works, and if not, disable button with proper + message - [#881](https://github.com/qarmin/czkawka/pull/881) - Apply some pydantic clippy lints on project - [#901](https://github.com/qarmin/czkawka/pull/901) ## Version 5.0.2 - 30.08.2022r -- Fixed problem with missing some similar images when using similarity > 0 - [#799](https://github.com/qarmin/czkawka/pull/799) -- Prebuilt Linux binaries are compiled without heif support - [24b](https://github.com/qarmin/czkawka/commit/24b64a32c65904c506b54270f0977ccbe5098cc8) -- Similar videos stops to proceed video after certain amount of time(fixes freezes) - [#815](https://github.com/qarmin/czkawka/pull/815) + +- Fixed problem with missing some similar images when using similarity > + 0 - [#799](https://github.com/qarmin/czkawka/pull/799) +- Prebuilt Linux binaries are compiled without heif + support - [24b](https://github.com/qarmin/czkawka/commit/24b64a32c65904c506b54270f0977ccbe5098cc8) +- Similar videos stops to proceed video after certain amount of time(fixes + freezes) - [#815](https://github.com/qarmin/czkawka/pull/815) - Add --version argument for czkawka_cli - [#806](https://github.com/qarmin/czkawka/pull/806) - Rewrite a little nonsense message about minimal file size - [#807](https://github.com/qarmin/czkawka/pull/807) ## Version 5.0.1 - 03.08.2022r -- Fixed problem with removing ending slash with empty disk window path - [975](https://github.com/qarmin/czkawka/commit/97563a7b2a70fb5fcf6463f28069e6ea3b0ff5c2) + +- Fixed problem with removing ending slash with empty disk window + path - [975](https://github.com/qarmin/czkawka/commit/97563a7b2a70fb5fcf6463f28069e6ea3b0ff5c2) - Added to CLI bad extensions mode - [#795](https://github.com/qarmin/czkawka/pull/795) -- Restore default sorting method in CLI where finding biggest files - [5d7](https://github.com/qarmin/czkawka/commit/5d79dc7ccfee6d5426e37c4e6a860fa555c5927a) +- Restore default sorting method in CLI where finding biggest + files - [5d7](https://github.com/qarmin/czkawka/commit/5d79dc7ccfee6d5426e37c4e6a860fa555c5927a) - Added tests to CI - [#791](https://github.com/qarmin/czkawka/pull/791) -- Show error message when all directories are set as reference folders - [#795](https://github.com/qarmin/czkawka/pull/795) +- Show error message when all directories are set as reference + folders - [#795](https://github.com/qarmin/czkawka/pull/795) - Added more info about new requirements on Linux - [#795](https://github.com/qarmin/czkawka/pull/795) ## 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) - Resize preview with window - [#466](https://github.com/qarmin/czkawka/pull/466) - Fix removing only one item from list view - [#466](https://github.com/qarmin/czkawka/pull/466) - Fix showing help command in duplicate CLI mode - [#720](https://github.com/qarmin/czkawka/pull/720) - Fix freeze when not choosing any tag in similar music mode - [#732](https://github.com/qarmin/czkawka/pull/732) -- Fix preview of files with non-lowercase extensions - [#694](https://github.com/qarmin/czkawka/pull/694) +- Fix preview of files with non-lowercase extensions - [#694](https://github.com/qarmin/czkawka/pull/694) - Read more tags from music files - [#705](https://github.com/qarmin/czkawka/pull/705) -- Improve checking for invalid extensions - [#705](https://github.com/qarmin/czkawka/pull/705), [#747](https://github.com/qarmin/czkawka/pull/747), [#749](https://github.com/qarmin/czkawka/pull/749) +- Improve checking for invalid + extensions - [#705](https://github.com/qarmin/czkawka/pull/705), [#747](https://github.com/qarmin/czkawka/pull/747), [#749](https://github.com/qarmin/czkawka/pull/749) - Support for finding invalid PDF files - [#705](https://github.com/qarmin/czkawka/pull/705) -- Re-enable checking for broken music files(`libasound.so.2` no longer needed) - [#705](https://github.com/qarmin/czkawka/pull/705) +- Re-enable checking for broken music files(`libasound.so.2` no longer + needed) - [#705](https://github.com/qarmin/czkawka/pull/705) - Fix disabled ui when using invalid settings in similar music - [#740](https://github.com/qarmin/czkawka/pull/740) - Speedup searching for invalid extensions - [#740](https://github.com/qarmin/czkawka/pull/740) - Support for finding the smallest files - [#741](https://github.com/qarmin/czkawka/pull/741) @@ -122,33 +193,48 @@ - Option to exclude files from other filesystems in GUI(Linux) - [#776](https://github.com/qarmin/czkawka/pull/776) ## Version 4.1.0 - 24.04.2022r -- New mode - finding files whose content not match with their extension - [#678](https://github.com/qarmin/czkawka/pull/678) + +- New mode - finding files whose content not match with their + extension - [#678](https://github.com/qarmin/czkawka/pull/678) - Builtin icons - no more invalid, theme/OS dependent icons - [#659](https://github.com/qarmin/czkawka/pull/659) -- Big(usually 2x) speedup of showing previews of images(both previews in scan and compare window) - [#660](https://github.com/qarmin/czkawka/pull/660) +- Big(usually 2x) speedup of showing previews of images(both previews in scan and compare + window) - [#660](https://github.com/qarmin/czkawka/pull/660) - Fix selecting records by custom selection popup - [#632](https://github.com/qarmin/czkawka/pull/632) - Support more tags when comparing music files - [#590](https://github.com/qarmin/czkawka/pull/590) - Fix not proper selecting path - [#656](https://github.com/qarmin/czkawka/pull/656) -- No more popups during scan for similar videos on Windows - [#656](https://github.com/qarmin/czkawka/pull/656) - external change [4056](https://github.com/Farmadupe/ffmpeg_cmdline_utils/commit/405687514f9d9e8984cbe2547c53e85b71e08b27) +- No more popups during scan for similar videos on Windows - [#656](https://github.com/qarmin/czkawka/pull/656) - + external + change [4056](https://github.com/Farmadupe/ffmpeg_cmdline_utils/commit/405687514f9d9e8984cbe2547c53e85b71e08b27) - Custom selecting is now case-insensitive by default - [#657](https://github.com/qarmin/czkawka/pull/657) - Better approximate comparison of tags - [#641](https://github.com/qarmin/czkawka/pull/641) - Fix search problem due accumulated stop events - [#623](https://github.com/qarmin/czkawka/pull/623) -- Option to ignore other filesystems in Unix OS(for now only in CLI) - [#673](https://github.com/qarmin/czkawka/pull/673) +- Option to ignore other filesystems in Unix OS(for now only in + CLI) - [#673](https://github.com/qarmin/czkawka/pull/673) - Fix file hardlinking on Windows - [#668](https://github.com/qarmin/czkawka/pull/668) - Support for case-insensitive name grouping of files - [#669](https://github.com/qarmin/czkawka/pull/669) - Directories for search GUI can be passed by CLI - [#677](https://github.com/qarmin/czkawka/pull/677) -- Prevent from getting non respond app notification from display servers - [#625](https://github.com/qarmin/czkawka/pull/625) +- Prevent from getting non respond app notification from display + servers - [#625](https://github.com/qarmin/czkawka/pull/625) ## Version 4.0.0 - 20.01.2022r -- Multithreading support for collecting files to check(2/3x speedup on 4 thread processor and SSD) - [#502](https://github.com/qarmin/czkawka/pull/502), [#504](https://github.com/qarmin/czkawka/pull/504) -- Add multiple translations - Polish, Italian, French, German, Russian ... - [#469](https://github.com/qarmin/czkawka/pull/469), [#508](https://github.com/qarmin/czkawka/pull/508), [5be](https://github.com/qarmin/czkawka/commit/5be801e76395855f07ab1da43cdbb8bd0b843834) + +- Multithreading support for collecting files to check(2/3x speedup on 4 thread processor and + SSD) - [#502](https://github.com/qarmin/czkawka/pull/502), [#504](https://github.com/qarmin/czkawka/pull/504) +- Add multiple translations - Polish, Italian, French, German, + Russian ... - [#469](https://github.com/qarmin/czkawka/pull/469), [#508](https://github.com/qarmin/czkawka/pull/508), [5be](https://github.com/qarmin/czkawka/commit/5be801e76395855f07ab1da43cdbb8bd0b843834) - Add support for finding similar videos - [#460](https://github.com/qarmin/czkawka/pull/460) -- GUI code refactoring and search code unification - [#462](https://github.com/qarmin/czkawka/pull/462), [#531](https://github.com/qarmin/czkawka/pull/531) +- GUI code refactoring and search code + unification - [#462](https://github.com/qarmin/czkawka/pull/462), [#531](https://github.com/qarmin/czkawka/pull/531) - Fixed crash when trying to hard/symlink 0 files - [#462](https://github.com/qarmin/czkawka/pull/462) -- GTK 4 compatibility improvements for future change of toolkit - [#467](https://github.com/qarmin/czkawka/pull/467), [#468](https://github.com/qarmin/czkawka/pull/468), [#473](https://github.com/qarmin/czkawka/pull/473), [#474](https://github.com/qarmin/czkawka/pull/474), [#503](https://github.com/qarmin/czkawka/pull/503), [#505](https://github.com/qarmin/czkawka/pull/505) +- GTK 4 compatibility improvements for future change of + toolkit - [#467](https://github.com/qarmin/czkawka/pull/467), [#468](https://github.com/qarmin/czkawka/pull/468), [#473](https://github.com/qarmin/czkawka/pull/473), [#474](https://github.com/qarmin/czkawka/pull/474), [#503](https://github.com/qarmin/czkawka/pull/503), [#505](https://github.com/qarmin/czkawka/pull/505) - Change minimal supported OS to Ubuntu 20.04(needed by GTK) - [#468](https://github.com/qarmin/czkawka/pull/468) -- Increased performance by avoiding creating unnecessary image previews - [#468](https://github.com/qarmin/czkawka/pull/468) -- Improved performance due caching hash of broken/not supported images/videos = [#471](https://github.com/qarmin/czkawka/pull/471) -- Option to not remove cache from non-existent files(e.g. from unplugged pendrive) - [#472](https://github.com/qarmin/czkawka/pull/472) +- Increased performance by avoiding creating unnecessary image + previews - [#468](https://github.com/qarmin/czkawka/pull/468) +- Improved performance due caching hash of broken/not supported + images/videos = [#471](https://github.com/qarmin/czkawka/pull/471) +- Option to not remove cache from non-existent files(e.g. from unplugged + pendrive) - [#472](https://github.com/qarmin/czkawka/pull/472) - Add multiple tooltips with helpful messages - [#472](https://github.com/qarmin/czkawka/pull/472) - Allow caching prehash - [#477](https://github.com/qarmin/czkawka/pull/477) - Improve custom selecting of records(allows to use Rust regex) - [#489](https://github.com/qarmin/czkawka/pull/478) @@ -159,28 +245,37 @@ - Allow hiding upper panel - [#491](https://github.com/qarmin/czkawka/pull/491) - Make UI take less space - [#500](https://github.com/qarmin/czkawka/pull/500) - Add support for raw images(NEF, CR2, KDC...) - [#532](https://github.com/qarmin/czkawka/pull/532) -- Image compare performance and usability improvements - [#529](https://github.com/qarmin/czkawka/pull/529), [#528](https://github.com/qarmin/czkawka/pull/528), [#530](https://github.com/qarmin/czkawka/pull/530), [#525](https://github.com/qarmin/czkawka/pull/525) +- Image compare performance and usability + improvements - [#529](https://github.com/qarmin/czkawka/pull/529), [#528](https://github.com/qarmin/czkawka/pull/528), [#530](https://github.com/qarmin/czkawka/pull/530), [#525](https://github.com/qarmin/czkawka/pull/525) - Reorganize(unify) saving/loading data from file - [#524](https://github.com/qarmin/czkawka/pull/524) - Add "reference folders" - [#516](https://github.com/qarmin/czkawka/pull/516) - Add cache for similar music files - [#558](https://github.com/qarmin/czkawka/pull/558) ## Version 3.3.1 - 22.11.2021r + - Fix crash when moving buttons [#457](https://github.com/qarmin/czkawka/pull/457) - Hide move button at start [c9ca230](https://github.com/qarmin/czkawka/commit/c9ca230dfd05e2166b2d68683b091cfd45037edd) ## Version 3.3.0 - 20.11.2021r + - Select files by pressing space key [#415](https://github.com/qarmin/czkawka/pull/415) -- Add additional info to printed errors [#446](https://github.com/qarmin/czkawka/pull/446) -- Add support for multiple image filters, hashes and sizes in similar images tool [#447](https://github.com/qarmin/czkawka/pull/447), [#448](https://github.com/qarmin/czkawka/pull/448) +- Add additional info to printed errors [#446](https://github.com/qarmin/czkawka/pull/446) +- Add support for multiple image filters, hashes and sizes in similar images + tool [#447](https://github.com/qarmin/czkawka/pull/447), [#448](https://github.com/qarmin/czkawka/pull/448) - Button to move files/folders to provided location [#449](https://github.com/qarmin/czkawka/pull/449) - Add non-clickable button to fix white theme [#450](https://github.com/qarmin/czkawka/pull/450) - Fixed freeze when opening in same thread file/folder [#448](https://github.com/qarmin/czkawka/pull/448) -- Tool to check performance of different image filters and hash types and sizes [#447](https://github.com/qarmin/czkawka/pull/447) -- Add scheduled CI and pin it to support Rust 1.53.0 [7bb](https://github.com/qarmin/czkawka/commit/7bbdf742739a513b80d0cc06ba61dfafec976b23), [#431](https://github.com/qarmin/czkawka/pull/431) -- Update snap file to use builtin rust plugin and update gnome extension [8f2](https://github.com/qarmin/czkawka/commit/8f232285e5c34bee6d5da8e1453d7f40a0ffd08d) -- Disable from checking in similar images `webp`, `gif`, `bmp`, `ico` extension which caused crashes [#445](https://github.com/qarmin/czkawka/pull/446), [49e](https://github.com/qarmin/czkawka/commit/49effca169adb57b33f666757966d43b244319cc) +- Tool to check performance of different image filters and hash types and + sizes [#447](https://github.com/qarmin/czkawka/pull/447) +- Add scheduled CI and pin it to support Rust + 1.53.0 [7bb](https://github.com/qarmin/czkawka/commit/7bbdf742739a513b80d0cc06ba61dfafec976b23), [#431](https://github.com/qarmin/czkawka/pull/431) +- Update snap file to use builtin rust plugin and update gnome + extension [8f2](https://github.com/qarmin/czkawka/commit/8f232285e5c34bee6d5da8e1453d7f40a0ffd08d) +- Disable from checking in similar images `webp`, `gif`, `bmp`, `ico` extension which caused + crashes [#445](https://github.com/qarmin/czkawka/pull/446), [49e](https://github.com/qarmin/czkawka/commit/49effca169adb57b33f666757966d43b244319cc) ## Version 3.2.0 - 07.08.2021r + - 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) - Fix symlink and hardlink creating - [#409](https://github.com/qarmin/czkawka/pull/409) @@ -190,22 +285,28 @@ - Update to Rust 1.54 [#400](https://github.com/qarmin/czkawka/pull/400) - Add webp support to similar images [#396](https://github.com/qarmin/czkawka/pull/396) - Use GtkScale instead radio buttons for similarity [#397](https://github.com/qarmin/czkawka/pull/397) -- Update all dependencies [#405](https://github.com/qarmin/czkawka/pull/405), [#395](https://github.com/qarmin/czkawka/pull/395) +- Update all + dependencies [#405](https://github.com/qarmin/czkawka/pull/405), [#395](https://github.com/qarmin/czkawka/pull/395) - Split UI into multiple files [#391](https://github.com/qarmin/czkawka/pull/391) - Update to gtk-rs 0.14 [#383](https://github.com/qarmin/czkawka/pull/383) - Fix bug with moving windows [#361](https://github.com/qarmin/czkawka/pull/361) - Generate Minimal Appimage [#339](https://github.com/qarmin/czkawka/pull/339) ## Version 3.1.0 - 09.05.2021r -- Clean README, by moving instructions to different files - [9aea6e9b](https://github.com/qarmin/czkawka/commit/9aea6e9b1ef5ac1e56ccd008e7456b80401179d0) + +- Clean README, by moving instructions to different + files - [9aea6e9b](https://github.com/qarmin/czkawka/commit/9aea6e9b1ef5ac1e56ccd008e7456b80401179d0) - Fix excluded items on Windows - [#324](https://github.com/qarmin/czkawka/pull/324) - Center windows and add missing settings icon - [#323](https://github.com/qarmin/czkawka/pull/323) - Sort cache - [#322](https://github.com/qarmin/czkawka/pull/322) -- Add desktop file to Snap - [018d5bebb](https://github.com/qarmin/czkawka/commit/018d5bebb0b297ba35529b03b8e2e68eb0a9b474), [ade2a756e2](https://github.com/qarmin/czkawka/commit/ade2a756e29c5ce5739d6268fcab7e76f59ed5f6) +- Add desktop file to + Snap - [018d5bebb](https://github.com/qarmin/czkawka/commit/018d5bebb0b297ba35529b03b8e2e68eb0a9b474), [ade2a756e2](https://github.com/qarmin/czkawka/commit/ade2a756e29c5ce5739d6268fcab7e76f59ed5f6) - Customize minimum file size of cached records - [#321](https://github.com/qarmin/czkawka/pull/321) - Update benchmarks - [2044b9185](https://github.com/qarmin/czkawka/commit/2044b91852fea89dfaf10dc1ab79c1d00e9e0c12) -- Rearrange Instruction - [8e7ac4a2d7f5b0](https://github.com/qarmin/czkawka/commit/8e7ac4a2d7f5b0beba2552581fb3a0d19c2efeb5) -- Add info that Czkawka and Bleachbit are not alternatives to each other - [30602a486](https://github.com/qarmin/czkawka/commit/30602a486f6ade6f9b7b91a73708225b4f4c2a7d) +- Rearrange + Instruction - [8e7ac4a2d7f5b0](https://github.com/qarmin/czkawka/commit/8e7ac4a2d7f5b0beba2552581fb3a0d19c2efeb5) +- Add info that Czkawka and Bleachbit are not alternatives to each + other - [30602a486](https://github.com/qarmin/czkawka/commit/30602a486f6ade6f9b7b91a73708225b4f4c2a7d) - Fix crashes with too small message queue - [#316](https://github.com/qarmin/czkawka/pull/316) - Fix a little unsorted results - [#304](https://github.com/qarmin/czkawka/pull/304) - Fix Appimage(external bug) - [#299](https://github.com/qarmin/czkawka/issues/299) @@ -213,27 +314,32 @@ - Update to Rust 1.5.1 - [#302](https://github.com/qarmin/czkawka/pull/302) ## Version 3.0.0 - 11.03.2021r + - Option to not ignore hardlinks - [#273](https://github.com/qarmin/czkawka/pull/273) - Hardlink support for GUI - [#276](https://github.com/qarmin/czkawka/pull/276) - New settings window - [#262](https://github.com/qarmin/czkawka/pull/262) - Unify file removing - [#278](https://github.com/qarmin/czkawka/pull/278) -- Dryrun in duplicates CLI - [#277](https://github.com/qarmin/czkawka/pull/277) +- Dryrun in duplicates CLI - [#277](https://github.com/qarmin/czkawka/pull/277) - Option to turn off cache - [#263](https://github.com/qarmin/czkawka/pull/263) -- Update Image dependency and fix crashes - [#270](https://github.com/qarmin/czkawka/pull/270), [e3aca69](https://github.com/qarmin/czkawka/commit/e3aca69499966499413e4b7cd4d1037bec6a5d68) +- Update Image dependency and fix + crashes - [#270](https://github.com/qarmin/czkawka/pull/270), [e3aca69](https://github.com/qarmin/czkawka/commit/e3aca69499966499413e4b7cd4d1037bec6a5d68) - Add confirmation dialog when trying to remove all files in group - [#281](https://github.com/qarmin/czkawka/pull/281) - Add confirmation dialog when removing files with delete key - [#282](https://github.com/qarmin/czkawka/pull/282) - Open file when clicking at the Enter button - [#285](https://github.com/qarmin/czkawka/pull/285) - Allow to put files to trash instead fully remove them - [#284](https://github.com/qarmin/czkawka/pull/284) ## Version 2.4.0 - 22.02.2021r + - Add about dialog - [#226](https://github.com/qarmin/czkawka/pull/226) - Remove checking for ico in similar images - [#227](https://github.com/qarmin/czkawka/pull/227) -- Change progress dialog to progress window - [#229](https://github.com/qarmin/czkawka/pull/229) -- Restore snap confinement - [#218](https://github.com/qarmin/czkawka/pull/218), [8dcb718](https://github.com/qarmin/czkawka/commit/8dcb7188434e1c1728368642e17ccec29a4b372d) +- Change progress dialog to progress window - [#229](https://github.com/qarmin/czkawka/pull/229) +- Restore snap + confinement - [#218](https://github.com/qarmin/czkawka/pull/218), [8dcb718](https://github.com/qarmin/czkawka/commit/8dcb7188434e1c1728368642e17ccec29a4b372d) - Add support for CRC32 and XXH3 hash - [#243](https://github.com/qarmin/czkawka/pull/243) - Add delete method to replace duplicate files with hard links - [#236](https://github.com/qarmin/czkawka/pull/236) - Add checking for broken music opt-in - [#249](https://github.com/qarmin/czkawka/pull/249) -- Allow to save to file similar images results - [10156ccfd3](https://github.com/qarmin/czkawka/commit/10156ccfd3ba880d26d4bbad1e025b0050d7753b) +- Allow to save to file similar images + results - [10156ccfd3](https://github.com/qarmin/czkawka/commit/10156ccfd3ba880d26d4bbad1e025b0050d7753b) - Keep original file if replacing duplicate with hardlink fails - [#256](https://github.com/qarmin/czkawka/pull/256) - Fix Windows theme - [#265](https://github.com/qarmin/czkawka/pull/265) - Windows taskbar progress support - [#264](https://github.com/qarmin/czkawka/pull/264) @@ -243,38 +349,47 @@ - Disable for now broken tga and gif files - [#270](https://github.com/qarmin/czkawka/pull/270) ## Version 2.3.2 - 21.01.2021r -- Add support for moving selection by keyboard to update similar image preview [#223](https://github.com/qarmin/czkawka/pull/223) + +- Add support for moving selection by keyboard to update similar image + preview [#223](https://github.com/qarmin/czkawka/pull/223) This version is only needed to test flatpak build ## Version 2.3.1 - 20.01.2021r + - Added flatpak support - [#203](https://github.com/qarmin/czkawka/pull/203) - Spell fixes - [#222](https://github.com/qarmin/czkawka/pull/222), [#219](https://github.com/qarmin/czkawka/pull/219) ## Version 2.3.0 - 15.01.2021r + - Add cache for duplicate finder - [#205](https://github.com/qarmin/czkawka/pull/205) - Add cache for broken files - [#204](https://github.com/qarmin/czkawka/pull/204) - Decrease ram usage - [#212](https://github.com/qarmin/czkawka/pull/212) - Add support for finding broken zip and audio files - [#210](https://github.com/qarmin/czkawka/pull/210) - Sort Results by path where it is possible - [#211](https://github.com/qarmin/czkawka/pull/211) - Add missing popover info for invalid symlinks - [#209](https://github.com/qarmin/czkawka/pull/209) -- Use the oldest available OS in Linux and Mac CI and the newest on Windows - [#206](https://github.com/qarmin/czkawka/pull/206) +- Use the oldest available OS in Linux and Mac CI and the newest on + Windows - [#206](https://github.com/qarmin/czkawka/pull/206) - Add broken files support - [#202](https://github.com/qarmin/czkawka/pull/202) - Remove save workaround and fix crashes when loading/saving cache - [#200](https://github.com/qarmin/czkawka/pull/200) - Fix error when closing dialog progress by X - [#199](https://github.com/qarmin/czkawka/pull/199) ## Version 2.2.0 - 11.01.2021r + - Adds Mac GUI - [#160](https://github.com/qarmin/czkawka/pull/160) - Use master gtk plugin again - [#179](https://github.com/qarmin/czkawka/pull/179) - Only show preview when 1 image is selected - [#183](https://github.com/qarmin/czkawka/pull/183) - Add buffered write/read - [#186](https://github.com/qarmin/czkawka/pull/186) - Fix included/excluded files which contains commas - [#195](https://github.com/qarmin/czkawka/pull/195) - Move image cache to cache from config dir - [#197](https://github.com/qarmin/czkawka/pull/197) -- Reorganize GUI Code(no visible changes) - [#184](https://github.com/qarmin/czkawka/pull/184), [#184](https://github.com/qarmin/czkawka/pull/184), [#189](https://github.com/qarmin/czkawka/pull/189), [#190](https://github.com/qarmin/czkawka/pull/190), [#194](https://github.com/qarmin/czkawka/pull/194) +- Reorganize GUI Code(no visible + changes) - [#184](https://github.com/qarmin/czkawka/pull/184), [#184](https://github.com/qarmin/czkawka/pull/184), [#189](https://github.com/qarmin/czkawka/pull/189), [#190](https://github.com/qarmin/czkawka/pull/190), [#194](https://github.com/qarmin/czkawka/pull/194) ## Version 2.1.0 - 31.12.2020r + - Hide preview when deleting images or symlinking it - [#167](https://github.com/qarmin/czkawka/pull/167) -- Add manual adding of directories - [#165](https://github.com/qarmin/czkawka/pull/165), [#168](https://github.com/qarmin/czkawka/pull/168) +- Add manual adding of + directories - [#165](https://github.com/qarmin/czkawka/pull/165), [#168](https://github.com/qarmin/czkawka/pull/168) - Add resizable top panel - [#164](https://github.com/qarmin/czkawka/pull/164) - Add support for delete button - [#159](https://github.com/qarmin/czkawka/pull/159) - Allow to select multiple entries in File Chooser - [#154](https://github.com/qarmin/czkawka/pull/154) @@ -283,6 +398,7 @@ This version is only needed to test flatpak build - Modernize popovers code and simplify later changes - [#137](https://github.com/qarmin/czkawka/pull/137) ## Version 2.0.0 - 23.12.2020r + - Add Snap support - [ee3d4](https://github.com/qarmin/czkawka/commit/ee3d450552cd0c37a114b05c557ff9381ef92466) - Select longer names by default - [#113](https://github.com/qarmin/czkawka/pull/113) - Add setting for deletion confirmation dialog - [#114](https://github.com/qarmin/czkawka/pull/114) @@ -302,19 +418,25 @@ This version is only needed to test flatpak build - Add option to open folders by double right click - [#128](https://github.com/qarmin/czkawka/pull/128) - Add minimal similarity level - [#129](https://github.com/qarmin/czkawka/pull/129) - Show errors in image previewer when failed to generate it - [#130](https://github.com/qarmin/czkawka/pull/130) -- Added instruction - [58e6221a](https://github.com/qarmin/czkawka/commit/58e6221a0e02d17d07c71152f56b948f616751a8), [598aec345e](https://github.com/qarmin/czkawka/commit/598aec345e9f5ac199fc3d642c0699d5228100a6), [afaa402b](https://github.com/qarmin/czkawka/commit/afaa402b31526aa8e6b47f3670bc62b26ad9f60f) +- Added + instruction - [58e6221a](https://github.com/qarmin/czkawka/commit/58e6221a0e02d17d07c71152f56b948f616751a8), [598aec345e](https://github.com/qarmin/czkawka/commit/598aec345e9f5ac199fc3d642c0699d5228100a6), [afaa402b](https://github.com/qarmin/czkawka/commit/afaa402b31526aa8e6b47f3670bc62b26ad9f60f) ## Version 1.5.1 - 08.12.2020r -- Fix errors in progress bar caused by dividing by 0 - [#109](https://github.com/qarmin/czkawka/pull/109) + +- Fix errors in progress bar caused by dividing by 0 - [#109](https://github.com/qarmin/czkawka/pull/109) - Add option to save file, store settings and load them - [#108](https://github.com/qarmin/czkawka/pull/108) -- Center dialog to current window - [a04](https://github.com/qarmin/czkawka/commit/a047380dbe8aa4d04f9c482364469e21d231fab2) +- Center dialog to current + window - [a04](https://github.com/qarmin/czkawka/commit/a047380dbe8aa4d04f9c482364469e21d231fab2) ## Version 1.5.0 - 02.12.2020r + - Added progress bar - [#106](https://github.com/qarmin/czkawka/pull/106) - Removed unused buttons - [#107](https://github.com/qarmin/czkawka/pull/107) ## Version 1.4.0 - 09.11.2020r -- Multithreading Support to most modules - [#98](https://github.com/qarmin/czkawka/pull/98) [#99](https://github.com/qarmin/czkawka/pull/99) [#100](https://github.com/qarmin/czkawka/pull/100) [#101](https://github.com/qarmin/czkawka/pull/101) + +- Multithreading Support to most + modules - [#98](https://github.com/qarmin/czkawka/pull/98) [#99](https://github.com/qarmin/czkawka/pull/99) [#100](https://github.com/qarmin/czkawka/pull/100) [#101](https://github.com/qarmin/czkawka/pull/101) - Simplify GUI code [#96](https://github.com/qarmin/czkawka/pull/96) - Group similar images - [#97](https://github.com/qarmin/czkawka/pull/97) - Add select buttons to each type of mode - [#102](https://github.com/qarmin/czkawka/pull/102) @@ -322,6 +444,7 @@ This version is only needed to test flatpak build - Add new similarity level - [#104](https://github.com/qarmin/czkawka/pull/104) ## Version 1.3.0 - 02.11.2020r + - Appimage support - [#77](https://github.com/qarmin/czkawka/pull/77) - Removed warnings about non-existed excluded directories - [#79](https://github.com/qarmin/czkawka/pull/79) - Updated README - [8ec](https://github.com/qarmin/czkawka/commit/8ecde0fc9adb3e6cedf432c4ba749e698b645a7a) @@ -333,31 +456,41 @@ This version is only needed to test flatpak build - Implemented finding duplicates by music tags - [#95](https://github.com/qarmin/czkawka/pull/95) ## Version 1.2.1 - 17.10.2020r + - Make image similarity search significantly faster. [#72](https://github.com/qarmin/czkawka/pull/72) -- Improve similar images GUI a little and add sorting to Similarity Enum [#73](https://github.com/qarmin/czkawka/pull/73) +- Improve similar images GUI a little and add sorting to Similarity + Enum [#73](https://github.com/qarmin/czkawka/pull/73) - Improve deleting files in Similar files in GUI [#75](https://github.com/qarmin/czkawka/pull/75) ## Version 1.2.0 - 15.10.2020r + - Replace String with PathBuf for paths [#59](https://github.com/qarmin/czkawka/pull/59) - Add test suite to PR [#65](https://github.com/qarmin/czkawka/pull/65) - Support for finding similar images to CLI [#66](https://github.com/qarmin/czkawka/pull/66) -- Fix grammar-related errors and Ponglish expressions [#62](https://github.com/qarmin/czkawka/pull/62), [#63](https://github.com/qarmin/czkawka/pull/63) -- Don't delete by default files in duplicate finder in CLI - [23f203](https://github.com/qarmin/czkawka/commit/23f203a061e254275c95ca23ca4f1a78bd941f02) +- Fix grammar-related errors and Ponglish + expressions [#62](https://github.com/qarmin/czkawka/pull/62), [#63](https://github.com/qarmin/czkawka/pull/63) +- Don't delete by default files in duplicate finder in + CLI - [23f203](https://github.com/qarmin/czkawka/commit/23f203a061e254275c95ca23ca4f1a78bd941f02) - Support for finding similar images to GUI [#69](https://github.com/qarmin/czkawka/pull/69) - Add support for opening files/folders from GUI with double-click [#70](https://github.com/qarmin/czkawka/pull/70) ## Version 1.1.0 - 10.10.2020r + - Windows support [#58](https://github.com/qarmin/czkawka/pull/58) - Improve code quality/Simplify codebase [#52](https://github.com/qarmin/czkawka/pull/52) -- Fixed skipping some correct results in specific situations [#52](https://github.com/qarmin/czkawka/pull/52#discussion_r502613895) +- Fixed skipping some correct results in specific + situations [#52](https://github.com/qarmin/czkawka/pull/52#discussion_r502613895) - Added support for searching in other thread [#51](https://github.com/qarmin/czkawka/pull/51) - Divide CI across files [#48](https://github.com/qarmin/czkawka/pull/48) - Added ability to stop task from GUI [#55](https://github.com/qarmin/czkawka/pull/55) -- Fixed removing directories which contains only empty directories from GUI [#57](https://github.com/qarmin/czkawka/pull/57) +- Fixed removing directories which contains only empty directories from + GUI [#57](https://github.com/qarmin/czkawka/pull/57) ## Version 1.0.1 - 06.10.2020r + - Replaced default argument parser with StructOpt [#37](https://github.com/qarmin/czkawka/pull/37) -- Added all(except macOS GTK build) builds to CI where can be freely downloaded [#41](https://github.com/qarmin/czkawka/pull/41) [#39](https://github.com/qarmin/czkawka/pull/39) +- Added all(except macOS GTK build) builds to CI where can be freely + downloaded [#41](https://github.com/qarmin/czkawka/pull/41) [#39](https://github.com/qarmin/czkawka/pull/39) - App can be downloaded also from Arch AUR and Cargo [#36](https://github.com/qarmin/czkawka/pull/36) - Fixed crash with invalid file modification date [#33](https://github.com/qarmin/czkawka/issues/33) - Upper tabs can hide and show when this is necessary [#38](https://github.com/qarmin/czkawka/pull/38) @@ -365,11 +498,13 @@ This version is only needed to test flatpak build - Added support for finding similar pictures in GUI [#69](https://github.com/qarmin/czkawka/issues/69) ## Version 1.0.0 - 02.10.2020r + - Added confirmation dialog to delete button - Updated Readme - Tested a lot app, so I think that it version 1.0.0 can be freely released ## Version 0.1.4 - 01.10.2020r + - Fixes -f default argument - Added save button to GUI - Cleaned a little code @@ -384,6 +519,7 @@ This version is only needed to test flatpak build - Added Big, Temporary and Empty folders finder to GUI ## Version 0.1.3 - 27.09.2020r + - Big code refactoring - now is a lot of easier create new modules and maintain old ones - Added finding empty files - Added new option to find duplicates by checking hash max 1MB of file @@ -392,6 +528,7 @@ This version is only needed to test flatpak build - Simplify CLI help and improve it ## Version 0.1.2 - 26.09.2020r + - Add basic search empty folders in GTK GUI - Remember place where button are placed - Read and parse more values from GUI @@ -403,6 +540,7 @@ This version is only needed to test flatpak build - The biggest files support in CLI ## Version 0.1.1 - 20.09.2020r + - Added images to readme - Better GTK buttons and glade file - Basic search in GTK @@ -418,6 +556,7 @@ This version is only needed to test flatpak build - Add basic idea config to misc folder ## Version 0.1.0 - 07.09.2020r + - Initial Version - Duplicate file finder - Empty folder finder diff --git a/ci_tester/src/main.rs b/ci_tester/src/main.rs index fd55c1726..20952320e 100644 --- a/ci_tester/src/main.rs +++ b/ci_tester/src/main.rs @@ -1,7 +1,6 @@ use std::collections::BTreeSet; use std::fs; -use std::process::Command; -use std::process::Stdio; +use std::process::{Command, Stdio}; use log::info; @@ -20,7 +19,7 @@ const PRINT_MESSAGES_CZKAWKA: bool = true; // App runs - ./ci_tester PATH_TO_CZKAWKA fn main() { - handsome_logger::init().unwrap(); + handsome_logger::init().expect("Should not fail in tests"); let args: Vec = std::env::args().collect(); let path_to_czkawka = args[1].clone(); CZKAWKA_PATH.set(path_to_czkawka); @@ -28,7 +27,7 @@ fn main() { run_with_good_status(&["ls"], false); unzip_files(); - let all_files = collect_all_files_and_dirs("TestFiles").unwrap(); + let all_files = collect_all_files_and_dirs("TestFiles").expect("Should not fail in tests"); COLLECTED_FILES.set(all_files); remove_test_dir(); @@ -266,7 +265,7 @@ fn run_with_good_status(str_command: &[&str], print_messages: bool) { if !print_messages { com = com.stderr(Stdio::piped()).stdout(Stdio::piped()); } - let status = com.spawn().expect("failed to execute process").wait().unwrap(); + let status = com.spawn().expect("failed to execute process").wait().expect("Should not fail in tests"); assert!(status.success()); } @@ -276,21 +275,21 @@ fn file_folder_diffs( mut expected_folders_differences: Vec<&'static str>, mut expected_symlinks_differences: Vec<&'static str>, ) { - let current_files = collect_all_files_and_dirs("TestFiles").unwrap(); + let current_files = collect_all_files_and_dirs("TestFiles").expect("Should not fail in tests"); let mut diff_files = all_files .files .difference(¤t_files.files) - .map(|e| e.strip_prefix("TestFiles/").unwrap().to_string()) + .map(|e| e.strip_prefix("TestFiles/").expect("Should not fail in tests").to_string()) .collect::>(); let mut diff_folders = all_files .folders .difference(¤t_files.folders) - .map(|e| e.strip_prefix("TestFiles/").unwrap().to_string()) + .map(|e| e.strip_prefix("TestFiles/").expect("Should not fail in tests").to_string()) .collect::>(); let mut diff_symlinks = all_files .symlinks .difference(¤t_files.symlinks) - .map(|e| e.strip_prefix("TestFiles/").unwrap().to_string()) + .map(|e| e.strip_prefix("TestFiles/").expect("Should not fail in tests").to_string()) .collect::>(); expected_symlinks_differences.sort(); @@ -313,7 +312,7 @@ fn collect_all_files_and_dirs(dir: &str) -> std::io::Result { let mut folders_to_check = vec![dir.to_string()]; while !folders_to_check.is_empty() { - let folder = folders_to_check.pop().unwrap(); + let folder = folders_to_check.pop().expect("Should not fail in tests"); let rd = fs::read_dir(folder)?; for entry in rd { let entry = entry?; diff --git a/czkawka_cli/Cargo.toml b/czkawka_cli/Cargo.toml index 4709a750b..58884fc82 100644 --- a/czkawka_cli/Cargo.toml +++ b/czkawka_cli/Cargo.toml @@ -3,7 +3,7 @@ name = "czkawka_cli" version = "7.0.0" authors = ["RafaÅ‚ Mikrut "] edition = "2021" -rust-version = "1.75.0" +rust-version = "1.79.0" description = "CLI frontend of Czkawka" license = "MIT" homepage = "https://github.com/qarmin/czkawka" @@ -13,9 +13,9 @@ repository = "https://github.com/qarmin/czkawka" clap = { version = "4.5", features = ["derive"] } # For enum types -image_hasher = "1.2" +image_hasher = "2.0" -log = "0.4.20" +log = "0.4.22" handsome_logger = "0.8" fun_time = { version = "0.3", features = ["log"] } czkawka_core = { path = "../czkawka_core", version = "7.0.0", features = [] } diff --git a/czkawka_cli/README.md b/czkawka_cli/README.md index aa9a47cca..4e8c156d2 100644 --- a/czkawka_cli/README.md +++ b/czkawka_cli/README.md @@ -3,29 +3,42 @@ CLI frontend, allows to use Czkawka from terminal. ## Requirements -Precompiled binaries should work without any additional dependencies with Linux(Ubuntu 20.04+), Windows(10+) and macOS(10.15+). -If you decide to compile the app, you probably will be able to run it on even older versions of OS, like Ubuntu 16.04 or Windows 7. +Precompiled binaries should work without any additional dependencies with Linux(Ubuntu 20.04+), Windows(10+) and macOS( +10.15+). + +If you decide to compile the app, you probably will be able to run it on even older versions of OS, like Ubuntu 16.04 or +Windows 7. On linux it is even possible with eyra to avoid entirely libc and using fully static rust binary. -If you want to use similar videos tool, you need to install ffmpeg(runtime dependency) or use heif/libraw(build/runtime dependency) you need to install required packages. +If you want to use similar videos tool, you need to install ffmpeg(runtime dependency) or use heif/libraw(build/runtime +dependency) you need to install required packages. + - mac - `brew install ffmpeg libraw libheif` - https://formulae.brew.sh/formula/ffmpeg - linux - `sudo apt install ffmpeg libraw-dev libheif-dev` -- windows - `choco install ffmpeg` - or if not working, download from https://ffmpeg.org/download.html#build-windows and unpack to location with `czkawka_cli.exe`, heif and libraw are not supported on windows +- windows - `choco install ffmpeg` - or if not working, download from https://ffmpeg.org/download.html#build-windows and + unpack to location with `czkawka_cli.exe`, heif and libraw are not supported on windows ## Compilation + For compilation, you need to have installed Rust via rustup - https://rustup.rs/ and compile it e.g. via + ```shell cargo run --release --bin czkawka_cli ``` + you can enable additional features via + ```shell cargo run --release --bin czkawka_cli --features "heif,libraw" ``` -on linux to build fully static binary with eyra you need to use (this is only for crazy people, so just use command above if you don't know what you are doing) + +on linux to build fully static binary with eyra you need to use (this is only for crazy people, so just use command +above if you don't know what you are doing) + ```shell -rustup default nightly-2024-02-06 # or any newer nightly that works fine with eyra +rustup default nightly-2024-09-25 # or any newer nightly that works fine with eyra cd czkawka_cli cargo add eyra --rename=std echo 'fn main() { println!("cargo:rustc-link-arg=-nostartfiles"); }' > build.rs @@ -34,11 +47,14 @@ cargo build --release --bin czkawka_cli ``` ## Limitations + Not all available features in core are available in CLI. List of not available features: + - Ability to use/choose referenced directories - See progress of scanning ## LICENSE + MIT \ No newline at end of file diff --git a/czkawka_cli/src/commands.rs b/czkawka_cli/src/commands.rs index db729490e..7a32879dd 100644 --- a/czkawka_cli/src/commands.rs +++ b/czkawka_cli/src/commands.rs @@ -1,13 +1,13 @@ use std::path::PathBuf; -use image_hasher::{FilterType, HashAlg}; - +use czkawka_core::broken_files::CheckedTypes; use czkawka_core::common_dir_traversal::CheckingMethod; use czkawka_core::common_tool::DeleteMethod; use czkawka_core::duplicate::HashType; use czkawka_core::same_music::MusicSimilarity; use czkawka_core::similar_images::SimilarityPreset; use czkawka_core::CZKAWKA_VERSION; +use image_hasher::{FilterType, HashAlg}; #[derive(clap::Parser)] #[clap( @@ -88,6 +88,22 @@ pub enum Commands { pub struct DuplicatesArgs { #[clap(flatten)] pub common_cli_items: CommonCliItems, + #[clap( + short = 'p', + long, + value_parser = parse_minimal_file_size, + default_value = "257144", + help = "Minimum prehash cache file size in bytes", + long_help = "Minimum size of prehash cached files in bytes" + )] + pub minimal_prehash_cache_file_size: u64, + #[clap( + short = 'u', + long, + help = "Use prehash cache", + long_help = "Use prehash cache to speed up the scanning process by avoiding rehashing files that have already been hashed" + )] + pub use_prehash_cache: bool, #[clap( short, long, @@ -215,12 +231,14 @@ pub struct SimilarImagesArgs { pub allow_hard_links: AllowHardLinks, #[clap(flatten)] pub dry_run: DryRun, + #[clap(flatten)] + pub ignore_same_size: IgnoreSameSize, #[clap( short = 'g', long, default_value = "Gradient", value_parser = parse_similar_hash_algorithm, - help = "Hash algorithm (allowed: Mean, Gradient, Blockhash, VertGradient, DoubleGradient)" + help = "Hash algorithm (allowed: Mean, Gradient, Blockhash, VertGradient, DoubleGradient, Median)" )] pub hash_alg: HashAlg, #[clap( @@ -249,6 +267,10 @@ pub struct SameMusicArgs { pub delete_method: DMethod, #[clap(flatten)] pub dry_run: DryRun, + #[clap(short, long, help = "Approximate comparison of music tags.")] + pub approximate_comparison: bool, + #[clap(short, long, help = "Compare only m.")] + pub compare_fingerprints_only_with_similar_titles: bool, #[clap( short = 'z', long, @@ -348,6 +370,15 @@ pub struct BrokenFilesArgs { pub common_cli_items: CommonCliItems, #[clap(short = 'D', long, help = "Delete found files")] pub delete_files: bool, + #[clap( + short, + long, + default_value = "PDF", + value_parser = parse_broken_files, + help = "Checking file types (PDF, AUDIO, IMAGE, ARCHIVE)", + long_help = "Methods to search files - default PDF.\nPDF - finds broken PDF files,\nAUDIO - finds broken audio files,\nIMAGE - finds broken image files,\nARCHIVE - finds broken archive files" + )] + pub checked_types: Vec, } #[derive(Debug, clap::Args)] @@ -360,6 +391,8 @@ pub struct SimilarVideosArgs { pub allow_hard_links: AllowHardLinks, #[clap(flatten)] pub dry_run: DryRun, + #[clap(flatten)] + pub ignore_same_size: IgnoreSameSize, #[clap( short, long, @@ -492,6 +525,12 @@ pub struct DryRun { pub dry_run: bool, } +#[derive(Debug, clap::Args)] +pub struct IgnoreSameSize { + #[clap(short, long, help = "Ignore files with the same size, leaving only one file of each size")] + pub ignore_same_size: bool, +} + impl FileToSave { pub fn file_name(&self) -> Option<&str> { if let Some(file_name) = &self.file_to_save { @@ -552,6 +591,16 @@ fn parse_checking_method_duplicate(src: &str) -> Result Result { + match src.to_ascii_lowercase().as_str() { + "pdf" => Ok(CheckedTypes::PDF), + "audio" => Ok(CheckedTypes::AUDIO), + "image" => Ok(CheckedTypes::IMAGE), + "archive" => Ok(CheckedTypes::ARCHIVE), + _ => Err("Couldn't parse the broken files type (allowed: PDF, AUDIO, IMAGE, ARCHIVE)"), + } +} + fn parse_checking_method_same_music(src: &str) -> Result { match src.to_ascii_lowercase().as_str() { "tags" => Ok(CheckingMethod::AudioTags), @@ -623,7 +672,8 @@ fn parse_similar_hash_algorithm(src: &str) -> Result { "blockhash" => HashAlg::Blockhash, "vertgradient" => HashAlg::VertGradient, "doublegradient" => HashAlg::DoubleGradient, - _ => return Err("Couldn't parse the hash algorithm (allowed: Mean, Gradient, Blockhash, VertGradient, DoubleGradient)".to_string()), + "median" => HashAlg::Median, + _ => return Err("Couldn't parse the hash algorithm (allowed: Mean, Gradient, Blockhash, VertGradient, DoubleGradient, Median)".to_string()), }; Ok(algorithm) } diff --git a/czkawka_cli/src/main.rs b/czkawka_cli/src/main.rs index 8cd62318f..644d417d4 100644 --- a/czkawka_cli/src/main.rs +++ b/czkawka_cli/src/main.rs @@ -1,4 +1,5 @@ #![allow(clippy::needless_late_init)] +#![warn(clippy::unwrap_used)] use std::thread; @@ -7,21 +8,21 @@ use crossbeam_channel::{bounded, unbounded, Receiver, Sender}; use log::error; use commands::Commands; -use czkawka_core::bad_extensions::BadExtensions; -use czkawka_core::big_file::{BigFile, SearchMode}; -use czkawka_core::broken_files::BrokenFiles; +use czkawka_core::bad_extensions::{BadExtensions, BadExtensionsParameters}; +use czkawka_core::big_file::{BigFile, BigFileParameters, SearchMode}; +use czkawka_core::broken_files::{BrokenFiles, BrokenFilesParameters, CheckedTypes}; use czkawka_core::common::{print_version_mode, set_number_of_threads, setup_logger, DEFAULT_THREAD_SIZE}; -use czkawka_core::common_dir_traversal::ProgressData; use czkawka_core::common_tool::{CommonData, DeleteMethod}; #[allow(unused_imports)] // It is used in release for print_results_to_output(). use czkawka_core::common_traits::*; -use czkawka_core::duplicate::DuplicateFinder; +use czkawka_core::duplicate::{DuplicateFinder, DuplicateFinderParameters}; use czkawka_core::empty_files::EmptyFiles; use czkawka_core::empty_folder::EmptyFolder; use czkawka_core::invalid_symlinks::InvalidSymlinks; -use czkawka_core::same_music::SameMusic; -use czkawka_core::similar_images::{return_similarity_from_similarity_preset, test_image_conversion_speed, SimilarImages}; -use czkawka_core::similar_videos::SimilarVideos; +use czkawka_core::progress_data::ProgressData; +use czkawka_core::same_music::{SameMusic, SameMusicParameters}; +use czkawka_core::similar_images::{return_similarity_from_similarity_preset, test_image_conversion_speed, SimilarImages, SimilarImagesParameters}; +use czkawka_core::similar_videos::{SimilarVideos, SimilarVideosParameters}; use czkawka_core::temporary::Temporary; use crate::commands::{ @@ -46,22 +47,23 @@ fn main() { let (progress_sender, progress_receiver): (Sender, Receiver) = unbounded(); let (stop_sender, stop_receiver): (Sender<()>, Receiver<()>) = bounded(1); - let calculate_thread = thread::Builder::new().stack_size(DEFAULT_THREAD_SIZE).spawn(move || match command { - Commands::Duplicates(duplicates_args) => duplicates(duplicates_args, &stop_receiver, &progress_sender), - Commands::EmptyFolders(empty_folders_args) => empty_folders(empty_folders_args, &stop_receiver, &progress_sender), - Commands::BiggestFiles(biggest_files_args) => biggest_files(biggest_files_args, &stop_receiver, &progress_sender), - Commands::EmptyFiles(empty_files_args) => empty_files(empty_files_args, &stop_receiver, &progress_sender), - Commands::Temporary(temporary_args) => temporary(temporary_args, &stop_receiver, &progress_sender), - Commands::SimilarImages(similar_images_args) => similar_images(similar_images_args, &stop_receiver, &progress_sender), - Commands::SameMusic(same_music_args) => same_music(same_music_args, &stop_receiver, &progress_sender), - Commands::InvalidSymlinks(invalid_symlinks_args) => invalid_symlinks(invalid_symlinks_args, &stop_receiver, &progress_sender), - Commands::BrokenFiles(broken_files_args) => broken_files(broken_files_args, &stop_receiver, &progress_sender), - Commands::SimilarVideos(similar_videos_args) => similar_videos(similar_videos_args, &stop_receiver, &progress_sender), - Commands::BadExtensions(bad_extensions_args) => bad_extensions(bad_extensions_args, &stop_receiver, &progress_sender), - Commands::Tester {} => { - test_image_conversion_speed(); - } - }); + let calculate_thread = thread::Builder::new() + .stack_size(DEFAULT_THREAD_SIZE) + .spawn(move || match command { + Commands::Duplicates(duplicates_args) => duplicates(duplicates_args, &stop_receiver, &progress_sender), + Commands::EmptyFolders(empty_folders_args) => empty_folders(empty_folders_args, &stop_receiver, &progress_sender), + Commands::BiggestFiles(biggest_files_args) => biggest_files(biggest_files_args, &stop_receiver, &progress_sender), + Commands::EmptyFiles(empty_files_args) => empty_files(empty_files_args, &stop_receiver, &progress_sender), + Commands::Temporary(temporary_args) => temporary(temporary_args, &stop_receiver, &progress_sender), + Commands::SimilarImages(similar_images_args) => similar_images(similar_images_args, &stop_receiver, &progress_sender), + Commands::SameMusic(same_music_args) => same_music(same_music_args, &stop_receiver, &progress_sender), + Commands::InvalidSymlinks(invalid_symlinks_args) => invalid_symlinks(invalid_symlinks_args, &stop_receiver, &progress_sender), + Commands::BrokenFiles(broken_files_args) => broken_files(broken_files_args, &stop_receiver, &progress_sender), + Commands::SimilarVideos(similar_videos_args) => similar_videos(similar_videos_args, &stop_receiver, &progress_sender), + Commands::BadExtensions(bad_extensions_args) => bad_extensions(bad_extensions_args, &stop_receiver, &progress_sender), + Commands::Tester {} => test_image_conversion_speed(), + }) + .expect("Failed to spawn calculation thread"); ctrlc::set_handler(move || { println!("Get Sender"); stop_sender.send(()).expect("Could not send signal on channel."); @@ -70,7 +72,7 @@ fn main() { connect_progress(&progress_receiver); - calculate_thread.unwrap().join().unwrap(); + calculate_thread.join().expect("Failed to join calculation thread"); } fn duplicates(duplicates: DuplicatesArgs, stop_receiver: &Receiver<()>, progress_sender: &Sender) { @@ -85,20 +87,26 @@ fn duplicates(duplicates: DuplicatesArgs, stop_receiver: &Receiver<()>, progress allow_hard_links, dry_run, case_sensitive_name_comparison, + minimal_prehash_cache_file_size, + use_prehash_cache, } = duplicates; - let mut item = DuplicateFinder::new(); + let params = DuplicateFinderParameters::new( + search_method, + hash_type, + !allow_hard_links.allow_hard_links, + use_prehash_cache, + minimal_cached_file_size, + minimal_prehash_cache_file_size, + case_sensitive_name_comparison.case_sensitive_name_comparison, + ); + let mut item = DuplicateFinder::new(params); set_common_settings(&mut item, &common_cli_items); item.set_minimal_file_size(minimal_file_size); item.set_maximal_file_size(maximal_file_size); - item.set_minimal_cache_file_size(minimal_cached_file_size); - item.set_check_method(search_method); item.set_delete_method(delete_method.delete_method); - item.set_hash_type(hash_type); - item.set_ignore_hard_links(!allow_hard_links.allow_hard_links); item.set_dry_run(dry_run.dry_run); - item.set_case_sensitive_name_comparison(case_sensitive_name_comparison.case_sensitive_name_comparison); item.find_duplicates(Some(stop_receiver), Some(progress_sender)); @@ -128,16 +136,14 @@ fn biggest_files(biggest_files: BiggestFilesArgs, stop_receiver: &Receiver<()>, smallest_mode, } = biggest_files; - let mut item = BigFile::new(); + let big_files_mode = if smallest_mode { SearchMode::SmallestFiles } else { SearchMode::BiggestFiles }; + let params = BigFileParameters::new(number_of_files, big_files_mode); + let mut item = BigFile::new(params); set_common_settings(&mut item, &common_cli_items); - item.set_number_of_files_to_check(number_of_files); if delete_files { item.set_delete_method(DeleteMethod::Delete); } - if smallest_mode { - item.set_search_mode(SearchMode::SmallestFiles); - } item.find_big_files(Some(stop_receiver), Some(progress_sender)); @@ -186,20 +192,25 @@ fn similar_images(similar_images: SimilarImagesArgs, stop_receiver: &Receiver<() delete_method, dry_run, allow_hard_links, + ignore_same_size, } = similar_images; - let mut item = SimilarImages::new(); + let similarity = return_similarity_from_similarity_preset(&similarity_preset, hash_size); + let params = SimilarImagesParameters::new( + similarity, + hash_size, + hash_alg, + image_filter, + ignore_same_size.ignore_same_size, + !allow_hard_links.allow_hard_links, + ); + let mut item = SimilarImages::new(params); set_common_settings(&mut item, &common_cli_items); item.set_minimal_file_size(minimal_file_size); item.set_maximal_file_size(maximal_file_size); - item.set_image_filter(image_filter); - item.set_hash_alg(hash_alg); - item.set_hash_size(hash_size); item.set_delete_method(delete_method.delete_method); item.set_dry_run(dry_run.dry_run); - item.set_similarity(return_similarity_from_similarity_preset(&similarity_preset, hash_size)); - item.set_ignore_hard_links(!allow_hard_links.allow_hard_links); item.find_similar_images(Some(stop_receiver), Some(progress_sender)); @@ -217,19 +228,25 @@ fn same_music(same_music: SameMusicArgs, stop_receiver: &Receiver<()>, progress_ minimum_segment_duration, maximum_difference, search_method, + approximate_comparison, + compare_fingerprints_only_with_similar_titles, } = same_music; - let mut item = SameMusic::new(); + let params = SameMusicParameters::new( + music_similarity, + approximate_comparison, + search_method, + minimum_segment_duration, + maximum_difference, + compare_fingerprints_only_with_similar_titles, + ); + let mut item = SameMusic::new(params); set_common_settings(&mut item, &common_cli_items); item.set_minimal_file_size(minimal_file_size); item.set_maximal_file_size(maximal_file_size); - item.set_music_similarity(music_similarity); item.set_delete_method(delete_method.delete_method); item.set_dry_run(dry_run.dry_run); - item.set_minimum_segment_duration(minimum_segment_duration); - item.set_maximum_difference(maximum_difference); - item.set_check_type(search_method); item.find_same_music(Some(stop_receiver), Some(progress_sender)); @@ -252,9 +269,18 @@ fn invalid_symlinks(invalid_symlinks: InvalidSymlinksArgs, stop_receiver: &Recei } fn broken_files(broken_files: BrokenFilesArgs, stop_receiver: &Receiver<()>, progress_sender: &Sender) { - let BrokenFilesArgs { common_cli_items, delete_files } = broken_files; + let BrokenFilesArgs { + common_cli_items, + delete_files, + checked_types, + } = broken_files; - let mut item = BrokenFiles::new(); + let mut checked_type = CheckedTypes::NONE; + for check_type in checked_types { + checked_type |= check_type; + } + let params = BrokenFilesParameters::new(checked_type); + let mut item = BrokenFiles::new(params); set_common_settings(&mut item, &common_cli_items); if delete_files { @@ -275,17 +301,17 @@ fn similar_videos(similar_videos: SimilarVideosArgs, stop_receiver: &Receiver<() delete_method, dry_run, allow_hard_links, + ignore_same_size, } = similar_videos; - let mut item = SimilarVideos::new(); + let params = SimilarVideosParameters::new(tolerance, ignore_same_size.ignore_same_size, !allow_hard_links.allow_hard_links); + let mut item = SimilarVideos::new(params); set_common_settings(&mut item, &common_cli_items); item.set_minimal_file_size(minimal_file_size); item.set_maximal_file_size(maximal_file_size); - item.set_tolerance(tolerance); item.set_delete_method(delete_method.delete_method); item.set_dry_run(dry_run.dry_run); - item.set_ignore_hard_links(!allow_hard_links.allow_hard_links); item.find_similar_videos(Some(stop_receiver), Some(progress_sender)); @@ -295,7 +321,8 @@ fn similar_videos(similar_videos: SimilarVideosArgs, stop_receiver: &Receiver<() fn bad_extensions(bad_extensions: BadExtensionsArgs, stop_receiver: &Receiver<()>, progress_sender: &Sender) { let BadExtensionsArgs { common_cli_items } = bad_extensions; - let mut item = BadExtensions::new(); + let params = BadExtensionsParameters::new(); + let mut item = BadExtensions::new(params); set_common_settings(&mut item, &common_cli_items); diff --git a/czkawka_cli/src/progress.rs b/czkawka_cli/src/progress.rs index 9fc0aaa33..526014b2e 100644 --- a/czkawka_cli/src/progress.rs +++ b/czkawka_cli/src/progress.rs @@ -3,28 +3,30 @@ use std::time::Duration; use crossbeam_channel::Receiver; use indicatif::{ProgressBar, ProgressStyle}; -use czkawka_core::common_dir_traversal::{CheckingMethod, ProgressData, ToolType}; +use czkawka_core::common_dir_traversal::ToolType; +use czkawka_core::progress_data::{CurrentStage, ProgressData}; pub fn connect_progress(progress_receiver: &Receiver) { let mut pb = ProgressBar::new(1); let mut latest_id = None; while let Ok(progress_data) = progress_receiver.recv() { - if latest_id != Some(progress_data.current_stage) { + // We only need to recreate progress bar if stage changed + if latest_id != Some(progress_data.current_stage_idx) { pb.finish_and_clear(); - if progress_data.current_stage == 0 { + if progress_data.current_stage_idx == 0 { pb = get_progress_bar_for_collect_files(); - } else if check_if_saving_cache(&progress_data) || check_if_loading_cache(&progress_data) { - pb = get_progress_loading_saving_cache(check_if_loading_cache(&progress_data)); + } else if progress_data.sstage.check_if_loading_saving_cache() { + pb = get_progress_loading_saving_cache(progress_data.sstage.check_if_loading_cache()); } else { pb = get_progress_known_values(progress_data.entries_to_check, &get_progress_message(&progress_data)); } - latest_id = Some(progress_data.current_stage); + latest_id = Some(progress_data.current_stage_idx); } pb.set_position(progress_data.entries_checked as u64); - if progress_data.current_stage == 0 && progress_data.tool_type != ToolType::EmptyFolders { + if progress_data.sstage == CurrentStage::CollectingFiles && progress_data.tool_type != ToolType::EmptyFolders { pb.set_message(format!("Collecting files: {}", progress_data.entries_checked)); - } else if progress_data.current_stage == 0 { + } else if progress_data.sstage == CurrentStage::CollectingFiles { pb.set_message(format!("Collecting folders: {}", progress_data.entries_checked)); } } @@ -32,43 +34,29 @@ pub fn connect_progress(progress_receiver: &Receiver) { } pub fn get_progress_message(progress_data: &ProgressData) -> String { - match (progress_data.tool_type, progress_data.current_stage, progress_data.checking_method) { - (ToolType::SameMusic, 2, CheckingMethod::AudioTags) | (ToolType::SameMusic, 5, CheckingMethod::AudioContent) => "Reading tags", - (ToolType::SameMusic, 2, CheckingMethod::AudioContent) => "Calculating fingerprint", - (ToolType::SameMusic, 4, CheckingMethod::AudioTags) => "Comparing tags", - (ToolType::SameMusic, 4, CheckingMethod::AudioContent) => "Comparing fingerprint", - - (ToolType::Duplicate, 2, CheckingMethod::Hash) => "Reading prehashes", - (ToolType::Duplicate, 5, CheckingMethod::Hash) => "Reading hashes", - (ToolType::SimilarImages, 1, _) => "Reading images", - (ToolType::SimilarImages, 2, _) => "Comparing image hashes", - (ToolType::SimilarVideos, 1, _) => "Reading similar values", - (ToolType::BrokenFiles, 1, _) => "Checking broken files", - (ToolType::BadExtensions, 1, _) => "Checking extensions of files", + match progress_data.sstage { + CurrentStage::SameMusicReadingTags => "Reading tags", + CurrentStage::SameMusicCalculatingFingerprints => "Calculating fingerprints", + CurrentStage::SameMusicComparingTags => "Comparing tags", + CurrentStage::SameMusicComparingFingerprints => "Comparing fingerprints", + CurrentStage::DuplicatePreHashing => "Calculating prehashes", + CurrentStage::DuplicateFullHashing => "Calculating hashes", + CurrentStage::SimilarImagesCalculatingHashes => "Calculating image hashes", + CurrentStage::SimilarImagesComparingHashes => "Comparing image hashes", + CurrentStage::SimilarVideosCalculatingHashes => "Reading similar values", + CurrentStage::BrokenFilesChecking => "Checking broken files", + CurrentStage::BadExtensionsChecking => "Checking extensions of files", _ => unreachable!(), } .to_string() } -pub fn check_if_loading_cache(progress_data: &ProgressData) -> bool { - matches!( - (progress_data.tool_type, progress_data.current_stage), - (ToolType::SameMusic, 1) | (ToolType::Duplicate, 1 | 4) - ) -} -pub fn check_if_saving_cache(progress_data: &ProgressData) -> bool { - matches!( - (progress_data.tool_type, progress_data.current_stage), - (ToolType::SameMusic, 3) | (ToolType::Duplicate, 3 | 6) - ) -} - pub fn get_progress_bar_for_collect_files() -> ProgressBar { let pb = ProgressBar::new_spinner(); pb.enable_steady_tick(Duration::from_millis(120)); pb.set_style( ProgressStyle::with_template("{msg} {spinner:.blue}") - .unwrap() + .expect("Failed to create progress bar style") .tick_strings(&["▹▹▹▹▹", "▸▹▹▹▹", "▹▸▹▹▹", "▹▹▸▹▹", "▹▹▹▸▹", "▹▹▹▹▸", "▪▪▪▪▪"]), ); pb @@ -76,7 +64,11 @@ pub fn get_progress_bar_for_collect_files() -> ProgressBar { pub fn get_progress_known_values(max_value: usize, msg: &str) -> ProgressBar { let pb = ProgressBar::new(max_value as u64); - pb.set_style(ProgressStyle::with_template(&format!("{msg} [{{bar}}] {{pos}}/{{len}} ")).unwrap().progress_chars("=> ")); + pb.set_style( + ProgressStyle::with_template(&format!("{msg} [{{bar}}] {{pos}}/{{len}} ")) + .expect("Failed to create progress bar style") + .progress_chars("=> "), + ); pb } @@ -86,7 +78,7 @@ pub fn get_progress_loading_saving_cache(loading: bool) -> ProgressBar { pb.enable_steady_tick(Duration::from_millis(120)); pb.set_style( ProgressStyle::with_template(&format!("{msg} {{spinner:.blue}}")) - .unwrap() + .expect("Failed to create progress bar style") .tick_strings(&["▹▹▹▹▹", "▸▹▹▹▹", "▹▸▹▹▹", "▹▹▸▹▹", "▹▹▹▸▹", "▹▹▹▹▸", "▪▪▪▪▪"]), ); pb diff --git a/czkawka_core/Cargo.toml b/czkawka_core/Cargo.toml index 26a26a8e5..eb098aa81 100644 --- a/czkawka_core/Cargo.toml +++ b/czkawka_core/Cargo.toml @@ -3,7 +3,7 @@ name = "czkawka_core" version = "7.0.0" authors = ["RafaÅ‚ Mikrut "] edition = "2021" -rust-version = "1.75.0" +rust-version = "1.79.0" description = "Core of Czkawka app" license = "MIT" homepage = "https://github.com/qarmin/czkawka" @@ -12,24 +12,24 @@ build = "build.rs" [dependencies] humansize = "2.1" -rayon = "1.8" +rayon = "1.10" crossbeam-channel = "0.5" # For saving/loading config files to specific directories directories-next = "2.0" # Needed by similar images -image_hasher = "1.2" +image_hasher = "2.0" bk-tree = "0.5" -image = { version = "0.24", default-features = false, features = ["gif", "jpeg", "ico", "png", "pnm", "tga", "tiff", "webp", "bmp", "hdr", "dxt", "dds", "farbfeld", "openexr", "qoi"] } +image = { version = "0.25", default-features = false, features = ["gif", "jpeg", "ico", "png", "pnm", "tga", "tiff", "webp", "bmp", "hdr", "dds", "qoi"] } hamming = "0.1" # Needed by same music -bitflags = "2.4" -lofty = "0.18" +bitflags = "2.6" +lofty = "0.21" # Needed by broken files -zip = { version = "0.6", features = ["aes-crypto", "bzip2", "deflate", "time"], default-features = false } +zip = { version = "2.2", features = ["aes-crypto", "bzip2", "deflate", "time"], default-features = false } audio_checker = "0.1" pdf = "0.9" @@ -42,7 +42,7 @@ blake3 = "1.5" crc32fast = "1.4" xxhash-rust = { version = "0.8", features = ["xxh3"] } -tempfile = "3.10" +tempfile = "3.12" # Video Duplicates vid_dup_finder_lib = "0.1" @@ -54,9 +54,9 @@ bincode = "1.3" serde_json = "1.0" # Language -i18n-embed = { version = "0.14", features = ["fluent-system", "desktop-requester"] } -i18n-embed-fl = "0.8" -rust-embed = { version = "8.2", features = ["debug-embed"] } +i18n-embed = { version = "0.15", features = ["fluent-system", "desktop-requester"] } +i18n-embed-fl = "0.9" +rust-embed = { version = "8.5", features = ["debug-embed"] } once_cell = "1.19" # Raw image files @@ -66,7 +66,7 @@ libraw-rs = { version = "0.0.4", optional = true } # Checking for invalid extensions mime_guess = "2.0" -infer = "0.15" +infer = "0.16" # Heif/Heic libheif-rs = { version = "=0.18.0", optional = true } # Do not upgrade now, since Ubuntu 22.04 not works with newer version @@ -75,10 +75,10 @@ anyhow = { version = "1.0" } state = "0.6" -trash = "3.3" +trash = "5.1" os_info = { version = "3", default-features = false } -log = "0.4.20" +log = "0.4.22" handsome_logger = "0.8" fun_time = { version = "0.3", features = ["log"] } diff --git a/czkawka_core/src/bad_extensions.rs b/czkawka_core/src/bad_extensions.rs index 6d621466c..144181930 100644 --- a/czkawka_core/src/bad_extensions.rs +++ b/czkawka_core/src/bad_extensions.rs @@ -13,9 +13,10 @@ use rayon::prelude::*; use serde::Serialize; use crate::common::{check_if_stop_received, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads}; -use crate::common_dir_traversal::{CheckingMethod, DirTraversalBuilder, DirTraversalResult, FileEntry, ProgressData, ToolType}; +use crate::common_dir_traversal::{DirTraversalBuilder, DirTraversalResult, FileEntry, ToolType}; use crate::common_tool::{CommonData, CommonToolData}; use crate::common_traits::*; +use crate::progress_data::{CurrentStage, ProgressData}; static DISABLED_EXTENSIONS: &[&str] = &["file", "cache", "bak", "data"]; // Such files can have any type inside @@ -186,22 +187,39 @@ pub struct Info { pub number_of_files_with_bad_extension: usize, } +pub struct BadExtensionsParameters { + pub include_files_without_extension: bool, +} + +impl BadExtensionsParameters { + pub fn new() -> Self { + Self { + include_files_without_extension: false, + } // TODO add option to all modes + } +} +impl Default for BadExtensionsParameters { + fn default() -> Self { + Self::new() + } +} + pub struct BadExtensions { common_data: CommonToolData, information: Info, files_to_check: Vec, bad_extensions_files: Vec, - include_files_without_extension: bool, + params: BadExtensionsParameters, } impl BadExtensions { - pub fn new() -> Self { + pub fn new(params: BadExtensionsParameters) -> Self { Self { common_data: CommonToolData::new(ToolType::BadExtensions), information: Info::default(), files_to_check: Default::default(), bad_extensions_files: Default::default(), - include_files_without_extension: true, + params, } } @@ -244,7 +262,7 @@ impl BadExtensions { #[fun_time(message = "look_for_bad_extensions_files", level = "debug")] fn look_for_bad_extensions_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&Sender>) -> bool { let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) = - prepare_thread_handler_common(progress_sender, 1, 1, self.files_to_check.len(), CheckingMethod::None, self.get_cd().tool_type); + prepare_thread_handler_common(progress_sender, CurrentStage::BadExtensionsChecking, self.files_to_check.len(), self.get_test_type()); let files_to_check = mem::take(&mut self.files_to_check); @@ -312,7 +330,7 @@ impl BadExtensions { // Not found any extension return Some(None); } else if current_extension.is_empty() { - if !self.include_files_without_extension { + if !self.params.include_files_without_extension { return Some(None); } } else if all_available_extensions.take(¤t_extension).is_some() { @@ -329,11 +347,11 @@ impl BadExtensions { })) }) .while_some() - .filter(Option::is_some) - .map(Option::unwrap) + .flatten() .collect::>() } + #[allow(clippy::unused_self)] fn get_and_validate_extension(&self, file_entry: &FileEntry, proper_extension: &str) -> Option { let current_extension; // Extract current extension from file @@ -400,12 +418,6 @@ impl BadExtensions { } } -impl Default for BadExtensions { - fn default() -> Self { - Self::new() - } -} - impl DebugPrint for BadExtensions { fn debug_print(&self) { if !cfg!(debug_assertions) { @@ -445,6 +457,10 @@ impl BadExtensions { &self.bad_extensions_files } + pub fn get_params(&self) -> &BadExtensionsParameters { + &self.params + } + pub const fn get_information(&self) -> &Info { &self.information } diff --git a/czkawka_core/src/big_file.rs b/czkawka_core/src/big_file.rs index cd086b023..9c221e153 100644 --- a/czkawka_core/src/big_file.rs +++ b/czkawka_core/src/big_file.rs @@ -1,16 +1,16 @@ use std::fs; use std::io::Write; +use crate::common_dir_traversal::{DirTraversalBuilder, DirTraversalResult, FileEntry, ToolType}; +use crate::common_tool::{CommonData, CommonToolData, DeleteMethod}; +use crate::common_traits::{DebugPrint, PrintResults}; +use crate::progress_data::ProgressData; use crossbeam_channel::{Receiver, Sender}; use fun_time::fun_time; use humansize::{format_size, BINARY}; use log::debug; use rayon::prelude::*; -use crate::common_dir_traversal::{DirTraversalBuilder, DirTraversalResult, FileEntry, ProgressData, ToolType}; -use crate::common_tool::{CommonData, CommonToolData, DeleteMethod}; -use crate::common_traits::{DebugPrint, PrintResults}; - #[derive(Copy, Clone, Eq, PartialEq)] pub enum SearchMode { BiggestFiles, @@ -22,22 +22,35 @@ pub struct Info { pub number_of_real_files: usize, } +pub struct BigFileParameters { + pub number_of_files_to_check: usize, + pub search_mode: SearchMode, +} + +impl BigFileParameters { + pub fn new(number_of_files: usize, search_mode: SearchMode) -> Self { + let number_of_files_to_check = if number_of_files == 0 { 1 } else { number_of_files }; + Self { + number_of_files_to_check, + search_mode, + } + } +} + pub struct BigFile { common_data: CommonToolData, information: Info, big_files: Vec, - number_of_files_to_check: usize, - search_mode: SearchMode, + params: BigFileParameters, } impl BigFile { - pub fn new() -> Self { + pub fn new(params: BigFileParameters) -> Self { Self { common_data: CommonToolData::new(ToolType::BigFile), information: Info::default(), big_files: Default::default(), - number_of_files_to_check: 50, - search_mode: SearchMode::BiggestFiles, + params, } } @@ -61,7 +74,6 @@ impl BigFile { .common_data(&self.common_data) .minimal_file_size(1) .maximal_file_size(u64::MAX) - .max_stage(0) .build() .run(); @@ -70,17 +82,18 @@ impl BigFile { let mut all_files = grouped_file_entries.into_values().flatten().collect::>(); all_files.par_sort_unstable_by_key(|fe| fe.size); - if self.search_mode == SearchMode::BiggestFiles { + if self.get_params().search_mode == SearchMode::BiggestFiles { all_files.reverse(); } - if all_files.len() > self.number_of_files_to_check { - all_files.truncate(self.number_of_files_to_check); + if all_files.len() > self.get_params().number_of_files_to_check { + all_files.truncate(self.get_params().number_of_files_to_check); } self.big_files = all_files; self.common_data.text_messages.warnings.extend(warnings); + self.information.number_of_real_files = self.big_files.len(); debug!("check_files - Found {} biggest/smallest files.", self.big_files.len()); true } @@ -106,12 +119,6 @@ impl BigFile { } } -impl Default for BigFile { - fn default() -> Self { - Self::new() - } -} - impl DebugPrint for BigFile { fn debug_print(&self) { if !cfg!(debug_assertions) { @@ -120,7 +127,7 @@ impl DebugPrint for BigFile { println!("### INDIVIDUAL DEBUG PRINT ###"); println!("Big files size {} in {} groups", self.information.number_of_real_files, self.big_files.len()); - println!("Number of files to check - {:?}", self.number_of_files_to_check); + println!("Number of files to check - {:?}", self.get_params().number_of_files_to_check); self.debug_print_common(); println!("-----------------------------------------"); } @@ -137,7 +144,7 @@ impl PrintResults for BigFile { )?; if self.information.number_of_real_files != 0 { - if self.search_mode == SearchMode::BiggestFiles { + if self.get_params().search_mode == SearchMode::BiggestFiles { writeln!(writer, "{} the biggest files.\n\n", self.information.number_of_real_files)?; } else { writeln!(writer, "{} the smallest files.\n\n", self.information.number_of_real_files)?; @@ -146,7 +153,7 @@ impl PrintResults for BigFile { writeln!(writer, "{} ({}) - {:?}", format_size(file_entry.size, BINARY), file_entry.size, file_entry.path)?; } } else { - write!(writer, "Not found any files.").unwrap(); + writeln!(writer, "Not found any files.")?; } Ok(()) @@ -167,10 +174,6 @@ impl CommonData for BigFile { } impl BigFile { - pub fn set_search_mode(&mut self, search_mode: SearchMode) { - self.search_mode = search_mode; - } - pub const fn get_big_files(&self) -> &Vec { &self.big_files } @@ -179,7 +182,7 @@ impl BigFile { &self.information } - pub fn set_number_of_files_to_check(&mut self, number_of_files_to_check: usize) { - self.number_of_files_to_check = number_of_files_to_check; + pub fn get_params(&self) -> &BigFileParameters { + &self.params } } diff --git a/czkawka_core/src/broken_files.rs b/czkawka_core/src/broken_files.rs index 95f2f787b..64755eff6 100644 --- a/czkawka_core/src/broken_files.rs +++ b/czkawka_core/src/broken_files.rs @@ -5,6 +5,15 @@ use std::path::{Path, PathBuf}; use std::sync::atomic::Ordering; use std::{fs, mem, panic}; +use crate::common::{ + check_if_stop_received, create_crash_message, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads, AUDIO_FILES_EXTENSIONS, + IMAGE_RS_BROKEN_FILES_EXTENSIONS, PDF_FILES_EXTENSIONS, ZIP_FILES_EXTENSIONS, +}; +use crate::common_cache::{get_broken_files_cache_file, load_cache_from_file_generalized_by_path, save_cache_to_file_generalized}; +use crate::common_dir_traversal::{DirTraversalBuilder, DirTraversalResult, FileEntry, ToolType}; +use crate::common_tool::{CommonData, CommonToolData, DeleteMethod}; +use crate::common_traits::*; +use crate::progress_data::{CurrentStage, ProgressData}; use crossbeam_channel::{Receiver, Sender}; use fun_time::fun_time; use log::debug; @@ -15,15 +24,6 @@ use pdf::PdfError::Try; use rayon::prelude::*; use serde::{Deserialize, Serialize}; -use crate::common::{ - check_if_stop_received, create_crash_message, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads, AUDIO_FILES_EXTENSIONS, - IMAGE_RS_BROKEN_FILES_EXTENSIONS, PDF_FILES_EXTENSIONS, ZIP_FILES_EXTENSIONS, -}; -use crate::common_cache::{get_broken_files_cache_file, load_cache_from_file_generalized_by_path, save_cache_to_file_generalized}; -use crate::common_dir_traversal::{CheckingMethod, DirTraversalBuilder, DirTraversalResult, FileEntry, ProgressData, ToolType}; -use crate::common_tool::{CommonData, CommonToolData, DeleteMethod}; -use crate::common_traits::*; - #[derive(Clone, Serialize, Deserialize, Debug)] pub struct BrokenEntry { pub path: PathBuf, @@ -66,10 +66,8 @@ pub enum TypeOfFile { PDF, } -const MAX_BROKEN_FILES_STAGE: u8 = 1; - bitflags! { - #[derive(PartialEq, Copy, Clone)] + #[derive(PartialEq, Copy, Clone, Debug)] pub struct CheckedTypes : u32 { const NONE = 0; @@ -85,22 +83,32 @@ pub struct Info { pub number_of_broken_files: usize, } +pub struct BrokenFilesParameters { + pub checked_types: CheckedTypes, +} + +impl BrokenFilesParameters { + pub fn new(checked_types: CheckedTypes) -> Self { + Self { checked_types } + } +} + pub struct BrokenFiles { common_data: CommonToolData, information: Info, files_to_check: BTreeMap, broken_files: Vec, - checked_types: CheckedTypes, + params: BrokenFilesParameters, } impl BrokenFiles { - pub fn new() -> Self { + pub fn new(params: BrokenFilesParameters) -> Self { Self { common_data: CommonToolData::new(ToolType::BrokenFiles), information: Info::default(), files_to_check: Default::default(), broken_files: Default::default(), - checked_types: CheckedTypes::PDF | CheckedTypes::AUDIO | CheckedTypes::IMAGE | CheckedTypes::ARCHIVE, + params, } } @@ -134,7 +142,7 @@ impl BrokenFiles { (CheckedTypes::IMAGE, IMAGE_RS_BROKEN_FILES_EXTENSIONS), ]; for (checked_type, extensions_to_add) in &vec_extensions { - if self.checked_types.contains(*checked_type) { + if self.get_params().checked_types.contains(*checked_type) { extensions.extend_from_slice(extensions_to_add); } } @@ -149,7 +157,6 @@ impl BrokenFiles { .stop_receiver(stop_receiver) .progress_sender(progress_sender) .common_data(&self.common_data) - .max_stage(MAX_BROKEN_FILES_STAGE) .build() .run(); @@ -296,7 +303,7 @@ impl BrokenFiles { let (loaded_hash_map, records_already_cached, non_cached_files_to_check) = self.load_cache(); let (progress_thread_handle, progress_thread_run, atomic_counter, _check_was_stopped) = - prepare_thread_handler_common(progress_sender, 1, 1, non_cached_files_to_check.len(), CheckingMethod::None, self.common_data.tool_type); + prepare_thread_handler_common(progress_sender, CurrentStage::BrokenFilesChecking, non_cached_files_to_check.len(), self.get_test_type()); debug!("look_for_broken_files - started finding for broken files"); let mut vec_file_entry: Vec = non_cached_files_to_check @@ -317,8 +324,7 @@ impl BrokenFiles { } }) .while_some() - .filter(Option::is_some) - .map(Option::unwrap) + .flatten() .collect::>(); debug!("look_for_broken_files - ended finding for broken files"); @@ -384,19 +390,14 @@ impl BrokenFiles { &self.broken_files } - pub fn set_checked_types(&mut self, checked_types: CheckedTypes) { - self.checked_types = checked_types; + pub fn get_params(&self) -> &BrokenFilesParameters { + &self.params } pub const fn get_information(&self) -> &Info { &self.information } } -impl Default for BrokenFiles { - fn default() -> Self { - Self::new() - } -} impl DebugPrint for BrokenFiles { fn debug_print(&self) { diff --git a/czkawka_core/src/common.rs b/czkawka_core/src/common.rs index 94c720117..e88b0daf7 100644 --- a/czkawka_core/src/common.rs +++ b/czkawka_core/src/common.rs @@ -1,7 +1,6 @@ #![allow(unused_imports)] +// I don't wanna fight with unused(heif) imports in this file, so simply ignore it to avoid too much complexity -use std::{fs, thread}; -// I don't wanna fight with unused imports in this file, so simply ignore it to avoid too much complexity use std::cmp::Ordering; use std::ffi::OsString; use std::fs::{DirEntry, File, OpenOptions}; @@ -10,6 +9,7 @@ use std::sync::atomic::{AtomicBool, AtomicUsize}; use std::sync::{atomic, Arc}; use std::thread::{sleep, JoinHandle}; use std::time::{Duration, Instant, SystemTime}; +use std::{fs, thread}; #[cfg(feature = "heif")] use anyhow::Result; @@ -29,13 +29,14 @@ use symphonia::core::conv::IntoSample; // #[cfg(feature = "heif")] // use libheif_rs::LibHeif; -use crate::common_dir_traversal::{CheckingMethod, ProgressData, ToolType}; +use crate::common_dir_traversal::{CheckingMethod, ToolType}; use crate::common_directory::Directories; use crate::common_items::{ExcludedItems, SingleExcludedItem}; use crate::common_messages::Messages; -use crate::common_tool::DeleteMethod; +use crate::common_tool::{CommonData, DeleteMethod}; use crate::common_traits::ResultEntry; use crate::duplicate::make_hard_link; +use crate::progress_data::{CurrentStage, ProgressData}; use crate::CZKAWKA_VERSION; static NUMBER_OF_THREADS: state::InitCell = state::InitCell::new(); @@ -64,7 +65,7 @@ pub fn setup_logger(disabled_printing: bool) { let log_level = if disabled_printing { LevelFilter::Off } else { LevelFilter::Info }; let config = ConfigBuilder::default().set_level(log_level).set_message_filtering(Some(filtering_messages)).build(); - handsome_logger::TermLogger::init(config, TerminalMode::Mixed, ColorChoice::Always).unwrap(); + handsome_logger::TermLogger::init(config, TerminalMode::Mixed, ColorChoice::Always).expect("Cannot initialize logger"); } pub fn get_all_available_threads() -> usize { @@ -116,7 +117,7 @@ pub fn set_number_of_threads(thread_number: usize) { .num_threads(get_number_of_threads()) .stack_size(DEFAULT_WORKER_THREAD_SIZE) .build_global() - .unwrap(); + .expect("Cannot set number of threads"); } pub const RAW_IMAGE_EXTENSIONS: &[&str] = &[ @@ -256,7 +257,7 @@ pub fn get_dynamic_image_from_heic(path: &str) -> Result { let width = image.width(); let height = image.height(); let planes = image.planes(); - let interleaved_plane = planes.interleaved.unwrap(); + let interleaved_plane = planes.interleaved.ok_or_else(|| anyhow::anyhow!("Failed to get interleaved plane"))?; ImageBuffer::from_raw(width, height, interleaved_plane.data.to_owned()) .map(DynamicImage::ImageRgb8) .ok_or_else(|| anyhow::anyhow!("Failed to create image buffer")) @@ -353,16 +354,23 @@ pub fn regex_check(expression_item: &SingleExcludedItem, directory_name: &str) - } // `git*` shouldn't be true for `/gitsfafasfs` - if !expression_item.expression.starts_with('*') && directory_name.find(&expression_item.expression_splits[0]).unwrap() > 0 { + if !expression_item.expression.starts_with('*') + && directory_name + .find(&expression_item.expression_splits[0]) + .expect("Cannot fail, because split must exists in directory_name") + > 0 + { return false; } // `*home` shouldn't be true for `/homeowner` - if !expression_item.expression.ends_with('*') && !directory_name.ends_with(expression_item.expression_splits.last().unwrap()) { + if !expression_item.expression.ends_with('*') + && !directory_name.ends_with(expression_item.expression_splits.last().expect("Cannot fail, because at least one item is available")) + { return false; } // At the end we check if parts between * are correctly positioned - let mut last_split_point = directory_name.find(&expression_item.expression_splits[0]).unwrap(); + let mut last_split_point = directory_name.find(&expression_item.expression_splits[0]).expect("Cannot fail, because is checked earlier"); let mut current_index: usize = 0; let mut found_index: usize; for spl in &expression_item.expression_splits[1..] { @@ -535,10 +543,10 @@ where let (mut files_from_referenced_folders, normal_files): (Vec<_>, Vec<_>) = vec_file_entry.into_iter().partition(|e| directories.is_in_referenced_directory(e.get_path())); - if files_from_referenced_folders.is_empty() || normal_files.is_empty() { + if normal_files.is_empty() { None } else { - Some((files_from_referenced_folders.pop().unwrap(), normal_files)) + files_from_referenced_folders.pop().map(|file| (file, normal_files)) } }) .collect::)>>() @@ -546,12 +554,11 @@ where pub fn prepare_thread_handler_common( progress_sender: Option<&Sender>, - current_stage: u8, - max_stage: u8, + sstage: CurrentStage, max_value: usize, - checking_method: CheckingMethod, - tool_type: ToolType, + test_type: (ToolType, CheckingMethod), ) -> (JoinHandle<()>, Arc, Arc, AtomicBool) { + let (tool_type, checking_method) = test_type; assert_ne!(tool_type, ToolType::None, "ToolType::None should not exist"); let progress_thread_run = Arc::new(AtomicBool::new(true)); let atomic_counter = Arc::new(AtomicUsize::new(0)); @@ -565,17 +572,20 @@ pub fn prepare_thread_handler_common( let mut time_since_last_send = SystemTime::now() - Duration::from_secs(10u64); loop { - if time_since_last_send.elapsed().unwrap().as_millis() > SEND_PROGRESS_DATA_TIME_BETWEEN as u128 { - progress_send - .send(ProgressData { - checking_method, - current_stage, - max_stage, - entries_checked: atomic_counter.load(atomic::Ordering::Relaxed), - entries_to_check: max_value, - tool_type, - }) - .unwrap(); + if time_since_last_send.elapsed().expect("Cannot count time backwards").as_millis() > SEND_PROGRESS_DATA_TIME_BETWEEN as u128 { + let progress_data = ProgressData { + sstage, + checking_method, + current_stage_idx: sstage.get_current_stage(), + max_stage_idx: tool_type.get_max_stage(checking_method), + entries_checked: atomic_counter.load(atomic::Ordering::Relaxed), + entries_to_check: max_value, + tool_type, + }; + + progress_data.validate(); + + progress_send.send(progress_data).expect("Cannot send progress data"); time_since_last_send = SystemTime::now(); } if !progress_thread_run.load(atomic::Ordering::Relaxed) { @@ -603,7 +613,7 @@ pub fn check_if_stop_received(stop_receiver: Option<&crossbeam_channel::Receiver #[fun_time(message = "send_info_and_wait_for_ending_all_threads", level = "debug")] pub fn send_info_and_wait_for_ending_all_threads(progress_thread_run: &Arc, progress_thread_handle: JoinHandle<()>) { progress_thread_run.store(false, atomic::Ordering::Relaxed); - progress_thread_handle.join().unwrap(); + progress_thread_handle.join().expect("Cannot join progress thread - quite fatal error, but happens rarely"); } #[cfg(test)] @@ -619,24 +629,24 @@ mod test { #[test] fn test_remove_folder_if_contains_only_empty_folders() { - let dir = tempdir().unwrap(); + let dir = tempdir().expect("Cannot create temporary directory"); let sub_dir = dir.path().join("sub_dir"); - fs::create_dir(&sub_dir).unwrap(); + fs::create_dir(&sub_dir).expect("Cannot create directory"); // Test with empty directory assert!(remove_folder_if_contains_only_empty_folders(&sub_dir, false).is_ok()); assert!(!Path::new(&sub_dir).exists()); // Test with directory containing an empty directory - fs::create_dir(&sub_dir).unwrap(); - fs::create_dir(sub_dir.join("empty_sub_dir")).unwrap(); + fs::create_dir(&sub_dir).expect("Cannot create directory"); + fs::create_dir(sub_dir.join("empty_sub_dir")).expect("Cannot create directory"); assert!(remove_folder_if_contains_only_empty_folders(&sub_dir, false).is_ok()); assert!(!Path::new(&sub_dir).exists()); // Test with directory containing a file - fs::create_dir(&sub_dir).unwrap(); - let mut file = fs::File::create(sub_dir.join("file.txt")).unwrap(); - writeln!(file, "Hello, world!").unwrap(); + fs::create_dir(&sub_dir).expect("Cannot create directory"); + let mut file = fs::File::create(sub_dir.join("file.txt")).expect("Cannot create file"); + writeln!(file, "Hello, world!").expect("Cannot write to file"); assert!(remove_folder_if_contains_only_empty_folders(&sub_dir, false).is_err()); assert!(Path::new(&sub_dir).exists()); } diff --git a/czkawka_core/src/common_cache.rs b/czkawka_core/src/common_cache.rs index 91375e71d..e78aac69a 100644 --- a/czkawka_core/src/common_cache.rs +++ b/czkawka_core/src/common_cache.rs @@ -56,7 +56,7 @@ where let hashmap_to_save = hashmap.values().filter(|t| t.get_size() >= minimum_file_size).collect::>(); { - let writer = BufWriter::new(file_handler.unwrap()); // Unwrap because cannot fail here + let writer = BufWriter::new(file_handler.expect("Cannot fail, because for saving, this always exists")); if let Err(e) = bincode::serialize_into(writer, &hashmap_to_save) { text_messages.warnings.push(format!("Cannot write data to cache file {cache_file:?}, reason {e}")); debug!("Failed to save cache to file {cache_file:?}"); @@ -187,7 +187,7 @@ where } }; } else { - let reader = BufReader::new(file_handler_json.unwrap()); // Unwrap cannot fail, because at least one file must be valid + let reader = BufReader::new(file_handler_json.expect("This cannot fail, because if file_handler is None, then this cannot be None")); vec_loaded_entries = match serde_json::from_reader(reader) { Ok(t) => t, Err(e) => { diff --git a/czkawka_core/src/common_dir_traversal.rs b/czkawka_core/src/common_dir_traversal.rs index 0e2a6633b..dcc53c0c3 100644 --- a/czkawka_core/src/common_dir_traversal.rs +++ b/czkawka_core/src/common_dir_traversal.rs @@ -21,16 +21,7 @@ use crate::common_items::ExcludedItems; use crate::common_tool::CommonToolData; use crate::common_traits::ResultEntry; use crate::flc; - -#[derive(Debug)] -pub struct ProgressData { - pub checking_method: CheckingMethod, - pub current_stage: u8, - pub max_stage: u8, - pub entries_checked: usize, - pub entries_to_check: usize, - pub tool_type: ToolType, -} +use crate::progress_data::{CurrentStage, ProgressData}; #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)] pub enum ToolType { @@ -119,7 +110,6 @@ pub struct DirTraversalBuilder<'a, 'b, F> { minimal_file_size: Option, maximal_file_size: Option, checking_method: CheckingMethod, - max_stage: u8, collect: Collect, recursive_search: bool, directories: Option, @@ -140,7 +130,6 @@ pub struct DirTraversal<'a, 'b, F> { minimal_file_size: u64, maximal_file_size: u64, checking_method: CheckingMethod, - max_stage: u8, tool_type: ToolType, collect: Collect, } @@ -159,7 +148,6 @@ impl<'a, 'b> DirTraversalBuilder<'a, 'b, ()> { stop_receiver: None, progress_sender: None, checking_method: CheckingMethod::None, - max_stage: 0, minimal_file_size: None, maximal_file_size: None, collect: Collect::Files, @@ -205,11 +193,6 @@ impl<'a, 'b, F> DirTraversalBuilder<'a, 'b, F> { self } - pub fn max_stage(mut self, max_stage: u8) -> Self { - self.max_stage = max_stage; - self - } - pub fn minimal_file_size(mut self, minimal_file_size: u64) -> Self { self.minimal_file_size = Some(minimal_file_size); self @@ -276,7 +259,6 @@ impl<'a, 'b, F> DirTraversalBuilder<'a, 'b, F> { minimal_file_size: self.minimal_file_size, collect: self.collect, checking_method: self.checking_method, - max_stage: self.max_stage, tool_type: self.tool_type, } } @@ -288,7 +270,6 @@ impl<'a, 'b, F> DirTraversalBuilder<'a, 'b, F> { stop_receiver: self.stop_receiver, progress_sender: self.progress_sender, checking_method: self.checking_method, - max_stage: self.max_stage, minimal_file_size: self.minimal_file_size.unwrap_or(0), maximal_file_size: self.maximal_file_size.unwrap_or(u64::MAX), collect: self.collect, @@ -337,7 +318,7 @@ where let mut folders_to_check: Vec = self.root_dirs.clone(); let (progress_thread_handle, progress_thread_run, atomic_counter, _check_was_stopped) = - prepare_thread_handler_common(self.progress_sender, 0, self.max_stage, 0, self.checking_method, self.tool_type); + prepare_thread_handler_common(self.progress_sender, CurrentStage::CollectingFiles, 0, (self.tool_type, self.checking_method)); let DirTraversal { collect, @@ -688,11 +669,10 @@ mod tests { use crate::common_tool::*; use once_cell::sync::Lazy; use std::collections::HashSet; - use std::fs; use std::fs::File; - use std::io; use std::io::prelude::*; use std::time::{Duration, SystemTime}; + use std::{fs, io}; use tempfile::TempDir; impl CommonData for CommonToolData { @@ -725,7 +705,7 @@ mod tests { fn test_traversal() -> io::Result<()> { let dir = tempfile::Builder::new().tempdir()?; let (src, hard, other) = create_files(&dir)?; - let secs = NOW.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs(); + let secs = NOW.duration_since(SystemTime::UNIX_EPOCH).expect("Cannot fail calculating duration since epoch").as_secs(); let mut common_data = CommonToolData::new(ToolType::SimilarImages); common_data.directories.set_included_directory([dir.path().to_owned()].to_vec()); @@ -770,7 +750,7 @@ mod tests { fn test_traversal_group_by_inode() -> io::Result<()> { let dir = tempfile::Builder::new().tempdir()?; let (src, _, other) = create_files(&dir)?; - let secs = NOW.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs(); + let secs = NOW.duration_since(SystemTime::UNIX_EPOCH).expect("Cannot fail calculating duration since epoch").as_secs(); let mut common_data = CommonToolData::new(ToolType::SimilarImages); common_data.directories.set_included_directory([dir.path().to_owned()].to_vec()); @@ -810,7 +790,7 @@ mod tests { fn test_traversal_group_by_inode() -> io::Result<()> { let dir = tempfile::Builder::new().tempdir()?; let (src, hard, other) = create_files(&dir)?; - let secs = NOW.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs(); + let secs = NOW.duration_since(SystemTime::UNIX_EPOCH).expect("Cannot fail duration from epoch").as_secs(); let mut common_data = CommonToolData::new(ToolType::SimilarImages); common_data.directories.set_included_directory([dir.path().to_owned()].to_vec()); diff --git a/czkawka_core/src/common_extensions.rs b/czkawka_core/src/common_extensions.rs index a3336e340..558452fbb 100644 --- a/czkawka_core/src/common_extensions.rs +++ b/czkawka_core/src/common_extensions.rs @@ -106,6 +106,7 @@ impl Extensions { // E.g. when using similar videos, user can provide extensions like "mp4,flv", but if user provide "mp4,jpg" then // it will be only "mp4" because "jpg" is not valid extension for videos + #[allow(clippy::unused_self)] fn union_allowed_extensions(&mut self, file_extensions: &[&str]) { let mut new_extensions = HashSet::new(); for extension in file_extensions { diff --git a/czkawka_core/src/common_tool.rs b/czkawka_core/src/common_tool.rs index 16d74cd46..208dbb241 100644 --- a/czkawka_core/src/common_tool.rs +++ b/czkawka_core/src/common_tool.rs @@ -1,6 +1,6 @@ use std::path::PathBuf; -use crate::common_dir_traversal::ToolType; +use crate::common_dir_traversal::{CheckingMethod, ToolType}; use crate::common_directory::Directories; use crate::common_extensions::Extensions; use crate::common_items::ExcludedItems; @@ -62,6 +62,16 @@ impl CommonToolData { pub trait CommonData { fn get_cd(&self) -> &CommonToolData; fn get_cd_mut(&mut self) -> &mut CommonToolData; + fn get_check_method(&self) -> CheckingMethod { + CheckingMethod::None + } + fn get_test_type(&self) -> (ToolType, CheckingMethod) { + (self.get_cd().tool_type, self.get_check_method()) + } + + fn get_tool_type(&self) -> ToolType { + self.get_cd().tool_type + } fn set_dry_run(&mut self, dry_run: bool) { self.get_cd_mut().dry_run = dry_run; diff --git a/czkawka_core/src/common_traits.rs b/czkawka_core/src/common_traits.rs index 744d33e1b..fccc6dde8 100644 --- a/czkawka_core/src/common_traits.rs +++ b/czkawka_core/src/common_traits.rs @@ -16,8 +16,9 @@ pub trait PrintResults { fn print_results_to_output(&self) { let stdout = std::io::stdout(); let mut handle = stdout.lock(); - self.write_results(&mut handle).unwrap(); - handle.flush().unwrap(); + // Panics here are allowed, because it is used only in CLI + self.write_results(&mut handle).expect("Error while writing to stdout"); + handle.flush().expect("Error while flushing stdout"); } #[fun_time(message = "print_results_to_file", level = "debug")] diff --git a/czkawka_core/src/duplicate.rs b/czkawka_core/src/duplicate.rs index 8a62f7b94..9212540b4 100644 --- a/czkawka_core/src/duplicate.rs +++ b/czkawka_core/src/duplicate.rs @@ -10,6 +10,12 @@ use std::path::{Path, PathBuf}; use std::sync::atomic::Ordering; use std::{fs, mem}; +use crate::common::{check_if_stop_received, delete_files_custom, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads}; +use crate::common_cache::{get_duplicate_cache_file, load_cache_from_file_generalized_by_size, save_cache_to_file_generalized}; +use crate::common_dir_traversal::{CheckingMethod, DirTraversalBuilder, DirTraversalResult, FileEntry, ToolType}; +use crate::common_tool::{CommonData, CommonToolData, DeleteMethod}; +use crate::common_traits::*; +use crate::progress_data::{CurrentStage, ProgressData}; use crossbeam_channel::{Receiver, Sender}; use fun_time::fun_time; use humansize::{format_size, BINARY}; @@ -18,12 +24,6 @@ use rayon::prelude::*; use serde::{Deserialize, Serialize}; use xxhash_rust::xxh3::Xxh3; -use crate::common::{check_if_stop_received, delete_files_custom, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads}; -use crate::common_cache::{get_duplicate_cache_file, load_cache_from_file_generalized_by_size, save_cache_to_file_generalized}; -use crate::common_dir_traversal::{CheckingMethod, DirTraversalBuilder, DirTraversalResult, FileEntry, ProgressData, ToolType}; -use crate::common_tool::{CommonData, CommonToolData, DeleteMethod}; -use crate::common_traits::*; - const TEMP_HARDLINK_FILE: &str = "rzeczek.rxrxrxl"; #[derive(PartialEq, Eq, Clone, Debug, Copy, Default)] @@ -34,9 +34,8 @@ pub enum HashType { Xxh3, } -const MAX_STAGE: u8 = 5; impl HashType { - fn hasher(self: &HashType) -> Box { + fn hasher(self: HashType) -> Box { match self { HashType::Blake3 => Box::new(blake3::Hasher::new()), HashType::Crc32 => Box::new(crc32fast::Hasher::new()), @@ -89,6 +88,38 @@ pub struct Info { pub lost_space_by_hash: u64, } +pub struct DuplicateFinderParameters { + pub check_method: CheckingMethod, + pub hash_type: HashType, + pub ignore_hard_links: bool, + pub use_prehash_cache: bool, + pub minimal_cache_file_size: u64, + pub minimal_prehash_cache_file_size: u64, + pub case_sensitive_name_comparison: bool, +} + +impl DuplicateFinderParameters { + pub fn new( + check_method: CheckingMethod, + hash_type: HashType, + ignore_hard_links: bool, + use_prehash_cache: bool, + minimal_cache_file_size: u64, + minimal_prehash_cache_file_size: u64, + case_sensitive_name_comparison: bool, + ) -> Self { + Self { + check_method, + hash_type, + ignore_hard_links, + use_prehash_cache, + minimal_cache_file_size, + minimal_prehash_cache_file_size, + case_sensitive_name_comparison, + } + } +} + pub struct DuplicateFinder { common_data: CommonToolData, information: Info, @@ -108,17 +139,11 @@ pub struct DuplicateFinder { files_with_identical_size_referenced: BTreeMap)>, // File Size, next grouped by file size, next grouped by hash files_with_identical_hashes_referenced: BTreeMap)>>, - check_method: CheckingMethod, - hash_type: HashType, - ignore_hard_links: bool, - use_prehash_cache: bool, - minimal_cache_file_size: u64, - minimal_prehash_cache_file_size: u64, - case_sensitive_name_comparison: bool, + params: DuplicateFinderParameters, } impl DuplicateFinder { - pub fn new() -> Self { + pub fn new(params: DuplicateFinderParameters) -> Self { Self { common_data: CommonToolData::new(ToolType::Duplicate), information: Info::default(), @@ -130,13 +155,7 @@ impl DuplicateFinder { files_with_identical_size_names_referenced: Default::default(), files_with_identical_size_referenced: Default::default(), files_with_identical_hashes_referenced: Default::default(), - check_method: CheckingMethod::None, - ignore_hard_links: true, - hash_type: HashType::Blake3, - use_prehash_cache: true, - minimal_cache_file_size: 1024 * 256, // By default cache only >= 256 KB files - minimal_prehash_cache_file_size: 0, - case_sensitive_name_comparison: false, + params, } } @@ -145,7 +164,7 @@ impl DuplicateFinder { self.prepare_items(); self.common_data.use_reference_folders = !self.common_data.directories.reference_directories.is_empty(); - match self.check_method { + match self.get_params().check_method { CheckingMethod::Name => { self.common_data.stopped_search = !self.check_files_name(stop_receiver, progress_sender); // TODO restore this to name if self.common_data.stopped_search { @@ -182,10 +201,22 @@ impl DuplicateFinder { #[fun_time(message = "check_files_name", level = "debug")] fn check_files_name(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&Sender>) -> bool { - let group_by_func = if self.case_sensitive_name_comparison { - |fe: &FileEntry| fe.path.file_name().unwrap().to_string_lossy().to_string() + let group_by_func = if self.get_params().case_sensitive_name_comparison { + |fe: &FileEntry| { + fe.path + .file_name() + .unwrap_or_else(|| panic!("Found invalid file_name {:?}", fe.path)) + .to_string_lossy() + .to_string() + } } else { - |fe: &FileEntry| fe.path.file_name().unwrap().to_string_lossy().to_lowercase() + |fe: &FileEntry| { + fe.path + .file_name() + .unwrap_or_else(|| panic!("Found invalid file_name {:?}", fe.path)) + .to_string_lossy() + .to_lowercase() + } }; let result = DirTraversalBuilder::new() @@ -222,10 +253,10 @@ impl DuplicateFinder { .into_iter() .partition(|e| self.common_data.directories.is_in_referenced_directory(e.get_path())); - if files_from_referenced_folders.is_empty() || normal_files.is_empty() { + if normal_files.is_empty() { None } else { - Some((files_from_referenced_folders.pop().unwrap(), normal_files)) + files_from_referenced_folders.pop().map(|file| (file, normal_files)) } }) .collect::)>>(); @@ -257,10 +288,28 @@ impl DuplicateFinder { #[fun_time(message = "check_files_size_name", level = "debug")] fn check_files_size_name(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&Sender>) -> bool { - let group_by_func = if self.case_sensitive_name_comparison { - |fe: &FileEntry| (fe.size, fe.path.file_name().unwrap().to_string_lossy().to_string()) + let group_by_func = if self.get_params().case_sensitive_name_comparison { + |fe: &FileEntry| { + ( + fe.size, + fe.path + .file_name() + .unwrap_or_else(|| panic!("Found invalid file_name {:?}", fe.path)) + .to_string_lossy() + .to_string(), + ) + } } else { - |fe: &FileEntry| (fe.size, fe.path.file_name().unwrap().to_string_lossy().to_lowercase()) + |fe: &FileEntry| { + ( + fe.size, + fe.path + .file_name() + .unwrap_or_else(|| panic!("Found invalid file_name {:?}", fe.path)) + .to_string_lossy() + .to_lowercase(), + ) + } }; let result = DirTraversalBuilder::new() @@ -296,10 +345,10 @@ impl DuplicateFinder { .into_iter() .partition(|e| self.common_data.directories.is_in_referenced_directory(e.get_path())); - if files_from_referenced_folders.is_empty() || normal_files.is_empty() { + if normal_files.is_empty() { None } else { - Some((files_from_referenced_folders.pop().unwrap(), normal_files)) + files_from_referenced_folders.pop().map(|file| (file, normal_files)) } }) .collect::)>>(); @@ -335,18 +384,12 @@ impl DuplicateFinder { #[fun_time(message = "check_files_size", level = "debug")] fn check_files_size(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&Sender>) -> bool { - let max_stage = match self.check_method { - CheckingMethod::Size => 0, - CheckingMethod::Hash => MAX_STAGE, - _ => panic!(), - }; let result = DirTraversalBuilder::new() .common_data(&self.common_data) .group_by(|fe| fe.size) .stop_receiver(stop_receiver) .progress_sender(progress_sender) - .checking_method(self.check_method) - .max_stage(max_stage) + .checking_method(self.get_params().check_method) .build() .run(); @@ -359,7 +402,7 @@ impl DuplicateFinder { continue; } - let vector = if self.ignore_hard_links { filter_hard_links(&vec) } else { vec }; + let vector = if self.get_params().ignore_hard_links { filter_hard_links(&vec) } else { vec }; if vector.len() > 1 { self.files_with_identical_size @@ -403,7 +446,7 @@ impl DuplicateFinder { #[fun_time(message = "filter_reference_folders_by_size", level = "debug")] fn filter_reference_folders_by_size(&mut self) { - if self.common_data.use_reference_folders && self.check_method == CheckingMethod::Size { + if self.common_data.use_reference_folders && self.get_params().check_method == CheckingMethod::Size { let vec = mem::take(&mut self.files_with_identical_size) .into_iter() .filter_map(|(_size, vec_file_entry)| { @@ -411,10 +454,10 @@ impl DuplicateFinder { .into_iter() .partition(|e| self.common_data.directories.is_in_referenced_directory(e.get_path())); - if files_from_referenced_folders.is_empty() || normal_files.is_empty() { + if normal_files.is_empty() { None } else { - Some((files_from_referenced_folders.pop().unwrap(), normal_files)) + files_from_referenced_folders.pop().map(|file| (file, normal_files)) } }) .collect::)>>(); @@ -434,9 +477,9 @@ impl DuplicateFinder { let mut records_already_cached: BTreeMap> = Default::default(); let mut non_cached_files_to_check: BTreeMap> = Default::default(); - if self.use_prehash_cache { + if self.get_params().use_prehash_cache { let (messages, loaded_items) = load_cache_from_file_generalized_by_size::( - &get_duplicate_cache_file(&self.hash_type, true), + &get_duplicate_cache_file(&self.get_params().hash_type, true), self.get_delete_outdated_cache(), &self.files_with_identical_size, ); @@ -483,12 +526,12 @@ impl DuplicateFinder { loaded_hash_map: BTreeMap>, pre_hash_results: &Vec<(u64, BTreeMap>, Vec)>, ) { - if self.use_prehash_cache { + if self.get_params().use_prehash_cache { // All results = records already cached + computed results let mut save_cache_to_hashmap: BTreeMap = Default::default(); for (size, vec_file_entry) in loaded_hash_map { - if size >= self.minimal_prehash_cache_file_size { + if size >= self.get_params().minimal_prehash_cache_file_size { for file_entry in vec_file_entry { save_cache_to_hashmap.insert(file_entry.path.to_string_lossy().to_string(), file_entry.clone()); } @@ -496,7 +539,7 @@ impl DuplicateFinder { } for (size, hash_map, _errors) in pre_hash_results { - if *size >= self.minimal_prehash_cache_file_size { + if *size >= self.get_params().minimal_prehash_cache_file_size { for vec_file_entry in hash_map.values() { for file_entry in vec_file_entry { save_cache_to_hashmap.insert(file_entry.path.to_string_lossy().to_string(), file_entry.clone()); @@ -506,10 +549,10 @@ impl DuplicateFinder { } let messages = save_cache_to_file_generalized( - &get_duplicate_cache_file(&self.hash_type, true), + &get_duplicate_cache_file(&self.get_params().hash_type, true), &save_cache_to_hashmap, self.common_data.save_also_as_json, - self.minimal_prehash_cache_file_size, + self.get_params().minimal_prehash_cache_file_size, ); self.get_text_messages_mut().extend_with_another_messages(messages); } @@ -522,9 +565,9 @@ impl DuplicateFinder { progress_sender: Option<&Sender>, pre_checked_map: &mut BTreeMap>, ) -> Option<()> { - let check_type = self.hash_type; + let check_type = self.get_params().hash_type; let (progress_thread_handle, progress_thread_run, _atomic_counter, _check_was_stopped) = - prepare_thread_handler_common(progress_sender, 1, MAX_STAGE, 0, self.check_method, self.common_data.tool_type); + prepare_thread_handler_common(progress_sender, CurrentStage::DuplicatePreHashCacheLoading, 0, self.get_test_type()); let (loaded_hash_map, records_already_cached, non_cached_files_to_check) = self.prehash_load_cache_at_start(); @@ -534,11 +577,9 @@ impl DuplicateFinder { } let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) = prepare_thread_handler_common( progress_sender, - 2, - MAX_STAGE, + CurrentStage::DuplicatePreHashing, non_cached_files_to_check.values().map(Vec::len).sum(), - self.check_method, - self.common_data.tool_type, + self.get_test_type(), ); debug!("Starting calculating prehash"); @@ -556,7 +597,7 @@ impl DuplicateFinder { return None; } for mut file_entry in vec_file_entry { - match hash_calculation(&mut buffer, &file_entry, &check_type, 0) { + match hash_calculation(&mut buffer, &file_entry, check_type, 0) { Ok(hash_string) => { file_entry.hash = hash_string.clone(); hashmap_with_hash.entry(hash_string).or_default().push(file_entry); @@ -574,7 +615,7 @@ impl DuplicateFinder { // Saving into cache let (progress_thread_handle, progress_thread_run, _atomic_counter, _check_was_stopped) = - prepare_thread_handler_common(progress_sender, 3, MAX_STAGE, 0, self.check_method, self.common_data.tool_type); + prepare_thread_handler_common(progress_sender, CurrentStage::DuplicatePreHashCacheSaving, 0, self.get_test_type()); // Add data from cache for (size, vec_file_entry) in &records_already_cached { @@ -614,8 +655,11 @@ impl DuplicateFinder { if self.common_data.use_cache { debug!("full_hashing_load_cache_at_start - using cache"); - let (messages, loaded_items) = - load_cache_from_file_generalized_by_size::(&get_duplicate_cache_file(&self.hash_type, false), self.get_delete_outdated_cache(), &pre_checked_map); + let (messages, loaded_items) = load_cache_from_file_generalized_by_size::( + &get_duplicate_cache_file(&self.get_params().hash_type, false), + self.get_delete_outdated_cache(), + &pre_checked_map, + ); self.get_text_messages_mut().extend_with_another_messages(messages); loaded_hash_map = loaded_items.unwrap_or_default(); @@ -698,10 +742,10 @@ impl DuplicateFinder { } let messages = save_cache_to_file_generalized( - &get_duplicate_cache_file(&self.hash_type, false), + &get_duplicate_cache_file(&self.get_params().hash_type, false), &all_results, self.common_data.save_also_as_json, - self.minimal_cache_file_size, + self.get_params().minimal_cache_file_size, ); self.get_text_messages_mut().extend_with_another_messages(messages); } @@ -714,7 +758,7 @@ impl DuplicateFinder { pre_checked_map: BTreeMap>, ) -> Option<()> { let (progress_thread_handle, progress_thread_run, _atomic_counter, _check_was_stopped) = - prepare_thread_handler_common(progress_sender, 4, MAX_STAGE, 0, self.check_method, self.common_data.tool_type); + prepare_thread_handler_common(progress_sender, CurrentStage::DuplicateCacheLoading, 0, self.get_test_type()); let (loaded_hash_map, records_already_cached, non_cached_files_to_check) = self.full_hashing_load_cache_at_start(pre_checked_map); @@ -725,14 +769,12 @@ impl DuplicateFinder { let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) = prepare_thread_handler_common( progress_sender, - 5, - MAX_STAGE, + CurrentStage::DuplicateFullHashing, non_cached_files_to_check.values().map(Vec::len).sum(), - self.check_method, - self.common_data.tool_type, + self.get_test_type(), ); - let check_type = self.hash_type; + let check_type = self.get_params().hash_type; debug!("Starting full hashing of {} files", non_cached_files_to_check.values().map(Vec::len).sum::()); let mut full_hash_results: Vec<(u64, BTreeMap>, Vec)> = non_cached_files_to_check .into_par_iter() @@ -748,7 +790,7 @@ impl DuplicateFinder { return None; } - match hash_calculation(&mut buffer, &file_entry, &check_type, u64::MAX) { + match hash_calculation(&mut buffer, &file_entry, check_type, u64::MAX) { Ok(hash_string) => { file_entry.hash = hash_string.clone(); hashmap_with_hash.entry(hash_string.clone()).or_default().push(file_entry); @@ -765,7 +807,7 @@ impl DuplicateFinder { // Even if clicked stop, save items to cache and show results send_info_and_wait_for_ending_all_threads(&progress_thread_run, progress_thread_handle); let (progress_thread_handle, progress_thread_run, _atomic_counter, _check_was_stopped) = - prepare_thread_handler_common(progress_sender, 6, MAX_STAGE, 0, self.check_method, self.common_data.tool_type); + prepare_thread_handler_common(progress_sender, CurrentStage::DuplicateCacheSaving, 0, self.get_test_type()); self.full_hashing_save_cache_at_exit(records_already_cached, &mut full_hash_results, loaded_hash_map); @@ -796,10 +838,12 @@ impl DuplicateFinder { .into_iter() .partition(|e| self.common_data.directories.is_in_referenced_directory(e.get_path())); - if files_from_referenced_folders.is_empty() || normal_files.is_empty() { + if normal_files.is_empty() { continue; } - all_results_with_same_size.push((files_from_referenced_folders.pop().unwrap(), normal_files)); + if let Some(file) = files_from_referenced_folders.pop() { + all_results_with_same_size.push((file, normal_files)); + } } if all_results_with_same_size.is_empty() { None @@ -834,7 +878,7 @@ impl DuplicateFinder { #[fun_time(message = "check_files_hash", level = "debug")] fn check_files_hash(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&Sender>) -> bool { - assert_eq!(self.check_method, CheckingMethod::Hash); + assert_eq!(self.get_params().check_method, CheckingMethod::Hash); let mut pre_checked_map: BTreeMap> = Default::default(); let ret = self.prehashing(stop_receiver, progress_sender, &mut pre_checked_map); @@ -861,7 +905,7 @@ impl DuplicateFinder { return; } - match self.check_method { + match self.get_params().check_method { CheckingMethod::Name => { let vec_files = self.files_with_identical_names.values().collect::>(); delete_files_custom(&vec_files, &self.common_data.delete_method, &mut self.common_data.text_messages, self.common_data.dry_run); @@ -886,30 +930,14 @@ impl DuplicateFinder { } impl DuplicateFinder { - pub fn set_case_sensitive_name_comparison(&mut self, case_sensitive_name_comparison: bool) { - self.case_sensitive_name_comparison = case_sensitive_name_comparison; - } - - pub const fn get_check_method(&self) -> &CheckingMethod { - &self.check_method - } - - pub fn set_minimal_cache_file_size(&mut self, minimal_cache_file_size: u64) { - self.minimal_cache_file_size = minimal_cache_file_size; - } - - pub fn set_minimal_prehash_cache_file_size(&mut self, minimal_prehash_cache_file_size: u64) { - self.minimal_prehash_cache_file_size = minimal_prehash_cache_file_size; + pub fn get_params(&self) -> &DuplicateFinderParameters { + &self.params } pub const fn get_files_sorted_by_names(&self) -> &BTreeMap> { &self.files_with_identical_names } - pub fn set_use_prehash_cache(&mut self, use_prehash_cache: bool) { - self.use_prehash_cache = use_prehash_cache; - } - pub const fn get_files_sorted_by_size(&self) -> &BTreeMap> { &self.files_with_identical_size } @@ -926,22 +954,10 @@ impl DuplicateFinder { &self.information } - pub fn set_hash_type(&mut self, hash_type: HashType) { - self.hash_type = hash_type; - } - - pub fn set_ignore_hard_links(&mut self, ignore_hard_links: bool) { - self.ignore_hard_links = ignore_hard_links; - } - pub fn set_dry_run(&mut self, dry_run: bool) { self.common_data.dry_run = dry_run; } - pub fn set_check_method(&mut self, check_method: CheckingMethod) { - self.check_method = check_method; - } - pub fn get_use_reference(&self) -> bool { self.common_data.use_reference_folders } @@ -963,12 +979,6 @@ impl DuplicateFinder { } } -impl Default for DuplicateFinder { - fn default() -> Self { - Self::new() - } -} - impl DebugPrint for DuplicateFinder { fn debug_print(&self) { if !cfg!(debug_assertions) { @@ -1002,7 +1012,7 @@ impl DebugPrint for DuplicateFinder { println!("Files list size - {}", self.files_with_identical_size.len()); println!("Hashed Files list size - {}", self.files_with_identical_hashes.len()); - println!("Checking Method - {:?}", self.check_method); + println!("Checking Method - {:?}", self.get_params().check_method); self.debug_print_common(); println!("-----------------------------------------"); } @@ -1018,7 +1028,7 @@ impl PrintResults for DuplicateFinder { self.common_data.excluded_items.get_excluded_items() )?; - match self.check_method { + match self.get_params().check_method { CheckingMethod::Name => { if !self.files_with_identical_names.is_empty() { writeln!( @@ -1196,7 +1206,7 @@ impl PrintResults for DuplicateFinder { // TODO - check if is possible to save also data in header about size and name in SizeName mode - https://github.com/qarmin/czkawka/issues/1137 fn save_results_to_file_as_json(&self, file_name: &str, pretty_print: bool) -> io::Result<()> { if self.get_use_reference() { - match self.check_method { + match self.get_params().check_method { CheckingMethod::Name => self.save_results_to_file_as_json_internal(file_name, &self.files_with_identical_names_referenced, pretty_print), CheckingMethod::SizeName => { self.save_results_to_file_as_json_internal(file_name, &self.files_with_identical_size_names_referenced.values().collect::>(), pretty_print) @@ -1206,7 +1216,7 @@ impl PrintResults for DuplicateFinder { _ => panic!(), } } else { - match self.check_method { + match self.get_params().check_method { CheckingMethod::Name => self.save_results_to_file_as_json_internal(file_name, &self.files_with_identical_names, pretty_print), CheckingMethod::SizeName => self.save_results_to_file_as_json_internal(file_name, &self.files_with_identical_size_names.values().collect::>(), pretty_print), CheckingMethod::Size => self.save_results_to_file_as_json_internal(file_name, &self.files_with_identical_size, pretty_print), @@ -1254,7 +1264,7 @@ pub trait MyHasher { fn finalize(&self) -> String; } -fn hash_calculation(buffer: &mut [u8], file_entry: &DuplicateEntry, hash_type: &HashType, limit: u64) -> Result { +fn hash_calculation(buffer: &mut [u8], file_entry: &DuplicateEntry, hash_type: HashType, limit: u64) -> Result { let mut file_handler = match File::open(&file_entry.path) { Ok(t) => t, Err(e) => return Err(format!("Unable to check hash of file {:?}, reason {e}", file_entry.path)), @@ -1312,6 +1322,9 @@ impl CommonData for DuplicateFinder { fn get_cd_mut(&mut self) -> &mut CommonToolData { &mut self.common_data } + fn get_check_method(&self) -> CheckingMethod { + self.get_params().check_method + } } #[cfg(test)] @@ -1351,7 +1364,7 @@ mod tests { assert_eq!(metadata.permissions(), fs::metadata(&src)?.permissions()); assert_eq!(metadata.modified()?, fs::metadata(&src)?.modified()?); - let mut actual = read_dir(&dir)?.map(|e| e.unwrap().path()).collect::>(); + let mut actual = read_dir(&dir)?.flatten().map(|e| e.path()).collect::>(); actual.sort_unstable(); assert_eq!(vec![src, dst], actual); Ok(()) @@ -1370,7 +1383,7 @@ mod tests { assert_eq!(metadata.permissions(), fs::metadata(&dst)?.permissions()); assert_eq!(metadata.modified()?, fs::metadata(&dst)?.modified()?); - assert_eq!(vec![dst], read_dir(&dir)?.map(|e| e.unwrap().path()).collect::>()); + assert_eq!(vec![dst], read_dir(&dir)?.flatten().map(|e| e.path()).collect::>()); Ok(()) } @@ -1415,7 +1428,7 @@ mod tests { let mut file = File::create(&src)?; file.write_all(b"aa")?; let e = DuplicateEntry { path: src, ..Default::default() }; - let r = hash_calculation(&mut buf, &e, &HashType::Blake3, 0).unwrap(); + let r = hash_calculation(&mut buf, &e, HashType::Blake3, 0).expect("hash_calculation failed"); assert!(!r.is_empty()); Ok(()) } @@ -1428,9 +1441,9 @@ mod tests { let mut file = File::create(&src)?; file.write_all(b"aa")?; let e = DuplicateEntry { path: src, ..Default::default() }; - let r1 = hash_calculation(&mut buf, &e, &HashType::Blake3, 1).unwrap(); - let r2 = hash_calculation(&mut buf, &e, &HashType::Blake3, 2).unwrap(); - let r3 = hash_calculation(&mut buf, &e, &HashType::Blake3, u64::MAX).unwrap(); + let r1 = hash_calculation(&mut buf, &e, HashType::Blake3, 1).expect("hash_calculation failed"); + let r2 = hash_calculation(&mut buf, &e, HashType::Blake3, 2).expect("hash_calculation failed"); + let r3 = hash_calculation(&mut buf, &e, HashType::Blake3, u64::MAX).expect("hash_calculation failed"); assert_ne!(r1, r2); assert_eq!(r2, r3); Ok(()) @@ -1442,7 +1455,7 @@ mod tests { let mut buf = [0u8; 1 << 10]; let src = dir.path().join("a"); let e = DuplicateEntry { path: src, ..Default::default() }; - let r = hash_calculation(&mut buf, &e, &HashType::Blake3, 0).unwrap_err(); + let r = hash_calculation(&mut buf, &e, HashType::Blake3, 0).expect_err("hash_calculation succeeded"); assert!(!r.is_empty()); Ok(()) } diff --git a/czkawka_core/src/empty_files.rs b/czkawka_core/src/empty_files.rs index b64d2b3d6..d43a03987 100644 --- a/czkawka_core/src/empty_files.rs +++ b/czkawka_core/src/empty_files.rs @@ -5,9 +5,10 @@ use crossbeam_channel::{Receiver, Sender}; use fun_time::fun_time; use log::debug; -use crate::common_dir_traversal::{DirTraversalBuilder, DirTraversalResult, FileEntry, ProgressData, ToolType}; +use crate::common_dir_traversal::{DirTraversalBuilder, DirTraversalResult, FileEntry, ToolType}; use crate::common_tool::{CommonData, CommonToolData, DeleteMethod}; use crate::common_traits::*; +use crate::progress_data::ProgressData; #[derive(Default)] pub struct Info { diff --git a/czkawka_core/src/empty_folder.rs b/czkawka_core/src/empty_folder.rs index bb13f88db..3001f8350 100644 --- a/czkawka_core/src/empty_folder.rs +++ b/czkawka_core/src/empty_folder.rs @@ -11,11 +11,12 @@ use log::debug; use rayon::prelude::*; use crate::common::{check_if_stop_received, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads}; -use crate::common_dir_traversal::{common_get_entry_data, common_get_metadata_dir, common_read_dir, get_modified_time, CheckingMethod, ProgressData, ToolType}; +use crate::common_dir_traversal::{common_get_entry_data, common_get_metadata_dir, common_read_dir, get_modified_time, ToolType}; use crate::common_directory::Directories; use crate::common_items::ExcludedItems; use crate::common_tool::{CommonData, CommonToolData, DeleteMethod}; use crate::common_traits::{DebugPrint, PrintResults}; +use crate::progress_data::{CurrentStage, ProgressData}; #[derive(Clone, Debug)] pub struct FolderEntry { @@ -105,7 +106,7 @@ impl EmptyFolder { let mut folders_to_check: Vec = self.common_data.directories.included_directories.clone(); let (progress_thread_handle, progress_thread_run, atomic_counter, _check_was_stopped) = - prepare_thread_handler_common(progress_sender, 0, 0, 0, CheckingMethod::None, self.common_data.tool_type); + prepare_thread_handler_common(progress_sender, CurrentStage::CollectingFiles, 0, self.get_test_type()); let excluded_items = self.common_data.excluded_items.clone(); let directories = self.common_data.directories.clone(); @@ -222,7 +223,9 @@ impl EmptyFolder { } pub(crate) fn set_as_not_empty_folder(folder_entries: &mut HashMap, current_folder: &str) { - let mut d = folder_entries.get_mut(current_folder).unwrap(); + let mut d = folder_entries + .get_mut(current_folder) + .unwrap_or_else(|| panic!("Folder {current_folder} not found in folder_entries")); if d.is_empty == FolderEmptiness::No { return; // Already set as non empty by one of his child } @@ -230,9 +233,10 @@ impl EmptyFolder { // Loop to recursively set as non empty this and all his parent folders loop { d.is_empty = FolderEmptiness::No; - if d.parent_path.is_some() { - let cf = d.parent_path.clone().unwrap(); - d = folder_entries.get_mut(&cf).unwrap(); + + if let Some(parent_path) = &d.parent_path { + let cf = parent_path.clone(); + d = folder_entries.get_mut(&cf).unwrap_or_else(|| panic!("Folder {cf} not found in folder_entries")); if d.is_empty == FolderEmptiness::No { break; // Already set as non empty, so one of child already set it to non empty } diff --git a/czkawka_core/src/invalid_symlinks.rs b/czkawka_core/src/invalid_symlinks.rs index a10c17516..02fae285e 100644 --- a/czkawka_core/src/invalid_symlinks.rs +++ b/czkawka_core/src/invalid_symlinks.rs @@ -7,9 +7,10 @@ use fun_time::fun_time; use log::debug; use serde::{Deserialize, Serialize}; -use crate::common_dir_traversal::{Collect, DirTraversalBuilder, DirTraversalResult, ErrorType, FileEntry, ProgressData, ToolType}; +use crate::common_dir_traversal::{Collect, DirTraversalBuilder, DirTraversalResult, ErrorType, FileEntry, ToolType}; use crate::common_tool::{CommonData, CommonToolData, DeleteMethod}; use crate::common_traits::*; +use crate::progress_data::ProgressData; #[derive(Default)] pub struct Info { @@ -98,9 +99,7 @@ impl InvalidSymlinks { .into_values() .flatten() .filter_map(|e| { - let Some((destination_path, type_of_error)) = Self::check_invalid_symlinks(&e.path) else { - return None; - }; + let (destination_path, type_of_error) = Self::check_invalid_symlinks(&e.path)?; Some(e.into_symlinks_entry(SymlinkInfo { destination_path, type_of_error })) }) .collect(); diff --git a/czkawka_core/src/lib.rs b/czkawka_core/src/lib.rs index 947b785b8..5d4479ade 100644 --- a/czkawka_core/src/lib.rs +++ b/czkawka_core/src/lib.rs @@ -2,6 +2,7 @@ #![allow(clippy::type_complexity)] #![allow(clippy::needless_late_init)] #![allow(clippy::too_many_arguments)] +#![warn(clippy::unwrap_used)] #[macro_use] extern crate bitflags; @@ -28,5 +29,6 @@ pub mod common_messages; pub mod common_tool; pub mod common_traits; pub mod localizer_core; +pub mod progress_data; pub const CZKAWKA_VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/czkawka_core/src/progress_data.rs b/czkawka_core/src/progress_data.rs new file mode 100644 index 000000000..e363f59d0 --- /dev/null +++ b/czkawka_core/src/progress_data.rs @@ -0,0 +1,232 @@ +use crate::common_dir_traversal::{CheckingMethod, ToolType}; +// Empty files +// 0 - Collecting files + +// Empty folders +// 0 - Collecting folders + +// Big files +// 0 - Collecting files + +// Same music +// 0 - Collecting files +// 1 - Loading cache +// 2 - Checking tags +// 3 - Saving cache +// 4 - TAGS - Comparing tags +// 4 - CONTENT - Loading cache +// 5 - CONTENT - Calculating fingerprints +// 6 - CONTENT - Saving cache +// 7 - CONTENT - Comparing fingerprints + +// Similar images +// 0 - Collecting files +// 1 - Scanning images +// 2 - Comparing hashes + +// Similar videos +// 0 - Collecting files +// 1 - Scanning videos + +// Temporary files +// 0 - Collecting files + +// Invalid symlinks +// 0 - Collecting files + +// Broken files +// 0 - Collecting files +// 1 - Scanning files + +// Bad extensions +// 0 - Collecting files +// 1 - Scanning files + +// Duplicates - Hash +// 0 - Collecting files +// 1 - Loading cache +// 2 - Hash - first 1KB file +// 3 - Saving cache +// 4 - Loading cache +// 5 - Hash - normal hash +// 6 - Saving cache + +// Duplicates - Name or SizeName or Size +// 0 - Collecting files + +#[derive(Debug)] +pub struct ProgressData { + pub sstage: CurrentStage, + pub checking_method: CheckingMethod, + pub current_stage_idx: u8, + pub max_stage_idx: u8, + pub entries_checked: usize, + pub entries_to_check: usize, + pub tool_type: ToolType, +} + +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub enum CurrentStage { + CollectingFiles, + DuplicateCacheSaving, + DuplicateCacheLoading, + DuplicatePreHashCacheSaving, + DuplicatePreHashCacheLoading, + DuplicateScanningName, + DuplicateScanningSizeName, + DuplicateScanningSize, + DuplicatePreHashing, + DuplicateFullHashing, + + SameMusicCacheSavingTags, + SameMusicCacheLoadingTags, + SameMusicCacheSavingFingerprints, + SameMusicCacheLoadingFingerprints, + SameMusicReadingTags, + SameMusicCalculatingFingerprints, + SameMusicComparingTags, + SameMusicComparingFingerprints, + + SimilarImagesCalculatingHashes, + SimilarImagesComparingHashes, + SimilarVideosCalculatingHashes, + BrokenFilesChecking, + BadExtensionsChecking, +} + +impl ProgressData { + // TODO change validations to debug_asserts + // Currently are too flaky to run asserts in normal builds + pub fn validate(&self) { + assert!( + self.current_stage_idx <= self.max_stage_idx, + "Current stage index: {}, max stage index: {}, stage {:?}", + self.current_stage_idx, + self.max_stage_idx, + self.sstage + ); + assert_eq!( + self.max_stage_idx, + self.tool_type.get_max_stage(self.checking_method), + "Max stage index: {}, tool type: {:?}, checking method: {:?}", + self.max_stage_idx, + self.tool_type, + self.checking_method + ); + + // TODO not sure about other types + // may need to be changed + if self.sstage != CurrentStage::CollectingFiles { + assert!( + self.entries_checked <= self.entries_to_check, + "Entries checked: {}, entries to check: {}, stage {:?}", + self.entries_checked, + self.entries_to_check, + self.sstage + ); + } + let tool_type_checking_method: Option = match self.checking_method { + CheckingMethod::AudioTags | CheckingMethod::AudioContent => Some(ToolType::SameMusic), + CheckingMethod::Name | CheckingMethod::SizeName | CheckingMethod::Size | CheckingMethod::Hash => Some(ToolType::Duplicate), + CheckingMethod::None => None, + }; + if let Some(tool_type) = tool_type_checking_method { + assert_eq!(self.tool_type, tool_type, "Tool type: {:?}, checking method: {:?}", self.tool_type, self.checking_method); + } + let tool_type_current_stage: Option = match self.sstage { + CurrentStage::CollectingFiles => None, + CurrentStage::DuplicateCacheSaving | CurrentStage::DuplicateCacheLoading | CurrentStage::DuplicatePreHashCacheSaving | CurrentStage::DuplicatePreHashCacheLoading => { + Some(ToolType::Duplicate) + } + CurrentStage::DuplicateScanningName + | CurrentStage::DuplicateScanningSizeName + | CurrentStage::DuplicateScanningSize + | CurrentStage::DuplicatePreHashing + | CurrentStage::DuplicateFullHashing => Some(ToolType::Duplicate), + CurrentStage::SameMusicCacheLoadingTags + | CurrentStage::SameMusicCacheSavingTags + | CurrentStage::SameMusicCacheLoadingFingerprints + | CurrentStage::SameMusicCacheSavingFingerprints + | CurrentStage::SameMusicComparingTags + | CurrentStage::SameMusicReadingTags + | CurrentStage::SameMusicComparingFingerprints + | CurrentStage::SameMusicCalculatingFingerprints => Some(ToolType::SameMusic), + CurrentStage::SimilarImagesCalculatingHashes | CurrentStage::SimilarImagesComparingHashes => Some(ToolType::SimilarImages), + CurrentStage::SimilarVideosCalculatingHashes => Some(ToolType::SimilarVideos), + CurrentStage::BrokenFilesChecking => Some(ToolType::BrokenFiles), + CurrentStage::BadExtensionsChecking => Some(ToolType::BadExtensions), + }; + if let Some(tool_type) = tool_type_current_stage { + assert_eq!(self.tool_type, tool_type, "Tool type: {:?}, stage {:?}", self.tool_type, self.sstage); + } + } +} + +impl ToolType { + pub fn get_max_stage(&self, checking_method: CheckingMethod) -> u8 { + match *self { + ToolType::Duplicate => 6, + ToolType::EmptyFolders | ToolType::EmptyFiles | ToolType::InvalidSymlinks | ToolType::BigFile | ToolType::TemporaryFiles => 0, + ToolType::BrokenFiles | ToolType::BadExtensions | ToolType::SimilarVideos => 1, + ToolType::SimilarImages => 2, + ToolType::None => unreachable!("ToolType::None is not allowed"), + ToolType::SameMusic => match checking_method { + CheckingMethod::AudioTags => 4, + CheckingMethod::AudioContent => 7, + _ => unreachable!("CheckingMethod {checking_method:?} in same music mode is not allowed"), + }, + } + } +} + +impl CurrentStage { + pub fn get_current_stage(&self) -> u8 { + #[allow(clippy::match_same_arms)] // Now it is easier to read + match self { + CurrentStage::CollectingFiles => 0, + CurrentStage::DuplicateScanningName => 0, + CurrentStage::DuplicateScanningSizeName => 0, + CurrentStage::DuplicateScanningSize => 0, + CurrentStage::DuplicatePreHashCacheLoading => 1, + CurrentStage::DuplicatePreHashing => 2, + CurrentStage::DuplicatePreHashCacheSaving => 3, + CurrentStage::DuplicateCacheLoading => 4, + CurrentStage::DuplicateFullHashing => 5, + CurrentStage::DuplicateCacheSaving => 6, + CurrentStage::SimilarImagesCalculatingHashes => 1, + CurrentStage::SimilarImagesComparingHashes => 2, + CurrentStage::SimilarVideosCalculatingHashes => 1, + CurrentStage::BrokenFilesChecking => 1, + CurrentStage::BadExtensionsChecking => 1, + CurrentStage::SameMusicCacheLoadingTags => 1, + CurrentStage::SameMusicReadingTags => 2, + CurrentStage::SameMusicCacheSavingTags => 3, + CurrentStage::SameMusicComparingTags => 4, + CurrentStage::SameMusicCacheLoadingFingerprints => 4, + CurrentStage::SameMusicCalculatingFingerprints => 5, + CurrentStage::SameMusicCacheSavingFingerprints => 6, + CurrentStage::SameMusicComparingFingerprints => 7, + } + } + pub fn check_if_loading_saving_cache(&self) -> bool { + self.check_if_saving_cache() || self.check_if_loading_cache() + } + pub fn check_if_loading_cache(&self) -> bool { + matches!( + self, + CurrentStage::SameMusicCacheLoadingFingerprints + | CurrentStage::SameMusicCacheLoadingTags + | CurrentStage::DuplicateCacheLoading + | CurrentStage::DuplicatePreHashCacheLoading + ) + } + pub fn check_if_saving_cache(&self) -> bool { + matches!( + self, + CurrentStage::SameMusicCacheSavingFingerprints + | CurrentStage::SameMusicCacheSavingTags + | CurrentStage::DuplicateCacheSaving + | CurrentStage::DuplicatePreHashCacheSaving + ) + } +} diff --git a/czkawka_core/src/same_music.rs b/czkawka_core/src/same_music.rs index b97215a00..d109938fc 100644 --- a/czkawka_core/src/same_music.rs +++ b/czkawka_core/src/same_music.rs @@ -1,4 +1,3 @@ -use std::cmp::max; use std::collections::{BTreeMap, HashSet}; use std::fs::File; use std::io::prelude::*; @@ -11,7 +10,9 @@ use anyhow::Context; use crossbeam_channel::{Receiver, Sender}; use fun_time::fun_time; use humansize::{format_size, BINARY}; -use lofty::{read_from, AudioFile, ItemKey, TaggedFileExt}; +use lofty::file::{AudioFile, TaggedFileExt}; +use lofty::prelude::*; +use lofty::read_from; use log::debug; use rayon::prelude::*; use rusty_chromaprint::{match_fingerprints, Configuration, Fingerprinter}; @@ -28,9 +29,10 @@ use crate::common::{ AUDIO_FILES_EXTENSIONS, }; use crate::common_cache::{get_similar_music_cache_file, load_cache_from_file_generalized_by_path, save_cache_to_file_generalized}; -use crate::common_dir_traversal::{CheckingMethod, DirTraversalBuilder, DirTraversalResult, FileEntry, ProgressData, ToolType}; +use crate::common_dir_traversal::{CheckingMethod, DirTraversalBuilder, DirTraversalResult, FileEntry, ToolType}; use crate::common_tool::{CommonData, CommonToolData, DeleteMethod}; use crate::common_traits::*; +use crate::progress_data::{CurrentStage, ProgressData}; bitflags! { #[derive(PartialEq, Copy, Clone, Debug)] @@ -62,9 +64,6 @@ pub struct MusicEntry { pub bitrate: u32, } -const MAX_STAGE_TAGS: u8 = 4; -const MAX_STAGE_CONTENT: u8 = 5; - impl ResultEntry for MusicEntry { fn get_path(&self) -> &Path { &self.path @@ -95,12 +94,48 @@ impl FileEntry { } } +struct GroupedFilesToCheck { + pub base_files: Vec, + pub files_to_compare: Vec, +} + #[derive(Default)] pub struct Info { pub number_of_duplicates: usize, pub number_of_groups: u64, } +pub struct SameMusicParameters { + pub music_similarity: MusicSimilarity, + pub approximate_comparison: bool, + pub check_type: CheckingMethod, + pub minimum_segment_duration: f32, + pub maximum_difference: f64, + pub compare_fingerprints_only_with_similar_titles: bool, +} + +impl SameMusicParameters { + pub fn new( + music_similarity: MusicSimilarity, + approximate_comparison: bool, + check_type: CheckingMethod, + minimum_segment_duration: f32, + maximum_difference: f64, + compare_fingerprints_only_with_similar_titles: bool, + ) -> Self { + assert!(!music_similarity.is_empty()); + assert!([CheckingMethod::AudioTags, CheckingMethod::AudioContent].contains(&check_type)); + Self { + music_similarity, + approximate_comparison, + check_type, + minimum_segment_duration, + maximum_difference, + compare_fingerprints_only_with_similar_titles, + } + } +} + pub struct SameMusic { common_data: CommonToolData, information: Info, @@ -108,29 +143,21 @@ pub struct SameMusic { music_entries: Vec, duplicated_music_entries: Vec>, duplicated_music_entries_referenced: Vec<(MusicEntry, Vec)>, - music_similarity: MusicSimilarity, - approximate_comparison: bool, - check_type: CheckingMethod, hash_preset_config: Configuration, - minimum_segment_duration: f32, - maximum_difference: f64, + params: SameMusicParameters, } impl SameMusic { - pub fn new() -> Self { + pub fn new(params: SameMusicParameters) -> Self { Self { common_data: CommonToolData::new(ToolType::SameMusic), information: Info::default(), music_entries: Vec::with_capacity(2048), - music_similarity: MusicSimilarity::NONE, duplicated_music_entries: vec![], music_to_check: Default::default(), - approximate_comparison: true, duplicated_music_entries_referenced: vec![], - check_type: CheckingMethod::AudioTags, - hash_preset_config: Configuration::preset_test1(), // TODO allow to change this - minimum_segment_duration: 10.0, - maximum_difference: 2.0, + hash_preset_config: Configuration::preset_test1(), // TODO allow to change this and move to parameters + params, } } @@ -142,7 +169,7 @@ impl SameMusic { self.common_data.stopped_search = true; return; } - match self.check_type { + match self.params.check_type { CheckingMethod::AudioTags => { if !self.read_tags(stop_receiver, progress_sender) { self.common_data.stopped_search = true; @@ -154,15 +181,15 @@ impl SameMusic { } } CheckingMethod::AudioContent => { - if !self.calculate_fingerprint(stop_receiver, progress_sender) { + if !self.read_tags(stop_receiver, progress_sender) { self.common_data.stopped_search = true; return; } - if !self.check_for_duplicate_fingerprints(stop_receiver, progress_sender) { + if !self.calculate_fingerprint(stop_receiver, progress_sender) { self.common_data.stopped_search = true; return; } - if !self.read_tags_to_files_similar_by_content(stop_receiver, progress_sender) { + if !self.check_for_duplicate_fingerprints(stop_receiver, progress_sender) { self.common_data.stopped_search = true; return; } @@ -180,19 +207,12 @@ impl SameMusic { return true; } - let max_stage = match self.check_type { - CheckingMethod::AudioTags => MAX_STAGE_TAGS, - CheckingMethod::AudioContent => MAX_STAGE_CONTENT, - _ => panic!(), - }; - let result = DirTraversalBuilder::new() .group_by(|_fe| ()) .stop_receiver(stop_receiver) .progress_sender(progress_sender) .common_data(&self.common_data) - .checking_method(self.check_type) - .max_stage(max_stage) + .checking_method(self.params.check_type) .build() .run(); @@ -265,8 +285,23 @@ impl SameMusic { #[fun_time(message = "calculate_fingerprint", level = "debug")] fn calculate_fingerprint(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&Sender>) -> bool { + // We only calculate fingerprints, for files with similar titles + // This saves a lot of time, because we don't need to calculate and later compare fingerprints for files with different titles + + if self.params.compare_fingerprints_only_with_similar_titles { + let grouped_by_title: BTreeMap> = Self::get_entries_grouped_by_title(mem::take(&mut self.music_entries)); + self.music_to_check = grouped_by_title + .into_iter() + .filter_map(|(_title, entries)| if entries.len() >= 2 { Some(entries) } else { None }) + .flatten() + .map(|e| (e.path.to_string_lossy().to_string(), e)) + .collect(); + } else { + self.music_to_check = mem::take(&mut self.music_entries).into_iter().map(|e| (e.path.to_string_lossy().to_string(), e)).collect(); + } + let (progress_thread_handle, progress_thread_run, _atomic_counter, _check_was_stopped) = - prepare_thread_handler_common(progress_sender, 1, MAX_STAGE_CONTENT, 0, self.check_type, self.common_data.tool_type); + prepare_thread_handler_common(progress_sender, CurrentStage::SameMusicCacheLoadingFingerprints, 0, self.get_test_type()); let (loaded_hash_map, records_already_cached, non_cached_files_to_check) = self.load_cache(false); @@ -277,11 +312,9 @@ impl SameMusic { let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) = prepare_thread_handler_common( progress_sender, - 2, - MAX_STAGE_CONTENT, + CurrentStage::SameMusicCalculatingFingerprints, non_cached_files_to_check.len(), - self.check_type, - self.common_data.tool_type, + self.get_test_type(), ); let configuration = &self.hash_preset_config; @@ -303,14 +336,13 @@ impl SameMusic { Some(Some(music_entry)) }) .while_some() - .filter(Option::is_some) - .map(Option::unwrap) + .flatten() .collect::>(); debug!("calculate_fingerprint - ended fingerprinting"); send_info_and_wait_for_ending_all_threads(&progress_thread_run, progress_thread_handle); let (progress_thread_handle, progress_thread_run, _atomic_counter, _check_was_stopped) = - prepare_thread_handler_common(progress_sender, 3, MAX_STAGE_CONTENT, 0, self.check_type, self.common_data.tool_type); + prepare_thread_handler_common(progress_sender, CurrentStage::SameMusicCacheSavingFingerprints, 0, self.get_test_type()); // Just connect loaded results with already calculated vec_file_entry.extend(records_already_cached.into_values()); @@ -330,7 +362,7 @@ impl SameMusic { #[fun_time(message = "read_tags", level = "debug")] fn read_tags(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&Sender>) -> bool { let (progress_thread_handle, progress_thread_run, _atomic_counter, _check_was_stopped) = - prepare_thread_handler_common(progress_sender, 1, MAX_STAGE_TAGS, 0, self.check_type, self.common_data.tool_type); + prepare_thread_handler_common(progress_sender, CurrentStage::SameMusicCacheLoadingTags, 0, self.get_test_type()); let (loaded_hash_map, records_already_cached, non_cached_files_to_check) = self.load_cache(true); @@ -339,14 +371,8 @@ impl SameMusic { return false; } - let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) = prepare_thread_handler_common( - progress_sender, - 2, - MAX_STAGE_TAGS, - non_cached_files_to_check.len(), - self.check_type, - self.common_data.tool_type, - ); + let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) = + prepare_thread_handler_common(progress_sender, CurrentStage::SameMusicReadingTags, non_cached_files_to_check.len(), self.get_test_type()); debug!("read_tags - starting reading tags"); // Clean for duplicate files @@ -365,14 +391,13 @@ impl SameMusic { } }) .while_some() - .filter(Option::is_some) - .map(Option::unwrap) + .filter_map(|e| e) .collect::>(); debug!("read_tags - ended reading tags"); send_info_and_wait_for_ending_all_threads(&progress_thread_run, progress_thread_handle); let (progress_thread_handle, progress_thread_run, _atomic_counter, _check_was_stopped) = - prepare_thread_handler_common(progress_sender, 3, MAX_STAGE_TAGS, 0, self.check_type, self.common_data.tool_type); + prepare_thread_handler_common(progress_sender, CurrentStage::SameMusicCacheSavingTags, 0, self.get_test_type()); // Just connect loaded results with already calculated vec_file_entry.extend(records_already_cached.into_values()); @@ -392,29 +417,32 @@ impl SameMusic { #[fun_time(message = "check_for_duplicate_tags", level = "debug")] fn check_for_duplicate_tags(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&Sender>) -> bool { + if self.music_entries.is_empty() { + return true; + } let (progress_thread_handle, progress_thread_run, atomic_counter, _check_was_stopped) = - prepare_thread_handler_common(progress_sender, 4, MAX_STAGE_TAGS, self.music_to_check.len(), self.check_type, self.common_data.tool_type); + prepare_thread_handler_common(progress_sender, CurrentStage::SameMusicComparingTags, self.music_entries.len(), self.get_test_type()); let mut old_duplicates: Vec> = vec![self.music_entries.clone()]; let mut new_duplicates: Vec> = Vec::new(); - if (self.music_similarity & MusicSimilarity::TRACK_TITLE) == MusicSimilarity::TRACK_TITLE { + if (self.params.music_similarity & MusicSimilarity::TRACK_TITLE) == MusicSimilarity::TRACK_TITLE { if check_if_stop_received(stop_receiver) { send_info_and_wait_for_ending_all_threads(&progress_thread_run, progress_thread_handle); return false; } - old_duplicates = self.check_music_item(old_duplicates, &atomic_counter, |fe| &fe.track_title, self.approximate_comparison); + old_duplicates = self.check_music_item(old_duplicates, &atomic_counter, |fe| &fe.track_title, self.params.approximate_comparison); } - if (self.music_similarity & MusicSimilarity::TRACK_ARTIST) == MusicSimilarity::TRACK_ARTIST { + if (self.params.music_similarity & MusicSimilarity::TRACK_ARTIST) == MusicSimilarity::TRACK_ARTIST { if check_if_stop_received(stop_receiver) { send_info_and_wait_for_ending_all_threads(&progress_thread_run, progress_thread_handle); return false; } - old_duplicates = self.check_music_item(old_duplicates, &atomic_counter, |fe| &fe.track_artist, self.approximate_comparison); + old_duplicates = self.check_music_item(old_duplicates, &atomic_counter, |fe| &fe.track_artist, self.params.approximate_comparison); } - if (self.music_similarity & MusicSimilarity::YEAR) == MusicSimilarity::YEAR { + if (self.params.music_similarity & MusicSimilarity::YEAR) == MusicSimilarity::YEAR { if check_if_stop_received(stop_receiver) { send_info_and_wait_for_ending_all_threads(&progress_thread_run, progress_thread_handle); return false; @@ -422,7 +450,7 @@ impl SameMusic { old_duplicates = self.check_music_item(old_duplicates, &atomic_counter, |fe| &fe.year, false); } - if (self.music_similarity & MusicSimilarity::LENGTH) == MusicSimilarity::LENGTH { + if (self.params.music_similarity & MusicSimilarity::LENGTH) == MusicSimilarity::LENGTH { if check_if_stop_received(stop_receiver) { send_info_and_wait_for_ending_all_threads(&progress_thread_run, progress_thread_handle); return false; @@ -430,7 +458,7 @@ impl SameMusic { old_duplicates = self.check_music_item(old_duplicates, &atomic_counter, |fe| &fe.length, false); } - if (self.music_similarity & MusicSimilarity::GENRE) == MusicSimilarity::GENRE { + if (self.params.music_similarity & MusicSimilarity::GENRE) == MusicSimilarity::GENRE { if check_if_stop_received(stop_receiver) { send_info_and_wait_for_ending_all_threads(&progress_thread_run, progress_thread_handle); return false; @@ -438,7 +466,7 @@ impl SameMusic { old_duplicates = self.check_music_item(old_duplicates, &atomic_counter, |fe| &fe.genre, false); } - if (self.music_similarity & MusicSimilarity::BITRATE) == MusicSimilarity::BITRATE { + if (self.params.music_similarity & MusicSimilarity::BITRATE) == MusicSimilarity::BITRATE { if check_if_stop_received(stop_receiver) { send_info_and_wait_for_ending_all_threads(&progress_thread_run, progress_thread_handle); return false; @@ -489,71 +517,46 @@ impl SameMusic { true } - #[fun_time(message = "read_tags_to_files_similar_by_content", level = "debug")] - fn read_tags_to_files_similar_by_content(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&Sender>) -> bool { - let groups_to_check = max(self.duplicated_music_entries.len(), self.duplicated_music_entries_referenced.len()); - let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) = - prepare_thread_handler_common(progress_sender, 5, MAX_STAGE_CONTENT, groups_to_check, self.check_type, self.common_data.tool_type); - if !self.duplicated_music_entries.is_empty() { - let _: Vec<_> = self - .duplicated_music_entries - .par_iter_mut() - .map(|vec_me| { - atomic_counter.fetch_add(1, Ordering::Relaxed); - if check_if_stop_received(stop_receiver) { - check_was_stopped.store(true, Ordering::Relaxed); - return None; - } - for me in vec_me { - let me_path = me.path.to_string_lossy().to_string(); - read_single_file_tag(&me_path, me); - } - Some(()) - }) - .while_some() - .collect(); + fn split_fingerprints_to_base_and_files_to_compare(&self, music_data: Vec) -> (Vec, Vec) { + if self.common_data.use_reference_folders { + music_data.into_iter().partition(|f| self.common_data.directories.is_in_referenced_directory(f.get_path())) } else { - let _: Vec<_> = self - .duplicated_music_entries_referenced - .par_iter_mut() - .map(|(me_o, vec_me)| { - atomic_counter.fetch_add(1, Ordering::Relaxed); - if check_if_stop_received(stop_receiver) { - check_was_stopped.store(true, Ordering::Relaxed); - return None; - } - let me_o_path = me_o.path.to_string_lossy().to_string(); - read_single_file_tag(&me_o_path, me_o); - for me in vec_me { - let me_path = me.path.to_string_lossy().to_string(); - read_single_file_tag(&me_path, me); - } - Some(()) - }) - .while_some() - .collect(); + (music_data.clone(), music_data) } + } - send_info_and_wait_for_ending_all_threads(&progress_thread_run, progress_thread_handle); - - !check_was_stopped.load(Ordering::Relaxed) + fn get_entries_grouped_by_title(music_data: Vec) -> BTreeMap> { + let mut entries_grouped_by_title: BTreeMap> = BTreeMap::new(); + for entry in music_data { + let simplified_track_title = get_simplified_name(&entry.track_title); + entries_grouped_by_title.entry(simplified_track_title).or_default().push(entry); + } + entries_grouped_by_title } - fn split_fingerprints_to_check(&mut self) -> (Vec, Vec) { - let base_files: Vec; - let files_to_compare: Vec; + fn split_fingerprints_to_check(&mut self) -> Vec { + if self.params.compare_fingerprints_only_with_similar_titles { + let entries_grouped_by_title: BTreeMap> = Self::get_entries_grouped_by_title(mem::take(&mut self.music_entries)); - if self.common_data.use_reference_folders { - (base_files, files_to_compare) = mem::take(&mut self.music_entries) + entries_grouped_by_title .into_iter() - .partition(|f| self.common_data.directories.is_in_referenced_directory(f.get_path())); + .filter_map(|(_title, entries)| { + let (base_files, files_to_compare) = self.split_fingerprints_to_base_and_files_to_compare(entries); + + if base_files.is_empty() || files_to_compare.is_empty() { + return None; + } + + Some(GroupedFilesToCheck { base_files, files_to_compare }) + }) + .collect() } else { - base_files = self.music_entries.clone(); - files_to_compare = mem::take(&mut self.music_entries); - } + let entries = mem::take(&mut self.music_entries); + let (base_files, files_to_compare) = self.split_fingerprints_to_base_and_files_to_compare(entries); - (base_files, files_to_compare) + vec![GroupedFilesToCheck { base_files, files_to_compare }] + } } #[fun_time(message = "compare_fingerprints", level = "debug")] @@ -567,8 +570,8 @@ impl SameMusic { let mut used_paths: HashSet = Default::default(); let configuration = &self.hash_preset_config; - let minimum_segment_duration = self.minimum_segment_duration; - let maximum_difference = self.maximum_difference; + let minimum_segment_duration = self.params.minimum_segment_duration; + let maximum_difference = self.params.maximum_difference; let mut duplicated_music_entries = Vec::new(); @@ -583,23 +586,39 @@ impl SameMusic { continue; } - let mut collected_similar_items = files_to_compare + let temp_collected_similar_items = files_to_compare .par_iter() - .filter_map(|e_entry| { + .map(|e_entry| { let e_string = e_entry.path.to_string_lossy().to_string(); if used_paths.contains(&e_string) || e_string == f_string { - return None; + return Ok(None); } - let mut segments = match_fingerprints(&f_entry.fingerprint, &e_entry.fingerprint, configuration).unwrap(); + let mut segments = match match_fingerprints(&f_entry.fingerprint, &e_entry.fingerprint, configuration) { + Ok(segments) => segments, + Err(e) => return Err(format!("Error while comparing fingerprints: {e}")), + }; segments.retain(|s| s.duration(configuration) > minimum_segment_duration && s.score < maximum_difference); if segments.is_empty() { - None + Ok(None) } else { - Some((e_string, e_entry)) + Ok(Some((e_string, e_entry))) } }) .collect::>(); + let mut collected_similar_items = Vec::with_capacity(temp_collected_similar_items.len()); + for result in temp_collected_similar_items { + match result { + Ok(Some(data)) => { + collected_similar_items.push(data); + } + Ok(None) => (), + Err(e) => { + self.common_data.text_messages.errors.push(e); + } + } + } + collected_similar_items.retain(|(path, _entry)| !used_paths.contains(path)); if !collected_similar_items.is_empty() { let mut music_entries = Vec::new(); @@ -617,14 +636,21 @@ impl SameMusic { #[fun_time(message = "check_for_duplicate_fingerprints", level = "debug")] fn check_for_duplicate_fingerprints(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&Sender>) -> bool { - let (base_files, files_to_compare) = self.split_fingerprints_to_check(); + let grouped_files_to_check = self.split_fingerprints_to_check(); + let base_files_number = grouped_files_to_check.iter().map(|g| g.base_files.len()).sum::(); + let (progress_thread_handle, progress_thread_run, atomic_counter, _check_was_stopped) = - prepare_thread_handler_common(progress_sender, 2, 3, base_files.len(), self.check_type, self.common_data.tool_type); + prepare_thread_handler_common(progress_sender, CurrentStage::SameMusicComparingFingerprints, base_files_number, self.get_test_type()); - let Some(duplicated_music_entries) = self.compare_fingerprints(stop_receiver, &atomic_counter, base_files, &files_to_compare) else { - send_info_and_wait_for_ending_all_threads(&progress_thread_run, progress_thread_handle); - return false; - }; + let mut duplicated_music_entries = Vec::new(); + for group in grouped_files_to_check { + let GroupedFilesToCheck { base_files, files_to_compare } = group; + let Some(temp_music_entries) = self.compare_fingerprints(stop_receiver, &atomic_counter, base_files, &files_to_compare) else { + send_info_and_wait_for_ending_all_threads(&progress_thread_run, progress_thread_handle); + return false; + }; + duplicated_music_entries.extend(temp_music_entries); + } send_info_and_wait_for_ending_all_threads(&progress_thread_run, progress_thread_handle); @@ -667,7 +693,7 @@ impl SameMusic { for file_entry in vec_file_entry { let mut thing = get_item(&file_entry).trim().to_lowercase(); if approximate_comparison { - get_approximate_conversion(&mut thing); + thing = get_simplified_name(&thing); } if !thing.is_empty() { hash_map.entry(thing).or_default().push(file_entry); @@ -700,38 +726,14 @@ impl SameMusic { &self.duplicated_music_entries } - pub const fn get_music_similarity(&self) -> &MusicSimilarity { - &self.music_similarity + pub fn get_params(&self) -> &SameMusicParameters { + &self.params } pub const fn get_information(&self) -> &Info { &self.information } - pub fn set_approximate_comparison(&mut self, approximate_comparison: bool) { - self.approximate_comparison = approximate_comparison; - } - - pub fn set_maximum_difference(&mut self, maximum_difference: f64) { - self.maximum_difference = maximum_difference; - } - pub fn set_minimum_segment_duration(&mut self, minimum_segment_duration: f32) { - self.minimum_segment_duration = minimum_segment_duration; - } - - pub fn set_check_type(&mut self, check_type: CheckingMethod) { - assert!([CheckingMethod::AudioTags, CheckingMethod::AudioContent].contains(&check_type)); - self.check_type = check_type; - } - - pub fn get_check_type(&self) -> CheckingMethod { - self.check_type - } - - pub fn set_music_similarity(&mut self, music_similarity: MusicSimilarity) { - self.music_similarity = music_similarity; - } - pub fn get_similar_music_referenced(&self) -> &Vec<(MusicEntry, Vec)> { &self.duplicated_music_entries_referenced } @@ -885,7 +887,7 @@ fn read_single_file_tag(path: &str, music_entry: &mut MusicEntry) -> bool { if minutes != 0 || seconds != 0 { length = format!("{minutes}:{seconds:02}"); } else if old_length_number > 0 { - // That means, that audio have length smaller that second, but length was properly read + // That means, that audio have length smaller that second but not zero length = "0:01".to_string(); } else { length = String::new(); @@ -904,12 +906,6 @@ fn read_single_file_tag(path: &str, music_entry: &mut MusicEntry) -> bool { true } -impl Default for SameMusic { - fn default() -> Self { - Self::new() - } -} - impl DebugPrint for SameMusic { #[fun_time(message = "debug_print", level = "debug")] fn debug_print(&self) { @@ -975,7 +971,7 @@ impl PrintResults for SameMusic { } } -fn get_approximate_conversion(what: &mut String) { +fn get_simplified_name(what: &str) -> String { let mut new_what = String::with_capacity(what.len()); let mut tab_number = 0; let mut space_before = true; @@ -1015,7 +1011,7 @@ fn get_approximate_conversion(what: &mut String) { if new_what.ends_with(' ') { new_what.pop(); } - *what = new_what; + new_what } impl CommonData for SameMusic { @@ -1025,28 +1021,31 @@ impl CommonData for SameMusic { fn get_cd_mut(&mut self) -> &mut CommonToolData { &mut self.common_data } + fn get_check_method(&self) -> CheckingMethod { + self.get_params().check_type + } } #[cfg(test)] mod tests { - use crate::same_music::get_approximate_conversion; + use crate::same_music::get_simplified_name; #[test] fn test_strings() { - let mut what = "roman ( ziemniak ) ".to_string(); - get_approximate_conversion(&mut what); - assert_eq!(what, "roman"); + let what = "roman ( ziemniak ) ".to_string(); + let res = get_simplified_name(&what); + assert_eq!(res, "roman"); - let mut what = " HH) ".to_string(); - get_approximate_conversion(&mut what); - assert_eq!(what, "HH"); + let what = " HH) ".to_string(); + let res = get_simplified_name(&what); + assert_eq!(res, "HH"); - let mut what = " fsf.f. ".to_string(); - get_approximate_conversion(&mut what); - assert_eq!(what, "fsf f"); + let what = " fsf.f. ".to_string(); + let res = get_simplified_name(&what); + assert_eq!(res, "fsf f"); - let mut what = "Kekistan (feat. roman) [Mix on Mix]".to_string(); - get_approximate_conversion(&mut what); - assert_eq!(what, "Kekistan"); + let what = "Kekistan (feat. roman) [Mix on Mix]".to_string(); + let res = get_simplified_name(&what); + assert_eq!(res, "Kekistan"); } } diff --git a/czkawka_core/src/similar_images.rs b/czkawka_core/src/similar_images.rs index 67440c462..d3b1c43b9 100644 --- a/czkawka_core/src/similar_images.rs +++ b/czkawka_core/src/similar_images.rs @@ -22,10 +22,11 @@ use crate::common::{ HEIC_EXTENSIONS, IMAGE_RS_SIMILAR_IMAGES_EXTENSIONS, RAW_IMAGE_EXTENSIONS, }; use crate::common_cache::{get_similar_images_cache_file, load_cache_from_file_generalized_by_path, save_cache_to_file_generalized}; -use crate::common_dir_traversal::{inode, take_1_per_inode, CheckingMethod, DirTraversalBuilder, DirTraversalResult, FileEntry, ProgressData, ToolType}; +use crate::common_dir_traversal::{inode, take_1_per_inode, DirTraversalBuilder, DirTraversalResult, FileEntry, ToolType}; use crate::common_tool::{CommonData, CommonToolData, DeleteMethod}; use crate::common_traits::{DebugPrint, PrintResults, ResultEntry}; use crate::flc; +use crate::progress_data::{CurrentStage, ProgressData}; type ImHash = Vec; @@ -83,8 +84,6 @@ pub enum ImageType { Unknown, } -const MAX_IMAGE_STAGE: u8 = 2; - #[derive(Clone, Debug, Copy)] pub enum SimilarityPreset { Original, @@ -101,7 +100,7 @@ struct Hamming; impl bk_tree::Metric for Hamming { fn distance(&self, a: &ImHash, b: &ImHash) -> u32 { - hamming::distance_fast(a, b).unwrap() as u32 + hamming::distance_fast(a, b).expect("Calculating hamming distance, cannot fail") as u32 } fn threshold_distance(&self, a: &ImHash, b: &ImHash, _threshold: u32) -> Option { @@ -109,6 +108,29 @@ impl bk_tree::Metric for Hamming { } } +pub struct SimilarImagesParameters { + pub similarity: u32, + pub hash_size: u8, + pub hash_alg: HashAlg, + pub image_filter: FilterType, + pub exclude_images_with_same_size: bool, + pub ignore_hard_links: bool, +} + +impl SimilarImagesParameters { + pub fn new(similarity: u32, hash_size: u8, hash_alg: HashAlg, image_filter: FilterType, exclude_images_with_same_size: bool, ignore_hard_links: bool) -> Self { + assert!([8, 16, 32, 64].contains(&hash_size)); + Self { + similarity, + hash_size, + hash_alg, + image_filter, + exclude_images_with_same_size, + ignore_hard_links, + } + } +} + pub struct SimilarImages { common_data: CommonToolData, information: Info, @@ -117,13 +139,8 @@ pub struct SimilarImages { similar_referenced_vectors: Vec<(ImagesEntry, Vec)>, // Hashmap with image hashes and Vector with names of files image_hashes: HashMap>, - similarity: u32, images_to_check: BTreeMap, - hash_size: u8, - hash_alg: HashAlg, - image_filter: FilterType, - exclude_images_with_same_size: bool, - ignore_hard_links: bool, + params: SimilarImagesParameters, } #[derive(Default)] @@ -133,21 +150,16 @@ pub struct Info { } impl SimilarImages { - pub fn new() -> Self { + pub fn new(params: SimilarImagesParameters) -> Self { Self { common_data: CommonToolData::new(ToolType::SimilarImages), information: Default::default(), bktree: BKTree::new(Hamming), similar_vectors: vec![], - similar_referenced_vectors: Default::default(), - image_hashes: Default::default(), - similarity: 0, + similar_referenced_vectors: vec![], + params, images_to_check: Default::default(), - hash_size: 8, - hash_alg: HashAlg::Gradient, - image_filter: FilterType::Lanczos3, - exclude_images_with_same_size: false, - ignore_hard_links: false, + image_hashes: Default::default(), } } @@ -195,7 +207,6 @@ impl SimilarImages { .stop_receiver(stop_receiver) .progress_sender(progress_sender) .common_data(&self.common_data) - .max_stage(MAX_IMAGE_STAGE) .build() .run(); @@ -203,7 +214,7 @@ impl SimilarImages { DirTraversalResult::SuccessFiles { grouped_file_entries, warnings } => { self.images_to_check = grouped_file_entries .into_iter() - .flat_map(if self.ignore_hard_links { |(_, fes)| fes } else { take_1_per_inode }) + .flat_map(if self.get_params().ignore_hard_links { |(_, fes)| fes } else { take_1_per_inode }) .map(|fe| { let fe_str = fe.path.to_string_lossy().to_string(); let extension_lowercase = fe.path.extension().unwrap_or_default().to_string_lossy().to_lowercase(); @@ -214,6 +225,8 @@ impl SimilarImages { image_entry.image_type = ImageType::Raw; } else if heic_extensions.contains(&extension_lowercase.as_str()) { image_entry.image_type = ImageType::Heic; + } else { + panic!("Unrecognized extension") } (fe_str, image_entry) }) @@ -236,7 +249,7 @@ impl SimilarImages { if self.common_data.use_cache { let (messages, loaded_items) = load_cache_from_file_generalized_by_path::( - &get_similar_images_cache_file(&self.hash_size, &self.hash_alg, &self.image_filter), + &get_similar_images_cache_file(&self.get_params().hash_size, &self.get_params().hash_alg, &self.get_params().image_filter), self.get_delete_outdated_cache(), &self.images_to_check, ); @@ -276,8 +289,12 @@ impl SimilarImages { fn hash_images(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&Sender>) -> bool { let (loaded_hash_map, records_already_cached, non_cached_files_to_check) = self.hash_images_load_cache(); - let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) = - prepare_thread_handler_common(progress_sender, 1, 2, non_cached_files_to_check.len(), CheckingMethod::None, self.common_data.tool_type); + let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) = prepare_thread_handler_common( + progress_sender, + CurrentStage::SimilarImagesCalculatingHashes, + non_cached_files_to_check.len(), + self.get_test_type(), + ); // Throw out images with not proper type - TODO why this happens, only broken cache? let non_cached_files_to_check = non_cached_files_to_check @@ -338,7 +355,7 @@ impl SimilarImages { } let messages = save_cache_to_file_generalized( - &get_similar_images_cache_file(&self.hash_size, &self.hash_alg, &self.image_filter), + &get_similar_images_cache_file(&self.get_params().hash_size, &self.get_params().hash_alg, &self.get_params().image_filter), &all_results, self.common_data.save_also_as_json, 0, @@ -407,9 +424,9 @@ impl SimilarImages { file_entry.height = dimensions.1; let hasher_config = HasherConfig::new() - .hash_size(self.hash_size as u32, self.hash_size as u32) - .hash_alg(self.hash_alg) - .resize_filter(self.image_filter); + .hash_size(self.get_params().hash_size as u32, self.get_params().hash_size as u32) + .hash_alg(self.get_params().hash_alg) + .resize_filter(self.get_params().image_filter); let hasher = hasher_config.to_hasher(); let hash = hasher.hash_image(&img); @@ -482,7 +499,10 @@ impl SimilarImages { for fe in &mut vec_fe { fe.similarity = similarity; } - collected_similar_images.get_mut(&parent_hash).unwrap().append(&mut vec_fe); + collected_similar_images + .get_mut(&parent_hash) + .expect("Cannot find parent hash - this should be added in previous step") + .append(&mut vec_fe); } } @@ -499,7 +519,7 @@ impl SimilarImages { let (base_hashes, hashes_with_multiple_images) = self.split_hashes(all_hashed_images); let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) = - prepare_thread_handler_common(progress_sender, 2, 2, base_hashes.len(), CheckingMethod::None, self.common_data.tool_type); + prepare_thread_handler_common(progress_sender, CurrentStage::SimilarImagesComparingHashes, base_hashes.len(), self.get_test_type()); let mut hashes_parents: HashMap = Default::default(); // Hashes used as parent (hash, children_number_of_hash) let mut hashes_similarity: HashMap = Default::default(); // Hashes used as child, (parent_hash, similarity) @@ -590,11 +610,13 @@ impl SimilarImages { if *current_similarity_with_parent > similarity { need_to_check = true; - *hashes_parents.get_mut(current_parent_hash).unwrap() -= 1; + *hashes_parents.get_mut(current_parent_hash).expect("Cannot find parent hash") -= 1; if hashes_parents.get(current_parent_hash) == Some(&0) && !hashes_with_multiple_images.contains(current_parent_hash) { hashes_parents.remove(current_parent_hash); } - hashes_similarity.remove(original_hash).unwrap(); + hashes_similarity + .remove(original_hash) + .expect("This should never fail, because we are iterating over this hash"); } } else { need_to_check = true; @@ -604,7 +626,7 @@ impl SimilarImages { if let Some((other_parent_hash, other_similarity)) = hashes_similarity.get(compared_hash) { if *other_similarity > similarity { need_to_add = true; - *hashes_parents.get_mut(other_parent_hash).unwrap() -= 1; + *hashes_parents.get_mut(other_parent_hash).expect("Cannot find parent hash") -= 1; } } // But when there is no record, just add it @@ -631,7 +653,7 @@ impl SimilarImages { return true; } - let tolerance = self.similarity; + let tolerance = self.get_params().similarity; // Results let mut collected_similar_images: HashMap> = Default::default(); @@ -680,7 +702,7 @@ impl SimilarImages { #[fun_time(message = "exclude_items_with_same_size", level = "debug")] fn exclude_items_with_same_size(&mut self) { - if self.exclude_images_with_same_size { + if self.get_params().exclude_images_with_same_size { for vec_file_entry in mem::take(&mut self.similar_vectors) { let mut bt_sizes: BTreeSet = Default::default(); let mut vec_values = Vec::new(); @@ -707,10 +729,10 @@ impl SimilarImages { .into_iter() .partition(|e| self.common_data.directories.is_in_referenced_directory(e.get_path())); - if files_from_referenced_folders.is_empty() || normal_files.is_empty() { + if normal_files.is_empty() { None } else { - Some((files_from_referenced_folders.pop().unwrap(), normal_files)) + files_from_referenced_folders.pop().map(|file| (file, normal_files)) } }) .collect::)>>(); @@ -765,12 +787,6 @@ fn is_in_reference_folder(reference_directories: &[PathBuf], path: &Path) -> boo reference_directories.iter().any(|e| path.starts_with(e)) } -impl Default for SimilarImages { - fn default() -> Self { - Self::new() - } -} - impl DebugPrint for SimilarImages { fn debug_print(&self) { if !cfg!(debug_assertions) { @@ -798,7 +814,7 @@ impl PrintResults for SimilarImages { file_entry.width, file_entry.height, format_size(file_entry.size, BINARY), - get_string_from_similarity(&file_entry.similarity, self.hash_size) + get_string_from_similarity(&file_entry.similarity, self.get_params().hash_size) )?; } writeln!(writer)?; @@ -816,7 +832,7 @@ impl PrintResults for SimilarImages { file_entry.width, file_entry.height, format_size(file_entry.size, BINARY), - get_string_from_similarity(&file_entry.similarity, self.hash_size) + get_string_from_similarity(&file_entry.similarity, self.get_params().hash_size) )?; for file_entry in vec_file_entry { writeln!( @@ -826,7 +842,7 @@ impl PrintResults for SimilarImages { file_entry.width, file_entry.height, format_size(file_entry.size, BINARY), - get_string_from_similarity(&file_entry.similarity, self.hash_size) + get_string_from_similarity(&file_entry.similarity, self.get_params().hash_size) )?; } writeln!(writer)?; @@ -913,6 +929,7 @@ pub fn convert_algorithm_to_string(hash_alg: &HashAlg) -> String { HashAlg::Blockhash => "Blockhash", HashAlg::VertGradient => "VertGradient", HashAlg::DoubleGradient => "DoubleGradient", + HashAlg::Median => "Median", } .to_string() } @@ -922,7 +939,14 @@ pub fn test_image_conversion_speed() { let file_path = Path::new(file_name); match image::open(file_path) { Ok(img_open) => { - for alg in [HashAlg::Blockhash, HashAlg::Gradient, HashAlg::DoubleGradient, HashAlg::VertGradient, HashAlg::Mean] { + for alg in [ + HashAlg::Blockhash, + HashAlg::Gradient, + HashAlg::DoubleGradient, + HashAlg::VertGradient, + HashAlg::Mean, + HashAlg::Median, + ] { for filter in [ FilterType::Lanczos3, FilterType::CatmullRom, @@ -940,7 +964,14 @@ pub fn test_image_conversion_speed() { let end = SystemTime::now(); - println!("{:?} us {:?} {:?} {}x{}", end.duration_since(start).unwrap().as_micros(), alg, filter, size, size); + println!( + "{:?} us {:?} {:?} {}x{}", + end.duration_since(start).expect("Used time backwards").as_micros(), + alg, + filter, + size, + size + ); } } } @@ -1030,25 +1061,8 @@ impl CommonData for SimilarImages { } impl SimilarImages { - pub fn set_hash_size(&mut self, hash_size: u8) { - self.hash_size = match hash_size { - 8 | 16 | 32 | 64 => hash_size, - e => { - panic!("Invalid value of hash size {e}"); - } - } - } - - pub fn set_exclude_images_with_same_size(&mut self, exclude_images_with_same_size: bool) { - self.exclude_images_with_same_size = exclude_images_with_same_size; - } - - pub fn set_hash_alg(&mut self, hash_alg: HashAlg) { - self.hash_alg = hash_alg; - } - - pub fn set_image_filter(&mut self, image_filter: FilterType) { - self.image_filter = image_filter; + pub fn get_params(&self) -> &SimilarImagesParameters { + &self.params } pub const fn get_similar_images(&self) -> &Vec> { @@ -1066,14 +1080,6 @@ impl SimilarImages { pub const fn get_information(&self) -> &Info { &self.information } - - pub fn set_similarity(&mut self, similarity: u32) { - self.similarity = similarity; - } - - pub fn set_ignore_hard_links(&mut self, ignore_hard_links: bool) { - self.ignore_hard_links = ignore_hard_links; - } } #[cfg(test)] @@ -1081,17 +1087,27 @@ mod tests { use std::collections::HashMap; use std::path::PathBuf; + use crate::common_tool::CommonData; + use crate::similar_images::{Hamming, ImHash, ImageType, ImagesEntry, SimilarImages, SimilarImagesParameters}; use bk_tree::BKTree; + use image::imageops::FilterType; + use image_hasher::HashAlg; - use crate::common_dir_traversal::ToolType; - use crate::common_directory::Directories; - use crate::common_tool::CommonToolData; - use crate::similar_images::{Hamming, ImHash, ImageType, ImagesEntry, SimilarImages}; + fn get_default_parameters() -> SimilarImagesParameters { + SimilarImagesParameters { + hash_alg: HashAlg::Gradient, + hash_size: 8, + similarity: 0, + image_filter: FilterType::Lanczos3, + exclude_images_with_same_size: false, + ignore_hard_links: false, + } + } #[test] fn test_compare_no_images() { for _ in 0..100 { - let mut similar_images = SimilarImages::default(); + let mut similar_images = SimilarImages::new(get_default_parameters()); similar_images.find_similar_images(None, None); assert_eq!(similar_images.get_similar_images().len(), 0); } @@ -1100,14 +1116,9 @@ mod tests { #[test] fn test_compare_tolerance_0_normal_mode() { for _ in 0..100 { - let mut similar_images = SimilarImages { - similarity: 0, - common_data: CommonToolData { - tool_type: ToolType::SimilarImages, - ..Default::default() - }, - ..Default::default() - }; + let mut parameters = get_default_parameters(); + parameters.similarity = 0; + let mut similar_images = SimilarImages::new(parameters); let fe1 = create_random_file_entry(vec![1, 1, 1, 1, 1, 1, 1, 1], "abc.txt"); let fe2 = create_random_file_entry(vec![1, 1, 1, 1, 1, 1, 1, 1], "bcd.txt"); @@ -1135,14 +1146,9 @@ mod tests { #[test] fn test_simple_normal_one_group() { for _ in 0..100 { - let mut similar_images = SimilarImages { - similarity: 1, - common_data: CommonToolData { - tool_type: ToolType::SimilarImages, - ..Default::default() - }, - ..Default::default() - }; + let mut parameters = get_default_parameters(); + parameters.similarity = 1; + let mut similar_images = SimilarImages::new(parameters); let fe1 = create_random_file_entry(vec![1, 1, 1, 1, 1, 1, 1, 1], "abc.txt"); let fe2 = create_random_file_entry(vec![1, 1, 1, 1, 1, 1, 1, 1], "bcd.txt"); @@ -1157,15 +1163,10 @@ mod tests { #[test] fn test_simple_normal_one_group_extended() { for _ in 0..100 { - let mut similar_images = SimilarImages { - similarity: 2, - common_data: CommonToolData { - use_reference_folders: false, - tool_type: ToolType::SimilarImages, - ..Default::default() - }, - ..Default::default() - }; + let mut parameters = get_default_parameters(); + parameters.similarity = 2; + let mut similar_images = SimilarImages::new(parameters); + similar_images.set_use_reference_folders(false); let fe1 = create_random_file_entry(vec![1, 1, 1, 1, 1, 1, 1, 1], "abc.txt"); let fe2 = create_random_file_entry(vec![1, 1, 1, 1, 1, 1, 1, 1], "bcd.txt"); @@ -1182,19 +1183,12 @@ mod tests { #[test] fn test_simple_referenced_same_group() { for _ in 0..100 { - let mut similar_images = SimilarImages { - similarity: 0, - common_data: CommonToolData { - tool_type: ToolType::SimilarImages, - directories: Directories { - reference_directories: vec![PathBuf::from("/home/rr/")], - ..Default::default() - }, - use_reference_folders: true, - ..Default::default() - }, - ..Default::default() - }; + let mut parameters = get_default_parameters(); + parameters.similarity = 0; + let mut similar_images = SimilarImages::new(parameters); + similar_images.set_use_reference_folders(true); + // Not using special method, because it validates if path exists + similar_images.common_data.directories.reference_directories = vec![PathBuf::from("/home/rr/")]; let fe1 = create_random_file_entry(vec![1, 1, 1, 1, 1, 1, 1, 1], "/home/rr/abc.txt"); let fe2 = create_random_file_entry(vec![1, 1, 1, 1, 1, 1, 1, 1], "/home/rr/bcd.txt"); @@ -1209,19 +1203,12 @@ mod tests { #[test] fn test_simple_referenced_group_extended() { for _ in 0..100 { - let mut similar_images = SimilarImages { - similarity: 0, - common_data: CommonToolData { - tool_type: ToolType::SimilarImages, - directories: Directories { - reference_directories: vec![PathBuf::from("/home/rr/")], - ..Default::default() - }, - use_reference_folders: true, - ..Default::default() - }, - ..Default::default() - }; + let mut parameters = get_default_parameters(); + parameters.similarity = 0; + let mut similar_images = SimilarImages::new(parameters); + similar_images.set_use_reference_folders(true); + // Not using special method, because it validates if path exists + similar_images.common_data.directories.reference_directories = vec![PathBuf::from("/home/rr/")]; let fe1 = create_random_file_entry(vec![1, 1, 1, 1, 1, 1, 1, 1], "/home/rr/abc.txt"); let fe2 = create_random_file_entry(vec![1, 1, 1, 1, 1, 1, 1, 1], "/home/kk/bcd.txt"); @@ -1237,19 +1224,12 @@ mod tests { #[test] fn test_simple_referenced_group_extended2() { for _ in 0..100 { - let mut similar_images = SimilarImages { - similarity: 0, - common_data: CommonToolData { - tool_type: ToolType::SimilarImages, - directories: Directories { - reference_directories: vec![PathBuf::from("/home/rr/")], - ..Default::default() - }, - use_reference_folders: true, - ..Default::default() - }, - ..Default::default() - }; + let mut parameters = get_default_parameters(); + parameters.similarity = 0; + let mut similar_images = SimilarImages::new(parameters); + similar_images.set_use_reference_folders(true); + // Not using special method, because it validates if path exists + similar_images.common_data.directories.reference_directories = vec![PathBuf::from("/home/rr/")]; let fe1 = create_random_file_entry(vec![1, 1, 1, 1, 1, 1, 1, 1], "/home/rr/abc.txt"); let fe2 = create_random_file_entry(vec![1, 1, 1, 1, 1, 1, 1, 1], "/home/rr/abc2.txt"); @@ -1269,15 +1249,10 @@ mod tests { #[test] fn test_simple_normal_too_small_similarity() { for _ in 0..100 { - let mut similar_images = SimilarImages { - similarity: 1, - common_data: CommonToolData { - tool_type: ToolType::SimilarImages, - use_reference_folders: false, - ..Default::default() - }, - ..Default::default() - }; + let mut parameters = get_default_parameters(); + parameters.similarity = 1; + let mut similar_images = SimilarImages::new(parameters); + similar_images.set_use_reference_folders(false); let fe1 = create_random_file_entry(vec![1, 1, 1, 1, 1, 1, 1, 0b00001], "abc.txt"); let fe2 = create_random_file_entry(vec![1, 1, 1, 1, 1, 1, 1, 0b00100], "bcd.txt"); @@ -1294,15 +1269,10 @@ mod tests { #[test] fn test_simple_normal_union_of_similarity() { for _ in 0..100 { - let mut similar_images = SimilarImages { - similarity: 4, - common_data: CommonToolData { - tool_type: ToolType::SimilarImages, - use_reference_folders: false, - ..Default::default() - }, - ..Default::default() - }; + let mut parameters = get_default_parameters(); + parameters.similarity = 4; + let mut similar_images = SimilarImages::new(parameters); + similar_images.set_use_reference_folders(false); let fe1 = create_random_file_entry(vec![1, 1, 1, 1, 1, 1, 1, 0b0000_0001], "abc.txt"); let fe2 = create_random_file_entry(vec![1, 1, 1, 1, 1, 1, 1, 0b0000_1111], "bcd.txt"); @@ -1328,19 +1298,12 @@ mod tests { #[test] fn test_reference_similarity_only_one() { for _ in 0..100 { - let mut similar_images = SimilarImages { - similarity: 1, - common_data: CommonToolData { - tool_type: ToolType::SimilarImages, - directories: Directories { - reference_directories: vec![PathBuf::from("/home/rr/")], - ..Default::default() - }, - use_reference_folders: true, - ..Default::default() - }, - ..Default::default() - }; + let mut parameters = get_default_parameters(); + parameters.similarity = 1; + let mut similar_images = SimilarImages::new(parameters); + similar_images.set_use_reference_folders(true); + // Not using special method, because it validates if path exists + similar_images.common_data.directories.reference_directories = vec![PathBuf::from("/home/rr/")]; let fe1 = create_random_file_entry(vec![1, 1, 1, 1, 1, 1, 1, 0b0001], "/home/rr/abc.txt"); let fe2 = create_random_file_entry(vec![1, 1, 1, 1, 1, 1, 1, 0b0011], "/home/kk/bcd.txt"); @@ -1359,19 +1322,12 @@ mod tests { #[test] fn test_reference_too_small_similarity() { for _ in 0..100 { - let mut similar_images = SimilarImages { - similarity: 1, - common_data: CommonToolData { - tool_type: ToolType::SimilarImages, - directories: Directories { - reference_directories: vec![PathBuf::from("/home/rr/")], - ..Default::default() - }, - use_reference_folders: true, - ..Default::default() - }, - ..Default::default() - }; + let mut parameters = get_default_parameters(); + parameters.similarity = 1; + let mut similar_images = SimilarImages::new(parameters); + similar_images.set_use_reference_folders(true); + // Not using special method, because it validates if path exists + similar_images.common_data.directories.reference_directories = vec![PathBuf::from("/home/rr/")]; let fe1 = create_random_file_entry(vec![1, 1, 1, 1, 1, 1, 1, 0b0001], "/home/rr/abc.txt"); let fe2 = create_random_file_entry(vec![1, 1, 1, 1, 1, 1, 1, 0b0010], "/home/kk/bcd.txt"); @@ -1387,19 +1343,12 @@ mod tests { #[test] fn test_reference_minimal() { for _ in 0..100 { - let mut similar_images = SimilarImages { - similarity: 1, - common_data: CommonToolData { - tool_type: ToolType::SimilarImages, - directories: Directories { - reference_directories: vec![PathBuf::from("/home/rr/")], - ..Default::default() - }, - use_reference_folders: true, - ..Default::default() - }, - ..Default::default() - }; + let mut parameters = get_default_parameters(); + parameters.similarity = 1; + let mut similar_images = SimilarImages::new(parameters); + similar_images.set_use_reference_folders(true); + // Not using special method, because it validates if path exists + similar_images.common_data.directories.reference_directories = vec![PathBuf::from("/home/rr/")]; let fe1 = create_random_file_entry(vec![1, 1, 1, 1, 1, 1, 1, 0b0001], "/home/rr/abc.txt"); let fe2 = create_random_file_entry(vec![1, 1, 1, 1, 1, 1, 1, 0b0011], "/home/kk/bcd.txt"); @@ -1426,19 +1375,12 @@ mod tests { #[test] fn test_reference_same() { for _ in 0..100 { - let mut similar_images = SimilarImages { - similarity: 1, - common_data: CommonToolData { - tool_type: ToolType::SimilarImages, - directories: Directories { - reference_directories: vec![PathBuf::from("/home/rr/")], - ..Default::default() - }, - use_reference_folders: true, - ..Default::default() - }, - ..Default::default() - }; + let mut parameters = get_default_parameters(); + parameters.similarity = 1; + let mut similar_images = SimilarImages::new(parameters); + similar_images.set_use_reference_folders(true); + // Not using special method, because it validates if path exists + similar_images.common_data.directories.reference_directories = vec![PathBuf::from("/home/rr/")]; let fe1 = create_random_file_entry(vec![1, 1, 1, 1, 1, 1, 1, 1], "/home/rr/abc.txt"); let fe2 = create_random_file_entry(vec![1, 1, 1, 1, 1, 1, 1, 1], "/home/kk/bcd.txt"); @@ -1455,19 +1397,12 @@ mod tests { #[test] fn test_reference_union() { for _ in 0..100 { - let mut similar_images = SimilarImages { - similarity: 10, - common_data: CommonToolData { - tool_type: ToolType::SimilarImages, - directories: Directories { - reference_directories: vec![PathBuf::from("/home/rr/")], - ..Default::default() - }, - use_reference_folders: true, - ..Default::default() - }, - ..Default::default() - }; + let mut parameters = get_default_parameters(); + parameters.similarity = 10; + let mut similar_images = SimilarImages::new(parameters); + similar_images.set_use_reference_folders(true); + // Not using special method, because it validates if path exists + similar_images.common_data.directories.reference_directories = vec![PathBuf::from("/home/rr/")]; let fe0 = create_random_file_entry(vec![1, 1, 1, 1, 1, 1, 1, 0b1000], "/home/rr/abc2.txt"); let fe1 = create_random_file_entry(vec![1, 1, 1, 1, 1, 1, 1, 0b0001], "/home/rr/abc.txt"); @@ -1495,21 +1430,21 @@ mod tests { let fe2 = vec![1, 1, 1, 1, 1, 1, 1, 2]; let mut bktree = BKTree::new(Hamming); bktree.add(fe1); - let (similarity, _hash) = bktree.find(&fe2, 100).next().unwrap(); + let (similarity, _hash) = bktree.find(&fe2, 100).next().expect("No similar images found"); assert_eq!(similarity, 2); let fe1 = vec![1, 1, 1, 1, 1, 1, 1, 1]; let fe2 = vec![1, 1, 1, 1, 1, 1, 1, 3]; let mut bktree = BKTree::new(Hamming); bktree.add(fe1); - let (similarity, _hash) = bktree.find(&fe2, 100).next().unwrap(); + let (similarity, _hash) = bktree.find(&fe2, 100).next().expect("No similar images found"); assert_eq!(similarity, 1); let fe1 = vec![1, 1, 1, 1, 1, 1, 1, 0b0000_0000]; let fe2 = vec![1, 1, 1, 1, 1, 1, 1, 0b0000_1000]; let mut bktree = BKTree::new(Hamming); bktree.add(fe1); - let (similarity, _hash) = bktree.find(&fe2, 100).next().unwrap(); + let (similarity, _hash) = bktree.find(&fe2, 100).next().expect("No similar images found"); assert_eq!(similarity, 1); } diff --git a/czkawka_core/src/similar_videos.rs b/czkawka_core/src/similar_videos.rs index 4fd3a73a8..49dfbd299 100644 --- a/czkawka_core/src/similar_videos.rs +++ b/czkawka_core/src/similar_videos.rs @@ -16,10 +16,11 @@ use vid_dup_finder_lib::{NormalizedTolerance, VideoHash}; use crate::common::{check_if_stop_received, delete_files_custom, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads, VIDEO_FILES_EXTENSIONS}; use crate::common_cache::{get_similar_videos_cache_file, load_cache_from_file_generalized_by_path, save_cache_to_file_generalized}; -use crate::common_dir_traversal::{inode, take_1_per_inode, CheckingMethod, DirTraversalBuilder, DirTraversalResult, FileEntry, ProgressData, ToolType}; +use crate::common_dir_traversal::{inode, take_1_per_inode, DirTraversalBuilder, DirTraversalResult, FileEntry, ToolType}; use crate::common_tool::{CommonData, CommonToolData, DeleteMethod}; use crate::common_traits::{DebugPrint, PrintResults, ResultEntry}; use crate::flc; +use crate::progress_data::{CurrentStage, ProgressData}; pub const MAX_TOLERANCE: i32 = 20; @@ -57,22 +58,23 @@ impl FileEntry { } } -struct Hamming; - -impl bk_tree::Metric> for Hamming { - #[inline] - fn distance(&self, a: &Vec, b: &Vec) -> u32 { - hamming::distance_fast(a, b).unwrap() as u32 - } +pub struct SimilarVideosParameters { + pub tolerance: i32, + pub exclude_videos_with_same_size: bool, + pub ignore_hard_links: bool, +} - #[inline] - fn threshold_distance(&self, a: &Vec, b: &Vec, _threshold: u32) -> Option { - Some(self.distance(a, b)) +impl SimilarVideosParameters { + pub fn new(tolerance: i32, exclude_videos_with_same_size: bool, ignore_hard_links: bool) -> Self { + assert!((0..=MAX_TOLERANCE).contains(&tolerance)); + Self { + tolerance, + exclude_videos_with_same_size, + ignore_hard_links, + } } } -const MAX_VIDEOS_STAGE: u8 = 1; - pub struct SimilarVideos { common_data: CommonToolData, information: Info, @@ -80,9 +82,7 @@ pub struct SimilarVideos { similar_referenced_vectors: Vec<(VideosEntry, Vec)>, videos_hashes: BTreeMap, Vec>, videos_to_check: BTreeMap, - tolerance: i32, - exclude_videos_with_same_size: bool, - ignore_hard_links: bool, + params: SimilarVideosParameters, } impl CommonData for SimilarVideos { @@ -101,17 +101,15 @@ pub struct Info { } impl SimilarVideos { - pub fn new() -> Self { + pub fn new(params: SimilarVideosParameters) -> Self { Self { common_data: CommonToolData::new(ToolType::SimilarVideos), information: Default::default(), similar_vectors: vec![], videos_hashes: Default::default(), videos_to_check: Default::default(), - tolerance: 10, - exclude_videos_with_same_size: false, similar_referenced_vectors: vec![], - ignore_hard_links: false, + params, } } @@ -154,7 +152,6 @@ impl SimilarVideos { .stop_receiver(stop_receiver) .progress_sender(progress_sender) .common_data(&self.common_data) - .max_stage(MAX_VIDEOS_STAGE) .build() .run(); @@ -162,7 +159,7 @@ impl SimilarVideos { DirTraversalResult::SuccessFiles { grouped_file_entries, warnings } => { self.videos_to_check = grouped_file_entries .into_iter() - .flat_map(if self.ignore_hard_links { |(_, fes)| fes } else { take_1_per_inode }) + .flat_map(if self.get_params().ignore_hard_links { |(_, fes)| fes } else { take_1_per_inode }) .map(|fe| (fe.path.to_string_lossy().to_string(), fe.into_videos_entry())) .collect(); self.common_data.text_messages.warnings.extend(warnings); @@ -204,8 +201,12 @@ impl SimilarVideos { fn sort_videos(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&Sender>) -> bool { let (loaded_hash_map, records_already_cached, non_cached_files_to_check) = self.load_cache_at_start(); - let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) = - prepare_thread_handler_common(progress_sender, 1, 1, non_cached_files_to_check.len(), CheckingMethod::None, self.common_data.tool_type); + let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) = prepare_thread_handler_common( + progress_sender, + CurrentStage::SimilarVideosCalculatingHashes, + non_cached_files_to_check.len(), + self.get_test_type(), + ); let mut vec_file_entry: Vec = non_cached_files_to_check .par_iter() @@ -296,14 +297,14 @@ impl SimilarVideos { #[fun_time(message = "match_groups_of_videos", level = "debug")] fn match_groups_of_videos(&mut self, vector_of_hashes: Vec, hashmap_with_file_entries: &HashMap) { - let match_group = vid_dup_finder_lib::search(vector_of_hashes, NormalizedTolerance::new(self.tolerance as f64 / 100.0f64)); + let match_group = vid_dup_finder_lib::search(vector_of_hashes, NormalizedTolerance::new(self.get_params().tolerance as f64 / 100.0f64)); let mut collected_similar_videos: Vec> = Default::default(); for i in match_group { let mut temp_vector: Vec = Vec::new(); let mut bt_size: BTreeSet = Default::default(); for j in i.duplicates() { - let file_entry = hashmap_with_file_entries.get(&j.to_string_lossy().to_string()).unwrap(); - if self.exclude_videos_with_same_size { + let file_entry = &hashmap_with_file_entries[&j.to_string_lossy().to_string()]; + if self.get_params().exclude_videos_with_same_size { if !bt_size.contains(&file_entry.size) { bt_size.insert(file_entry.size); temp_vector.push(file_entry.clone()); @@ -330,10 +331,10 @@ impl SimilarVideos { .into_iter() .partition(|e| self.common_data.directories.is_in_referenced_directory(e.get_path())); - if files_from_referenced_folders.is_empty() || normal_files.is_empty() { + if normal_files.is_empty() { None } else { - Some((files_from_referenced_folders.pop().unwrap(), normal_files)) + files_from_referenced_folders.pop().map(|file| (file, normal_files)) } }) .collect::)>>(); @@ -350,12 +351,6 @@ impl SimilarVideos { } } -impl Default for SimilarVideos { - fn default() -> Self { - Self::new() - } -} - impl DebugPrint for SimilarVideos { #[fun_time(message = "debug_print", level = "debug")] fn debug_print(&self) { @@ -423,13 +418,8 @@ pub fn check_if_ffmpeg_is_installed() -> bool { } impl SimilarVideos { - pub fn set_exclude_videos_with_same_size(&mut self, exclude_videos_with_same_size: bool) { - self.exclude_videos_with_same_size = exclude_videos_with_same_size; - } - - pub fn set_tolerance(&mut self, tolerance: i32) { - assert!((0..=MAX_TOLERANCE).contains(&tolerance)); - self.tolerance = tolerance; + pub fn get_params(&self) -> &SimilarVideosParameters { + &self.params } pub const fn get_similar_videos(&self) -> &Vec> { @@ -455,8 +445,4 @@ impl SimilarVideos { pub fn get_use_reference(&self) -> bool { self.common_data.use_reference_folders } - - pub fn set_ignore_hard_links(&mut self, ignore_hard_links: bool) { - self.ignore_hard_links = ignore_hard_links; - } } diff --git a/czkawka_core/src/temporary.rs b/czkawka_core/src/temporary.rs index 649f2572a..bcea554a8 100644 --- a/czkawka_core/src/temporary.rs +++ b/czkawka_core/src/temporary.rs @@ -11,9 +11,10 @@ use rayon::prelude::*; use serde::Serialize; use crate::common::{check_folder_children, check_if_stop_received, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads}; -use crate::common_dir_traversal::{common_read_dir, get_modified_time, CheckingMethod, ProgressData, ToolType}; +use crate::common_dir_traversal::{common_read_dir, get_modified_time, ToolType}; use crate::common_tool::{CommonData, CommonToolData, DeleteMethod}; use crate::common_traits::*; +use crate::progress_data::{CurrentStage, ProgressData}; const TEMP_EXTENSIONS: &[&str] = &[ "#", @@ -82,7 +83,7 @@ impl Temporary { let mut folders_to_check: Vec = self.common_data.directories.included_directories.clone(); let (progress_thread_handle, progress_thread_run, atomic_counter, _check_was_stopped) = - prepare_thread_handler_common(progress_sender, 0, 0, 0, CheckingMethod::None, self.common_data.tool_type); + prepare_thread_handler_common(progress_sender, CurrentStage::CollectingFiles, 0, self.get_test_type()); while !folders_to_check.is_empty() { if check_if_stop_received(stop_receiver) { diff --git a/czkawka_gui/Cargo.toml b/czkawka_gui/Cargo.toml index cb87c2ce5..db0262357 100644 --- a/czkawka_gui/Cargo.toml +++ b/czkawka_gui/Cargo.toml @@ -3,19 +3,19 @@ name = "czkawka_gui" version = "7.0.0" authors = ["RafaÅ‚ Mikrut "] edition = "2021" -rust-version = "1.75.0" +rust-version = "1.79.0" description = "GTK frontend of Czkawka" license = "MIT" homepage = "https://github.com/qarmin/czkawka" repository = "https://github.com/qarmin/czkawka" [dependencies] -gdk4 = "0.8" -glib = "0.19" -gtk4 = { version = "0.8", default-features = false, features = ["v4_6"] } +gdk4 = "0.9" +glib = "0.20" +gtk4 = { version = "0.9", default-features = false, features = ["v4_6"] } humansize = "2.1" -chrono = "0.4.34" +chrono = "0.4.38" # Used for sending stop signal across threads crossbeam-channel = "0.5" @@ -24,33 +24,33 @@ crossbeam-channel = "0.5" directories-next = "2.0" # For opening files -open = "5.0" +open = "5.3" # To get image preview -image = "0.24" +image = "0.25" # To be able to use custom select regex = "1.10" # To get image_hasher types -image_hasher = "1.2" +image_hasher = "2.0" # Move files to trash -trash = "3.3" +trash = "5.1" # For moving files(why std::fs doesn't have such features?) fs_extra = "1.3" # Language -i18n-embed = { version = "0.14", features = ["fluent-system", "desktop-requester"] } -i18n-embed-fl = "0.8" -rust-embed = { version = "8.2", features = ["debug-embed"] } +i18n-embed = { version = "0.15", features = ["fluent-system", "desktop-requester"] } +i18n-embed-fl = "0.9" +rust-embed = { version = "8.5", features = ["debug-embed"] } once_cell = "1.19" -log = "0.4.20" +log = "0.4.22" handsome_logger = "0.8" fun_time = { version = "0.3", features = ["log"] } -rayon = "1.8" +rayon = "1.10" czkawka_core = { path = "../czkawka_core", version = "7.0.0", features = [] } diff --git a/czkawka_gui/README.md b/czkawka_gui/README.md index 3e8a77b23..fbbdc44c2 100644 --- a/czkawka_gui/README.md +++ b/czkawka_gui/README.md @@ -55,7 +55,7 @@ lot build and runtime dependencies. | Program | Minimal version | |:-------:|:---------------:| -| Rust | 1.75.0 | +| Rust | 1.79.0 | | GTK | 4.6 | ### Linux (Ubuntu, but on other OS should work similar) diff --git a/czkawka_gui/src/compute_results.rs b/czkawka_gui/src/compute_results.rs index 7959d316c..4ff2205aa 100644 --- a/czkawka_gui/src/compute_results.rs +++ b/czkawka_gui/src/compute_results.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use std::rc::Rc; use std::time::Duration; -use chrono::NaiveDateTime; +use chrono::DateTime; use crossbeam_channel::Receiver; use fun_time::fun_time; use gtk4::prelude::*; @@ -74,7 +74,7 @@ pub fn connect_compute_results(gui_data: &GuiData, result_receiver: Receiver>, + shared_state: &SharedState, shared_buttons: &Rc>>>, buttons_array: &[Widget; 9], buttons_names: &[BottomButtonsEnum; 9], @@ -280,7 +280,9 @@ fn compute_bad_extensions( (ColumnsBadExtensions::ValidExtensions as u32, &file_entry.proper_extensions), ( ColumnsBadExtensions::Modification as u32, - &(NaiveDateTime::from_timestamp_opt(file_entry.modified_date as i64, 0).unwrap().to_string()), + &(DateTime::from_timestamp(file_entry.modified_date as i64, 0) + .expect("Modified date always should be in valid range") + .to_string()), ), (ColumnsBadExtensions::ModificationAsSecs as u32, &(file_entry.modified_date as i64)), ]; @@ -291,12 +293,12 @@ fn compute_bad_extensions( // Set state { - *shared_state.borrow_mut() = be; + *shared_state.borrow_mut() = Some(be); - set_specific_buttons_as_active(shared_buttons, &NotebookMainEnum::Temporary, bad_extensions_number > 0); + set_specific_buttons_as_active(shared_buttons, NotebookMainEnum::Temporary, bad_extensions_number > 0); set_buttons( - &mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Temporary).unwrap(), + &mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Temporary).expect("Failed to borrow buttons"), buttons_array, buttons_names, ); @@ -310,7 +312,7 @@ fn compute_broken_files( entry_info: &Entry, tree_view: &TreeView, text_view_errors: &TextView, - shared_state: &Rc>, + shared_state: &SharedState, shared_buttons: &Rc>>>, buttons_array: &[Widget; 9], buttons_names: &[BottomButtonsEnum; 9], @@ -345,7 +347,9 @@ fn compute_broken_files( (ColumnsBrokenFiles::ErrorType as u32, &file_entry.error_string), ( ColumnsBrokenFiles::Modification as u32, - &(NaiveDateTime::from_timestamp_opt(file_entry.modified_date as i64, 0).unwrap().to_string()), + &(DateTime::from_timestamp(file_entry.modified_date as i64, 0) + .expect("Modified date always should be in valid range") + .to_string()), ), (ColumnsBrokenFiles::ModificationAsSecs as u32, &(file_entry.modified_date as i64)), ]; @@ -356,12 +360,12 @@ fn compute_broken_files( // Set state { - *shared_state.borrow_mut() = br; + *shared_state.borrow_mut() = Some(br); - set_specific_buttons_as_active(shared_buttons, &NotebookMainEnum::BrokenFiles, broken_files_number > 0); + set_specific_buttons_as_active(shared_buttons, NotebookMainEnum::BrokenFiles, broken_files_number > 0); set_buttons( - &mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BrokenFiles).unwrap(), + &mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BrokenFiles).expect("Failed to borrow buttons"), buttons_array, buttons_names, ); @@ -375,7 +379,7 @@ fn compute_invalid_symlinks( entry_info: &Entry, tree_view: &TreeView, text_view_errors: &TextView, - shared_state: &Rc>, + shared_state: &SharedState, shared_buttons: &Rc>>>, buttons_array: &[Widget; 9], buttons_names: &[BottomButtonsEnum; 9], @@ -405,13 +409,12 @@ fn compute_invalid_symlinks( (ColumnsInvalidSymlinks::Name as u32, &file), (ColumnsInvalidSymlinks::Path as u32, &directory), (ColumnsInvalidSymlinks::DestinationPath as u32, &symlink_info.destination_path.to_string_lossy().to_string()), - ( - ColumnsInvalidSymlinks::TypeOfError as u32, - &get_text_from_invalid_symlink_cause(&symlink_info.type_of_error), - ), + (ColumnsInvalidSymlinks::TypeOfError as u32, &get_text_from_invalid_symlink_cause(symlink_info.type_of_error)), ( ColumnsInvalidSymlinks::Modification as u32, - &(NaiveDateTime::from_timestamp_opt(file_entry.modified_date as i64, 0).unwrap().to_string()), + &(DateTime::from_timestamp(file_entry.modified_date as i64, 0) + .expect("Modified date always should be in valid range") + .to_string()), ), (ColumnsInvalidSymlinks::ModificationAsSecs as u32, &(file_entry.modified_date as i64)), ]; @@ -422,12 +425,12 @@ fn compute_invalid_symlinks( // Set state { - *shared_state.borrow_mut() = ifs; + *shared_state.borrow_mut() = Some(ifs); - set_specific_buttons_as_active(shared_buttons, &NotebookMainEnum::Symlinks, invalid_symlinks > 0); + set_specific_buttons_as_active(shared_buttons, NotebookMainEnum::Symlinks, invalid_symlinks > 0); set_buttons( - &mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Symlinks).unwrap(), + &mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Symlinks).expect("Failed to borrow buttons"), buttons_array, buttons_names, ); @@ -441,7 +444,7 @@ fn compute_same_music( entry_info: &Entry, tree_view: &TreeView, text_view_errors: &TextView, - shared_state: &Rc>, + shared_state: &SharedState, shared_buttons: &Rc>>>, buttons_array: &[Widget; 9], buttons_names: &[BottomButtonsEnum; 9], @@ -473,7 +476,7 @@ fn compute_same_music( { let list_store = get_list_store(tree_view); - let music_similarity = *mf.get_music_similarity(); + let music_similarity = mf.get_params().music_similarity; let is_track_title = (MusicSimilarity::TRACK_TITLE & music_similarity) != MusicSimilarity::NONE; let is_track_artist = (MusicSimilarity::TRACK_ARTIST & music_similarity) != MusicSimilarity::NONE; @@ -535,7 +538,7 @@ fn compute_same_music( } else { let vector = mf.get_duplicated_music_entries(); - let text: &str = if mf.get_check_type() == CheckingMethod::AudioTags { "-----" } else { "" }; + let text: &str = if mf.get_params().check_type == CheckingMethod::AudioTags { "-----" } else { "" }; for vec_file_entry in vector { // Sort @@ -589,12 +592,12 @@ fn compute_same_music( // Set state { - *shared_state.borrow_mut() = mf; + *shared_state.borrow_mut() = Some(mf); - set_specific_buttons_as_active(shared_buttons, &NotebookMainEnum::SameMusic, same_music_number > 0); + set_specific_buttons_as_active(shared_buttons, NotebookMainEnum::SameMusic, same_music_number > 0); set_buttons( - &mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SameMusic).unwrap(), + &mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SameMusic).expect("Failed to borrow buttons"), buttons_array, buttons_names, ); @@ -608,7 +611,7 @@ fn compute_similar_videos( entry_info: &Entry, tree_view: &TreeView, text_view_errors: &TextView, - shared_state: &Rc>, + shared_state: &SharedState, shared_buttons: &Rc>>>, buttons_array: &[Widget; 9], buttons_names: &[BottomButtonsEnum; 9], @@ -683,12 +686,12 @@ fn compute_similar_videos( // Set state { - *shared_state.borrow_mut() = ff; + *shared_state.borrow_mut() = Some(ff); - set_specific_buttons_as_active(shared_buttons, &NotebookMainEnum::SimilarVideos, found_any_duplicates); + set_specific_buttons_as_active(shared_buttons, NotebookMainEnum::SimilarVideos, found_any_duplicates); set_buttons( - &mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SimilarVideos).unwrap(), + &mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SimilarVideos).expect("Failed to borrow buttons"), buttons_array, buttons_names, ); @@ -702,7 +705,7 @@ fn compute_similar_images( entry_info: &Entry, tree_view: &TreeView, text_view_errors: &TextView, - shared_state: &Rc>, + shared_state: &SharedState, shared_buttons: &Rc>>>, buttons_array: &[Widget; 9], buttons_names: &[BottomButtonsEnum; 9], @@ -814,12 +817,12 @@ fn compute_similar_images( // Set state { - *shared_state.borrow_mut() = sf; + *shared_state.borrow_mut() = Some(sf); - set_specific_buttons_as_active(shared_buttons, &NotebookMainEnum::SimilarImages, found_any_duplicates); + set_specific_buttons_as_active(shared_buttons, NotebookMainEnum::SimilarImages, found_any_duplicates); set_buttons( - &mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SimilarImages).unwrap(), + &mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SimilarImages).expect("Failed to borrow buttons"), buttons_array, buttons_names, ); @@ -833,7 +836,7 @@ fn compute_temporary_files( entry_info: &Entry, tree_view: &TreeView, text_view_errors: &TextView, - shared_state: &Rc>, + shared_state: &SharedState, shared_buttons: &Rc>>>, buttons_array: &[Widget; 9], buttons_names: &[BottomButtonsEnum; 9], @@ -866,7 +869,9 @@ fn compute_temporary_files( (ColumnsTemporaryFiles::Path as u32, &directory), ( ColumnsTemporaryFiles::Modification as u32, - &(NaiveDateTime::from_timestamp_opt(file_entry.modified_date as i64, 0).unwrap().to_string()), + &(DateTime::from_timestamp(file_entry.modified_date as i64, 0) + .expect("Modified date always should be in valid range") + .to_string()), ), (ColumnsTemporaryFiles::ModificationAsSecs as u32, &(file_entry.modified_date as i64)), ]; @@ -877,12 +882,12 @@ fn compute_temporary_files( // Set state { - *shared_state.borrow_mut() = tf; + *shared_state.borrow_mut() = Some(tf); - set_specific_buttons_as_active(shared_buttons, &NotebookMainEnum::Temporary, temporary_files_number > 0); + set_specific_buttons_as_active(shared_buttons, NotebookMainEnum::Temporary, temporary_files_number > 0); set_buttons( - &mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Temporary).unwrap(), + &mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Temporary).expect("Failed to borrow buttons"), buttons_array, buttons_names, ); @@ -896,7 +901,7 @@ fn compute_big_files( entry_info: &Entry, tree_view: &TreeView, text_view_errors: &TextView, - shared_state: &Rc>, + shared_state: &SharedState, shared_buttons: &Rc>>>, buttons_array: &[Widget; 9], buttons_names: &[BottomButtonsEnum; 9], @@ -927,7 +932,9 @@ fn compute_big_files( (ColumnsBigFiles::Path as u32, &directory), ( ColumnsBigFiles::Modification as u32, - &(NaiveDateTime::from_timestamp_opt(file_entry.modified_date as i64, 0).unwrap().to_string()), + &(DateTime::from_timestamp(file_entry.modified_date as i64, 0) + .expect("Modified date always should be in valid range") + .to_string()), ), (ColumnsBigFiles::ModificationAsSecs as u32, &(file_entry.modified_date as i64)), (ColumnsBigFiles::SizeAsBytes as u32, &(file_entry.size)), @@ -939,12 +946,12 @@ fn compute_big_files( // Set state { - *shared_state.borrow_mut() = bf; + *shared_state.borrow_mut() = Some(bf); - set_specific_buttons_as_active(shared_buttons, &NotebookMainEnum::BigFiles, biggest_files_number > 0); + set_specific_buttons_as_active(shared_buttons, NotebookMainEnum::BigFiles, biggest_files_number > 0); set_buttons( - &mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BigFiles).unwrap(), + &mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BigFiles).expect("Failed to borrow buttons"), buttons_array, buttons_names, ); @@ -958,7 +965,7 @@ fn compute_empty_files( entry_info: &Entry, tree_view: &TreeView, text_view_errors: &TextView, - shared_state: &Rc>, + shared_state: &SharedState, shared_buttons: &Rc>>>, buttons_array: &[Widget; 9], buttons_names: &[BottomButtonsEnum; 9], @@ -989,7 +996,9 @@ fn compute_empty_files( (ColumnsEmptyFiles::Path as u32, &directory), ( ColumnsEmptyFiles::Modification as u32, - &(NaiveDateTime::from_timestamp_opt(file_entry.modified_date as i64, 0).unwrap().to_string()), + &(DateTime::from_timestamp(file_entry.modified_date as i64, 0) + .expect("Modified date always should be in valid range") + .to_string()), ), (ColumnsEmptyFiles::ModificationAsSecs as u32, &(file_entry.modified_date as i64)), ]; @@ -1000,12 +1009,12 @@ fn compute_empty_files( // Set state { - *shared_state.borrow_mut() = vf; + *shared_state.borrow_mut() = Some(vf); - set_specific_buttons_as_active(shared_buttons, &NotebookMainEnum::EmptyFiles, empty_files_number > 0); + set_specific_buttons_as_active(shared_buttons, NotebookMainEnum::EmptyFiles, empty_files_number > 0); set_buttons( - &mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::EmptyFiles).unwrap(), + &mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::EmptyFiles).expect("Failed to borrow buttons"), buttons_array, buttons_names, ); @@ -1019,7 +1028,7 @@ fn compute_empty_folders( entry_info: &Entry, tree_view: &TreeView, text_view_errors: &TextView, - shared_state: &Rc>, + shared_state: &SharedState, shared_buttons: &Rc>>>, buttons_array: &[Widget; 9], buttons_names: &[BottomButtonsEnum; 9], @@ -1052,7 +1061,9 @@ fn compute_empty_folders( (ColumnsEmptyFolders::Path as u32, &directory), ( ColumnsEmptyFolders::Modification as u32, - &(NaiveDateTime::from_timestamp_opt(fe.modified_date as i64, 0).unwrap().to_string()), + &(DateTime::from_timestamp(fe.modified_date as i64, 0) + .expect("Modified date always should be in valid range") + .to_string()), ), (ColumnsEmptyFolders::ModificationAsSecs as u32, &(fe.modified_date)), ]; @@ -1063,12 +1074,12 @@ fn compute_empty_folders( // Set state { - *shared_state.borrow_mut() = ef; + *shared_state.borrow_mut() = Some(ef); - set_specific_buttons_as_active(shared_buttons, &NotebookMainEnum::EmptyDirectories, empty_folder_number > 0); + set_specific_buttons_as_active(shared_buttons, NotebookMainEnum::EmptyDirectories, empty_folder_number > 0); set_buttons( - &mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::EmptyDirectories).unwrap(), + &mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::EmptyDirectories).expect("Failed to borrow buttons"), buttons_array, buttons_names, ); @@ -1082,7 +1093,7 @@ fn compute_duplicate_finder( entry_info: &Entry, tree_view_duplicate_finder: &TreeView, text_view_errors: &TextView, - shared_state: &Rc>, + shared_state: &SharedState, shared_buttons: &Rc>>>, buttons_array: &[Widget; 9], buttons_names: &[BottomButtonsEnum; 9], @@ -1103,7 +1114,7 @@ fn compute_duplicate_finder( let duplicates_size: u64; let duplicates_group: usize; - match df.get_check_method() { + match df.get_params().check_method { CheckingMethod::Name => { duplicates_number = information.number_of_duplicated_files_by_name; duplicates_size = 0; @@ -1145,7 +1156,7 @@ fn compute_duplicate_finder( let list_store = get_list_store(tree_view_duplicate_finder); if df.get_use_reference() { - match df.get_check_method() { + match df.get_params().check_method { CheckingMethod::Name => { let btreemap = df.get_files_with_identical_name_referenced(); @@ -1204,7 +1215,7 @@ fn compute_duplicate_finder( _ => panic!(), } } else { - match df.get_check_method() { + match df.get_params().check_method { CheckingMethod::Name => { let btreemap = df.get_files_sorted_by_names(); @@ -1266,12 +1277,12 @@ fn compute_duplicate_finder( // Set state { - *shared_state.borrow_mut() = df; + *shared_state.borrow_mut() = Some(df); - set_specific_buttons_as_active(shared_buttons, &NotebookMainEnum::Duplicate, duplicates_number > 0); + set_specific_buttons_as_active(shared_buttons, NotebookMainEnum::Duplicate, duplicates_number > 0); set_buttons( - &mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Duplicate).unwrap(), + &mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::Duplicate).expect("Failed to borrow buttons"), buttons_array, buttons_names, ); @@ -1314,7 +1325,9 @@ fn duplicates_add_to_list_store(list_store: &ListStore, file: &str, directory: & string_date = String::new(); } else { size_str = format_size(size, BINARY); - string_date = NaiveDateTime::from_timestamp_opt(modified_date as i64, 0).unwrap().to_string(); + string_date = DateTime::from_timestamp(modified_date as i64, 0) + .expect("Modified date always should be in valid range") + .to_string(); }; let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [ @@ -1362,7 +1375,9 @@ fn similar_images_add_to_list_store( string_date = String::new(); } else { size_str = format_size(size, BINARY); - string_date = NaiveDateTime::from_timestamp_opt(modified_date as i64, 0).unwrap().to_string(); + string_date = DateTime::from_timestamp(modified_date as i64, 0) + .expect("Modified date always should be in valid range") + .to_string(); } let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [ @@ -1393,7 +1408,9 @@ fn similar_videos_add_to_list_store(list_store: &ListStore, file: &str, director string_date = String::new(); } else { size_str = format_size(size, BINARY); - string_date = NaiveDateTime::from_timestamp_opt(modified_date as i64, 0).unwrap().to_string(); + string_date = DateTime::from_timestamp(modified_date as i64, 0) + .expect("Modified date always should be in valid range") + .to_string(); }; let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [ @@ -1438,7 +1455,9 @@ fn same_music_add_to_list_store( string_date = String::new(); } else { size_str = format_size(size, BINARY); - string_date = NaiveDateTime::from_timestamp_opt(modified_date as i64, 0).unwrap().to_string(); + string_date = DateTime::from_timestamp(modified_date as i64, 0) + .expect("Modified date always should be in valid range") + .to_string(); }; let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [ @@ -1465,11 +1484,11 @@ fn same_music_add_to_list_store( list_store.set(&list_store.append(), &values); } -fn set_specific_buttons_as_active(buttons_array: &Rc>>>, notebook_enum: &NotebookMainEnum, value_to_set: bool) { +fn set_specific_buttons_as_active(buttons_array: &Rc>>>, notebook_enum: NotebookMainEnum, value_to_set: bool) { let mut b_mut = buttons_array.borrow_mut(); - let butt = b_mut.get_mut(notebook_enum).unwrap(); - let allowed_buttons = NOTEBOOKS_INFO[*notebook_enum as usize].bottom_buttons; + let butt = b_mut.get_mut(¬ebook_enum).expect("Failed to borrow buttons"); + let allowed_buttons = NOTEBOOKS_INFO[notebook_enum as usize].bottom_buttons; for i in allowed_buttons { - *butt.get_mut(i).unwrap() = value_to_set; + *butt.get_mut(i).expect("Failed to borrow buttons") = value_to_set; } } diff --git a/czkawka_gui/src/connect_things/connect_button_compare.rs b/czkawka_gui/src/connect_things/connect_button_compare.rs index 679d74fea..4b0e4f8b0 100644 --- a/czkawka_gui/src/connect_things/connect_button_compare.rs +++ b/czkawka_gui/src/connect_things/connect_button_compare.rs @@ -47,19 +47,19 @@ pub fn connect_button_compare(gui_data: &GuiData) { window_compare.set_default_size(700, 700); button_compare.connect_clicked(move |_| { - let nb_number = notebook_main.current_page().unwrap(); + let nb_number = notebook_main.current_page().expect("Current page not set"); let tree_view = &main_tree_views[nb_number as usize]; let nb_object = &NOTEBOOKS_INFO[nb_number as usize]; - let model = tree_view.model().unwrap(); + let model = tree_view.model().expect("Missing tree_view model"); - let group_number = count_number_of_groups(tree_view, nb_object.column_header.unwrap()); + let group_number = count_number_of_groups(tree_view, nb_object.column_header.expect("Missing column_header")); if group_number == 0 { return; } // Check selected items - let (current_group, tree_path) = get_current_group_and_iter_from_selection(&model, &tree_view.selection(), nb_object.column_header.unwrap()); + let (current_group, tree_path) = get_current_group_and_iter_from_selection(&model, &tree_view.selection(), nb_object.column_header.expect("Missing column_header")); *shared_current_of_groups.borrow_mut() = current_group; *shared_numbers_of_groups.borrow_mut() = group_number; @@ -126,17 +126,22 @@ pub fn connect_button_compare(gui_data: &GuiData) { let image_compare_right = gui_data.compare_images.image_compare_right.clone(); button_go_previous_compare_group.connect_clicked(move |button_go_previous_compare_group| { - let nb_number = notebook_main.current_page().unwrap(); + let nb_number = notebook_main.current_page().expect("Current page not set"); let tree_view = &main_tree_views[nb_number as usize]; let nb_object = &NOTEBOOKS_INFO[nb_number as usize]; - let model = tree_view.model().unwrap(); + let model = tree_view.model().expect("Missing tree_view model"); *shared_current_of_groups.borrow_mut() -= 1; let current_group = *shared_current_of_groups.borrow(); let group_number = *shared_numbers_of_groups.borrow(); - let tree_path = move_iter(&model, shared_current_path.borrow().as_ref().unwrap(), nb_object.column_header.unwrap(), false); + let tree_path = move_iter( + &model, + shared_current_path.borrow().as_ref().expect("Missing current path"), + nb_object.column_header.expect("Missing column_header"), + false, + ); populate_groups_at_start( nb_object, @@ -178,17 +183,22 @@ pub fn connect_button_compare(gui_data: &GuiData) { let image_compare_right = gui_data.compare_images.image_compare_right.clone(); button_go_next_compare_group.connect_clicked(move |button_go_next_compare_group| { - let nb_number = notebook_main.current_page().unwrap(); + let nb_number = notebook_main.current_page().expect("Current page not set"); let tree_view = &main_tree_views[nb_number as usize]; let nb_object = &NOTEBOOKS_INFO[nb_number as usize]; - let model = tree_view.model().unwrap(); + let model = tree_view.model().expect("Missing tree_view model"); *shared_current_of_groups.borrow_mut() += 1; let current_group = *shared_current_of_groups.borrow(); let group_number = *shared_numbers_of_groups.borrow(); - let tree_path = move_iter(&model, shared_current_path.borrow().as_ref().unwrap(), nb_object.column_header.unwrap(), true); + let tree_path = move_iter( + &model, + shared_current_path.borrow().as_ref().expect("Missing current path"), + nb_object.column_header.expect("Missing column_header"), + true, + ); populate_groups_at_start( nb_object, @@ -216,20 +226,28 @@ pub fn connect_button_compare(gui_data: &GuiData) { let shared_current_path = gui_data.compare_images.shared_current_path.clone(); let main_tree_views = gui_data.main_notebook.get_main_tree_views(); check_button_left_preview_text.connect_toggled(move |check_button_left_preview_text| { - let nb_number = notebook_main.current_page().unwrap(); + let nb_number = notebook_main.current_page().expect("Current page not set"); let tree_view = &main_tree_views[nb_number as usize]; let nb_object = &NOTEBOOKS_INFO[nb_number as usize]; - let model = tree_view.model().unwrap().downcast::().unwrap(); - - let main_tree_path = shared_current_path.borrow().as_ref().unwrap().clone(); - let this_tree_path = shared_using_for_preview.borrow().0.clone().unwrap(); + let model = tree_view + .model() + .expect("Missing tree_view model") + .downcast::() + .expect("Failed to downcast to ListStore"); + + let main_tree_path = shared_current_path.borrow().as_ref().expect("Missing current path").clone(); + let this_tree_path = shared_using_for_preview.borrow().0.clone().expect("Missing left preview path"); if main_tree_path == this_tree_path { return; // Selected header, so we don't need to select result in treeview // TODO this should be handled by disabling entirely check box } let is_active = check_button_left_preview_text.is_active(); - model.set_value(&model.iter(&this_tree_path).unwrap(), nb_object.column_selection as u32, &is_active.to_value()); + model.set_value( + &model.iter(&this_tree_path).expect("Using invalid tree_path"), + nb_object.column_selection as u32, + &is_active.to_value(), + ); }); let check_button_right_preview_text = gui_data.compare_images.check_button_right_preview_text.clone(); @@ -239,20 +257,28 @@ pub fn connect_button_compare(gui_data: &GuiData) { let main_tree_views = gui_data.main_notebook.get_main_tree_views(); check_button_right_preview_text.connect_toggled(move |check_button_right_preview_text| { - let nb_number = notebook_main.current_page().unwrap(); + let nb_number = notebook_main.current_page().expect("Current page not set"); let tree_view = &main_tree_views[nb_number as usize]; let nb_object = &NOTEBOOKS_INFO[nb_number as usize]; - let model = tree_view.model().unwrap().downcast::().unwrap(); - - let main_tree_path = shared_current_path.borrow().as_ref().unwrap().clone(); - let this_tree_path = shared_using_for_preview.borrow().1.clone().unwrap(); + let model = tree_view + .model() + .expect("Missing tree_view model") + .downcast::() + .expect("Failed to downcast to ListStore"); + + let main_tree_path = shared_current_path.borrow().as_ref().expect("Missing current path").clone(); + let this_tree_path = shared_using_for_preview.borrow().1.clone().expect("Missing right preview path"); if main_tree_path == this_tree_path { return; // Selected header, so we don't need to select result in treeview // TODO this should be handled by disabling entirely check box } let is_active = check_button_right_preview_text.is_active(); - model.set_value(&model.iter(&this_tree_path).unwrap(), nb_object.column_selection as u32, &is_active.to_value()); + model.set_value( + &model.iter(&this_tree_path).expect("Using invalid tree_path"), + nb_object.column_selection as u32, + &is_active.to_value(), + ); }); } @@ -285,7 +311,13 @@ fn populate_groups_at_start( button_go_next_compare_group.set_sensitive(true); } - let all_vec = get_all_path(model, &tree_path, nb_object.column_header.unwrap(), nb_object.column_path, nb_object.column_name); + let all_vec = get_all_path( + model, + &tree_path, + nb_object.column_header.expect("Missing column_header"), + nb_object.column_path, + nb_object.column_name, + ); *shared_current_path.borrow_mut() = Some(tree_path); let cache_all_images = generate_cache_for_results(all_vec); @@ -325,9 +357,15 @@ fn populate_groups_at_start( *shared_image_cache.borrow_mut() = cache_all_images.clone(); let mut found = false; - for i in get_all_direct_children(&scrolled_window_compare_choose_images.child().unwrap().downcast::().unwrap()) { + for i in get_all_direct_children( + &scrolled_window_compare_choose_images + .child() + .expect("Failed to get child of scrolled_window_compare_choose_images") + .downcast::() + .expect("Failed to downcast to Viewport"), + ) { if i.widget_name() == "all_box" { - let gtk_box = i.downcast::().unwrap(); + let gtk_box = i.downcast::().expect("Failed to downcast to Box"); update_bottom_buttons(>k_box, shared_using_for_preview, shared_image_cache); found = true; break; @@ -335,9 +373,9 @@ fn populate_groups_at_start( } assert!(found); - let is_active = model.get::(&model.iter(&cache_all_images[0].4).unwrap(), nb_object.column_selection); + let is_active = model.get::(&model.iter(&cache_all_images[0].4).expect("Using invalid tree_path"), nb_object.column_selection); check_button_left_preview_text.set_active(is_active); - let is_active = model.get::(&model.iter(&cache_all_images[1].4).unwrap(), nb_object.column_selection); + let is_active = model.get::(&model.iter(&cache_all_images[1].4).expect("Using invalid tree_path"), nb_object.column_selection); check_button_right_preview_text.set_active(is_active); } @@ -349,7 +387,7 @@ fn generate_cache_for_results(vector_with_path: Vec<(String, String, TreePath)>) let small_img = Image::new(); let big_img = Image::new(); - let mut pixbuf = get_pixbuf_from_dynamic_image(&DynamicImage::new_rgb8(1, 1)).unwrap(); + let mut pixbuf = get_pixbuf_from_dynamic_image(&DynamicImage::new_rgb8(1, 1)).expect("Failed to create pixbuf"); let extension_lowercase = full_path.split('.').last().map(str::to_lowercase); let is_heic = match extension_lowercase { Some(extension) => HEIC_EXTENSIONS.iter().any(|e| e == &extension), @@ -413,7 +451,7 @@ fn generate_cache_for_results(vector_with_path: Vec<(String, String, TreePath)>) } fn get_all_path(model: &TreeModel, current_path: &TreePath, column_header: i32, column_path: i32, column_name: i32) -> Vec<(String, String, TreePath)> { - let used_iter = model.iter(current_path).unwrap(); + let used_iter = model.iter(current_path).expect("Using invalid tree_path"); assert!(model.get::(&used_iter, column_header)); let using_reference = !model.get::(&used_iter, column_path).is_empty(); @@ -454,7 +492,7 @@ fn get_all_path(model: &TreeModel, current_path: &TreePath, column_header: i32, } fn move_iter(model: &TreeModel, tree_path: &TreePath, column_header: i32, go_next: bool) -> TreePath { - let tree_iter = model.iter(tree_path).unwrap(); + let tree_iter = model.iter(tree_path).expect("Using invalid tree_path"); assert!(model.get::(&tree_iter, column_header)); @@ -507,7 +545,7 @@ fn populate_similar_scrolled_view( let smaller_box = gtk4::Box::new(Orientation::Horizontal, 2); let button_left = gtk4::Button::builder().label(&flg!("compare_move_left_button")).build(); - let label = gtk4::Label::builder().label(&(number + 1).to_string()).build(); + let label = gtk4::Label::builder().label((number + 1).to_string()).build(); let button_right = gtk4::Button::builder().label(&flg!("compare_move_right_button")).build(); let image_compare_left = image_compare_left.clone(); @@ -527,7 +565,7 @@ fn populate_similar_scrolled_view( update_bottom_buttons(&all_gtk_box_clone, &shared_using_for_preview_clone, &shared_image_cache_clone); image_compare_left.set_paintable(big_thumbnail_clone.paintable().as_ref()); - let is_active = model_clone.get::(&model_clone.iter(&tree_path_clone).unwrap(), column_selection); + let is_active = model_clone.get::(&model_clone.iter(&tree_path_clone).expect("Invalid tree_path"), column_selection); check_button_left_preview_text_clone.set_active(is_active); check_button_left_preview_text_clone.set_label(Some(&format!("{}. {}", number + 1, get_max_file_name(&path_clone, 60)))); }); @@ -546,7 +584,7 @@ fn populate_similar_scrolled_view( update_bottom_buttons(&all_gtk_box_clone, &shared_using_for_preview_clone, &shared_image_cache_clone); image_compare_right.set_paintable(big_thumbnail_clone.paintable().as_ref()); - let is_active = model_clone.get::(&model_clone.iter(&tree_path_clone).unwrap(), column_selection); + let is_active = model_clone.get::(&model_clone.iter(&tree_path_clone).expect("Invalid tree_path"), column_selection); check_button_right_preview_text_clone.set_active(is_active); check_button_right_preview_text_clone.set_label(Some(&format!("{}. {}", number + 1, get_max_file_name(&path_clone, 60)))); }); @@ -581,15 +619,15 @@ fn update_bottom_buttons( shared_using_for_preview: &Rc, Option)>>, image_cache: &Rc>>, ) { - let left_tree_view = (shared_using_for_preview.borrow()).0.clone().unwrap(); - let right_tree_view = (shared_using_for_preview.borrow()).1.clone().unwrap(); + let left_tree_view = (shared_using_for_preview.borrow()).0.clone().expect("Left tree_view not set"); + let right_tree_view = (shared_using_for_preview.borrow()).1.clone().expect("Right tree_view not set"); for (number, i) in get_all_direct_children(all_gtk_box).into_iter().enumerate() { let cache_tree_path = (*image_cache.borrow())[number].4.clone(); let is_chosen = cache_tree_path != right_tree_view && cache_tree_path != left_tree_view; - let bx = i.downcast::().unwrap(); - let smaller_bx = bx.first_child().unwrap().downcast::().unwrap(); + let bx = i.downcast::().expect("Not Box"); + let smaller_bx = bx.first_child().expect("No first child").downcast::().expect("First child is not Box"); for items in get_all_direct_children(&smaller_bx) { if let Ok(btn) = items.downcast::() { btn.set_sensitive(is_chosen); @@ -606,7 +644,7 @@ fn get_current_group_and_iter_from_selection(model: &TreeModel, selection: &Tree let selected_records = selection.selected_rows().0; - let iter = model.iter_first().unwrap(); // Checking that treeview is not empty should be done before + let iter = model.iter_first().expect("Model is no empty, so should have first item"); // Checking that treeview is not empty should be done before header_clone = iter; // if nothing selected, use first group possible_header = iter; // if nothing selected, use first group assert!(model.get::(&iter, column_header)); // First element should be header diff --git a/czkawka_gui/src/connect_things/connect_button_delete.rs b/czkawka_gui/src/connect_things/connect_button_delete.rs index 22ac25a77..1c8a01992 100644 --- a/czkawka_gui/src/connect_things/connect_button_delete.rs +++ b/czkawka_gui/src/connect_things/connect_button_delete.rs @@ -16,7 +16,7 @@ use crate::notebook_info::NOTEBOOKS_INFO; pub fn connect_button_delete(gui_data: &GuiData) { let buttons_delete = gui_data.bottom_buttons.buttons_delete.clone(); - let gui_data = gui_data.clone(); // TODO this maybe can be replaced, not sure if worth to do it + let gui_data = gui_data.clone(); // TODO this maybe can be replaced, not sure if worth to clone everything buttons_delete.connect_clicked(move |_| { glib::MainContext::default().spawn_local(delete_things(gui_data.clone())); @@ -41,7 +41,7 @@ pub async fn delete_things(gui_data: GuiData) { let text_view_errors = gui_data.text_view_errors.clone(); - let nb_number = notebook_main.current_page().unwrap(); + let nb_number = notebook_main.current_page().expect("Current page not set"); let tree_view = &main_tree_views[nb_number as usize]; let nb_object = &NOTEBOOKS_INFO[nb_number as usize]; @@ -164,7 +164,7 @@ fn create_dialog_ask_for_deletion(window_main: >k4::Window, number_of_selected button_ok.grab_focus(); - let parent = button_ok.parent().unwrap().parent().unwrap().downcast::().unwrap(); // TODO Hack, but not so ugly as before + let parent = button_ok.parent().expect("Hack 1").parent().expect("Hack 2").downcast::().expect("Hack 3"); // TODO Hack, but not so ugly as before parent.set_orientation(Orientation::Vertical); parent.insert_child_after(&label, None::<>k4::Widget>); parent.insert_child_after(&label2, Some(&label)); @@ -189,7 +189,7 @@ fn create_dialog_group_deletion(window_main: >k4::Window) -> (Dialog, CheckBut button_ok.grab_focus(); - let parent = button_ok.parent().unwrap().parent().unwrap().downcast::().unwrap(); // TODO Hack, but not so ugly as before + let parent = button_ok.parent().expect("Hack 1").parent().expect("Hack 2").downcast::().expect("Hack 3"); // TODO Hack, but not so ugly as before parent.set_orientation(Orientation::Vertical); parent.insert_child_after(&label, None::<>k4::Widget>); parent.insert_child_after(&label2, Some(&label)); @@ -294,7 +294,7 @@ pub fn empty_folder_remover( // Must be deleted from end to start, because when deleting entries, TreePath(and also TreeIter) will points to invalid data for tree_path in selected_rows.iter().rev() { - let iter = model.iter(tree_path).unwrap(); + let iter = model.iter(tree_path).expect("Using invalid tree_path"); let name = model.get::(&iter, column_file_name); let path = model.get::(&iter, column_path); @@ -302,10 +302,8 @@ pub fn empty_folder_remover( // We must check if folder is really empty or contains only other empty folders let mut error_happened = false; let mut folders_to_check: Vec = vec![get_full_name_from_path_name(&path, &name)]; - let mut current_folder: String; let mut next_folder: String; - 'dir: while !folders_to_check.is_empty() { - current_folder = folders_to_check.pop().unwrap(); + 'dir: while let Some(current_folder) = folders_to_check.pop() { let read_dir = match fs::read_dir(¤t_folder) { Ok(t) => t, Err(_inspected) => { @@ -407,7 +405,7 @@ pub fn basic_remove( // Must be deleted from end to start, because when deleting entries, TreePath(and also TreeIter) will points to invalid data for tree_path in selected_rows.iter().rev() { - let iter = model.iter(tree_path).unwrap(); + let iter = model.iter(tree_path).expect("Using invalid tree_path"); let name = model.get::(&iter, column_file_name); let path = model.get::(&iter, column_path); @@ -482,7 +480,7 @@ pub fn tree_remove( // Save to variable paths of files, and remove it when not removing all occurrences. for tree_path in selected_rows.iter().rev() { - let iter = model.iter(tree_path).unwrap(); + let iter = model.iter(tree_path).expect("Using invalid tree_path"); let file_name = model.get::(&iter, column_file_name); let path = model.get::(&iter, column_path); diff --git a/czkawka_gui/src/connect_things/connect_button_hardlink.rs b/czkawka_gui/src/connect_things/connect_button_hardlink.rs index 4adaf9e4d..12007e5ad 100644 --- a/czkawka_gui/src/connect_things/connect_button_hardlink.rs +++ b/czkawka_gui/src/connect_things/connect_button_hardlink.rs @@ -59,7 +59,7 @@ async fn sym_hard_link_things(gui_data: GuiData, hardlinking: TypeOfTool) { let preview_path = gui_data.preview_path.clone(); let window_main = gui_data.window_main.clone(); - let nb_number = notebook_main.current_page().unwrap(); + let nb_number = notebook_main.current_page().expect("Current page not set"); let tree_view = &main_tree_views[nb_number as usize]; let nb_object = &NOTEBOOKS_INFO[nb_number as usize]; @@ -85,7 +85,7 @@ async fn sym_hard_link_things(gui_data: GuiData, hardlinking: TypeOfTool) { nb_object.column_path, column_header, nb_object.column_selection, - &hardlinking, + hardlinking, &text_view_errors, ); @@ -108,7 +108,7 @@ fn hardlink_symlink( column_path: i32, column_header: i32, column_selection: i32, - hardlinking: &TypeOfTool, + hardlinking: TypeOfTool, text_view_errors: &TextView, ) { reset_text_view(text_view_errors); @@ -163,11 +163,10 @@ fn hardlink_symlink( let path = model.get::(¤t_iter, column_path); let full_file_path = get_full_name_from_path_name(&path, &file_name); - if current_symhardlink_data.is_some() { + if let Some(mut current_data) = current_symhardlink_data { vec_tree_path_to_remove.push(model.path(¤t_iter)); - let mut temp_data = current_symhardlink_data.unwrap(); - temp_data.files_to_symhardlink.push(full_file_path); - current_symhardlink_data = Some(temp_data); + current_data.files_to_symhardlink.push(full_file_path); + current_symhardlink_data = Some(current_data); } else { current_symhardlink_data = Some(SymHardlinkData { original_data: full_file_path, @@ -197,7 +196,7 @@ fn hardlink_symlink( break; } } - if hardlinking == &TypeOfTool::Hardlinking { + if hardlinking == TypeOfTool::Hardlinking { for symhardlink_data in vec_symhardlink_data { for file_to_hardlink in symhardlink_data.files_to_symhardlink { if let Err(e) = make_hard_link(&PathBuf::from(&symhardlink_data.original_data), &PathBuf::from(&file_to_hardlink)) { @@ -232,7 +231,7 @@ fn hardlink_symlink( } } for tree_path in vec_tree_path_to_remove.iter().rev() { - model.remove(&model.iter(tree_path).unwrap()); + model.remove(&model.iter(tree_path).expect("Using invalid tree_path")); } clean_invalid_headers(&model, column_header, column_path); @@ -253,7 +252,7 @@ fn create_dialog_non_group(window_main: >k4::Window) -> Dialog { button_ok.grab_focus(); - let parent = button_ok.parent().unwrap().parent().unwrap().downcast::().unwrap(); // TODO Hack, but not so ugly as before + let parent = button_ok.parent().expect("Hack 1").parent().expect("Hack 2").downcast::().expect("Hack 3"); // TODO Hack, but not so ugly as before parent.set_orientation(Orientation::Vertical); parent.insert_child_after(&label, None::<>k4::Widget>); parent.insert_child_after(&label2, Some(&label)); @@ -357,7 +356,7 @@ fn create_dialog_ask_for_linking(window_main: >k4::Window) -> (Dialog, CheckBu button_ok.grab_focus(); - let parent = button_ok.parent().unwrap().parent().unwrap().downcast::().unwrap(); // TODO Hack, but not so ugly as before + let parent = button_ok.parent().expect("Hack 1").parent().expect("Hack 2").downcast::().expect("Hack 3"); // TODO Hack, but not so ugly as before parent.set_orientation(Orientation::Vertical); parent.insert_child_after(&label, None::<>k4::Widget>); parent.insert_child_after(&check_button, Some(&label)); diff --git a/czkawka_gui/src/connect_things/connect_button_move.rs b/czkawka_gui/src/connect_things/connect_button_move.rs index 334663899..14e632fab 100644 --- a/czkawka_gui/src/connect_things/connect_button_move.rs +++ b/czkawka_gui/src/connect_things/connect_button_move.rs @@ -26,7 +26,7 @@ pub fn connect_button_move(gui_data: &GuiData) { let file_dialog_move_to_folder = gui_data.file_dialog_move_to_folder.clone(); file_dialog_move_to_folder.connect_response(move |file_chooser, response_type| { - let nb_number = notebook_main.current_page().unwrap(); + let nb_number = notebook_main.current_page().expect("Current page not set"); let tree_view = &main_tree_views[nb_number as usize]; let nb_object = &NOTEBOOKS_INFO[nb_number as usize]; @@ -45,7 +45,7 @@ pub fn connect_button_move(gui_data: &GuiData) { for index in 0..g_files.n_items() { let file = &g_files.item(index); if let Some(file) = file { - let ss = file.clone().downcast::().unwrap(); + let ss = file.clone().downcast::().expect("Failed to downcast to gio::File"); if let Some(path_buf) = ss.path() { folders.push(path_buf); } @@ -184,7 +184,7 @@ fn move_files_common( // Save to variable paths of files, and remove it when not removing all occurrences. 'next_result: for tree_path in selected_rows.iter().rev() { - let iter = model.iter(tree_path).unwrap(); + let iter = model.iter(tree_path).expect("Using invalid tree_path"); let file_name = model.get::(&iter, column_file_name); let path = model.get::(&iter, column_path); diff --git a/czkawka_gui/src/connect_things/connect_button_save.rs b/czkawka_gui/src/connect_things/connect_button_save.rs index 75b1f7ed6..7fbc7b961 100644 --- a/czkawka_gui/src/connect_things/connect_button_save.rs +++ b/czkawka_gui/src/connect_things/connect_button_save.rs @@ -31,18 +31,18 @@ pub fn connect_button_save(gui_data: &GuiData) { let entry_info = gui_data.entry_info.clone(); let notebook_main = gui_data.main_notebook.notebook_main.clone(); buttons_save.connect_clicked(move |_| { - let result = match to_notebook_main_enum(notebook_main.current_page().unwrap()) { - NotebookMainEnum::Duplicate => shared_duplication_state.borrow().save_all_in_one("results_duplicates"), - NotebookMainEnum::EmptyDirectories => shared_empty_folders_state.borrow().save_all_in_one("results_empty_directories"), - NotebookMainEnum::EmptyFiles => shared_empty_files_state.borrow().save_all_in_one("results_empty_files"), - NotebookMainEnum::Temporary => shared_temporary_files_state.borrow().save_all_in_one("results_temporary_files"), - NotebookMainEnum::BigFiles => shared_big_files_state.borrow().save_all_in_one("results_big_files"), - NotebookMainEnum::SimilarImages => shared_similar_images_state.borrow().save_all_in_one("results_similar_images"), - NotebookMainEnum::SimilarVideos => shared_similar_videos_state.borrow().save_all_in_one("results_similar_videos"), - NotebookMainEnum::SameMusic => shared_same_music_state.borrow().save_all_in_one("results_same_music"), - NotebookMainEnum::Symlinks => shared_same_invalid_symlinks.borrow().save_all_in_one("results_invalid_symlinks"), - NotebookMainEnum::BrokenFiles => shared_broken_files_state.borrow().save_all_in_one("results_broken_files"), - NotebookMainEnum::BadExtensions => shared_bad_extensions_state.borrow().save_all_in_one("results_bad_extensions"), + let result = match to_notebook_main_enum(notebook_main.current_page().expect("Current page not set")) { + NotebookMainEnum::Duplicate => shared_duplication_state.borrow().as_ref().map(|x| x.save_all_in_one("results_duplicates")), + NotebookMainEnum::EmptyDirectories => shared_empty_folders_state.borrow().as_ref().map(|x| x.save_all_in_one("results_empty_directories")), + NotebookMainEnum::EmptyFiles => shared_empty_files_state.borrow().as_ref().map(|x| x.save_all_in_one("results_empty_files")), + NotebookMainEnum::Temporary => shared_temporary_files_state.borrow().as_ref().map(|x| x.save_all_in_one("results_temporary_files")), + NotebookMainEnum::BigFiles => shared_big_files_state.borrow().as_ref().map(|x| x.save_all_in_one("results_big_files")), + NotebookMainEnum::SimilarImages => shared_similar_images_state.borrow().as_ref().map(|x| x.save_all_in_one("results_similar_images")), + NotebookMainEnum::SimilarVideos => shared_similar_videos_state.borrow().as_ref().map(|x| x.save_all_in_one("results_similar_videos")), + NotebookMainEnum::SameMusic => shared_same_music_state.borrow().as_ref().map(|x| x.save_all_in_one("results_same_music")), + NotebookMainEnum::Symlinks => shared_same_invalid_symlinks.borrow().as_ref().map(|x| x.save_all_in_one("results_invalid_symlinks")), + NotebookMainEnum::BrokenFiles => shared_broken_files_state.borrow().as_ref().map(|x| x.save_all_in_one("results_broken_files")), + NotebookMainEnum::BadExtensions => shared_bad_extensions_state.borrow().as_ref().map(|x| x.save_all_in_one("results_bad_extensions")), }; let current_path = match env::current_dir() { @@ -50,7 +50,7 @@ pub fn connect_button_save(gui_data: &GuiData) { Err(_) => "".to_string(), }; - match result { + match result.expect("Tried to save results, without running scan(bug which needs to be fixed)") { Ok(()) => (), Err(e) => { entry_info.set_text(&format!("Failed to save results to folder {current_path}, reason {e}")); @@ -59,7 +59,7 @@ pub fn connect_button_save(gui_data: &GuiData) { } post_save_things( - &to_notebook_main_enum(notebook_main.current_page().unwrap()), + to_notebook_main_enum(notebook_main.current_page().expect("Current page not set")), &shared_buttons, &entry_info, &buttons_save_clone, @@ -69,7 +69,7 @@ pub fn connect_button_save(gui_data: &GuiData) { } fn post_save_things( - type_of_tab: &NotebookMainEnum, + type_of_tab: NotebookMainEnum, shared_buttons: &Rc>>>, entry_info: &Entry, buttons_save: &Button, @@ -79,6 +79,11 @@ fn post_save_things( // Set state { buttons_save.hide(); - *shared_buttons.borrow_mut().get_mut(type_of_tab).unwrap().get_mut(&BottomButtonsEnum::Save).unwrap() = false; + *shared_buttons + .borrow_mut() + .get_mut(&type_of_tab) + .expect("Failed to get current tab") + .get_mut(&BottomButtonsEnum::Save) + .expect("Failed to get save button") = false; } } diff --git a/czkawka_gui/src/connect_things/connect_button_search.rs b/czkawka_gui/src/connect_things/connect_button_search.rs index 4108d74ab..ef30c445f 100644 --- a/czkawka_gui/src/connect_things/connect_button_search.rs +++ b/czkawka_gui/src/connect_things/connect_button_search.rs @@ -8,19 +8,20 @@ use fun_time::fun_time; use gtk4::prelude::*; use gtk4::Grid; -use czkawka_core::bad_extensions::BadExtensions; -use czkawka_core::big_file::BigFile; -use czkawka_core::broken_files::{BrokenFiles, CheckedTypes}; +use czkawka_core::bad_extensions::{BadExtensions, BadExtensionsParameters}; +use czkawka_core::big_file::{BigFile, BigFileParameters}; +use czkawka_core::broken_files::{BrokenFiles, BrokenFilesParameters, CheckedTypes}; use czkawka_core::common::DEFAULT_THREAD_SIZE; -use czkawka_core::common_dir_traversal::{CheckingMethod, ProgressData}; +use czkawka_core::common_dir_traversal::CheckingMethod; use czkawka_core::common_tool::CommonData; -use czkawka_core::duplicate::DuplicateFinder; +use czkawka_core::duplicate::{DuplicateFinder, DuplicateFinderParameters}; use czkawka_core::empty_files::EmptyFiles; use czkawka_core::empty_folder::EmptyFolder; use czkawka_core::invalid_symlinks::InvalidSymlinks; -use czkawka_core::same_music::{MusicSimilarity, SameMusic}; -use czkawka_core::similar_images::SimilarImages; -use czkawka_core::similar_videos::SimilarVideos; +use czkawka_core::progress_data::ProgressData; +use czkawka_core::same_music::{MusicSimilarity, SameMusic, SameMusicParameters}; +use czkawka_core::similar_images::{SimilarImages, SimilarImagesParameters}; +use czkawka_core::similar_videos::{SimilarVideos, SimilarVideosParameters}; use czkawka_core::temporary::Temporary; use crate::gui_structs::gui_data::GuiData; @@ -91,7 +92,7 @@ pub fn connect_button_search(gui_data: &GuiData, result_sender: Sender, let progress_sender = progress_sender.clone(); - match to_notebook_main_enum(notebook_main.current_page().unwrap()) { + match to_notebook_main_enum(notebook_main.current_page().expect("Current page not set")) { NotebookMainEnum::Duplicate => duplicate_search(&gui_data, loaded_commons, stop_receiver, result_sender, &grid_progress, progress_sender), NotebookMainEnum::EmptyFiles => empty_files_search(&gui_data, loaded_commons, stop_receiver, result_sender, &grid_progress, progress_sender), NotebookMainEnum::EmptyDirectories => empty_dirs_search(&gui_data, loaded_commons, stop_receiver, result_sender, &grid_progress, progress_sender), @@ -157,13 +158,7 @@ impl LoadedCommonItems { Some(ColumnsIncludedDirectory::ReferenceButton as i32), )); let recursive_search = check_button_recursive.is_active(); - let excluded_items = entry_excluded_items - .text() - .as_str() - .to_string() - .split(',') - .map(ToString::to_string) - .collect::>(); + let excluded_items = entry_excluded_items.text().as_str().split(',').map(ToString::to_string).collect::>(); let allowed_extensions = entry_allowed_extensions.text().as_str().to_string(); let excluded_extensions = entry_excluded_extensions.text().as_str().to_string(); let hide_hard_links = check_button_settings_hide_hard_links.is_active(); @@ -173,18 +168,18 @@ impl LoadedCommonItems { .text() .as_str() .parse::() - .unwrap_or_else(|_| DEFAULT_MINIMAL_CACHE_SIZE.parse::().unwrap()); + .unwrap_or_else(|_| DEFAULT_MINIMAL_CACHE_SIZE.parse::().expect("Failed to parse minimal_cache_file_size")); let minimal_file_size = entry_general_minimal_size .text() .as_str() .parse::() - .unwrap_or_else(|_| DEFAULT_MINIMAL_FILE_SIZE.parse::().unwrap()); + .unwrap_or_else(|_| DEFAULT_MINIMAL_FILE_SIZE.parse::().expect("Failed to parse minimal_file_size")); let maximal_file_size = entry_general_maximal_size .text() .as_str() .parse::() - .unwrap_or_else(|_| DEFAULT_MAXIMAL_FILE_SIZE.parse::().unwrap()); + .unwrap_or_else(|_| DEFAULT_MAXIMAL_FILE_SIZE.parse::().expect("Failed to parse maximal_file_size")); let ignore_other_filesystems = check_button_settings_one_filesystem.is_active(); LoadedCommonItems { @@ -228,10 +223,10 @@ fn duplicate_search( image_preview_duplicates.hide(); clean_tree_view(&tree_view_duplicate_finder); - let check_method_index = combo_box_duplicate_check_method.active().unwrap() as usize; + let check_method_index = combo_box_duplicate_check_method.active().expect("Failed to get active item") as usize; let check_method = DUPLICATES_CHECK_METHOD_COMBO_BOX[check_method_index].check_method; - let hash_type_index = combo_box_duplicate_hash_type.active().unwrap() as usize; + let hash_type_index = combo_box_duplicate_hash_type.active().expect("Failed to get active item") as usize; let hash_type = DUPLICATES_HASH_TYPE_COMBO_BOX[hash_type_index].hash_type; let use_prehash_cache = check_button_duplicates_use_prehash_cache.is_active(); @@ -245,21 +240,23 @@ fn duplicate_search( thread::Builder::new() .stack_size(DEFAULT_THREAD_SIZE) .spawn(move || { - let mut item = DuplicateFinder::new(); + let params = DuplicateFinderParameters::new( + check_method, + hash_type, + loaded_commons.hide_hard_links, + use_prehash_cache, + loaded_commons.minimal_cache_file_size, + minimal_prehash_cache_file_size, + case_sensitive_name_comparison, + ); + let mut item = DuplicateFinder::new(params); set_common_settings(&mut item, &loaded_commons); - item.set_minimal_cache_file_size(loaded_commons.minimal_cache_file_size); - item.set_minimal_prehash_cache_file_size(minimal_prehash_cache_file_size); - item.set_check_method(check_method); - item.set_hash_type(hash_type); - item.set_ignore_hard_links(loaded_commons.hide_hard_links); - item.set_use_prehash_cache(use_prehash_cache); item.set_delete_outdated_cache(delete_outdated_cache); - item.set_case_sensitive_name_comparison(case_sensitive_name_comparison); item.find_duplicates(Some(&stop_receiver), Some(&progress_data_sender)); - result_sender.send(Message::Duplicates(item)).unwrap(); + result_sender.send(Message::Duplicates(item)).expect("Failed to send Duplicates message"); }) - .unwrap(); + .expect("Failed to spawn DuplicateFinder thread"); } fn empty_files_search( @@ -282,9 +279,9 @@ fn empty_files_search( set_common_settings(&mut item, &loaded_commons); item.find_empty_files(Some(&stop_receiver), Some(&progress_data_sender)); - result_sender.send(Message::EmptyFiles(item)).unwrap(); + result_sender.send(Message::EmptyFiles(item)).expect("Failed to send EmptyFiles message"); }) - .unwrap(); + .expect("Failed to spawn EmptyFiles thread"); } fn empty_dirs_search( @@ -307,9 +304,9 @@ fn empty_dirs_search( set_common_settings(&mut item, &loaded_commons); item.find_empty_folders(Some(&stop_receiver), Some(&progress_data_sender)); - result_sender.send(Message::EmptyFolders(item)).unwrap(); + result_sender.send(Message::EmptyFolders(item)).expect("Failed to send EmptyFolders message"); }) - .unwrap(); + .expect("Failed to spawn EmptyFolders thread"); } fn big_files_search( @@ -327,7 +324,7 @@ fn big_files_search( let tree_view_big_files_finder = gui_data.main_notebook.tree_view_big_files_finder.clone(); clean_tree_view(&tree_view_big_files_finder); - let big_files_mode_index = combo_box_big_files_mode.active().unwrap() as usize; + let big_files_mode_index = combo_box_big_files_mode.active().expect("Failed to get active item") as usize; let big_files_mode = BIG_FILES_CHECK_METHOD_COMBO_BOX[big_files_mode_index].check_method; let numbers_of_files_to_check = entry_big_files_number.text().as_str().parse::().unwrap_or(50); @@ -335,15 +332,14 @@ fn big_files_search( thread::Builder::new() .stack_size(DEFAULT_THREAD_SIZE) .spawn(move || { - let mut item = BigFile::new(); + let params = BigFileParameters::new(numbers_of_files_to_check, big_files_mode); + let mut item = BigFile::new(params); set_common_settings(&mut item, &loaded_commons); - item.set_number_of_files_to_check(numbers_of_files_to_check); - item.set_search_mode(big_files_mode); item.find_big_files(Some(&stop_receiver), Some(&progress_data_sender)); - result_sender.send(Message::BigFiles(item)).unwrap(); + result_sender.send(Message::BigFiles(item)).expect("Failed to send BigFiles message"); }) - .unwrap(); + .expect("Failed to spawn BigFiles thread"); } fn temporary_files_search( @@ -366,9 +362,9 @@ fn temporary_files_search( set_common_settings(&mut item, &loaded_commons); item.find_temporary_files(Some(&stop_receiver), Some(&progress_data_sender)); - result_sender.send(Message::Temporary(item)).unwrap(); + result_sender.send(Message::Temporary(item)).expect("Failed to send Temporary message"); }) - .unwrap(); + .expect("Failed to spawn Temporary thread"); } fn same_music_search( @@ -391,12 +387,14 @@ fn same_music_search( let tree_view_same_music_finder = gui_data.main_notebook.tree_view_same_music_finder.clone(); let combo_box_audio_check_type = gui_data.main_notebook.combo_box_audio_check_type.clone(); let check_button_music_approximate_comparison = gui_data.main_notebook.check_button_music_approximate_comparison.clone(); + let check_button_music_compare_only_in_title_group = gui_data.main_notebook.check_button_music_compare_only_in_title_group.clone(); let scale_seconds_same_music = gui_data.main_notebook.scale_seconds_same_music.clone(); let scale_similarity_same_music = gui_data.main_notebook.scale_similarity_same_music.clone(); clean_tree_view(&tree_view_same_music_finder); let approximate_comparison = check_button_music_approximate_comparison.is_active(); + let comparison_only_in_title_group = check_button_music_compare_only_in_title_group.is_active(); let mut music_similarity: MusicSimilarity = MusicSimilarity::NONE; @@ -419,7 +417,7 @@ fn same_music_search( music_similarity |= MusicSimilarity::LENGTH; } - let check_method_index = combo_box_audio_check_type.active().unwrap() as usize; + let check_method_index = combo_box_audio_check_type.active().expect("Failed to get active item") as usize; let check_method = AUDIO_TYPE_CHECK_METHOD_COMBO_BOX[check_method_index].check_method; let maximum_difference = scale_similarity_same_music.value(); @@ -429,18 +427,21 @@ fn same_music_search( thread::Builder::new() .stack_size(DEFAULT_THREAD_SIZE) .spawn(move || { - let mut item = SameMusic::new(); + let params = SameMusicParameters::new( + music_similarity, + approximate_comparison, + check_method, + minimum_segment_duration, + maximum_difference, + comparison_only_in_title_group, + ); + let mut item = SameMusic::new(params); set_common_settings(&mut item, &loaded_commons); - item.set_music_similarity(music_similarity); - item.set_maximum_difference(maximum_difference); - item.set_minimum_segment_duration(minimum_segment_duration); - item.set_check_type(check_method); - item.set_approximate_comparison(approximate_comparison); item.find_same_music(Some(&stop_receiver), Some(&progress_data_sender)); - result_sender.send(Message::SameMusic(item)).unwrap(); + result_sender.send(Message::SameMusic(item)).expect("Failed to send SameMusic message"); }) - .unwrap(); + .expect("Failed to spawn SameMusic thread"); } else { let shared_buttons = gui_data.shared_buttons.clone(); let buttons_array = gui_data.bottom_buttons.buttons_array.clone(); @@ -452,7 +453,7 @@ fn same_music_search( let button_app_info = gui_data.header.button_app_info.clone(); set_buttons( - &mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SameMusic).unwrap(), + &mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::SameMusic).expect("Failed to get SameMusic button"), &buttons_array, &buttons_names, ); @@ -504,14 +505,14 @@ fn broken_files_search( thread::Builder::new() .stack_size(DEFAULT_THREAD_SIZE) .spawn(move || { - let mut item = BrokenFiles::new(); + let params = BrokenFilesParameters::new(checked_types); + let mut item = BrokenFiles::new(params); set_common_settings(&mut item, &loaded_commons); - item.set_checked_types(checked_types); item.find_broken_files(Some(&stop_receiver), Some(&progress_data_sender)); - result_sender.send(Message::BrokenFiles(item)).unwrap(); + result_sender.send(Message::BrokenFiles(item)).expect("Failed to send BrokenFiles message"); }) - .unwrap(); + .expect("Failed to spawn BrokenFiles thread"); } else { let shared_buttons = gui_data.shared_buttons.clone(); let buttons_array = gui_data.bottom_buttons.buttons_array.clone(); @@ -523,7 +524,10 @@ fn broken_files_search( let button_app_info = gui_data.header.button_app_info.clone(); set_buttons( - &mut *shared_buttons.borrow_mut().get_mut(&NotebookMainEnum::BrokenFiles).unwrap(), + &mut *shared_buttons + .borrow_mut() + .get_mut(&NotebookMainEnum::BrokenFiles) + .expect("Failed to get BrokenFiles button"), &buttons_array, &buttons_names, ); @@ -559,13 +563,13 @@ fn similar_image_search( clean_tree_view(&tree_view_similar_images_finder); image_preview_similar_images.hide(); - let hash_size_index = combo_box_image_hash_size.active().unwrap() as usize; + let hash_size_index = combo_box_image_hash_size.active().expect("Failed to get active item") as usize; let hash_size = IMAGES_HASH_SIZE_COMBO_BOX[hash_size_index] as u8; - let image_filter_index = combo_box_image_resize_algorithm.active().unwrap() as usize; + let image_filter_index = combo_box_image_resize_algorithm.active().expect("Failed to get active item") as usize; let image_filter = IMAGES_RESIZE_ALGORITHM_COMBO_BOX[image_filter_index].filter; - let hash_alg_index = combo_box_image_hash_algorithm.active().unwrap() as usize; + let hash_alg_index = combo_box_image_hash_algorithm.active().expect("Failed to get active item") as usize; let hash_alg = IMAGES_HASH_TYPE_COMBO_BOX[hash_alg_index].hash_alg; let ignore_same_size = check_button_image_ignore_same_size.is_active(); @@ -577,19 +581,15 @@ fn similar_image_search( thread::Builder::new() .stack_size(DEFAULT_THREAD_SIZE) .spawn(move || { - let mut item = SimilarImages::new(); + let params = SimilarImagesParameters::new(similarity, hash_size, hash_alg, image_filter, ignore_same_size, loaded_commons.hide_hard_links); + let mut item = SimilarImages::new(params); set_common_settings(&mut item, &loaded_commons); - item.set_similarity(similarity); - item.set_hash_alg(hash_alg); - item.set_hash_size(hash_size); - item.set_image_filter(image_filter); item.set_delete_outdated_cache(delete_outdated_cache); - item.set_exclude_images_with_same_size(ignore_same_size); item.find_similar_images(Some(&stop_receiver), Some(&progress_data_sender)); - result_sender.send(Message::SimilarImages(item)).unwrap(); + result_sender.send(Message::SimilarImages(item)).expect("Failed to send SimilarImages message"); }) - .unwrap(); + .expect("Failed to spawn SimilarImages thread"); } fn similar_video_search( @@ -617,16 +617,15 @@ fn similar_video_search( thread::Builder::new() .stack_size(DEFAULT_THREAD_SIZE) .spawn(move || { - let mut item = SimilarVideos::new(); + let params = SimilarVideosParameters::new(tolerance, ignore_same_size, loaded_commons.hide_hard_links); + let mut item = SimilarVideos::new(params); set_common_settings(&mut item, &loaded_commons); - item.set_tolerance(tolerance); item.set_delete_outdated_cache(delete_outdated_cache); - item.set_exclude_videos_with_same_size(ignore_same_size); item.find_similar_videos(Some(&stop_receiver), Some(&progress_data_sender)); - result_sender.send(Message::SimilarVideos(item)).unwrap(); + result_sender.send(Message::SimilarVideos(item)).expect("Failed to send SimilarVideos message"); }) - .unwrap(); + .expect("Failed to spawn SimilarVideos thread"); } fn bad_symlinks_search( @@ -649,9 +648,9 @@ fn bad_symlinks_search( set_common_settings(&mut item, &loaded_commons); item.find_invalid_links(Some(&stop_receiver), Some(&progress_data_sender)); - result_sender.send(Message::InvalidSymlinks(item)).unwrap(); + result_sender.send(Message::InvalidSymlinks(item)).expect("Failed to send InvalidSymlinks message"); }) - .unwrap(); + .expect("Failed to spawn InvalidSymlinks thread"); } fn bad_extensions_search( @@ -670,13 +669,14 @@ fn bad_extensions_search( thread::Builder::new() .stack_size(DEFAULT_THREAD_SIZE) .spawn(move || { - let mut item = BadExtensions::new(); + let params = BadExtensionsParameters::new(); + let mut item = BadExtensions::new(params); set_common_settings(&mut item, &loaded_commons); item.find_bad_extensions_files(Some(&stop_receiver), Some(&progress_data_sender)); - result_sender.send(Message::BadExtensions(item)).unwrap(); + result_sender.send(Message::BadExtensions(item)).expect("Failed to send BadExtensions message"); }) - .unwrap(); + .expect("Failed to spawn BadExtensions thread"); } fn set_common_settings(component: &mut T, loaded_commons: &LoadedCommonItems) diff --git a/czkawka_gui/src/connect_things/connect_button_select.rs b/czkawka_gui/src/connect_things/connect_button_select.rs index 07b9692dc..832132aea 100644 --- a/czkawka_gui/src/connect_things/connect_button_select.rs +++ b/czkawka_gui/src/connect_things/connect_button_select.rs @@ -12,11 +12,11 @@ pub fn connect_button_select(gui_data: &GuiData) { let gc_buttons_select = gui_data.bottom_buttons.gc_buttons_select.clone(); gc_buttons_select.connect_pressed(move |_, _, _, _| { - show_required_popovers(&popovers_select, &to_notebook_main_enum(notebook_main.current_page().unwrap())); + show_required_popovers(&popovers_select, to_notebook_main_enum(notebook_main.current_page().expect("Current page not set"))); }); } -fn show_required_popovers(popovers_select: &GuiSelectPopovers, current_mode: &NotebookMainEnum) { +fn show_required_popovers(popovers_select: &GuiSelectPopovers, current_mode: NotebookMainEnum) { let buttons_popover_select_all = popovers_select.buttons_popover_select_all.clone(); let buttons_popover_unselect_all = popovers_select.buttons_popover_unselect_all.clone(); let buttons_popover_reverse = popovers_select.buttons_popover_reverse.clone(); @@ -34,7 +34,7 @@ fn show_required_popovers(popovers_select: &GuiSelectPopovers, current_mode: &No let separator_select_image_size = popovers_select.separator_select_image_size.clone(); let separator_select_reverse = popovers_select.separator_select_reverse.clone(); - let arr = &NOTEBOOKS_INFO[*current_mode as usize].available_modes; + let arr = &NOTEBOOKS_INFO[current_mode as usize].available_modes; if arr.contains(&PopoverTypes::All) { buttons_popover_select_all.show(); diff --git a/czkawka_gui/src/connect_things/connect_button_sort.rs b/czkawka_gui/src/connect_things/connect_button_sort.rs index cb90d6e81..ae7ebfd8e 100644 --- a/czkawka_gui/src/connect_things/connect_button_sort.rs +++ b/czkawka_gui/src/connect_things/connect_button_sort.rs @@ -12,18 +12,18 @@ pub fn connect_button_sort(gui_data: &GuiData) { let gc_buttons_sort = gui_data.bottom_buttons.gc_buttons_sort.clone(); gc_buttons_sort.connect_pressed(move |_, _, _, _| { - show_required_popovers(&popovers_sort, &to_notebook_main_enum(notebook_main.current_page().unwrap())); + show_required_popovers(&popovers_sort, to_notebook_main_enum(notebook_main.current_page().expect("Current page not set"))); }); } -fn show_required_popovers(popovers_sort: &GuiSortPopovers, current_mode: &NotebookMainEnum) { +fn show_required_popovers(popovers_sort: &GuiSortPopovers, current_mode: NotebookMainEnum) { let buttons_popover_sort_file_name = popovers_sort.buttons_popover_sort_file_name.clone(); let buttons_popover_sort_size = popovers_sort.buttons_popover_sort_size.clone(); let buttons_popover_sort_folder_name = popovers_sort.buttons_popover_sort_folder_name.clone(); let buttons_popover_sort_full_name = popovers_sort.buttons_popover_sort_full_name.clone(); let buttons_popover_sort_selection = popovers_sort.buttons_popover_sort_selection.clone(); - let arr = &NOTEBOOKS_INFO[*current_mode as usize].available_modes; + let arr = &NOTEBOOKS_INFO[current_mode as usize].available_modes; buttons_popover_sort_full_name.hide(); diff --git a/czkawka_gui/src/connect_things/connect_button_stop.rs b/czkawka_gui/src/connect_things/connect_button_stop.rs index f4d8dfb87..57638fc97 100644 --- a/czkawka_gui/src/connect_things/connect_button_stop.rs +++ b/czkawka_gui/src/connect_things/connect_button_stop.rs @@ -9,7 +9,7 @@ fn send_stop_message(stop_sender: &Sender<()>) { stop_sender .try_send(()) .map_or_else(|e| if matches!(e, TrySendError::Full(())) { Ok(()) } else { Err(e) }, |()| Ok(())) - .unwrap(); + .expect("Failed to send stop message"); } pub fn connect_button_stop(gui_data: &GuiData) { diff --git a/czkawka_gui/src/connect_things/connect_change_language.rs b/czkawka_gui/src/connect_things/connect_change_language.rs index f52817e16..a297c96a5 100644 --- a/czkawka_gui/src/connect_things/connect_change_language.rs +++ b/czkawka_gui/src/connect_things/connect_change_language.rs @@ -23,9 +23,9 @@ fn change_language(gui_data: &GuiData) { ("czkawka_gui", localizer_gui::localizer_gui()), ]; - let lang_short = get_language_from_combo_box_text(&gui_data.settings.combo_box_settings_language.active_text().unwrap()).short_text; + let lang_short = get_language_from_combo_box_text(&gui_data.settings.combo_box_settings_language.active_text().expect("No active text")).short_text; - let lang_identifier = vec![LanguageIdentifier::from_bytes(lang_short.as_bytes()).unwrap()]; + let lang_identifier = vec![LanguageIdentifier::from_bytes(lang_short.as_bytes()).expect("Failed to create LanguageIdentifier")]; for (lib, localizer) in localizers { if let Err(error) = localizer.select(&lang_identifier) { eprintln!("Error while loadings languages for {lib} {error:?}"); diff --git a/czkawka_gui/src/connect_things/connect_notebook_tabs.rs b/czkawka_gui/src/connect_things/connect_notebook_tabs.rs index 02801ccc4..b59fe87d5 100644 --- a/czkawka_gui/src/connect_things/connect_notebook_tabs.rs +++ b/czkawka_gui/src/connect_things/connect_notebook_tabs.rs @@ -13,7 +13,7 @@ pub fn connect_notebook_tabs(gui_data: &GuiData) { // Buttons set_buttons( - &mut *shared_buttons.borrow_mut().get_mut(¤t_tab_in_main_notebook).unwrap(), + &mut *shared_buttons.borrow_mut().get_mut(¤t_tab_in_main_notebook).expect("Failed to get current tab"), &buttons_array, &buttons_names, ); diff --git a/czkawka_gui/src/connect_things/connect_popovers_select.rs b/czkawka_gui/src/connect_things/connect_popovers_select.rs index 9aa853369..fd173d115 100644 --- a/czkawka_gui/src/connect_things/connect_popovers_select.rs +++ b/czkawka_gui/src/connect_things/connect_popovers_select.rs @@ -134,11 +134,11 @@ fn popover_all_except_oldest_newest( break; } } - if used_index.is_none() { + let Some(used_index) = used_index else { continue; - } + }; for (index, tree_iter) in tree_iter_array.iter().enumerate() { - if index != used_index.unwrap() { + if index != used_index { model.set_value(tree_iter, column_button_selection, &true.to_value()); } else { model.set_value(tree_iter, column_button_selection, &false.to_value()); @@ -206,11 +206,12 @@ fn popover_one_oldest_newest( break; } } - if used_index.is_none() { + let Some(used_index) = used_index else { continue; - } + }; + for (index, tree_iter) in tree_iter_array.iter().enumerate() { - if index == used_index.unwrap() { + if index == used_index { model.set_value(tree_iter, column_button_selection, &true.to_value()); } else { model.set_value(tree_iter, column_button_selection, &false.to_value()); @@ -393,7 +394,7 @@ fn popover_custom_select_unselect( return; } } else { - Regex::new("").unwrap() + Regex::new("").expect("Empty regex should compile properly.") }; let model = get_list_store(&tree_view); @@ -577,11 +578,11 @@ fn popover_all_except_biggest_smallest( break; } } - if used_index.is_none() { + let Some(used_index) = used_index else { continue; - } + }; for (index, tree_iter) in tree_iter_array.iter().enumerate() { - if index != used_index.unwrap() { + if index != used_index { model.set_value(tree_iter, column_button_selection, &true.to_value()); } else { model.set_value(tree_iter, column_button_selection, &false.to_value()); @@ -604,7 +605,7 @@ pub fn connect_popover_select(gui_data: &GuiData) { let main_tree_views = gui_data.main_notebook.get_main_tree_views(); buttons_popover_select_all.connect_clicked(move |_| { - let nb_number = notebook_main.current_page().unwrap(); + let nb_number = notebook_main.current_page().expect("Current page not set"); let tree_view = &main_tree_views[nb_number as usize]; let nb_object = &NOTEBOOKS_INFO[nb_number as usize]; @@ -616,7 +617,7 @@ pub fn connect_popover_select(gui_data: &GuiData) { let notebook_main = gui_data.main_notebook.notebook_main.clone(); let main_tree_views = gui_data.main_notebook.get_main_tree_views(); buttons_popover_unselect_all.connect_clicked(move |_| { - let nb_number = notebook_main.current_page().unwrap(); + let nb_number = notebook_main.current_page().expect("Current page not set"); let tree_view = &main_tree_views[nb_number as usize]; let nb_object = &NOTEBOOKS_INFO[nb_number as usize]; @@ -628,7 +629,7 @@ pub fn connect_popover_select(gui_data: &GuiData) { let notebook_main = gui_data.main_notebook.notebook_main.clone(); let main_tree_views = gui_data.main_notebook.get_main_tree_views(); buttons_popover_reverse.connect_clicked(move |_| { - let nb_number = notebook_main.current_page().unwrap(); + let nb_number = notebook_main.current_page().expect("Current page not set"); let tree_view = &main_tree_views[nb_number as usize]; let nb_object = &NOTEBOOKS_INFO[nb_number as usize]; @@ -640,7 +641,7 @@ pub fn connect_popover_select(gui_data: &GuiData) { let notebook_main = gui_data.main_notebook.notebook_main.clone(); let main_tree_views = gui_data.main_notebook.get_main_tree_views(); buttons_popover_select_all_except_oldest.connect_clicked(move |_| { - let nb_number = notebook_main.current_page().unwrap(); + let nb_number = notebook_main.current_page().expect("Current page not set"); let tree_view = &main_tree_views[nb_number as usize]; let nb_object = &NOTEBOOKS_INFO[nb_number as usize]; @@ -660,7 +661,7 @@ pub fn connect_popover_select(gui_data: &GuiData) { let notebook_main = gui_data.main_notebook.notebook_main.clone(); let main_tree_views = gui_data.main_notebook.get_main_tree_views(); buttons_popover_select_all_except_newest.connect_clicked(move |_| { - let nb_number = notebook_main.current_page().unwrap(); + let nb_number = notebook_main.current_page().expect("Current page not set"); let tree_view = &main_tree_views[nb_number as usize]; let nb_object = &NOTEBOOKS_INFO[nb_number as usize]; @@ -680,7 +681,7 @@ pub fn connect_popover_select(gui_data: &GuiData) { let notebook_main = gui_data.main_notebook.notebook_main.clone(); let main_tree_views = gui_data.main_notebook.get_main_tree_views(); buttons_popover_select_one_oldest.connect_clicked(move |_| { - let nb_number = notebook_main.current_page().unwrap(); + let nb_number = notebook_main.current_page().expect("Current page not set"); let tree_view = &main_tree_views[nb_number as usize]; let nb_object = &NOTEBOOKS_INFO[nb_number as usize]; @@ -700,7 +701,7 @@ pub fn connect_popover_select(gui_data: &GuiData) { let notebook_main = gui_data.main_notebook.notebook_main.clone(); let main_tree_views = gui_data.main_notebook.get_main_tree_views(); buttons_popover_select_one_newest.connect_clicked(move |_| { - let nb_number = notebook_main.current_page().unwrap(); + let nb_number = notebook_main.current_page().expect("Current page not set"); let tree_view = &main_tree_views[nb_number as usize]; let nb_object = &NOTEBOOKS_INFO[nb_number as usize]; @@ -721,7 +722,7 @@ pub fn connect_popover_select(gui_data: &GuiData) { let main_tree_views = gui_data.main_notebook.get_main_tree_views(); let window_main = gui_data.window_main.clone(); buttons_popover_select_custom.connect_clicked(move |_| { - let nb_number = notebook_main.current_page().unwrap(); + let nb_number = notebook_main.current_page().expect("Current page not set"); let tree_view = &main_tree_views[nb_number as usize]; let nb_object = &NOTEBOOKS_INFO[nb_number as usize]; @@ -743,7 +744,7 @@ pub fn connect_popover_select(gui_data: &GuiData) { let main_tree_views = gui_data.main_notebook.get_main_tree_views(); let window_main = gui_data.window_main.clone(); buttons_popover_unselect_custom.connect_clicked(move |_| { - let nb_number = notebook_main.current_page().unwrap(); + let nb_number = notebook_main.current_page().expect("Current page not set"); let tree_view = &main_tree_views[nb_number as usize]; let nb_object = &NOTEBOOKS_INFO[nb_number as usize]; @@ -764,7 +765,7 @@ pub fn connect_popover_select(gui_data: &GuiData) { let notebook_main = gui_data.main_notebook.notebook_main.clone(); let main_tree_views = gui_data.main_notebook.get_main_tree_views(); buttons_popover_select_all_images_except_biggest.connect_clicked(move |_| { - let nb_number = notebook_main.current_page().unwrap(); + let nb_number = notebook_main.current_page().expect("Current page not set"); let tree_view = &main_tree_views[nb_number as usize]; let nb_object = &NOTEBOOKS_INFO[nb_number as usize]; @@ -784,7 +785,7 @@ pub fn connect_popover_select(gui_data: &GuiData) { let notebook_main = gui_data.main_notebook.notebook_main.clone(); let main_tree_views = gui_data.main_notebook.get_main_tree_views(); buttons_popover_select_all_images_except_smallest.connect_clicked(move |_| { - let nb_number = notebook_main.current_page().unwrap(); + let nb_number = notebook_main.current_page().expect("Current page not set"); let tree_view = &main_tree_views[nb_number as usize]; let nb_object = &NOTEBOOKS_INFO[nb_number as usize]; diff --git a/czkawka_gui/src/connect_things/connect_popovers_sort.rs b/czkawka_gui/src/connect_things/connect_popovers_sort.rs index d23406454..d8ff5995a 100644 --- a/czkawka_gui/src/connect_things/connect_popovers_sort.rs +++ b/czkawka_gui/src/connect_things/connect_popovers_sort.rs @@ -70,11 +70,16 @@ pub fn connect_popover_sort(gui_data: &GuiData) { let main_tree_views = gui_data.main_notebook.get_main_tree_views(); buttons_popover_file_name.connect_clicked(move |_| { - let nb_number = notebook_main.current_page().unwrap(); + let nb_number = notebook_main.current_page().expect("Current page not set"); let tree_view = &main_tree_views[nb_number as usize]; let nb_object = &NOTEBOOKS_INFO[nb_number as usize]; - popover_sort_general::(&popover_sort, tree_view, nb_object.column_name, nb_object.column_header.unwrap()); + popover_sort_general::( + &popover_sort, + tree_view, + nb_object.column_name, + nb_object.column_header.expect("Failed to get header column"), + ); }); let popover_sort = gui_data.popovers_sort.popover_sort.clone(); @@ -83,11 +88,16 @@ pub fn connect_popover_sort(gui_data: &GuiData) { let main_tree_views = gui_data.main_notebook.get_main_tree_views(); buttons_popover_sort_folder_name.connect_clicked(move |_| { - let nb_number = notebook_main.current_page().unwrap(); + let nb_number = notebook_main.current_page().expect("Current page not set"); let tree_view = &main_tree_views[nb_number as usize]; let nb_object = &NOTEBOOKS_INFO[nb_number as usize]; - popover_sort_general::(&popover_sort, tree_view, nb_object.column_path, nb_object.column_header.unwrap()); + popover_sort_general::( + &popover_sort, + tree_view, + nb_object.column_path, + nb_object.column_header.expect("Failed to get header column"), + ); }); let popover_sort = gui_data.popovers_sort.popover_sort.clone(); @@ -96,11 +106,16 @@ pub fn connect_popover_sort(gui_data: &GuiData) { let main_tree_views = gui_data.main_notebook.get_main_tree_views(); buttons_popover_sort_selection.connect_clicked(move |_| { - let nb_number = notebook_main.current_page().unwrap(); + let nb_number = notebook_main.current_page().expect("Current page not set"); let tree_view = &main_tree_views[nb_number as usize]; let nb_object = &NOTEBOOKS_INFO[nb_number as usize]; - popover_sort_general::(&popover_sort, tree_view, nb_object.column_selection, nb_object.column_header.unwrap()); + popover_sort_general::( + &popover_sort, + tree_view, + nb_object.column_selection, + nb_object.column_header.expect("Failed to get header column"), + ); }); let popover_sort = gui_data.popovers_sort.popover_sort.clone(); @@ -109,11 +124,16 @@ pub fn connect_popover_sort(gui_data: &GuiData) { let main_tree_views = gui_data.main_notebook.get_main_tree_views(); buttons_popover_sort_size.connect_clicked(move |_| { - let nb_number = notebook_main.current_page().unwrap(); + let nb_number = notebook_main.current_page().expect("Current page not set"); let tree_view = &main_tree_views[nb_number as usize]; let nb_object = &NOTEBOOKS_INFO[nb_number as usize]; - popover_sort_general::(&popover_sort, tree_view, nb_object.column_size_as_bytes.unwrap(), nb_object.column_header.unwrap()); + popover_sort_general::( + &popover_sort, + tree_view, + nb_object.column_size_as_bytes.expect("Failed to get size as bytes column"), + nb_object.column_header.expect("Failed to get header column"), + ); }); } @@ -135,7 +155,7 @@ mod test { list_store.set(&list_store.append(), i); } let mut iters = Vec::new(); - let iter = list_store.iter_first().unwrap(); + let iter = list_store.iter_first().expect("Failed to get first iter"); iters.push(iter); list_store.iter_next(&iter); iters.push(iter); @@ -145,7 +165,7 @@ mod test { sort_iters::(&list_store, iters, 1); let expected = [(2, "AAA"), (1, "BBB"), (3, "CCC")]; - let curr_iter = list_store.iter_first().unwrap(); + let curr_iter = list_store.iter_first().expect("Failed to get first iter"); for exp in expected { let real_0 = list_store.get::(&curr_iter, 0); assert_eq!(real_0, exp.0); @@ -170,7 +190,7 @@ mod test { popover_sort_general::(&popover, &tree_view, 1, 0); let expected = ["DDD", "BBB", "CCC"]; - let curr_iter = list_store.iter_first().unwrap(); + let curr_iter = list_store.iter_first().expect("Failed to get first iter"); for exp in expected { let real = list_store.get::(&curr_iter, 1); assert_eq!(real, exp); @@ -203,7 +223,7 @@ mod test { popover_sort_general::(&popover, &tree_view, 1, 0); let expected = ["AAA", "BBB", "CCC", "TTT", "AAA", "PPP", "RRR", "WWW", "ZZZ"]; - let curr_iter = list_store.iter_first().unwrap(); + let curr_iter = list_store.iter_first().expect("Failed to get first iter"); for exp in expected { let real = list_store.get::(&curr_iter, 1); assert_eq!(real, exp); diff --git a/czkawka_gui/src/connect_things/connect_progress_window.rs b/czkawka_gui/src/connect_things/connect_progress_window.rs index 9121842c1..474e10274 100644 --- a/czkawka_gui/src/connect_things/connect_progress_window.rs +++ b/czkawka_gui/src/connect_things/connect_progress_window.rs @@ -8,72 +8,18 @@ use glib::MainContext; use gtk4::prelude::*; use gtk4::ProgressBar; -use common_dir_traversal::CheckingMethod; -use czkawka_core::common_dir_traversal; -use czkawka_core::common_dir_traversal::{ProgressData, ToolType}; - use crate::flg; use crate::gui_structs::gui_data::GuiData; use crate::localizer_core::generate_translation_hashmap; use crate::taskbar_progress::tbp_flags::TBPF_INDETERMINATE; use crate::taskbar_progress::TaskbarProgress; - -// Empty files -// 0 - Collecting files - -// Empty folders -// 0 - Collecting folders - -// Big files -// 0 - Collecting files - -// Same music -// 0 - Collecting files -// 1 - Loading cache -// 2 - Checking tags / content -// 3 - Saving cache -// 4 - Checking tags / content - progress -// 5 - Only content - ending - -// Similar images -// 0 - Collecting files -// 1 - Scanning images -// 2 - Comparing hashes - -// Similar videos -// 0 - Collecting files -// 1 - Scanning videos - -// Temporary files -// 0 - Collecting files - -// Invalid symlinks -// 0 - Collecting files - -// Broken files -// 0 - Collecting files -// 1 - Scanning files - -// Bad extensions -// 0 - Collecting files -// 1 - Scanning files - -// Duplicates - Hash -// 0 - Collecting files -// 1 - Loading cache -// 2 - Hash - first 1KB file -// 3 - Saving cache -// 4 - Loading cache -// 5 - Hash - normal hash -// 6 - Saving cache - -// Duplicates - Name or SizeName or Size -// 0 - Collecting files +use czkawka_core::common_dir_traversal::ToolType; +use czkawka_core::progress_data::{CurrentStage, ProgressData}; #[allow(clippy::too_many_arguments)] pub fn connect_progress_window(gui_data: &GuiData, progress_receiver: Receiver) { let main_context = MainContext::default(); - let _guard = main_context.acquire().unwrap(); + let _guard = main_context.acquire().expect("Failed to acquire main context"); let gui_data = gui_data.clone(); @@ -82,9 +28,9 @@ pub fn connect_progress_window(gui_data: &GuiData, progress_receiver: Receiver

bool { - matches!( - (progress_data.tool_type, progress_data.current_stage), - (ToolType::SameMusic, 1 | 3) | (ToolType::Duplicate, 1 | 3 | 4 | 6) - ) -} + fn progress_save_load_cache(gui_data: &GuiData, item: &ProgressData) { let label_stage = gui_data.progress_window.label_stage.clone(); let progress_bar_current_stage = gui_data.progress_window.progress_bar_current_stage.clone(); @@ -112,27 +53,29 @@ fn progress_save_load_cache(gui_data: &GuiData, item: &ProgressData) { progress_bar_current_stage.hide(); taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE); - let text = match (item.tool_type, item.checking_method, item.current_stage) { - (ToolType::SameMusic, CheckingMethod::AudioTags | CheckingMethod::AudioContent, 1) => { + + let text = match item.sstage { + CurrentStage::SameMusicCacheLoadingFingerprints | CurrentStage::SameMusicCacheLoadingTags => { flg!("progress_cache_loading") } - (ToolType::SameMusic, CheckingMethod::AudioTags | CheckingMethod::AudioContent, 3) => { + CurrentStage::SameMusicCacheSavingFingerprints | CurrentStage::SameMusicCacheSavingTags => { flg!("progress_cache_saving") } - (ToolType::Duplicate, CheckingMethod::Hash, 1) => { - flg!("progress_prehash_cache_loading") - } - (ToolType::Duplicate, CheckingMethod::Hash, 3) => { - flg!("progress_prehash_cache_saving") - } - (ToolType::Duplicate, CheckingMethod::Hash, 4) => { + CurrentStage::DuplicateCacheLoading => { flg!("progress_hash_cache_loading") } - (ToolType::Duplicate, CheckingMethod::Hash, 6) => { + CurrentStage::DuplicateCacheSaving => { flg!("progress_hash_cache_saving") } - _ => panic!(), + CurrentStage::DuplicatePreHashCacheLoading => { + flg!("progress_prehash_cache_loading") + } + CurrentStage::DuplicatePreHashCacheSaving => { + flg!("progress_prehash_cache_saving") + } + _ => panic!("Invalid stage {:?}", item.sstage), }; + label_stage.set_text(&text); } @@ -144,26 +87,23 @@ fn progress_collect_items(gui_data: &GuiData, item: &ProgressData, files: bool) progress_bar_current_stage.hide(); taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE); - match (item.tool_type, item.checking_method) { - (ToolType::Duplicate, CheckingMethod::Name) => { + match item.sstage { + CurrentStage::DuplicateScanningName => { label_stage.set_text(&flg!("progress_scanning_name", file_number_tm(item))); - return; } - (ToolType::Duplicate, CheckingMethod::SizeName) => { + CurrentStage::DuplicateScanningSizeName => { label_stage.set_text(&flg!("progress_scanning_size_name", file_number_tm(item))); - return; } - (ToolType::Duplicate, CheckingMethod::Size | CheckingMethod::Hash) => { + CurrentStage::DuplicateScanningSize => { label_stage.set_text(&flg!("progress_scanning_size", file_number_tm(item))); - return; } - _ => {} - } - - if files { - label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(item))); - } else { - label_stage.set_text(&flg!("progress_scanning_empty_folders", folder_number = item.entries_checked)); + _ => { + if files { + label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(item))); + } else { + label_stage.set_text(&flg!("progress_scanning_empty_folders", folder_number = item.entries_checked)); + } + } } } @@ -177,60 +117,60 @@ fn progress_default(gui_data: &GuiData, item: &ProgressData) { common_set_data(item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state); taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE); - match (item.tool_type, item.checking_method, item.current_stage) { - (ToolType::SameMusic, CheckingMethod::AudioTags, 2) | (ToolType::SameMusic, CheckingMethod::AudioContent, 5) => { + match item.sstage { + CurrentStage::SameMusicReadingTags => { label_stage.set_text(&flg!("progress_scanning_music_tags", progress_ratio_tm(item))); } - (ToolType::SameMusic, CheckingMethod::AudioContent, 2) => { + CurrentStage::SameMusicCalculatingFingerprints => { label_stage.set_text(&flg!("progress_scanning_music_content", progress_ratio_tm(item))); } - (ToolType::SameMusic, CheckingMethod::AudioTags, 4) => { + CurrentStage::SameMusicComparingTags => { label_stage.set_text(&flg!("progress_scanning_music_tags_end", progress_ratio_tm(item))); } - (ToolType::SameMusic, CheckingMethod::AudioContent, 4) => { + CurrentStage::SameMusicComparingFingerprints => { label_stage.set_text(&flg!("progress_scanning_music_content_end", progress_ratio_tm(item))); } - (ToolType::SimilarImages, _, 1) => { + CurrentStage::SimilarImagesCalculatingHashes => { label_stage.set_text(&flg!("progress_scanning_image", progress_ratio_tm(item))); } - (ToolType::SimilarImages, _, 2) => { + CurrentStage::SimilarImagesComparingHashes => { label_stage.set_text(&flg!("progress_comparing_image_hashes", progress_ratio_tm(item))); } - (ToolType::SimilarVideos, _, 1) => { + CurrentStage::SimilarVideosCalculatingHashes => { label_stage.set_text(&flg!("progress_scanning_video", progress_ratio_tm(item))); } - (ToolType::BrokenFiles, _, 1) => { + CurrentStage::BrokenFilesChecking => { label_stage.set_text(&flg!("progress_scanning_broken_files", progress_ratio_tm(item))); } - (ToolType::BadExtensions, _, 1) => { + CurrentStage::BadExtensionsChecking => { label_stage.set_text(&flg!("progress_scanning_extension_of_files", progress_ratio_tm(item))); } - (ToolType::Duplicate, CheckingMethod::Hash, 2) => { + CurrentStage::DuplicatePreHashing => { label_stage.set_text(&flg!("progress_analyzed_partial_hash", progress_ratio_tm(item))); } - (ToolType::Duplicate, CheckingMethod::Hash, 5) => { + CurrentStage::DuplicateFullHashing => { label_stage.set_text(&flg!("progress_analyzed_full_hash", progress_ratio_tm(item))); } - _ => unreachable!(), + _ => unreachable!("Invalid stage {:?}", item.sstage), } } fn common_set_data(item: &ProgressData, progress_bar_all_stages: &ProgressBar, progress_bar_current_stage: &ProgressBar, taskbar_state: &Rc>) { if item.entries_to_check != 0 { - let all_stages = (item.current_stage as f64 + item.entries_checked as f64 / item.entries_to_check as f64) / (item.max_stage + 1) as f64; - let all_stages = if all_stages > 0.99 { 0.99 } else { all_stages }; + let all_stages = (item.current_stage_idx as f64 + item.entries_checked as f64 / item.entries_to_check as f64) / (item.max_stage_idx + 1) as f64; + let all_stages = all_stages.min(0.99); progress_bar_all_stages.set_fraction(all_stages); progress_bar_current_stage.set_fraction(item.entries_checked as f64 / item.entries_to_check as f64); taskbar_state.borrow().set_progress_value( - ((item.current_stage as usize) * item.entries_to_check + item.entries_checked) as u64, - item.entries_to_check as u64 * (item.max_stage + 1) as u64, + ((item.current_stage_idx as usize) * item.entries_to_check + item.entries_checked) as u64, + item.entries_to_check as u64 * (item.max_stage_idx + 1) as u64, ); } else { - let all_stages = (item.current_stage as f64) / (item.max_stage + 1) as f64; - let all_stages = if all_stages > 0.99 { 0.99 } else { all_stages }; + let all_stages = (item.current_stage_idx as f64) / (item.max_stage_idx + 1) as f64; + let all_stages = all_stages.min(0.99); progress_bar_all_stages.set_fraction(all_stages); progress_bar_current_stage.set_fraction(0f64); - taskbar_state.borrow().set_progress_value(item.current_stage as u64, 1 + item.max_stage as u64); + taskbar_state.borrow().set_progress_value(item.current_stage_idx as u64, 1 + item.max_stage_idx as u64); } } diff --git a/czkawka_gui/src/connect_things/connect_same_music_mode_changed.rs b/czkawka_gui/src/connect_things/connect_same_music_mode_changed.rs index 332a531c3..2d8747aff 100644 --- a/czkawka_gui/src/connect_things/connect_same_music_mode_changed.rs +++ b/czkawka_gui/src/connect_things/connect_same_music_mode_changed.rs @@ -32,6 +32,9 @@ pub fn connect_same_music_change_mode(gui_data: &GuiData) { check_button_music_length, ]; + let check_button_music_compare_only_in_title_group = gui_data.main_notebook.check_button_music_compare_only_in_title_group.clone(); + let reversed_buttons = [check_button_music_compare_only_in_title_group]; + let scale_seconds_same_music = gui_data.main_notebook.scale_seconds_same_music.clone(); let scale_similarity_same_music = gui_data.main_notebook.scale_similarity_same_music.clone(); let label_same_music_similarity = gui_data.main_notebook.label_same_music_similarity.clone(); @@ -49,27 +52,29 @@ pub fn connect_same_music_change_mode(gui_data: &GuiData) { let combo_box_audio_check_type = gui_data.main_notebook.combo_box_audio_check_type.clone(); - let check_method_index = combo_box_audio_check_type.active().unwrap() as usize; + let check_method_index = combo_box_audio_check_type.active().expect("Failed to get active item") as usize; let check_method = AUDIO_TYPE_CHECK_METHOD_COMBO_BOX[check_method_index].check_method; - disable_enable_buttons(&buttons, &scales_and_labels, check_method); + disable_enable_buttons(&buttons, &reversed_buttons, &scales_and_labels, check_method); combo_box_audio_check_type.connect_changed(move |combo_box_text| { if let Some(active) = combo_box_text.active() { let check_method = AUDIO_TYPE_CHECK_METHOD_COMBO_BOX[active as usize].check_method; - disable_enable_buttons(&buttons, &scales_and_labels, check_method); + disable_enable_buttons(&buttons, &reversed_buttons, &scales_and_labels, check_method); } }); } -fn disable_enable_buttons(buttons: &[CheckButton; 7], scales: &[Widget; 4], current_mode: CheckingMethod) { +fn disable_enable_buttons(buttons: &[CheckButton; 7], reverse_buttons: &[CheckButton; 1], scales: &[Widget; 4], current_mode: CheckingMethod) { match current_mode { CheckingMethod::AudioTags => { buttons.iter().for_each(WidgetExt::show); + reverse_buttons.iter().for_each(WidgetExt::hide); scales.iter().for_each(WidgetExt::hide); } CheckingMethod::AudioContent => { buttons.iter().for_each(WidgetExt::hide); + reverse_buttons.iter().for_each(WidgetExt::show); scales.iter().for_each(WidgetExt::show); } _ => panic!(), 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 daeb6cc33..8bc3b1ebf 100644 --- a/czkawka_gui/src/connect_things/connect_selection_of_directories.rs +++ b/czkawka_gui/src/connect_things/connect_selection_of_directories.rs @@ -79,7 +79,7 @@ pub fn connect_selection_of_directories(gui_data: &GuiData) { let (vec_tree_path, _tree_model) = selection.selected_rows(); for tree_path in vec_tree_path.iter().rev() { - list_store.remove(&list_store.iter(tree_path).unwrap()); + list_store.remove(&list_store.iter(tree_path).expect("Using invalid tree_path")); } }); } @@ -94,7 +94,7 @@ pub fn connect_selection_of_directories(gui_data: &GuiData) { let (vec_tree_path, _tree_model) = selection.selected_rows(); for tree_path in vec_tree_path.iter().rev() { - list_store.remove(&list_store.iter(tree_path).unwrap()); + list_store.remove(&list_store.iter(tree_path).expect("Using invalid tree_path")); } }); } @@ -130,7 +130,7 @@ fn connect_file_dialog(file_dialog_include_exclude_folder_selection: &FileChoose file_dialog_include_exclude_folder_selection.connect_response(move |file_chooser, response_type| { if response_type == ResponseType::Accept { let excluded_items; - let tree_view = match to_notebook_upper_enum(notebook_upper.current_page().unwrap()) { + let tree_view = match to_notebook_upper_enum(notebook_upper.current_page().expect("Current page not set")) { NotebookUpperEnum::IncludedDirectories => { excluded_items = false; &include_tree_view @@ -147,7 +147,7 @@ fn connect_file_dialog(file_dialog_include_exclude_folder_selection: &FileChoose for index in 0..g_files.n_items() { let file = &g_files.item(index); if let Some(file) = file { - let ss = file.clone().downcast::().unwrap(); + let ss = file.clone().downcast::().expect("Failed to downcast to File"); if let Some(path_buf) = ss.path() { folders.push(path_buf); } @@ -192,7 +192,7 @@ fn add_manually_directories(window_main: &Window, tree_view: &TreeView, excluded let added_button = dialog.add_button(&flg!("general_ok_button"), ResponseType::Ok); dialog.add_button(&flg!("general_close_button"), ResponseType::Cancel); - let parent = added_button.parent().unwrap().parent().unwrap().downcast::().unwrap(); // TODO Hack, but not so ugly as before + let parent = added_button.parent().expect("Hack 1").parent().expect("Hack 2").downcast::().expect("Hack 3"); // TODO Hack, but not so ugly as before parent.set_orientation(Orientation::Vertical); parent.insert_child_after(&entry, None::<>k4::Widget>); diff --git a/czkawka_gui/src/connect_things/connect_settings.rs b/czkawka_gui/src/connect_things/connect_settings.rs index 44266109c..e6e361c32 100644 --- a/czkawka_gui/src/connect_things/connect_settings.rs +++ b/czkawka_gui/src/connect_things/connect_settings.rs @@ -177,7 +177,14 @@ pub fn connect_settings(gui_data: &GuiData) { FilterType::Nearest, FilterType::Triangle, ] { - for hash_alg in &[HashAlg::Blockhash, HashAlg::Gradient, HashAlg::DoubleGradient, HashAlg::VertGradient, HashAlg::Mean] { + for hash_alg in &[ + HashAlg::Blockhash, + HashAlg::Gradient, + HashAlg::DoubleGradient, + HashAlg::VertGradient, + HashAlg::Mean, + HashAlg::Median, + ] { let (mut messages, loaded_items) = load_cache_from_file_generalized_by_path::( &get_similar_images_cache_file(hash_size, hash_alg, image_filter), true, diff --git a/czkawka_gui/src/connect_things/connect_similar_image_size_change.rs b/czkawka_gui/src/connect_things/connect_similar_image_size_change.rs index 82e8003f4..a5c209b2d 100644 --- a/czkawka_gui/src/connect_things/connect_similar_image_size_change.rs +++ b/czkawka_gui/src/connect_things/connect_similar_image_size_change.rs @@ -13,7 +13,7 @@ pub fn connect_similar_image_size_change(gui_data: &GuiData) { let label_similar_images_minimal_similarity = gui_data.main_notebook.label_similar_images_minimal_similarity.clone(); let scale_similarity_similar_images = gui_data.main_notebook.scale_similarity_similar_images.clone(); combo_box_image_hash_size.connect_changed(move |combo_box_image_hash_size| { - let hash_size_index = combo_box_image_hash_size.active().unwrap() as usize; + let hash_size_index = combo_box_image_hash_size.active().expect("Failed to get active item") as usize; let hash_size = IMAGES_HASH_SIZE_COMBO_BOX[hash_size_index]; let index = match hash_size { diff --git a/czkawka_gui/src/create_tree_view.rs b/czkawka_gui/src/create_tree_view.rs index bfb2b746c..6c0fff7df 100644 --- a/czkawka_gui/src/create_tree_view.rs +++ b/czkawka_gui/src/create_tree_view.rs @@ -212,7 +212,7 @@ fn create_default_selection_button_column( ) -> (CellRendererToggle, TreeViewColumn) { let renderer = CellRendererToggle::new(); renderer.connect_toggled(move |_r, path| { - let iter = model.iter(&path).unwrap(); + let iter = model.iter(&path).expect("Failed to get iter from tree_path"); let mut fixed = model.get::(&iter, column_id); fixed = !fixed; model.set_value(&iter, column_id as u32, &fixed.to_value()); diff --git a/czkawka_gui/src/gui_structs/gui_about.rs b/czkawka_gui/src/gui_structs/gui_about.rs index 798f425db..51a55a98a 100644 --- a/czkawka_gui/src/gui_structs/gui_about.rs +++ b/czkawka_gui/src/gui_structs/gui_about.rs @@ -20,7 +20,7 @@ impl GuiAbout { let glade_src = include_str!("../../ui/about_dialog.ui").to_string(); let builder = Builder::from_string(glade_src.as_str()); - let about_dialog: gtk4::AboutDialog = builder.object("about_dialog").unwrap(); + let about_dialog: gtk4::AboutDialog = builder.object("about_dialog").expect("Cambalache"); about_dialog.set_modal(true); about_dialog.set_transient_for(Some(window_main)); diff --git a/czkawka_gui/src/gui_structs/gui_bottom_buttons.rs b/czkawka_gui/src/gui_structs/gui_bottom_buttons.rs index 66ee5e16b..7389985d5 100644 --- a/czkawka_gui/src/gui_structs/gui_bottom_buttons.rs +++ b/czkawka_gui/src/gui_structs/gui_bottom_buttons.rs @@ -34,21 +34,21 @@ pub struct GuiBottomButtons { impl GuiBottomButtons { pub fn create_from_builder(builder: >k4::Builder, popover_select: >k4::Popover, popover_sort: >k4::Popover) -> Self { - let buttons_search: gtk4::Button = builder.object("buttons_search").unwrap(); - let buttons_select: gtk4::MenuButton = builder.object("buttons_select").unwrap(); - let buttons_delete: gtk4::Button = builder.object("buttons_delete").unwrap(); - let buttons_save: gtk4::Button = builder.object("buttons_save").unwrap(); - let buttons_symlink: gtk4::Button = builder.object("buttons_symlink").unwrap(); - let buttons_hardlink: gtk4::Button = builder.object("buttons_hardlink").unwrap(); - let buttons_move: gtk4::Button = builder.object("buttons_move").unwrap(); - let buttons_compare: gtk4::Button = builder.object("buttons_compare").unwrap(); - let buttons_sort: gtk4::MenuButton = builder.object("buttons_sort").unwrap(); - - let buttons_show_errors: gtk4::Button = builder.object("buttons_show_errors").unwrap(); - let buttons_show_upper_notebook: gtk4::Button = builder.object("buttons_show_upper_notebook").unwrap(); - - let label_buttons_select: gtk4::Label = builder.object("label_buttons_select").unwrap(); - let label_buttons_sort: gtk4::Label = builder.object("label_buttons_sort").unwrap(); + let buttons_search: gtk4::Button = builder.object("buttons_search").expect("Cambalache"); + let buttons_select: gtk4::MenuButton = builder.object("buttons_select").expect("Cambalache"); + let buttons_delete: gtk4::Button = builder.object("buttons_delete").expect("Cambalache"); + let buttons_save: gtk4::Button = builder.object("buttons_save").expect("Cambalache"); + let buttons_symlink: gtk4::Button = builder.object("buttons_symlink").expect("Cambalache"); + let buttons_hardlink: gtk4::Button = builder.object("buttons_hardlink").expect("Cambalache"); + let buttons_move: gtk4::Button = builder.object("buttons_move").expect("Cambalache"); + let buttons_compare: gtk4::Button = builder.object("buttons_compare").expect("Cambalache"); + let buttons_sort: gtk4::MenuButton = builder.object("buttons_sort").expect("Cambalache"); + + let buttons_show_errors: gtk4::Button = builder.object("buttons_show_errors").expect("Cambalache"); + let buttons_show_upper_notebook: gtk4::Button = builder.object("buttons_show_upper_notebook").expect("Cambalache"); + + let label_buttons_select: gtk4::Label = builder.object("label_buttons_select").expect("Cambalache"); + let label_buttons_sort: gtk4::Label = builder.object("label_buttons_sort").expect("Cambalache"); let gc_buttons_select: GestureClick = GestureClick::new(); let gc_buttons_sort: GestureClick = GestureClick::new(); diff --git a/czkawka_gui/src/gui_structs/gui_compare_images.rs b/czkawka_gui/src/gui_structs/gui_compare_images.rs index 3cc31c016..b46aa26ba 100644 --- a/czkawka_gui/src/gui_structs/gui_compare_images.rs +++ b/czkawka_gui/src/gui_structs/gui_compare_images.rs @@ -36,23 +36,23 @@ impl GuiCompareImages { let glade_src = include_str!("../../ui/compare_images.ui").to_string(); let builder = Builder::from_string(glade_src.as_str()); - let window_compare: gtk4::Window = builder.object("window_compare").unwrap(); + let window_compare: gtk4::Window = builder.object("window_compare").expect("Cambalache"); window_compare.set_title(Some(&flg!("window_compare_images"))); window_compare.set_modal(true); window_compare.set_transient_for(Some(window_main)); - let label_group_info: gtk4::Label = builder.object("label_group_info").unwrap(); + let label_group_info: gtk4::Label = builder.object("label_group_info").expect("Cambalache"); - let button_go_previous_compare_group: gtk4::Button = builder.object("button_go_previous_compare_group").unwrap(); - let button_go_next_compare_group: gtk4::Button = builder.object("button_go_next_compare_group").unwrap(); + let button_go_previous_compare_group: gtk4::Button = builder.object("button_go_previous_compare_group").expect("Cambalache"); + let button_go_next_compare_group: gtk4::Button = builder.object("button_go_next_compare_group").expect("Cambalache"); - let check_button_left_preview_text: gtk4::CheckButton = builder.object("check_button_left_preview_text").unwrap(); - let check_button_right_preview_text: gtk4::CheckButton = builder.object("check_button_right_preview_text").unwrap(); + let check_button_left_preview_text: gtk4::CheckButton = builder.object("check_button_left_preview_text").expect("Cambalache"); + let check_button_right_preview_text: gtk4::CheckButton = builder.object("check_button_right_preview_text").expect("Cambalache"); - let image_compare_left: gtk4::Image = builder.object("image_compare_left").unwrap(); - let image_compare_right: gtk4::Image = builder.object("image_compare_right").unwrap(); + let image_compare_left: gtk4::Image = builder.object("image_compare_left").expect("Cambalache"); + let image_compare_right: gtk4::Image = builder.object("image_compare_right").expect("Cambalache"); - let scrolled_window_compare_choose_images: gtk4::ScrolledWindow = builder.object("scrolled_window_compare_choose_images").unwrap(); + let scrolled_window_compare_choose_images: gtk4::ScrolledWindow = builder.object("scrolled_window_compare_choose_images").expect("Cambalache"); let shared_numbers_of_groups = Rc::new(RefCell::new(0)); let shared_current_of_groups = Rc::new(RefCell::new(0)); diff --git a/czkawka_gui/src/gui_structs/gui_data.rs b/czkawka_gui/src/gui_structs/gui_data.rs index f00e2d31b..64d5966db 100644 --- a/czkawka_gui/src/gui_structs/gui_data.rs +++ b/czkawka_gui/src/gui_structs/gui_data.rs @@ -31,7 +31,7 @@ use crate::gui_structs::gui_popovers_sort::GuiSortPopovers; use crate::gui_structs::gui_progress_dialog::GuiProgressDialog; use crate::gui_structs::gui_settings::GuiSettings; use crate::gui_structs::gui_upper_notebook::GuiUpperNotebook; -use crate::help_functions::BottomButtonsEnum; +use crate::help_functions::{BottomButtonsEnum, SharedState}; use crate::notebook_enums::*; use crate::taskbar_progress::TaskbarProgress; @@ -58,10 +58,6 @@ pub const CZK_ICON_TRASH: &[u8] = include_bytes!("../../icons/czk_trash.svg"); #[derive(Clone)] pub struct GuiData { - // Glade builder - pub glade_src: String, - pub builder: Builder, - // Windows pub window_main: gtk4::Window, @@ -86,17 +82,17 @@ pub struct GuiData { pub shared_buttons: Rc>>>, // State of search results - pub shared_duplication_state: Rc>, - pub shared_empty_folders_state: Rc>, - pub shared_empty_files_state: Rc>, - pub shared_temporary_files_state: Rc>, - pub shared_big_files_state: Rc>, - pub shared_similar_images_state: Rc>, - pub shared_similar_videos_state: Rc>, - pub shared_same_music_state: Rc>, - pub shared_same_invalid_symlinks: Rc>, - pub shared_broken_files_state: Rc>, - pub shared_bad_extensions_state: Rc>, + pub shared_duplication_state: SharedState, + pub shared_empty_folders_state: SharedState, + pub shared_empty_files_state: SharedState, + pub shared_temporary_files_state: SharedState, + pub shared_big_files_state: SharedState, + pub shared_similar_images_state: SharedState, + pub shared_similar_videos_state: SharedState, + pub shared_same_music_state: SharedState, + pub shared_same_invalid_symlinks: SharedState, + pub shared_broken_files_state: SharedState, + pub shared_bad_extensions_state: SharedState, pub preview_path: Rc>, @@ -119,11 +115,11 @@ impl GuiData { let builder = Builder::from_string(glade_src.as_str()); //// Windows - let window_main: gtk4::Window = builder.object("window_main").unwrap(); + let window_main: gtk4::Window = builder.object("window_main").expect("Cambalache"); window_main.set_title(Some(&flg!("window_main_title"))); window_main.show(); - let pixbuf = Pixbuf::from_read(BufReader::new(ICON_ABOUT)).unwrap(); + let pixbuf = Pixbuf::from_read(BufReader::new(ICON_ABOUT)).expect("Couldn't load icon"); window_main.set_application(Some(application)); @@ -177,34 +173,32 @@ impl GuiData { // State of search results - let shared_duplication_state: Rc> = Rc::new(RefCell::new(DuplicateFinder::new())); - let shared_empty_folders_state: Rc> = Rc::new(RefCell::new(EmptyFolder::new())); - let shared_empty_files_state: Rc> = Rc::new(RefCell::new(EmptyFiles::new())); - let shared_temporary_files_state: Rc> = Rc::new(RefCell::new(Temporary::new())); - let shared_big_files_state: Rc> = Rc::new(RefCell::new(BigFile::new())); - let shared_similar_images_state: Rc> = Rc::new(RefCell::new(SimilarImages::new())); - let shared_similar_videos_state: Rc> = Rc::new(RefCell::new(SimilarVideos::new())); - let shared_same_music_state: Rc> = Rc::new(RefCell::new(SameMusic::new())); - let shared_same_invalid_symlinks: Rc> = Rc::new(RefCell::new(InvalidSymlinks::new())); - let shared_broken_files_state: Rc> = Rc::new(RefCell::new(BrokenFiles::new())); - let shared_bad_extensions_state: Rc> = Rc::new(RefCell::new(BadExtensions::new())); + let shared_duplication_state: Rc> = Rc::new(RefCell::new(None)); + let shared_empty_folders_state: Rc> = Rc::new(RefCell::new(None)); + let shared_empty_files_state: Rc> = Rc::new(RefCell::new(None)); + let shared_temporary_files_state: Rc> = Rc::new(RefCell::new(None)); + let shared_big_files_state: Rc> = Rc::new(RefCell::new(None)); + let shared_similar_images_state: Rc> = Rc::new(RefCell::new(None)); + let shared_similar_videos_state: Rc> = Rc::new(RefCell::new(None)); + let shared_same_music_state: Rc> = Rc::new(RefCell::new(None)); + let shared_same_invalid_symlinks: Rc> = Rc::new(RefCell::new(None)); + let shared_broken_files_state: Rc> = Rc::new(RefCell::new(None)); + let shared_bad_extensions_state: Rc> = Rc::new(RefCell::new(None)); let preview_path: Rc> = Rc::new(RefCell::new(String::new())); //// Entry - let entry_info: gtk4::Entry = builder.object("entry_info").unwrap(); + let entry_info: gtk4::Entry = builder.object("entry_info").expect("Cambalache"); //// Bottom - let text_view_errors: gtk4::TextView = builder.object("text_view_errors").unwrap(); - let scrolled_window_errors: gtk4::ScrolledWindow = builder.object("scrolled_window_errors").unwrap(); + let text_view_errors: gtk4::TextView = builder.object("text_view_errors").expect("Cambalache"); + let scrolled_window_errors: gtk4::ScrolledWindow = builder.object("scrolled_window_errors").expect("Cambalache"); scrolled_window_errors.show(); // Not sure why needed, but without it text view errors sometimes hide itself // Used for sending stop signal to thread let (stop_sender, stop_receiver): (crossbeam_channel::Sender<()>, crossbeam_channel::Receiver<()>) = bounded(1); Self { - glade_src, - builder, window_main, main_notebook, upper_notebook, diff --git a/czkawka_gui/src/gui_structs/gui_header.rs b/czkawka_gui/src/gui_structs/gui_header.rs index 729053ecb..d720ad4bf 100644 --- a/czkawka_gui/src/gui_structs/gui_header.rs +++ b/czkawka_gui/src/gui_structs/gui_header.rs @@ -11,8 +11,8 @@ pub struct GuiHeader { impl GuiHeader { pub fn create_from_builder(builder: >k4::Builder) -> Self { - let button_settings: gtk4::Button = builder.object("button_settings").unwrap(); - let button_app_info: gtk4::Button = builder.object("button_app_info").unwrap(); + let button_settings: gtk4::Button = builder.object("button_settings").expect("Cambalache"); + let button_app_info: gtk4::Button = builder.object("button_app_info").expect("Cambalache"); set_icon_of_button(&button_settings, CZK_ICON_SETTINGS); set_icon_of_button(&button_app_info, CZK_ICON_INFO); diff --git a/czkawka_gui/src/gui_structs/gui_main_notebook.rs b/czkawka_gui/src/gui_structs/gui_main_notebook.rs index 153445a58..89bdea1e4 100644 --- a/czkawka_gui/src/gui_structs/gui_main_notebook.rs +++ b/czkawka_gui/src/gui_structs/gui_main_notebook.rs @@ -121,6 +121,8 @@ pub struct GuiMainNotebook { pub check_button_music_genre: CheckButton, pub check_button_music_length: CheckButton, pub check_button_music_approximate_comparison: CheckButton, + pub check_button_music_compare_only_in_title_group: CheckButton, + #[allow(unused)] pub label_audio_check_type: Label, pub combo_box_audio_check_type: ComboBoxText, pub label_same_music_seconds: Label, @@ -131,19 +133,19 @@ pub struct GuiMainNotebook { impl GuiMainNotebook { pub fn create_from_builder(builder: &Builder) -> Self { - let notebook_main: Notebook = builder.object("notebook_main").unwrap(); - - let scrolled_window_duplicate_finder: ScrolledWindow = builder.object("scrolled_window_duplicate_finder").unwrap(); - let scrolled_window_empty_folder_finder: ScrolledWindow = builder.object("scrolled_window_empty_folder_finder").unwrap(); - let scrolled_window_empty_files_finder: ScrolledWindow = builder.object("scrolled_window_empty_files_finder").unwrap(); - let scrolled_window_temporary_files_finder: ScrolledWindow = builder.object("scrolled_window_temporary_files_finder").unwrap(); - let scrolled_window_big_files_finder: ScrolledWindow = builder.object("scrolled_window_big_files_finder").unwrap(); - let scrolled_window_similar_images_finder: ScrolledWindow = builder.object("scrolled_window_similar_images_finder").unwrap(); - let scrolled_window_similar_videos_finder: ScrolledWindow = builder.object("scrolled_window_similar_videos_finder").unwrap(); - let scrolled_window_same_music_finder: ScrolledWindow = builder.object("scrolled_window_same_music_finder").unwrap(); - let scrolled_window_invalid_symlinks: ScrolledWindow = builder.object("scrolled_window_invalid_symlinks").unwrap(); - let scrolled_window_broken_files: ScrolledWindow = builder.object("scrolled_window_broken_files").unwrap(); - let scrolled_window_bad_extensions: ScrolledWindow = builder.object("scrolled_window_bad_extensions").unwrap(); + let notebook_main: Notebook = builder.object("notebook_main").expect("Cambalache"); + + let scrolled_window_duplicate_finder: ScrolledWindow = builder.object("scrolled_window_duplicate_finder").expect("Cambalache"); + let scrolled_window_empty_folder_finder: ScrolledWindow = builder.object("scrolled_window_empty_folder_finder").expect("Cambalache"); + let scrolled_window_empty_files_finder: ScrolledWindow = builder.object("scrolled_window_empty_files_finder").expect("Cambalache"); + let scrolled_window_temporary_files_finder: ScrolledWindow = builder.object("scrolled_window_temporary_files_finder").expect("Cambalache"); + let scrolled_window_big_files_finder: ScrolledWindow = builder.object("scrolled_window_big_files_finder").expect("Cambalache"); + let scrolled_window_similar_images_finder: ScrolledWindow = builder.object("scrolled_window_similar_images_finder").expect("Cambalache"); + let scrolled_window_similar_videos_finder: ScrolledWindow = builder.object("scrolled_window_similar_videos_finder").expect("Cambalache"); + let scrolled_window_same_music_finder: ScrolledWindow = builder.object("scrolled_window_same_music_finder").expect("Cambalache"); + let scrolled_window_invalid_symlinks: ScrolledWindow = builder.object("scrolled_window_invalid_symlinks").expect("Cambalache"); + let scrolled_window_broken_files: ScrolledWindow = builder.object("scrolled_window_broken_files").expect("Cambalache"); + let scrolled_window_bad_extensions: ScrolledWindow = builder.object("scrolled_window_bad_extensions").expect("Cambalache"); let tree_view_duplicate_finder: TreeView = TreeView::new(); tree_view_duplicate_finder.set_widget_name("PIERD"); @@ -204,61 +206,62 @@ impl GuiMainNotebook { let gc_tree_view_bad_extensions: GestureClick = GestureClick::new(); tree_view_bad_extensions.add_controller(gc_tree_view_bad_extensions.clone()); - let combo_box_duplicate_check_method: ComboBoxText = builder.object("combo_box_duplicate_check_method").unwrap(); - let combo_box_duplicate_hash_type: ComboBoxText = builder.object("combo_box_duplicate_hash_type").unwrap(); + let combo_box_duplicate_check_method: ComboBoxText = builder.object("combo_box_duplicate_check_method").expect("Cambalache"); + let combo_box_duplicate_hash_type: ComboBoxText = builder.object("combo_box_duplicate_hash_type").expect("Cambalache"); - let entry_big_files_number: Entry = builder.object("entry_big_files_number").unwrap(); + let entry_big_files_number: Entry = builder.object("entry_big_files_number").expect("Cambalache"); //// Check Buttons - let check_button_duplicate_case_sensitive_name: CheckButton = builder.object("check_button_duplicate_case_sensitive_name").unwrap(); - let check_button_music_title: CheckButton = builder.object("check_button_music_title").unwrap(); - let check_button_music_artist: CheckButton = builder.object("check_button_music_artist").unwrap(); - let check_button_music_year: CheckButton = builder.object("check_button_music_year").unwrap(); - let check_button_music_bitrate: CheckButton = builder.object("check_button_music_bitrate").unwrap(); - let check_button_music_genre: CheckButton = builder.object("check_button_music_genre").unwrap(); - let check_button_music_length: CheckButton = builder.object("check_button_music_length").unwrap(); - let check_button_music_approximate_comparison: CheckButton = builder.object("check_button_music_approximate_comparison").unwrap(); - - let check_button_broken_files_audio: CheckButton = builder.object("check_button_broken_files_audio").unwrap(); - let check_button_broken_files_pdf: CheckButton = builder.object("check_button_broken_files_pdf").unwrap(); - let check_button_broken_files_archive: CheckButton = builder.object("check_button_broken_files_archive").unwrap(); - let check_button_broken_files_image: CheckButton = builder.object("check_button_broken_files_image").unwrap(); - - let scale_similarity_similar_images: Scale = builder.object("scale_similarity_similar_images").unwrap(); - let scale_similarity_similar_videos: Scale = builder.object("scale_similarity_similar_videos").unwrap(); - - let combo_box_image_resize_algorithm: ComboBoxText = builder.object("combo_box_image_resize_algorithm").unwrap(); - let combo_box_image_hash_algorithm: ComboBoxText = builder.object("combo_box_image_hash_algorithm").unwrap(); - let combo_box_image_hash_size: ComboBoxText = builder.object("combo_box_image_hash_size").unwrap(); - let combo_box_big_files_mode: ComboBoxText = builder.object("combo_box_big_files_mode").unwrap(); - - let check_button_image_ignore_same_size: CheckButton = builder.object("check_button_image_ignore_same_size").unwrap(); - let check_button_video_ignore_same_size: CheckButton = builder.object("check_button_video_ignore_same_size").unwrap(); - - let label_similar_images_minimal_similarity: Label = builder.object("label_similar_images_minimal_similarity").unwrap(); - - let label_duplicate_check_method: Label = builder.object("label_duplicate_check_method").unwrap(); - let label_duplicate_hash_type: Label = builder.object("label_duplicate_hash_type").unwrap(); - let label_big_shown_files: Label = builder.object("label_big_shown_files").unwrap(); - let label_image_resize_algorithm: Label = builder.object("label_image_resize_algorithm").unwrap(); - let label_image_hash_type: Label = builder.object("label_image_hash_type").unwrap(); - let label_image_hash_size: Label = builder.object("label_image_hash_size").unwrap(); - let label_image_similarity: Label = builder.object("label_image_similarity").unwrap(); - let label_image_similarity_max: Label = builder.object("label_image_similarity_max").unwrap(); - let label_video_similarity: Label = builder.object("label_video_similarity").unwrap(); - let label_video_similarity_min: Label = builder.object("label_video_similarity_min").unwrap(); - let label_video_similarity_max: Label = builder.object("label_video_similarity_max").unwrap(); - let label_big_files_mode: Label = builder.object("label_big_files_mode").unwrap(); - - let image_preview_similar_images: Image = builder.object("image_preview_similar_images").unwrap(); - let image_preview_duplicates: Image = builder.object("image_preview_duplicates").unwrap(); - - let label_audio_check_type: Label = builder.object("label_audio_check_type").unwrap(); - let combo_box_audio_check_type: ComboBoxText = builder.object("combo_box_audio_check_type").unwrap(); - let label_same_music_seconds: Label = builder.object("label_same_music_seconds").unwrap(); - let label_same_music_similarity: Label = builder.object("label_same_music_similarity").unwrap(); - let scale_seconds_same_music: Scale = builder.object("scale_seconds_same_music").unwrap(); - let scale_similarity_same_music: Scale = builder.object("scale_similarity_same_music").unwrap(); + let check_button_duplicate_case_sensitive_name: CheckButton = builder.object("check_button_duplicate_case_sensitive_name").expect("Cambalache"); + let check_button_music_title: CheckButton = builder.object("check_button_music_title").expect("Cambalache"); + let check_button_music_artist: CheckButton = builder.object("check_button_music_artist").expect("Cambalache"); + let check_button_music_year: CheckButton = builder.object("check_button_music_year").expect("Cambalache"); + let check_button_music_bitrate: CheckButton = builder.object("check_button_music_bitrate").expect("Cambalache"); + let check_button_music_genre: CheckButton = builder.object("check_button_music_genre").expect("Cambalache"); + let check_button_music_length: CheckButton = builder.object("check_button_music_length").expect("Cambalache"); + let check_button_music_approximate_comparison: CheckButton = builder.object("check_button_music_approximate_comparison").expect("Cambalache"); + let check_button_music_compare_only_in_title_group: CheckButton = builder.object("check_button_music_compare_only_in_title_group").expect("Cambalache"); + + let check_button_broken_files_audio: CheckButton = builder.object("check_button_broken_files_audio").expect("Cambalache"); + let check_button_broken_files_pdf: CheckButton = builder.object("check_button_broken_files_pdf").expect("Cambalache"); + let check_button_broken_files_archive: CheckButton = builder.object("check_button_broken_files_archive").expect("Cambalache"); + let check_button_broken_files_image: CheckButton = builder.object("check_button_broken_files_image").expect("Cambalache"); + + let scale_similarity_similar_images: Scale = builder.object("scale_similarity_similar_images").expect("Cambalache"); + let scale_similarity_similar_videos: Scale = builder.object("scale_similarity_similar_videos").expect("Cambalache"); + + let combo_box_image_resize_algorithm: ComboBoxText = builder.object("combo_box_image_resize_algorithm").expect("Cambalache"); + let combo_box_image_hash_algorithm: ComboBoxText = builder.object("combo_box_image_hash_algorithm").expect("Cambalache"); + let combo_box_image_hash_size: ComboBoxText = builder.object("combo_box_image_hash_size").expect("Cambalache"); + let combo_box_big_files_mode: ComboBoxText = builder.object("combo_box_big_files_mode").expect("Cambalache"); + + let check_button_image_ignore_same_size: CheckButton = builder.object("check_button_image_ignore_same_size").expect("Cambalache"); + let check_button_video_ignore_same_size: CheckButton = builder.object("check_button_video_ignore_same_size").expect("Cambalache"); + + let label_similar_images_minimal_similarity: Label = builder.object("label_similar_images_minimal_similarity").expect("Cambalache"); + + let label_duplicate_check_method: Label = builder.object("label_duplicate_check_method").expect("Cambalache"); + let label_duplicate_hash_type: Label = builder.object("label_duplicate_hash_type").expect("Cambalache"); + let label_big_shown_files: Label = builder.object("label_big_shown_files").expect("Cambalache"); + let label_image_resize_algorithm: Label = builder.object("label_image_resize_algorithm").expect("Cambalache"); + let label_image_hash_type: Label = builder.object("label_image_hash_type").expect("Cambalache"); + let label_image_hash_size: Label = builder.object("label_image_hash_size").expect("Cambalache"); + let label_image_similarity: Label = builder.object("label_image_similarity").expect("Cambalache"); + let label_image_similarity_max: Label = builder.object("label_image_similarity_max").expect("Cambalache"); + let label_video_similarity: Label = builder.object("label_video_similarity").expect("Cambalache"); + let label_video_similarity_min: Label = builder.object("label_video_similarity_min").expect("Cambalache"); + let label_video_similarity_max: Label = builder.object("label_video_similarity_max").expect("Cambalache"); + let label_big_files_mode: Label = builder.object("label_big_files_mode").expect("Cambalache"); + + let image_preview_similar_images: Image = builder.object("image_preview_similar_images").expect("Cambalache"); + let image_preview_duplicates: Image = builder.object("image_preview_duplicates").expect("Cambalache"); + + let label_audio_check_type: Label = builder.object("label_audio_check_type").expect("Cambalache"); + let combo_box_audio_check_type: ComboBoxText = builder.object("combo_box_audio_check_type").expect("Cambalache"); + let label_same_music_seconds: Label = builder.object("label_same_music_seconds").expect("Cambalache"); + let label_same_music_similarity: Label = builder.object("label_same_music_similarity").expect("Cambalache"); + let scale_seconds_same_music: Scale = builder.object("scale_seconds_same_music").expect("Cambalache"); + let scale_similarity_same_music: Scale = builder.object("scale_similarity_same_music").expect("Cambalache"); Self { notebook_main, @@ -294,42 +297,6 @@ impl GuiMainNotebook { evk_tree_view_same_music_finder, evk_tree_view_invalid_symlinks, evk_tree_view_broken_files, - entry_big_files_number, - check_button_music_title, - check_button_music_artist, - check_button_music_year, - check_button_music_bitrate, - check_button_music_genre, - check_button_music_length, - check_button_music_approximate_comparison, - label_audio_check_type, - scale_similarity_similar_images, - scale_similarity_similar_videos, - check_button_broken_files_audio, - check_button_broken_files_pdf, - check_button_broken_files_archive, - check_button_image_ignore_same_size, - label_similar_images_minimal_similarity, - label_duplicate_check_method, - label_duplicate_hash_type, - combo_box_duplicate_check_method, - label_big_shown_files, - label_image_resize_algorithm, - label_image_hash_type, - label_image_hash_size, - combo_box_image_resize_algorithm, - combo_box_image_hash_algorithm, - label_image_similarity, - label_image_similarity_max, - label_video_similarity, - label_video_similarity_min, - label_video_similarity_max, - image_preview_similar_images, - image_preview_duplicates, - combo_box_duplicate_hash_type, - combo_box_image_hash_size, - check_button_video_ignore_same_size, - check_button_duplicate_case_sensitive_name, evk_tree_view_bad_extensions, gc_tree_view_duplicate_finder, gc_tree_view_empty_folder_finder, @@ -342,9 +309,46 @@ impl GuiMainNotebook { gc_tree_view_invalid_symlinks, gc_tree_view_broken_files, gc_tree_view_bad_extensions, - combo_box_big_files_mode, + combo_box_duplicate_check_method, + combo_box_duplicate_hash_type, + label_duplicate_check_method, + label_duplicate_hash_type, + check_button_duplicate_case_sensitive_name, + image_preview_duplicates, + label_big_shown_files, + entry_big_files_number, label_big_files_mode, + combo_box_big_files_mode, + scale_similarity_similar_images, + label_image_resize_algorithm, + label_image_hash_type, + label_image_hash_size, + combo_box_image_resize_algorithm, + combo_box_image_hash_algorithm, + combo_box_image_hash_size, + check_button_image_ignore_same_size, + check_button_video_ignore_same_size, + label_image_similarity, + label_image_similarity_max, + image_preview_similar_images, + label_similar_images_minimal_similarity, + label_video_similarity, + label_video_similarity_min, + label_video_similarity_max, + scale_similarity_similar_videos, + check_button_broken_files_audio, + check_button_broken_files_pdf, + check_button_broken_files_archive, check_button_broken_files_image, + check_button_music_title, + check_button_music_artist, + check_button_music_year, + check_button_music_bitrate, + check_button_music_genre, + check_button_music_length, + check_button_music_approximate_comparison, + check_button_music_compare_only_in_title_group, + label_audio_check_type, combo_box_audio_check_type, label_same_music_seconds, label_same_music_similarity, @@ -434,7 +438,7 @@ impl GuiMainNotebook { self.scale_similarity_similar_videos.set_tooltip_text(Some(&flg!("same_music_tooltip"))); { - let hash_size_index = self.combo_box_image_hash_size.active().unwrap() as usize; + let hash_size_index = self.combo_box_image_hash_size.active().expect("Some hash size must be active") as usize; let hash_size = IMAGES_HASH_SIZE_COMBO_BOX[hash_size_index]; match hash_size { 8 => { @@ -475,9 +479,9 @@ impl GuiMainNotebook { ] { self.notebook_main .tab_label(&vec_children[main_enum]) - .unwrap() + .expect("Tab label must be set") .downcast::