1
0
Fork 0
mirror of synced 2024-04-28 09:33:30 +12:00

Add sort button (#894)

* Add sort button

* Update lofty and gtk-rs

* Fix bug with invalid music tags with reference folders

* Remove try at

* Fix loading of certain directories with disabled loading settings at start

* Change FileChooserDialog to FileChooserNative

* Any

* Copy Clone

* Popover sort basic

* Builder using

* Basic sorting

* Fix not working sorting by size

* Changelog
This commit is contained in:
Rafał Mikrut 2023-02-19 10:21:14 +01:00 committed by GitHub
parent 8ea9b4b800
commit f1c6e6da17
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
48 changed files with 1185 additions and 568 deletions

371
Cargo.lock generated
View file

@ -46,9 +46,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.68"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800"
[[package]]
name = "arc-swap"
@ -70,9 +70,9 @@ checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
[[package]]
name = "async-trait"
version = "0.1.63"
version = "0.1.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eff18d764974428cf3a9328e23fc5c986f5fbed46e6cd4cdf42544df5d297ec1"
checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2"
dependencies = [
"proc-macro2",
"quote",
@ -102,9 +102,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]]
name = "base64"
version = "0.20.0"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ea22880d78093b0cbe17c89f64a7d457941e65759157ec6cb31a31d652b05e5"
checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
[[package]]
name = "base64ct"
@ -229,9 +229,9 @@ dependencies = [
[[package]]
name = "cairo-rs"
version = "0.16.7"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3125b15ec28b84c238f6f476c6034016a5f6cc0221cb514ca46c532139fc97d"
checksum = "a8af54f5d48af1226928adc1f57edd22f5df1349e7da1fc96ae15cf43db0e871"
dependencies = [
"bitflags",
"cairo-sys-rs",
@ -243,9 +243,9 @@ dependencies = [
[[package]]
name = "cairo-sys-rs"
version = "0.16.3"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c48f4af05fabdcfa9658178e1326efa061853f040ce7d72e33af6885196f421"
checksum = "f55382a01d30e5e53f185eee269124f5e21ab526595b872751278dfbb463594e"
dependencies = [
"glib-sys",
"libc",
@ -254,9 +254,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.0.78"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
[[package]]
name = "cfb"
@ -310,9 +310,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.1.4"
version = "4.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f13b9c79b5d1dd500d20ef541215a6423c75829ef43117e1b4d17fd8af0b5d76"
checksum = "ec0b0588d44d4d63a87dbd75c136c166bbfd9a86a31cb89e09906521c7d3f5e3"
dependencies = [
"bitflags",
"clap_derive",
@ -458,9 +458,9 @@ dependencies = [
[[package]]
name = "cxx"
version = "1.0.88"
version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "322296e2f2e5af4270b54df9e85a02ff037e271af20ba3e7fe1575515dc840b8"
checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62"
dependencies = [
"cc",
"cxxbridge-flags",
@ -470,9 +470,9 @@ dependencies = [
[[package]]
name = "cxx-build"
version = "1.0.88"
version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "017a1385b05d631e7875b1f151c9f012d37b53491e2a87f65bff5c262b2111d8"
checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690"
dependencies = [
"cc",
"codespan-reporting",
@ -485,15 +485,15 @@ dependencies = [
[[package]]
name = "cxxbridge-flags"
version = "1.0.88"
version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c26bbb078acf09bc1ecda02d4223f03bdd28bd4874edcb0379138efc499ce971"
checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf"
[[package]]
name = "cxxbridge-macro"
version = "1.0.88"
version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "357f40d1f06a24b60ae1fe122542c1fb05d28d32acb2aed064e84bc2ad1e252e"
checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892"
dependencies = [
"proc-macro2",
"quote",
@ -675,9 +675,9 @@ checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]]
name = "encoding_rs"
version = "0.8.31"
version = "0.8.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b"
checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394"
dependencies = [
"cfg-if",
]
@ -716,9 +716,9 @@ dependencies = [
[[package]]
name = "exr"
version = "1.5.2"
version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eb5f255b5980bb0c8cf676b675d1a99be40f316881444f44e0462eaf5df5ded"
checksum = "e8af5ef47e2ed89d23d0ecbc1b681b30390069de70260937877514377fc24feb"
dependencies = [
"bit_field",
"flume",
@ -727,13 +727,14 @@ dependencies = [
"miniz_oxide",
"smallvec",
"threadpool",
"zune-inflate",
]
[[package]]
name = "fastrand"
version = "1.8.0"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
dependencies = [
"instant",
]
@ -874,16 +875,22 @@ dependencies = [
]
[[package]]
name = "fs_extra"
version = "1.2.0"
name = "four-cc"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394"
checksum = "92d73a076bdabd78c2f9045dba1b90664a655fa8372581c238596e1eb3a5e1b7"
[[package]]
name = "fs_extra"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
[[package]]
name = "futures"
version = "0.3.25"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0"
checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84"
dependencies = [
"futures-channel",
"futures-core",
@ -896,9 +903,9 @@ dependencies = [
[[package]]
name = "futures-channel"
version = "0.3.25"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed"
checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5"
dependencies = [
"futures-core",
"futures-sink",
@ -906,15 +913,15 @@ dependencies = [
[[package]]
name = "futures-core"
version = "0.3.25"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac"
checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608"
[[package]]
name = "futures-executor"
version = "0.3.25"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2"
checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e"
dependencies = [
"futures-core",
"futures-task",
@ -923,15 +930,15 @@ dependencies = [
[[package]]
name = "futures-io"
version = "0.3.25"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb"
checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531"
[[package]]
name = "futures-macro"
version = "0.3.25"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d"
checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70"
dependencies = [
"proc-macro2",
"quote",
@ -940,21 +947,21 @@ dependencies = [
[[package]]
name = "futures-sink"
version = "0.3.25"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9"
checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364"
[[package]]
name = "futures-task"
version = "0.3.25"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea"
checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366"
[[package]]
name = "futures-util"
version = "0.3.25"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6"
checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1"
dependencies = [
"futures-channel",
"futures-core",
@ -970,22 +977,23 @@ dependencies = [
[[package]]
name = "gdk-pixbuf"
version = "0.16.7"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3578c60dee9d029ad86593ed88cb40f35c1b83360e12498d055022385dd9a05"
checksum = "b023fbe0c6b407bd3d9805d107d9800da3829dc5a676653210f1d5f16d7f59bf"
dependencies = [
"bitflags",
"gdk-pixbuf-sys",
"gio",
"glib",
"libc",
"once_cell",
]
[[package]]
name = "gdk-pixbuf-sys"
version = "0.16.3"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3092cf797a5f1210479ea38070d9ae8a5b8e9f8f1be9f32f4643c529c7d70016"
checksum = "7b41bd2b44ed49d99277d3925652a163038bd5ed943ec9809338ffb2f4391e3b"
dependencies = [
"gio-sys",
"glib-sys",
@ -996,9 +1004,9 @@ dependencies = [
[[package]]
name = "gdk4"
version = "0.5.5"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb2181330ebf9d091f8ea7fed6877f7adc92114128592e1fdaeb1da28e0d01e9"
checksum = "6e4887e17b6926db51f1e538d871a8b1f5ceb5dfa3bd0034dc42ec355b390d8f"
dependencies = [
"bitflags",
"cairo-rs",
@ -1012,9 +1020,9 @@ dependencies = [
[[package]]
name = "gdk4-sys"
version = "0.5.5"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de55cb49432901fe2b3534177fa06844665b9b0911d85d8601a8d8b88b7791db"
checksum = "f4993c019bf03d18137c00ddafb2b23e73f7cbb45ae244f52af2542a3f4a9452"
dependencies = [
"cairo-sys-rs",
"gdk-pixbuf-sys",
@ -1075,9 +1083,9 @@ dependencies = [
[[package]]
name = "gio"
version = "0.16.7"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a1c84b4534a290a29160ef5c6eff2a9c95833111472e824fc5cb78b513dd092"
checksum = "1981edf8679d2f2c8ec3120015867f45aa0a1c2d5e3e129ca2f7dda174d3d2a9"
dependencies = [
"bitflags",
"futures-channel",
@ -1095,9 +1103,9 @@ dependencies = [
[[package]]
name = "gio-sys"
version = "0.16.3"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9b693b8e39d042a95547fc258a7b07349b1f0b48f4b2fa3108ba3c51c0b5229"
checksum = "b5d3076ecb86c8c3a672c9843d6232b3a344fb81d304d0ba1ac64b23343efa46"
dependencies = [
"glib-sys",
"gobject-sys",
@ -1108,9 +1116,9 @@ dependencies = [
[[package]]
name = "glib"
version = "0.16.7"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddd4df61a866ed7259d6189b8bcb1464989a77f1d85d25d002279bbe9dd38b2f"
checksum = "91b429154ec5943185aeeaf79e646297567b6a056965f1e89da2657a0e23255b"
dependencies = [
"bitflags",
"futures-channel",
@ -1123,6 +1131,7 @@ dependencies = [
"glib-sys",
"gobject-sys",
"libc",
"memchr",
"once_cell",
"smallvec",
"thiserror",
@ -1130,9 +1139,9 @@ dependencies = [
[[package]]
name = "glib-macros"
version = "0.16.3"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e084807350b01348b6d9dbabb724d1a0bb987f47a2c85de200e98e12e30733bf"
checksum = "9bc80ac951300ca288dd9ab3863743c37a608fb0e5ca12863495640ec6b781ab"
dependencies = [
"anyhow",
"heck",
@ -1145,9 +1154,9 @@ dependencies = [
[[package]]
name = "glib-sys"
version = "0.16.3"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61a4f46316d06bfa33a7ac22df6f0524c8be58e3db2d9ca99ccb1f357b62a65"
checksum = "9ddcb73fa8236277bedadaaadb76aef49c85d66340f83bece244f46c2d4f0e01"
dependencies = [
"libc",
"system-deps",
@ -1170,9 +1179,9 @@ dependencies = [
[[package]]
name = "gobject-sys"
version = "0.16.3"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3520bb9c07ae2a12c7f2fbb24d4efc11231c8146a86956413fb1a79bb760a0f1"
checksum = "9a0155d388840c77d61b033b66ef4f9bc7f4133d83df83572d6b4fb234a3be7d"
dependencies = [
"glib-sys",
"libc",
@ -1181,9 +1190,9 @@ dependencies = [
[[package]]
name = "graphene-rs"
version = "0.16.3"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95ecb4d347e6d09820df3bdfd89a74a8eec07753a06bb92a3aac3ad31d04447b"
checksum = "21cf11565bb0e4dfc2f99d4775b6c329f0d40a2cff9c0066214d31a0e1b46256"
dependencies = [
"glib",
"graphene-sys",
@ -1192,9 +1201,9 @@ dependencies = [
[[package]]
name = "graphene-sys"
version = "0.16.3"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9aa82337d3972b4eafdea71e607c23f47be6f27f749aab613f1ad8ddbe6dcd6"
checksum = "cf80a4849a8d9565410a8fec6fc3678e9c617f4ac7be182ca55ab75016e07af9"
dependencies = [
"glib-sys",
"libc",
@ -1204,9 +1213,9 @@ dependencies = [
[[package]]
name = "gsk4"
version = "0.5.5"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "591239f5c52ca803b222124ac9c47f230cd180cee9b114c4d672e4a94b74f491"
checksum = "432f981e4ea9f0739a5731d8a649acb794a3a729d2254e559ce7d613b17caf95"
dependencies = [
"bitflags",
"cairo-rs",
@ -1220,9 +1229,9 @@ dependencies = [
[[package]]
name = "gsk4-sys"
version = "0.5.5"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "195a63f0be42529f98c3eb3bae0decfd0428ba2cc683b3e20ced88f340904ec5"
checksum = "096cb59175b0915ebf69c05a45263c0c989bd8537b8f2169912d0de644ba6a76"
dependencies = [
"cairo-sys-rs",
"gdk4-sys",
@ -1236,9 +1245,9 @@ dependencies = [
[[package]]
name = "gtk4"
version = "0.5.5"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd89dba65def483a233dc4fdd3f3dab01576e3d83f80f6c9303ebe421661855e"
checksum = "73421200ad9c3919d0720779b345b05d31a6ce9998e74fc27012f12580822e46"
dependencies = [
"bitflags",
"cairo-rs",
@ -1259,9 +1268,9 @@ dependencies = [
[[package]]
name = "gtk4-macros"
version = "0.5.5"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "832687a415d9d8bc11fe9c17dda1bf13ee262c41b995dd4df1d1cce33cead405"
checksum = "db4676c4f90d8b010e88cb4558f61f47d76d6f6b8e6f6b89e62640f443907f61"
dependencies = [
"anyhow",
"proc-macro-crate",
@ -1273,9 +1282,9 @@ dependencies = [
[[package]]
name = "gtk4-sys"
version = "0.5.5"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e370564e3fdacff7cffc99f7366b6a4689feb44e819d3ccee598a9a215b71605"
checksum = "e13cf3bc9559f71963c957eb639060b643e1276ae47b892ef6091d5bc15c3e1b"
dependencies = [
"cairo-sys-rs",
"gdk-pixbuf-sys",
@ -1313,9 +1322,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "heck"
version = "0.4.0"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "hermit-abi"
@ -1326,6 +1335,12 @@ dependencies = [
"libc",
]
[[package]]
name = "hermit-abi"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
[[package]]
name = "hmac"
version = "0.12.1"
@ -1558,24 +1573,24 @@ dependencies = [
[[package]]
name = "io-lifetimes"
version = "1.0.4"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7d6c6f8c91b4b9ed43484ad1a938e393caf35960fce7f82a040497207bd8e9e"
checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3"
dependencies = [
"libc",
"windows-sys",
"windows-sys 0.45.0",
]
[[package]]
name = "is-terminal"
version = "0.4.2"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189"
checksum = "22e18b0a45d56fe973d6db23972bf5bc46f988a4a2385deac9cc29572f09daef"
dependencies = [
"hermit-abi",
"hermit-abi 0.3.1",
"io-lifetimes",
"rustix",
"windows-sys",
"windows-sys 0.45.0",
]
[[package]]
@ -1613,9 +1628,9 @@ dependencies = [
[[package]]
name = "js-sys"
version = "0.3.60"
version = "0.3.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
dependencies = [
"wasm-bindgen",
]
@ -1640,19 +1655,20 @@ checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]]
name = "libheif-rs"
version = "0.15.1"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edf58b5301fc9c13d446e2a75e363ebf848f624ab7026d5cda567b11a6f21056"
checksum = "0b324293a40899ce7fa7077d5ab5ccfc3bf54bac4fdf06d2328cecbedf9bfe41"
dependencies = [
"enumn",
"four-cc",
"libheif-sys",
]
[[package]]
name = "libheif-sys"
version = "1.12.0"
version = "1.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9426b3c799fe53b9636aac80ddc60efa5060c1959faee2e9d3edf0da6b8536a"
checksum = "6af8b7a4151ae10f6d2e8684f7172c43f09c0258c84190fd9704422588ceec63"
dependencies = [
"libc",
]
@ -1709,11 +1725,11 @@ dependencies = [
[[package]]
name = "lofty"
version = "0.10.0"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "935294f6c058df75c16721ac510398d42afb4cb6a4e3752737e362166fe2ba67"
checksum = "fed685b48b30ef8f5213a32422d08c80b765f954ad5b6f6b634f901e7844ca52"
dependencies = [
"base64 0.20.0",
"base64 0.21.0",
"byteorder",
"cfg-if",
"flate2",
@ -1726,9 +1742,9 @@ dependencies = [
[[package]]
name = "lofty_attr"
version = "0.5.0"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02f2d46cb443ab8285492be02e5dda3e3a3f39f07cd50e5655069567e67a7de2"
checksum = "336dfabb2fdfd932cebfcaa5d0fc57abac0d49f6ae9ddaa7c47a51bf9f74f966"
dependencies = [
"proc-macro2",
"quote",
@ -1923,7 +1939,7 @@ version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
"hermit-abi",
"hermit-abi 0.2.6",
"libc",
]
@ -1958,18 +1974,18 @@ dependencies = [
[[package]]
name = "ogg_pager"
version = "0.4.0"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a05065bb6e0b933aef28cae4c5469b85011aa0d0285bd5fe3f568bed1f1a1bc"
checksum = "0d218a406e5de88e1c492d0162d569916f7436efe851ba5cc40a4bf4fa97cb40"
dependencies = [
"byteorder",
]
[[package]]
name = "once_cell"
version = "1.17.0"
version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]]
name = "opaque-debug"
@ -1984,7 +2000,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2078c0039e6a54a0c42c28faa984e115fb4c2d5bf2208f77d1961002df8576f8"
dependencies = [
"pathdiff",
"windows-sys",
"windows-sys 0.42.0",
]
[[package]]
@ -2001,9 +2017,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]]
name = "pango"
version = "0.16.5"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdff66b271861037b89d028656184059e03b0b6ccb36003820be19f7200b1e94"
checksum = "243c048be90312220fb3bd578176eed8290568274a93c95040289d39349384bc"
dependencies = [
"bitflags",
"gio",
@ -2015,9 +2031,9 @@ dependencies = [
[[package]]
name = "pango-sys"
version = "0.16.3"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e134909a9a293e04d2cc31928aa95679c5e4df954d0b85483159bd20d8f047f"
checksum = "4293d0f0b5525eb5c24734d30b0ed02cd02aa734f216883f376b54de49625de8"
dependencies = [
"glib-sys",
"gobject-sys",
@ -2037,15 +2053,15 @@ dependencies = [
[[package]]
name = "parking_lot_core"
version = "0.9.6"
version = "0.9.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba1ef8814b5c993410bb3adfad7a5ed269563e4a2f90c41f5d85be7fb47133bf"
checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-sys",
"windows-sys 0.45.0",
]
[[package]]
@ -2129,9 +2145,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
[[package]]
name = "pest"
version = "2.5.4"
version = "2.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ab62d2fa33726dbe6321cc97ef96d8cde531e3eeaf858a058de53a8a6d40d8f"
checksum = "028accff104c4e513bad663bbcd2ad7cfd5304144404c31ed0a77ac103d00660"
dependencies = [
"thiserror",
"ucd-trie",
@ -2238,9 +2254,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.50"
version = "1.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
dependencies = [
"unicode-ident",
]
@ -2483,16 +2499,16 @@ dependencies = [
[[package]]
name = "rustix"
version = "0.36.7"
version = "0.36.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fdebc4b395b7fbb9ab11e462e20ed9051e7b16e42d24042c776eca0ac81b03"
checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
"windows-sys",
"windows-sys 0.45.0",
]
[[package]]
@ -2592,9 +2608,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.91"
version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76"
dependencies = [
"itoa",
"ryu",
@ -2644,6 +2660,12 @@ dependencies = [
"lazy_static",
]
[[package]]
name = "simd-adler32"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14a5df39617d7c8558154693a1bb8157a4aab8179209540cc0b10e5dc24e0b18"
[[package]]
name = "slab"
version = "0.4.7"
@ -2683,9 +2705,9 @@ dependencies = [
[[package]]
name = "spin"
version = "0.9.4"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09"
checksum = "7dccf47db1b41fa1573ed27ccf5e08e3ca771cb994f776668c5ebda893b248fc"
dependencies = [
"lock_api",
]
@ -2979,10 +3001,11 @@ dependencies = [
[[package]]
name = "thread_local"
version = "1.1.4"
version = "1.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
dependencies = [
"cfg-if",
"once_cell",
]
@ -3019,14 +3042,12 @@ dependencies = [
[[package]]
name = "time"
version = "0.3.17"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376"
checksum = "53250a3b3fed8ff8fd988587d8925d26a83ac3845d9e03b220b37f34c2b8d6c2"
dependencies = [
"itoa",
"serde",
"time-core",
"time-macros",
]
[[package]]
@ -3035,15 +3056,6 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
[[package]]
name = "time-macros"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2"
dependencies = [
"time-core",
]
[[package]]
name = "tinystr"
version = "0.7.1"
@ -3064,9 +3076,9 @@ dependencies = [
[[package]]
name = "tinyvec_macros"
version = "0.1.0"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "toml"
@ -3168,9 +3180,9 @@ dependencies = [
[[package]]
name = "trash"
version = "3.0.0"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f74274f95c7e7340d7c5bcd4863af87a9ed6a117cf73cf483c71cb4d744a948"
checksum = "a27b2a127810fceb959593bbc6c7b8e0282c2d318d76f0749252197c52a1dd0c"
dependencies = [
"chrono",
"libc",
@ -3179,7 +3191,7 @@ dependencies = [
"once_cell",
"scopeguard",
"url",
"windows 0.43.0",
"windows 0.44.0",
]
[[package]]
@ -3277,9 +3289,9 @@ dependencies = [
[[package]]
name = "uuid"
version = "1.2.2"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "422ee0de9031b5b948b97a8fc04e3aa35230001a722ddd27943e0be31564ce4c"
checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79"
[[package]]
name = "valuable"
@ -3341,9 +3353,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.83"
version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@ -3351,9 +3363,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.83"
version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
dependencies = [
"bumpalo",
"log",
@ -3366,9 +3378,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.83"
version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@ -3376,9 +3388,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.83"
version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
dependencies = [
"proc-macro2",
"quote",
@ -3389,9 +3401,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.83"
version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
[[package]]
name = "weezl"
@ -3445,9 +3457,18 @@ dependencies = [
[[package]]
name = "windows"
version = "0.43.0"
version = "0.44.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04662ed0e3e5630dfa9b26e4cb823b817f1a9addda855d973a9458c236556244"
checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-sys"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc 0.42.1",
@ -3460,9 +3481,18 @@ dependencies = [
[[package]]
name = "windows-sys"
version = "0.42.0"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc 0.42.1",
@ -3562,9 +3592,9 @@ dependencies = [
[[package]]
name = "zip"
version = "0.6.3"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "537ce7411d25e54e8ae21a7ce0b15840e7bfcff15b51d697ec3266cc76bdf080"
checksum = "0445d0fbc924bb93539b4316c11afb121ea39296f99a3c4c9edad09e3658cdef"
dependencies = [
"aes",
"byteorder",
@ -3576,5 +3606,14 @@ dependencies = [
"hmac",
"pbkdf2",
"sha1",
"time 0.3.17",
"time 0.3.19",
]
[[package]]
name = "zune-inflate"
version = "0.2.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589245df6230839c305984dcc0a8385cc72af1fd223f360ffd5d65efa4216d40"
dependencies = [
"simd-adler32",
]

View file

@ -14,6 +14,6 @@ panic = "unwind"
# LTO setting is disabled by default, because release mode is usually needed to develop app and compilation with LTO would take a lot of time
#lto = "fat"
# Optimize all dependencies except application/workspaces
# Optimize all dependencies except application/workspaces, even in debug builds
[profile.dev.package."*"]
opt-level = 3

View file

@ -1,3 +1,17 @@
## 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)
- 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)
- 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)

View file

@ -369,7 +369,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Icons used inside GUI version
Reshot license
Reshot license - https://www.reshot.com/
czkawka_gui/icons/*

View file

@ -1,6 +1,6 @@
![com github qarmin czkawka](https://user-images.githubusercontent.com/41945903/102616149-66490400-4137-11eb-9cd6-813b2b070834.png)
**Czkawka** (_tch•kav•ka_ (IPA: [ʈ͡ʂkafka]), "hiccup" in Polish) is a simple, fast and free app to remove unnecessary files from your computer.
**Czkawka** (_tch•kav•ka_ (IPA: [ˈʧ̑kafka]), "hiccup" in Polish) is a simple, fast and free app to remove unnecessary files from your computer.
## Features
- Written in memory-safe Rust

View file

@ -26,13 +26,13 @@ hamming = "0.1.3"
# Needed by same music
bitflags = "1.3.2"
lofty = "0.10.0"
lofty = "0.11.0"
# Futures - needed by async progress sender
futures = "0.3.25"
futures = "0.3.26"
# Needed by broken files
zip = { version = "0.6.3", features = ["aes-crypto", "bzip2", "deflate", "time"], default-features = false }
zip = { version = "0.6.4", features = ["aes-crypto", "bzip2", "deflate", "time"], default-features = false }
audio_checker = "0.1.0"
pdf = "0.8.0"
@ -56,7 +56,7 @@ serde_json = "1.0"
i18n-embed = { version = "0.13.8", features = ["fluent-system", "desktop-requester"] }
i18n-embed-fl = "0.6.5"
rust-embed = "6.4.2"
once_cell = "1.17.0"
once_cell = "1.17.1"
# Raw image files
rawloader = "0.37.1"
@ -69,7 +69,7 @@ infer = "0.12.0"
num_cpus = "1.15.0"
# Heif/Heic
libheif-rs = { version = "0.15.1", optional = true }
libheif-rs = { version = "0.16.0", optional = true }
anyhow = { version = "1.0", optional = true }
state="0.5.3"

View file

@ -43,7 +43,7 @@ pub enum SearchMode {
SmallestFiles,
}
#[derive(Eq, PartialEq, Clone, Debug)]
#[derive(Eq, PartialEq, Clone, Debug, Copy)]
pub enum DeleteMethod {
None,
Delete,
@ -394,7 +394,7 @@ impl BigFile {
match self.delete_method {
DeleteMethod::Delete => {
for (_, file_entry) in &self.big_files {
if fs::remove_file(file_entry.path.clone()).is_err() {
if fs::remove_file(&file_entry.path).is_err() {
self.text_messages.warnings.push(file_entry.path.display().to_string());
}
}

View file

@ -10,6 +10,7 @@ use std::time::{Duration, SystemTime, UNIX_EPOCH};
use std::{fs, mem, panic, thread};
use crossbeam_channel::Receiver;
use pdf::object::ParseOptions;
use pdf::PdfError;
use pdf::PdfError::Try;
use rayon::prelude::*;
@ -33,7 +34,7 @@ pub struct ProgressData {
pub files_to_check: usize,
}
#[derive(Eq, PartialEq, Clone, Debug)]
#[derive(Eq, PartialEq, Clone, Debug, Copy)]
pub enum DeleteMethod {
None,
Delete,
@ -521,41 +522,40 @@ impl BrokenFiles {
Err(_inspected) => Some(None),
},
TypeOfFile::PDF => {
match fs::read(&file_entry.path) {
Ok(content) => {
// Will be available in pdf > 0.7.2
// let parser_options = ParseOptions {
// allow_error_in_option: true,
// allow_xref_error: true,
// allow_invalid_ops: true,
// allow_missing_endobj: true,
// };
// if let Err(e) = pdf::file::File::from_data_with_options(content, parser_options) {
TypeOfFile::PDF => match fs::read(&file_entry.path) {
Ok(content) => {
let parser_options = ParseOptions::tolerant(); // Only show as broken files with really big bugs
let mut file_entry_clone = file_entry.clone();
let result = panic::catch_unwind(|| {
if let Err(e) = pdf::file::File::from_data(content) {
file_entry.error_string = e.to_string();
let error = unpack_pdf_error(e);
if let PdfError::InvalidPassword = error {
return Some(None);
let mut file_entry_clone = file_entry.clone();
let result = panic::catch_unwind(|| {
if let Err(e) = pdf::file::File::from_data_with_options(content, parser_options) {
let mut error_string = e.to_string();
// Workaround for strange error message https://github.com/qarmin/czkawka/issues/898
if error_string.starts_with("Try at") {
if let Some(start_index) = error_string.find("/pdf-") {
error_string = format!("Decoding error in pdf-rs library - {}", &error_string[start_index..]);
}
}
Some(Some(file_entry))
});
if let Ok(pdf_result) = result {
pdf_result
} else {
let message = create_crash_message("PDF-rs", &file_entry_clone.path.to_string_lossy(), "https://github.com/pdf-rs/pdf");
println!("{message}");
file_entry_clone.error_string = message;
Some(Some(file_entry_clone))
file_entry.error_string = error_string;
let error = unpack_pdf_error(e);
if let PdfError::InvalidPassword = error {
return Some(None);
}
}
Some(Some(file_entry))
});
if let Ok(pdf_result) = result {
pdf_result
} else {
let message = create_crash_message("PDF-rs", &file_entry_clone.path.to_string_lossy(), "https://github.com/pdf-rs/pdf");
println!("{message}");
file_entry_clone.error_string = message;
Some(Some(file_entry_clone))
}
Err(_inspected) => Some(None),
}
}
Err(_inspected) => Some(None),
},
// This means that cache read invalid value because maybe cache comes from different czkawka version
TypeOfFile::Unknown => Some(None),

View file

@ -128,7 +128,7 @@ pub fn open_cache_folder(cache_file_name: &str, save_to_cache: bool, use_json: b
pub fn get_dynamic_image_from_heic(path: &str) -> Result<DynamicImage> {
let im = HeifContext::read_from_file(path)?;
let handle = im.primary_image_handle()?;
let image = handle.decode(ColorSpace::Rgb(RgbChroma::Rgb), false)?;
let image = handle.decode(ColorSpace::Rgb(RgbChroma::Rgb), None)?;
let width = image.width(Channel::Interleaved).map_err(|e| anyhow::anyhow!("{}", e))?;
let height = image.height(Channel::Interleaved).map_err(|e| anyhow::anyhow!("{}", e))?;
let planes = image.planes();

View file

@ -53,7 +53,7 @@ pub struct SymlinkInfo {
pub type_of_error: ErrorType,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug, PartialEq, Eq, Copy)]
pub enum ErrorType {
InfiniteRecursion,
NonExistentFile,
@ -87,7 +87,7 @@ pub enum Collect {
Files,
}
#[derive(Eq, PartialEq)]
#[derive(Eq, PartialEq, Copy, Clone)]
enum EntryType {
File,
Dir,

View file

@ -49,7 +49,7 @@ impl HashType {
}
}
#[derive(Eq, PartialEq, Clone, Debug)]
#[derive(Eq, PartialEq, Clone, Debug, Copy)]
pub enum DeleteMethod {
None,
AllExceptNewest,

View file

@ -15,7 +15,7 @@ use crate::common_items::ExcludedItems;
use crate::common_messages::Messages;
use crate::common_traits::*;
#[derive(Eq, PartialEq, Clone, Debug)]
#[derive(Eq, PartialEq, Clone, Debug, Copy)]
pub enum DeleteMethod {
None,
Delete,

View file

@ -24,7 +24,7 @@ use crate::common_items::ExcludedItems;
use crate::common_messages::Messages;
use crate::common_traits::*;
#[derive(Eq, PartialEq, Clone, Debug)]
#[derive(Eq, PartialEq, Clone, Debug, Copy)]
pub enum DeleteMethod {
None,
Delete,
@ -666,7 +666,7 @@ impl SameMusic {
for file_entry in vec_file_entry {
let thing = file_entry.genre.trim().to_lowercase();
if !thing.is_empty() {
hash_map.entry(thing.clone()).or_insert_with(Vec::new).push(file_entry);
hash_map.entry(thing).or_insert_with(Vec::new).push(file_entry);
}
}
for (_title, vec_file_entry) in hash_map {

View file

@ -59,7 +59,7 @@ pub struct FileEntry {
}
/// Used by CLI tool when we cannot use directly values
#[derive(Clone, Debug)]
#[derive(Clone, Debug, Copy)]
pub enum SimilarityPreset {
Original,
VeryHigh,

View file

@ -391,6 +391,7 @@ impl SimilarVideos {
if self.excluded_items.is_excluded(&current_file_name) {
continue 'dir;
}
let current_file_name_str = current_file_name.to_string_lossy().to_string();
let fe: FileEntry = FileEntry {
path: current_file_name.clone(),
@ -401,7 +402,7 @@ impl SimilarVideos {
Err(_inspected) => {
warnings.push(flc!(
"core_file_modified_before_epoch",
generate_translation_hashmap(vec![("name", current_file_name.display().to_string())])
generate_translation_hashmap(vec![("name", current_file_name_str.clone())])
));
0
}
@ -409,7 +410,7 @@ impl SimilarVideos {
Err(e) => {
warnings.push(flc!(
"core_file_no_modification_date",
generate_translation_hashmap(vec![("name", current_file_name.display().to_string()), ("reason", e.to_string())])
generate_translation_hashmap(vec![("name", current_file_name_str.clone()), ("reason", e.to_string())])
));
0
}
@ -418,7 +419,7 @@ impl SimilarVideos {
error: String::new(),
};
fe_result.push((current_file_name.to_string_lossy().to_string(), fe));
fe_result.push((current_file_name_str, fe));
}
}
}

View file

@ -26,7 +26,7 @@ pub struct ProgressData {
pub files_checked: usize,
}
#[derive(Eq, PartialEq, Clone, Debug)]
#[derive(Eq, PartialEq, Clone, Debug, Copy)]
pub enum DeleteMethod {
None,
Delete,

View file

@ -10,8 +10,8 @@ homepage = "https://github.com/qarmin/czkawka"
repository = "https://github.com/qarmin/czkawka"
[dependencies]
gdk4 = "0.5.5"
glib = "0.16.7"
gdk4 = "0.6.0"
glib = "0.17.1"
humansize = "2.1.3"
chrono = "0.4.23"
@ -20,7 +20,7 @@ chrono = "0.4.23"
crossbeam-channel = "0.5.6"
# To get information about progress
futures = "0.3.25"
futures = "0.3.26"
# For saving/loading config files to specific directories
directories-next = "2.0.0"
@ -38,22 +38,22 @@ regex = "1.7.1"
image_hasher = "1.1.2"
# Move files to trash
trash = "3.0.0"
trash = "3.0.1"
# For moving files(why std::fs doesn't have such features)
fs_extra = "1.2.0"
fs_extra = "1.3.0"
# Language
i18n-embed = { version = "0.13.8", features = ["fluent-system", "desktop-requester"] }
i18n-embed-fl = "0.6.5"
rust-embed = "6.4.2"
once_cell = "1.17.0"
once_cell = "1.17.1"
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3.9", features = ["combaseapi", "objbase", "shobjidl_core", "windef", "winerror", "wtypesbase", "winuser"] }
[dependencies.gtk4]
version = "0.5.5"
version = "0.6.1"
default-features = false
features = ["v4_6"]

View file

@ -238,6 +238,11 @@ popover_custom_all_in_group_label = Don't select all records in group
popover_custom_mode_unselect = Unselect Custom
popover_custom_mode_select = Select Custom
popover_sort_file_name = File name
popover_sort_folder_name = Folder name
popover_sort_full_name = Full name
popover_sort_size = Size
popover_sort_selection = Selection
popover_invalid_regex = Regex is invalid
popover_valid_regex = Regex is valid
@ -250,6 +255,7 @@ bottom_save_button = Save
bottom_symlink_button = Symlink
bottom_hardlink_button = Hardlink
bottom_move_button = Move
bottom_sort_button = Sort
bottom_search_button_tooltip = Start search
bottom_select_button_tooltip = Select records. Only selected files/folders can be later processed.
@ -268,10 +274,12 @@ bottom_hardlink_button_not_available_tooltip =
Button is disabled, because hardlinks cannot be created.
Hardlinks only works with administrator privileges on Windows, so be sure to run app as administrator.
If app already works with such privileges check for similar issues on Github.
bottom_move_button_tooltip =
bottom_move_button_tooltip =
Moves files to chosen directory.
It copies all files to the directory without preserving the directory tree.
When trying to move two files with identical name to folder, second will fail and show error.
bottom_sort_button_tooltip =
Sorts files/folders according to selected method.
bottom_show_errors_tooltip = Show/Hide bottom text panel.
bottom_show_upper_notebook_tooltip = Show/Hide upper notebook panel.

View file

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<polygon style="fill:#298983;" points="358.206,345.663 357.688,227.522 292.942,227.806 293.462,345.948 325.975,378.178 "/>
<rect x="359.234" y="336.67" transform="matrix(0.7102 0.704 -0.704 0.7102 381.6591 -165.2999)" style="fill:#A5F2E5;" width="64.748" height="88.511"/>
<path d="M462.868,366.489l-57.464-56.96c-1.514-1.501-3.559-2.342-5.69-2.342c-0.012,0-0.024,0-0.036,0
c-2.144,0.01-4.197,0.871-5.705,2.392L374.3,329.428l-0.484-110.058c-0.019-4.452-3.635-8.047-8.082-8.047c-0.012,0-0.025,0-0.037,0
l-80.91,0.356c-2.144,0.01-4.197,0.87-5.705,2.392s-2.352,3.582-2.342,5.726l0.484,110.059l-19.848-19.674
c-3.169-3.143-8.287-3.121-11.43,0.051l-56.96,57.464c-3.143,3.169-3.12,8.287,0.051,11.43l32.136,31.855
c3.169,3.143,8.287,3.121,11.43-0.051l0,0c3.143-3.169,3.12-8.287-0.051-11.43l-26.396-26.164l45.58-45.983l120.207,119.152
l-45.58,45.983l-62.014-61.471c-3.169-3.143-8.287-3.121-11.43,0.051l0,0c-3.143,3.169-3.12,8.287,0.051,11.43l67.754,67.162
c1.514,1.501,3.559,2.342,5.69,2.342c0.012,0,0.024,0,0.036,0c0.035,0,0.069-0.005,0.103-0.005c0.031,0,0.061,0.004,0.092,0.004
c0.012,0,0.024,0,0.036,0c2.144-0.01,4.197-0.871,5.705-2.392l130.535-131.686C466.061,374.75,466.039,369.632,462.868,366.489z
M383.439,435.138l-45.983-45.581l62.308-62.858l45.983,45.58L383.439,435.138z M292.942,227.806l64.745-0.285l0.519,118.141
l-32.23,32.515l-32.515-32.23L292.942,227.806z"/>
<path style="fill:#62D9C7;" d="M264.35,431.016l62.014,61.471l45.58-45.983L251.738,327.351l-45.58,45.983l26.396,26.164
c3.171,3.143,3.193,8.261,0.051,11.43l0,0l20.316,20.138C256.061,427.895,261.179,427.874,264.35,431.016z"/>
<polygon style="fill:#298983;" points="153.794,166.333 154.313,284.474 219.058,284.189 218.539,166.049 186.024,133.818 "/>
<path d="M235.259,292.201l-0.484-110.058l19.848,19.674c1.576,1.563,3.633,2.342,5.69,2.342c2.08,0,4.16-0.799,5.741-2.392
l56.96-57.464c3.143-3.169,3.12-8.287-0.051-11.43l-32.136-31.855c-3.169-3.141-8.287-3.121-11.43,0.051l0,0
c-3.143,3.171-3.12,8.287,0.051,11.43l26.396,26.165l-45.58,45.983L140.057,65.492l45.58-45.983L247.65,80.98
c3.169,3.143,8.287,3.121,11.43-0.05l0,0c3.143-3.171,3.12-8.287-0.051-11.431L191.275,2.338c-1.614-1.6-3.733-2.375-5.84-2.336
c-2.107-0.02-4.219,0.773-5.821,2.387L49.081,134.076c-3.143,3.171-3.12,8.289,0.051,11.431l57.464,56.96
c1.514,1.501,3.559,2.342,5.69,2.342c0.012,0,0.024,0,0.036,0c2.144-0.01,4.197-0.871,5.705-2.392l19.673-19.848l0.484,110.058
c0.01,2.144,0.871,4.197,2.392,5.705c1.514,1.501,3.559,2.342,5.69,2.342c0.012,0,0.024,0,0.036,0l80.91-0.356
C231.675,300.3,235.278,296.665,235.259,292.201z M219.058,284.189l-64.745,0.285l-0.519-118.141l32.23-32.515l32.515,32.23
L219.058,284.189z M66.253,139.716l62.308-62.858l45.983,45.581l-62.308,62.858L66.253,139.716z"/>
<rect x="88.025" y="86.823" transform="matrix(-0.7102 -0.704 0.704 -0.7102 113.6271 308.9317)" style="fill:#A5F2E5;" width="64.748" height="88.511"/>
<path style="fill:#62D9C7;" d="M247.651,80.98l-62.014-61.471l-45.581,45.983l120.207,119.155l45.58-45.983l-26.396-26.165
c-3.171-3.143-3.193-8.26-0.051-11.43l-20.316-20.138C255.939,84.1,250.821,84.122,247.651,80.98z"/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

View file

@ -79,6 +79,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
match msg {
Message::Duplicates(df) => {
const COLUMNS_NUMBER: usize = 11;
if df.get_stopped_search() {
entry_info.set_text(&flg!("compute_stopped_by_user"));
} else {
@ -169,10 +170,11 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
// HEADER
let (directory, file) = split_path(&base_file_entry.path);
let values: [(u32, &dyn ToValue); 10] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsDuplicates::ActivatableSelectButton as u32, &false),
(ColumnsDuplicates::SelectionButton as u32, &false),
(ColumnsDuplicates::Size as u32, (&format_size(base_file_entry.size, BINARY))),
(ColumnsDuplicates::SizeAsBytes as u32, &base_file_entry.size),
(ColumnsDuplicates::Name as u32, &file),
(ColumnsDuplicates::Path as u32, &directory),
(
@ -190,10 +192,12 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
// MEAT
for entry in vector {
let (directory, file) = split_path(&entry.path);
let values: [(u32, &dyn ToValue); 10] = [
println!("{}", entry.size);
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsDuplicates::ActivatableSelectButton as u32, &true),
(ColumnsDuplicates::SelectionButton as u32, &false),
(ColumnsDuplicates::Size as u32, (&format_size(entry.size, BINARY))),
(ColumnsDuplicates::SizeAsBytes as u32, &entry.size),
(ColumnsDuplicates::Name as u32, &file),
(ColumnsDuplicates::Path as u32, &directory),
(
@ -228,10 +232,11 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
// HEADER
let (directory, file) = split_path(&base_file_entry.path);
let values: [(u32, &dyn ToValue); 10] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsDuplicates::ActivatableSelectButton as u32, &false),
(ColumnsDuplicates::SelectionButton as u32, &false),
(ColumnsDuplicates::Size as u32, (&format_size(base_file_entry.size, BINARY))),
(ColumnsDuplicates::SizeAsBytes as u32, &base_file_entry.size),
(ColumnsDuplicates::Name as u32, &file),
(ColumnsDuplicates::Path as u32, &directory),
(
@ -249,10 +254,11 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
for entry in vector {
let (directory, file) = split_path(&entry.path);
let values: [(u32, &dyn ToValue); 10] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsDuplicates::ActivatableSelectButton as u32, &true),
(ColumnsDuplicates::SelectionButton as u32, &false),
(ColumnsDuplicates::Size as u32, (&format_size(entry.size, BINARY))),
(ColumnsDuplicates::SizeAsBytes as u32, &entry.size),
(ColumnsDuplicates::Name as u32, &file),
(ColumnsDuplicates::Path as u32, &directory),
(
@ -288,10 +294,11 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
// HEADER
let (directory, file) = split_path(&base_file_entry.path);
let values: [(u32, &dyn ToValue); 10] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsDuplicates::ActivatableSelectButton as u32, &false),
(ColumnsDuplicates::SelectionButton as u32, &false),
(ColumnsDuplicates::Size as u32, (&format_size(base_file_entry.size, BINARY))),
(ColumnsDuplicates::SizeAsBytes as u32, &base_file_entry.size),
(ColumnsDuplicates::Name as u32, &file),
(ColumnsDuplicates::Path as u32, &directory),
(
@ -308,10 +315,11 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
list_store.set(&list_store.append(), &values);
for entry in vector {
let (directory, file) = split_path(&entry.path);
let values: [(u32, &dyn ToValue); 10] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsDuplicates::ActivatableSelectButton as u32, &true),
(ColumnsDuplicates::SelectionButton as u32, &false),
(ColumnsDuplicates::Size as u32, (&format_size(entry.size, BINARY))),
(ColumnsDuplicates::SizeAsBytes as u32, &entry.size),
(ColumnsDuplicates::Name as u32, &file),
(ColumnsDuplicates::Path as u32, &directory),
(
@ -349,10 +357,11 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
vector.clone()
};
let values: [(u32, &dyn ToValue); 10] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsDuplicates::ActivatableSelectButton as u32, &false),
(ColumnsDuplicates::SelectionButton as u32, &false),
(ColumnsDuplicates::Size as u32, (&String::new())),
(ColumnsDuplicates::SizeAsBytes as u32, &0),
(ColumnsDuplicates::Name as u32, (&String::new())),
(ColumnsDuplicates::Path as u32, (&(format!("{} results", vector.len())))),
(ColumnsDuplicates::Modification as u32, (&String::new())), // No text in 3 column
@ -365,10 +374,11 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
list_store.set(&list_store.append(), &values);
for entry in vector {
let (directory, file) = split_path(&entry.path);
let values: [(u32, &dyn ToValue); 10] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsDuplicates::ActivatableSelectButton as u32, &true),
(ColumnsDuplicates::SelectionButton as u32, &false),
(ColumnsDuplicates::Size as u32, (&format_size(entry.size, BINARY))),
(ColumnsDuplicates::SizeAsBytes as u32, &entry.size),
(ColumnsDuplicates::Name as u32, &file),
(ColumnsDuplicates::Path as u32, &directory),
(
@ -405,10 +415,11 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
vector.clone()
};
let values: [(u32, &dyn ToValue); 10] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsDuplicates::ActivatableSelectButton as u32, &false),
(ColumnsDuplicates::SelectionButton as u32, &false),
(ColumnsDuplicates::Size as u32, (&String::new())),
(ColumnsDuplicates::SizeAsBytes as u32, &0),
(ColumnsDuplicates::Name as u32, (&String::new())),
(ColumnsDuplicates::Path as u32, (&String::new())),
(ColumnsDuplicates::Modification as u32, &String::new()), // No text in 3 column
@ -422,10 +433,11 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
for entry in vector {
let (directory, file) = split_path(&entry.path);
let values: [(u32, &dyn ToValue); 10] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsDuplicates::ActivatableSelectButton as u32, &true),
(ColumnsDuplicates::SelectionButton as u32, &false),
(ColumnsDuplicates::Size as u32, (&format_size(entry.size, BINARY))),
(ColumnsDuplicates::SizeAsBytes as u32, &entry.size),
(ColumnsDuplicates::Name as u32, &file),
(ColumnsDuplicates::Path as u32, &directory),
(
@ -458,10 +470,11 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
} else {
vector.clone()
};
let values: [(u32, &dyn ToValue); 10] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsDuplicates::ActivatableSelectButton as u32, &false),
(ColumnsDuplicates::SelectionButton as u32, &false),
(ColumnsDuplicates::Size as u32, (&String::new())),
(ColumnsDuplicates::SizeAsBytes as u32, &0),
(ColumnsDuplicates::Name as u32, (&String::new())),
(ColumnsDuplicates::Path as u32, (&String::new())),
(ColumnsDuplicates::Modification as u32, &String::new()), // No text in 3 column
@ -474,10 +487,11 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
list_store.set(&list_store.append(), &values);
for entry in vector {
let (directory, file) = split_path(&entry.path);
let values: [(u32, &dyn ToValue); 10] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsDuplicates::ActivatableSelectButton as u32, &true),
(ColumnsDuplicates::SelectionButton as u32, &false),
(ColumnsDuplicates::Size as u32, (&format_size(entry.size, BINARY))),
(ColumnsDuplicates::SizeAsBytes as u32, &entry.size),
(ColumnsDuplicates::Name as u32, &file),
(ColumnsDuplicates::Path as u32, &directory),
(
@ -512,6 +526,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
BottomButtonsEnum::Save,
BottomButtonsEnum::Delete,
BottomButtonsEnum::Select,
BottomButtonsEnum::Sort,
BottomButtonsEnum::Symlink,
BottomButtonsEnum::Hardlink,
BottomButtonsEnum::Move,
@ -528,6 +543,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
}
}
Message::EmptyFolders(ef) => {
const COLUMNS_NUMBER: usize = 5;
if ef.get_stopped_search() {
entry_info.set_text(&flg!("compute_stopped_by_user"));
} else {
@ -558,7 +574,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
for path in vector {
let (directory, file) = split_path(&path);
let values: [(u32, &dyn ToValue); 5] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsEmptyFolders::SelectionButton as u32, &false),
(ColumnsEmptyFolders::Name as u32, &file),
(ColumnsEmptyFolders::Path as u32, &directory),
@ -593,6 +609,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
}
}
Message::EmptyFiles(vf) => {
const COLUMNS_NUMBER: usize = 5;
if vf.get_stopped_search() {
entry_info.set_text(&flg!("compute_stopped_by_user"));
} else {
@ -624,7 +641,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
for file_entry in vector {
let (directory, file) = split_path(&file_entry.path);
let values: [(u32, &dyn ToValue); 5] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsEmptyFiles::SelectionButton as u32, &false),
(ColumnsEmptyFiles::Name as u32, &file),
(ColumnsEmptyFiles::Path as u32, &directory),
@ -659,6 +676,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
}
}
Message::BigFiles(bf) => {
const COLUMNS_NUMBER: usize = 7;
if bf.get_stopped_search() {
entry_info.set_text(&flg!("compute_stopped_by_user"));
} else {
@ -683,7 +701,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
for (size, file_entry) in vector.iter() {
let (directory, file) = split_path(&file_entry.path);
let values: [(u32, &dyn ToValue); 7] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsBigFiles::SelectionButton as u32, &false),
(ColumnsBigFiles::Size as u32, &(format_size(*size, BINARY))),
(ColumnsBigFiles::Name as u32, &file),
@ -720,6 +738,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
}
}
Message::Temporary(tf) => {
const COLUMNS_NUMBER: usize = 5;
if tf.get_stopped_search() {
entry_info.set_text(&flg!("compute_stopped_by_user"));
} else {
@ -750,7 +769,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
for file_entry in vector {
let (directory, file) = split_path(&file_entry.path);
let values: [(u32, &dyn ToValue); 5] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsTemporaryFiles::SelectionButton as u32, &false),
(ColumnsTemporaryFiles::Name as u32, &file),
(ColumnsTemporaryFiles::Path as u32, &directory),
@ -785,6 +804,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
}
}
Message::SimilarImages(sf) => {
const COLUMNS_NUMBER: usize = 13;
if sf.get_stopped_search() {
entry_info.set_text(&flg!("compute_stopped_by_user"));
} else {
@ -828,7 +848,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
// Header
let (directory, file) = split_path(&base_file_entry.path);
let values: [(u32, &dyn ToValue); 13] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsSimilarImages::ActivatableSelectButton as u32, &false),
(ColumnsSimilarImages::SelectionButton as u32, &false),
(ColumnsSimilarImages::Similarity as u32, &String::new()),
@ -851,7 +871,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
// Meat
for file_entry in &vec_file_entry {
let (directory, file) = split_path(&file_entry.path);
let values: [(u32, &dyn ToValue); 13] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsSimilarImages::ActivatableSelectButton as u32, &true),
(ColumnsSimilarImages::SelectionButton as u32, &false),
(
@ -889,7 +909,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
};
// Header
let values: [(u32, &dyn ToValue); 13] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsSimilarImages::ActivatableSelectButton as u32, &false),
(ColumnsSimilarImages::SelectionButton as u32, &false),
(ColumnsSimilarImages::Similarity as u32, &String::new()),
@ -909,7 +929,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
// Meat
for file_entry in &vec_file_entry {
let (directory, file) = split_path(&file_entry.path);
let values: [(u32, &dyn ToValue); 13] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsSimilarImages::ActivatableSelectButton as u32, &true),
(ColumnsSimilarImages::SelectionButton as u32, &false),
(
@ -949,6 +969,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
BottomButtonsEnum::Save,
BottomButtonsEnum::Delete,
BottomButtonsEnum::Select,
BottomButtonsEnum::Sort,
BottomButtonsEnum::Symlink,
BottomButtonsEnum::Hardlink,
BottomButtonsEnum::Move,
@ -966,6 +987,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
}
}
Message::SimilarVideos(ff) => {
const COLUMNS_NUMBER: usize = 11;
if ff.get_stopped_search() {
entry_info.set_text(&flg!("compute_stopped_by_user"));
} else {
@ -1011,7 +1033,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
// Header
let (directory, file) = split_path(&base_file_entry.path);
let values: [(u32, &dyn ToValue); 11] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsSimilarVideos::ActivatableSelectButton as u32, &false),
(ColumnsSimilarVideos::SelectionButton as u32, &false),
(ColumnsSimilarVideos::Size as u32, &format_size(base_file_entry.size, BINARY)),
@ -1032,7 +1054,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
// Meat
for file_entry in &vec_file_entry {
let (directory, file) = split_path(&file_entry.path);
let values: [(u32, &dyn ToValue); 11] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsSimilarVideos::ActivatableSelectButton as u32, &true),
(ColumnsSimilarVideos::SelectionButton as u32, &false),
(ColumnsSimilarVideos::Size as u32, &format_size(file_entry.size, BINARY)),
@ -1068,7 +1090,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
};
// Header
let values: [(u32, &dyn ToValue); 11] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsSimilarVideos::ActivatableSelectButton as u32, &false),
(ColumnsSimilarVideos::SelectionButton as u32, &false),
(ColumnsSimilarVideos::Size as u32, &String::new()),
@ -1086,7 +1108,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
// Meat
for file_entry in &vec_file_entry {
let (directory, file) = split_path(&file_entry.path);
let values: [(u32, &dyn ToValue); 11] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsSimilarVideos::ActivatableSelectButton as u32, &true),
(ColumnsSimilarVideos::SelectionButton as u32, &false),
(ColumnsSimilarVideos::Size as u32, &format_size(file_entry.size, BINARY)),
@ -1121,6 +1143,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
BottomButtonsEnum::Save,
BottomButtonsEnum::Delete,
BottomButtonsEnum::Select,
BottomButtonsEnum::Sort,
BottomButtonsEnum::Symlink,
BottomButtonsEnum::Hardlink,
BottomButtonsEnum::Move,
@ -1137,6 +1160,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
}
}
Message::SameMusic(mf) => {
const COLUMNS_NUMBER: usize = 18;
if mf.get_stopped_search() {
entry_info.set_text(&flg!("compute_stopped_by_user"));
} else {
@ -1192,7 +1216,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
};
let (directory, file) = split_path(&base_file_entry.path);
let values: [(u32, &dyn ToValue); 18] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsSameMusic::ActivatableSelectButton as u32, &false),
(ColumnsSameMusic::SelectionButton as u32, &false),
(ColumnsSameMusic::Size as u32, &format_size(base_file_entry.size, BINARY)),
@ -1218,20 +1242,20 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
list_store.set(&list_store.append(), &values);
for file_entry in vec_file_entry {
let (directory, file) = split_path(&file_entry.path);
let values: [(u32, &dyn ToValue); 18] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsSameMusic::ActivatableSelectButton as u32, &true),
(ColumnsSameMusic::SelectionButton as u32, &false),
(ColumnsSameMusic::Size as u32, &format_size(file_entry.size, BINARY)),
(ColumnsSameMusic::SizeAsBytes as u32, &file_entry.size),
(ColumnsSameMusic::Name as u32, &file),
(ColumnsSameMusic::Path as u32, &directory),
(ColumnsSameMusic::Title as u32, &base_file_entry.track_title),
(ColumnsSameMusic::Artist as u32, &base_file_entry.track_artist),
(ColumnsSameMusic::Year as u32, &base_file_entry.year.to_string()),
(ColumnsSameMusic::Genre as u32, &base_file_entry.genre),
(ColumnsSameMusic::Bitrate as u32, &(format!("{} kbps", base_file_entry.bitrate))),
(ColumnsSameMusic::BitrateAsNumber as u32, &(base_file_entry.bitrate)),
(ColumnsSameMusic::Length as u32, &base_file_entry.length),
(ColumnsSameMusic::Title as u32, &file_entry.track_title),
(ColumnsSameMusic::Artist as u32, &file_entry.track_artist),
(ColumnsSameMusic::Year as u32, &file_entry.year.to_string()),
(ColumnsSameMusic::Genre as u32, &file_entry.genre),
(ColumnsSameMusic::Bitrate as u32, &(format!("{} kbps", file_entry.bitrate))),
(ColumnsSameMusic::BitrateAsNumber as u32, &(file_entry.bitrate)),
(ColumnsSameMusic::Length as u32, &file_entry.length),
(
ColumnsSameMusic::Modification as u32,
&(NaiveDateTime::from_timestamp_opt(file_entry.modified_date as i64, 0).unwrap().to_string()),
@ -1262,7 +1286,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
vec_file_entry.clone()
};
let values: [(u32, &dyn ToValue); 18] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsSameMusic::ActivatableSelectButton as u32, &false),
(ColumnsSameMusic::SelectionButton as u32, &false),
(ColumnsSameMusic::Size as u32, &String::new()),
@ -1285,7 +1309,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
list_store.set(&list_store.append(), &values);
for file_entry in vec_file_entry {
let (directory, file) = split_path(&file_entry.path);
let values: [(u32, &dyn ToValue); 18] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsSameMusic::ActivatableSelectButton as u32, &true),
(ColumnsSameMusic::SelectionButton as u32, &false),
(ColumnsSameMusic::Size as u32, &format_size(file_entry.size, BINARY)),
@ -1326,6 +1350,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
BottomButtonsEnum::Save,
BottomButtonsEnum::Delete,
BottomButtonsEnum::Select,
BottomButtonsEnum::Sort,
BottomButtonsEnum::Symlink,
BottomButtonsEnum::Hardlink,
BottomButtonsEnum::Move,
@ -1342,6 +1367,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
}
}
Message::InvalidSymlinks(ifs) => {
const COLUMNS_NUMBER: usize = 7;
if ifs.get_stopped_search() {
entry_info.set_text(&flg!("compute_stopped_by_user"));
} else {
@ -1375,7 +1401,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
for file_entry in vector {
let (directory, file) = split_path(&file_entry.path);
let symlink_info = file_entry.symlink_info.clone().expect("invalid traversal result");
let values: [(u32, &dyn ToValue); 7] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsInvalidSymlinks::SelectionButton as u32, &false),
(ColumnsInvalidSymlinks::Name as u32, &file),
(ColumnsInvalidSymlinks::Path as u32, &directory),
@ -1415,6 +1441,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
}
}
Message::BrokenFiles(br) => {
const COLUMNS_NUMBER: usize = 6;
if br.get_stopped_search() {
entry_info.set_text(&flg!("compute_stopped_by_user"));
} else {
@ -1446,7 +1473,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
for file_entry in vector {
let (directory, file) = split_path(&file_entry.path);
let values: [(u32, &dyn ToValue); 6] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsBrokenFiles::SelectionButton as u32, &false),
(ColumnsBrokenFiles::Name as u32, &file),
(ColumnsBrokenFiles::Path as u32, &directory),
@ -1482,6 +1509,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
}
}
Message::BadExtensions(be) => {
const COLUMNS_NUMBER: usize = 7;
if be.get_stopped_search() {
entry_info.set_text(&flg!("compute_stopped_by_user"));
} else {
@ -1512,7 +1540,7 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
for file_entry in vector {
let (directory, file) = split_path(&file_entry.path);
let values: [(u32, &dyn ToValue); 7] = [
let values: [(u32, &dyn ToValue); COLUMNS_NUMBER] = [
(ColumnsBadExtensions::SelectionButton as u32, &false),
(ColumnsBadExtensions::Name as u32, &file),
(ColumnsBadExtensions::Path as u32, &directory),

View file

@ -140,7 +140,7 @@ pub async fn check_if_can_delete_files(
}
fn create_dialog_ask_for_deletion(window_main: &gtk4::Window, number_of_selected_items: u64, number_of_selected_groups: u64) -> (Dialog, CheckButton) {
let dialog = Dialog::builder().title(&flg!("delete_title_dialog")).transient_for(window_main).modal(true).build();
let dialog = Dialog::builder().title(flg!("delete_title_dialog")).transient_for(window_main).modal(true).build();
let button_ok = dialog.add_button(&flg!("general_ok_button"), ResponseType::Ok);
dialog.add_button(&flg!("general_close_button"), ResponseType::Cancel);
@ -157,9 +157,13 @@ fn create_dialog_ask_for_deletion(window_main: &gtk4::Window, number_of_selected
generate_translation_hashmap(vec![("items", number_of_selected_items.to_string()), ("groups", number_of_selected_groups.to_string())])
))),
};
let check_button: CheckButton = CheckButton::with_label(&flg!("dialogs_ask_next_time"));
check_button.set_active(true);
check_button.set_halign(Align::Center);
let check_button: CheckButton = CheckButton::builder()
.label(flg!("dialogs_ask_next_time"))
.active(true)
.halign(Align::Center)
.margin_top(5)
.build();
button_ok.grab_focus();
@ -169,16 +173,13 @@ fn create_dialog_ask_for_deletion(window_main: &gtk4::Window, number_of_selected
parent.insert_child_after(&label2, Some(&label));
parent.insert_child_after(&check_button, Some(&label2));
// parent.set_margin(5); // TODO
check_button.set_margin_top(5);
dialog.show();
(dialog, check_button)
}
fn create_dialog_group_deletion(window_main: &gtk4::Window) -> (Dialog, CheckButton) {
let dialog = Dialog::builder()
.title(&flg!("delete_all_files_in_group_title"))
.title(flg!("delete_all_files_in_group_title"))
.transient_for(window_main)
.modal(true)
.build();
@ -187,9 +188,7 @@ fn create_dialog_group_deletion(window_main: &gtk4::Window) -> (Dialog, CheckBut
let label: gtk4::Label = gtk4::Label::new(Some(&flg!("delete_all_files_in_group_label1")));
let label2: gtk4::Label = gtk4::Label::new(Some(&flg!("delete_all_files_in_group_label2")));
let check_button: CheckButton = CheckButton::with_label(&flg!("dialogs_ask_next_time"));
check_button.set_active(true);
check_button.set_halign(Align::Center);
let check_button: CheckButton = CheckButton::builder().label(flg!("dialogs_ask_next_time")).active(true).halign(Align::Center).build();
button_ok.grab_focus();

View file

@ -13,7 +13,7 @@ use crate::localizer_core::generate_translation_hashmap;
use crate::notebook_enums::*;
use crate::notebook_info::NOTEBOOKS_INFO;
#[derive(PartialEq, Eq)]
#[derive(PartialEq, Eq, Copy, Clone)]
enum TypeOfTool {
Hardlinking,
Symlinking,
@ -262,7 +262,7 @@ fn hardlink_symlink(
fn create_dialog_non_group(window_main: &gtk4::Window) -> Dialog {
let dialog = Dialog::builder()
.title(&flg!("hard_sym_invalid_selection_title_dialog"))
.title(flg!("hard_sym_invalid_selection_title_dialog"))
.transient_for(window_main)
.modal(true)
.build();
@ -370,14 +370,12 @@ pub async fn check_if_can_link_files(check_button_settings_confirm_link: &CheckB
}
fn create_dialog_ask_for_linking(window_main: &gtk4::Window) -> (Dialog, CheckButton) {
let dialog = Dialog::builder().title(&flg!("hard_sym_link_title_dialog")).transient_for(window_main).modal(true).build();
let dialog = Dialog::builder().title(flg!("hard_sym_link_title_dialog")).transient_for(window_main).modal(true).build();
let button_ok = dialog.add_button(&flg!("general_ok_button"), ResponseType::Ok);
dialog.add_button(&flg!("general_close_button"), ResponseType::Cancel);
let label: gtk4::Label = gtk4::Label::new(Some(&flg!("hard_sym_link_label")));
let check_button: CheckButton = CheckButton::with_label(&flg!("dialogs_ask_next_time"));
check_button.set_active(true);
check_button.set_halign(Align::Center);
let check_button: CheckButton = CheckButton::builder().label(flg!("dialogs_ask_next_time")).active(true).halign(Align::Center).build();
button_ok.grab_focus();

View file

@ -1,7 +1,7 @@
use std::path::{Path, PathBuf};
use gtk4::prelude::*;
use gtk4::{ResponseType, TreePath};
use gtk4::{FileChooserNative, ResponseType, TreePath};
use crate::flg;
use crate::gui_structs::gui_data::GuiData;
@ -22,9 +22,8 @@ pub fn connect_button_move(gui_data: &GuiData) {
let entry_info = gui_data.entry_info.clone();
let text_view_errors = gui_data.text_view_errors.clone();
let window_main = gui_data.window_main.clone();
let preview_path = gui_data.preview_path.clone();
let file_dialog_move_to_folder = gui_data.file_dialog_move_to_folder.clone();
buttons_move.connect_clicked(move |_| {
let nb_number = notebook_main.current_page().unwrap();
@ -45,7 +44,7 @@ pub fn connect_button_move(gui_data: &GuiData) {
nb_object.column_selection,
&entry_info,
&text_view_errors,
&window_main,
&file_dialog_move_to_folder,
);
match &nb_object.notebook_type {
@ -71,26 +70,14 @@ fn move_things(
column_selection: i32,
entry_info: &gtk4::Entry,
text_view_errors: &gtk4::TextView,
window_main: &gtk4::Window,
file_dialog_move_to_folder: &FileChooserNative,
) {
reset_text_view(text_view_errors);
let chooser = gtk4::FileChooserDialog::builder()
.title(&flg!("move_files_title_dialog"))
.action(gtk4::FileChooserAction::SelectFolder)
.transient_for(window_main)
.modal(true)
.build();
chooser.add_button(&flg!("general_ok_button"), ResponseType::Ok);
chooser.add_button(&flg!("general_close_button"), ResponseType::Cancel);
chooser.set_select_multiple(false);
chooser.show();
let entry_info = entry_info.clone();
let text_view_errors = text_view_errors.clone();
let tree_view = tree_view.clone();
chooser.connect_response(move |file_chooser, response_type| {
file_dialog_move_to_folder.connect_response(move |file_chooser, response_type| {
if response_type == ResponseType::Ok {
let mut folders: Vec<PathBuf> = Vec::new();
let g_files = file_chooser.files();
@ -131,7 +118,7 @@ fn move_things(
}
}
}
file_chooser.close();
// file_chooser.close();
});
}

View file

@ -1,40 +1,40 @@
use gtk4::prelude::*;
use crate::gui_structs::gui_data::GuiData;
use crate::gui_structs::gui_popovers::GuiPopovers;
use crate::gui_structs::gui_popovers_select::GuiSelectPopovers;
use crate::help_functions::PopoverTypes;
use crate::notebook_enums::*;
use crate::notebook_info::NOTEBOOKS_INFO;
pub fn connect_button_select(gui_data: &GuiData) {
let popovers = gui_data.popovers.clone();
let popovers_select = gui_data.popovers_select.clone();
let notebook_main = gui_data.main_notebook.notebook_main.clone();
let gc_buttons_select = gui_data.bottom_buttons.gc_buttons_select.clone();
gc_buttons_select.connect_pressed(move |_, _, _, _| {
show_required_popovers(&popovers, &to_notebook_main_enum(notebook_main.current_page().unwrap()));
show_required_popovers(&popovers_select, &to_notebook_main_enum(notebook_main.current_page().unwrap()));
});
}
fn show_required_popovers(popovers: &GuiPopovers, current_mode: &NotebookMainEnum) {
let buttons_popover_select_all = popovers.buttons_popover_select_all.clone();
let buttons_popover_unselect_all = popovers.buttons_popover_unselect_all.clone();
let buttons_popover_reverse = popovers.buttons_popover_reverse.clone();
let buttons_popover_select_all_except_oldest = popovers.buttons_popover_select_all_except_oldest.clone();
let buttons_popover_select_all_except_newest = popovers.buttons_popover_select_all_except_newest.clone();
let buttons_popover_select_one_oldest = popovers.buttons_popover_select_one_oldest.clone();
let buttons_popover_select_one_newest = popovers.buttons_popover_select_one_newest.clone();
let buttons_popover_select_custom = popovers.buttons_popover_select_custom.clone();
let buttons_popover_unselect_custom = popovers.buttons_popover_unselect_custom.clone();
let buttons_popover_select_all_images_except_biggest = popovers.buttons_popover_select_all_images_except_biggest.clone();
let buttons_popover_select_all_images_except_smallest = popovers.buttons_popover_select_all_images_except_smallest.clone();
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();
let buttons_popover_select_all_except_oldest = popovers_select.buttons_popover_select_all_except_oldest.clone();
let buttons_popover_select_all_except_newest = popovers_select.buttons_popover_select_all_except_newest.clone();
let buttons_popover_select_one_oldest = popovers_select.buttons_popover_select_one_oldest.clone();
let buttons_popover_select_one_newest = popovers_select.buttons_popover_select_one_newest.clone();
let buttons_popover_select_custom = popovers_select.buttons_popover_select_custom.clone();
let buttons_popover_unselect_custom = popovers_select.buttons_popover_unselect_custom.clone();
let buttons_popover_select_all_images_except_biggest = popovers_select.buttons_popover_select_all_images_except_biggest.clone();
let buttons_popover_select_all_images_except_smallest = popovers_select.buttons_popover_select_all_images_except_smallest.clone();
let separator_select_custom = popovers.separator_select_custom.clone();
let separator_select_date = popovers.separator_select_date.clone();
let separator_select_image_size = popovers.separator_select_image_size.clone();
let separator_select_reverse = popovers.separator_select_reverse.clone();
let separator_select_custom = popovers_select.separator_select_custom.clone();
let separator_select_date = popovers_select.separator_select_date.clone();
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.clone() as usize].available_modes;
let arr = &NOTEBOOKS_INFO[*current_mode as usize].available_modes;
if arr.contains(&PopoverTypes::All) {
buttons_popover_select_all.show();

View file

@ -0,0 +1,46 @@
use crate::gui_structs::gui_data::GuiData;
use crate::gui_structs::gui_popovers_sort::GuiSortPopovers;
use crate::help_functions::PopoverTypes;
use crate::notebook_enums::{to_notebook_main_enum, NotebookMainEnum};
use crate::notebook_info::NOTEBOOKS_INFO;
use gtk4::prelude::*;
pub fn connect_button_sort(gui_data: &GuiData) {
let popovers_sort = gui_data.popovers_sort.clone();
let notebook_main = gui_data.main_notebook.notebook_main.clone();
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()));
});
}
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;
buttons_popover_sort_full_name.hide();
if arr.contains(&PopoverTypes::All) {
buttons_popover_sort_selection.show();
buttons_popover_sort_file_name.show();
buttons_popover_sort_folder_name.show();
// buttons_popover_sort_full_name.show(); // TODO, this needs to be handled a little different
} else {
buttons_popover_sort_selection.hide();
buttons_popover_sort_file_name.hide();
buttons_popover_sort_folder_name.hide();
// buttons_popover_sort_full_name.hide();
}
if arr.contains(&PopoverTypes::Size) {
buttons_popover_sort_size.show();
} else {
buttons_popover_sort_size.hide();
}
}

View file

@ -245,41 +245,44 @@ fn popover_custom_select_unselect(
// Dialog for select/unselect items
{
let dialog = gtk4::Dialog::builder().title(&window_title).transient_for(window_main).modal(true).build();
let dialog = gtk4::Dialog::builder().title(window_title).transient_for(window_main).modal(true).build();
dialog.add_button(&flg!("general_ok_button"), ResponseType::Ok);
dialog.add_button(&flg!("general_close_button"), ResponseType::Cancel);
let check_button_path = gtk4::CheckButton::builder().label(&flg!("popover_custom_regex_path_label")).build();
let check_button_name = gtk4::CheckButton::builder().label(&flg!("popover_custom_regex_name_label")).build();
let check_button_rust_regex = gtk4::CheckButton::builder().label(&flg!("popover_custom_regex_regex_label")).build();
let check_button_path = gtk4::CheckButton::builder()
.label(flg!("popover_custom_regex_path_label"))
.tooltip_text(flg!("popover_custom_path_check_button_entry_tooltip"))
.build();
let check_button_name = gtk4::CheckButton::builder()
.label(flg!("popover_custom_regex_name_label"))
.tooltip_text(flg!("popover_custom_name_check_button_entry_tooltip"))
.build();
let check_button_rust_regex = gtk4::CheckButton::builder()
.label(flg!("popover_custom_regex_regex_label"))
.tooltip_text(flg!("popover_custom_regex_check_button_entry_tooltip"))
.build();
let check_button_case_sensitive = gtk4::CheckButton::builder().label(&flg!("popover_custom_case_sensitive_check_button")).build();
check_button_case_sensitive.set_active(false);
let check_button_case_sensitive = gtk4::CheckButton::builder()
.label(flg!("popover_custom_case_sensitive_check_button"))
.tooltip_text(flg!("popover_custom_case_sensitive_check_button_tooltip"))
.active(false)
.build();
let check_button_select_not_all_results = gtk4::CheckButton::builder().label(&flg!("popover_custom_all_in_group_label")).build();
check_button_select_not_all_results.set_active(true);
let check_button_select_not_all_results = gtk4::CheckButton::builder()
.label(flg!("popover_custom_all_in_group_label"))
.tooltip_text(flg!("popover_custom_not_all_check_button_tooltip"))
.active(true)
.build();
let entry_path = gtk4::Entry::new();
let entry_name = gtk4::Entry::new();
let entry_rust_regex = gtk4::Entry::new();
entry_rust_regex.set_sensitive(false); // By default check button regex is disabled
let entry_path = gtk4::Entry::builder().tooltip_text(flg!("popover_custom_path_check_button_entry_tooltip")).build();
let entry_name = gtk4::Entry::builder().tooltip_text(flg!("popover_custom_name_check_button_entry_tooltip")).build();
let entry_rust_regex = gtk4::Entry::builder()
.tooltip_text(flg!("popover_custom_regex_check_button_entry_tooltip"))
.sensitive(false)
.build(); // By default check button regex is disabled
let label_regex_valid = gtk4::Label::new(None);
// Tooltips
{
check_button_path.set_tooltip_text(Some(&flg!("popover_custom_path_check_button_entry_tooltip")));
entry_path.set_tooltip_text(Some(&flg!("popover_custom_path_check_button_entry_tooltip")));
check_button_name.set_tooltip_text(Some(&flg!("popover_custom_name_check_button_entry_tooltip")));
entry_name.set_tooltip_text(Some(&flg!("popover_custom_name_check_button_entry_tooltip")));
check_button_rust_regex.set_tooltip_text(Some(&flg!("popover_custom_regex_check_button_entry_tooltip")));
entry_rust_regex.set_tooltip_text(Some(&flg!("popover_custom_regex_check_button_entry_tooltip")));
check_button_case_sensitive.set_tooltip_text(Some(&flg!("popover_custom_case_sensitive_check_button_tooltip")));
check_button_select_not_all_results.set_tooltip_text(Some(&flg!("popover_custom_not_all_check_button_tooltip")));
}
{
let label_regex_valid = label_regex_valid.clone();
entry_rust_regex.connect_changed(move |entry_rust_regex| {
@ -332,9 +335,7 @@ fn popover_custom_select_unselect(
// Configure look of things
{
// TODO Label should have const width, and rest should fill entry, but for now is 50%-50%
let grid = gtk4::Grid::new();
grid.set_row_homogeneous(true);
grid.set_column_homogeneous(true);
let grid = gtk4::Grid::builder().row_homogeneous(true).column_homogeneous(true).build();
grid.attach(&check_button_name, 0, 1, 1, 1);
grid.attach(&check_button_path, 0, 2, 1, 1);
@ -593,9 +594,9 @@ fn popover_all_except_biggest_smallest(
popover.popdown();
}
pub fn connect_popovers(gui_data: &GuiData) {
let popover_select = gui_data.popovers.popover_select.clone();
let buttons_popover_select_all = gui_data.popovers.buttons_popover_select_all.clone();
pub fn connect_popover_select(gui_data: &GuiData) {
let popover_select = gui_data.popovers_select.popover_select.clone();
let buttons_popover_select_all = gui_data.popovers_select.buttons_popover_select_all.clone();
let notebook_main = gui_data.main_notebook.notebook_main.clone();
let main_tree_views = gui_data.main_notebook.get_main_tree_views();
@ -607,8 +608,8 @@ pub fn connect_popovers(gui_data: &GuiData) {
popover_select_all(&popover_select, tree_view, nb_object.column_selection as u32, nb_object.column_header);
});
let popover_select = gui_data.popovers.popover_select.clone();
let buttons_popover_unselect_all = gui_data.popovers.buttons_popover_unselect_all.clone();
let popover_select = gui_data.popovers_select.popover_select.clone();
let buttons_popover_unselect_all = gui_data.popovers_select.buttons_popover_unselect_all.clone();
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 |_| {
@ -619,8 +620,8 @@ pub fn connect_popovers(gui_data: &GuiData) {
popover_unselect_all(&popover_select, tree_view, nb_object.column_selection as u32);
});
let popover_select = gui_data.popovers.popover_select.clone();
let buttons_popover_reverse = gui_data.popovers.buttons_popover_reverse.clone();
let popover_select = gui_data.popovers_select.popover_select.clone();
let buttons_popover_reverse = gui_data.popovers_select.buttons_popover_reverse.clone();
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 |_| {
@ -631,8 +632,8 @@ pub fn connect_popovers(gui_data: &GuiData) {
popover_reverse(&popover_select, tree_view, nb_object.column_selection as u32, nb_object.column_header);
});
let popover_select = gui_data.popovers.popover_select.clone();
let buttons_popover_select_all_except_oldest = gui_data.popovers.buttons_popover_select_all_except_oldest.clone();
let popover_select = gui_data.popovers_select.popover_select.clone();
let buttons_popover_select_all_except_oldest = gui_data.popovers_select.buttons_popover_select_all_except_oldest.clone();
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 |_| {
@ -651,8 +652,8 @@ pub fn connect_popovers(gui_data: &GuiData) {
);
});
let popover_select = gui_data.popovers.popover_select.clone();
let buttons_popover_select_all_except_newest = gui_data.popovers.buttons_popover_select_all_except_newest.clone();
let popover_select = gui_data.popovers_select.popover_select.clone();
let buttons_popover_select_all_except_newest = gui_data.popovers_select.buttons_popover_select_all_except_newest.clone();
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 |_| {
@ -671,8 +672,8 @@ pub fn connect_popovers(gui_data: &GuiData) {
);
});
let popover_select = gui_data.popovers.popover_select.clone();
let buttons_popover_select_one_oldest = gui_data.popovers.buttons_popover_select_one_oldest.clone();
let popover_select = gui_data.popovers_select.popover_select.clone();
let buttons_popover_select_one_oldest = gui_data.popovers_select.buttons_popover_select_one_oldest.clone();
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 |_| {
@ -691,8 +692,8 @@ pub fn connect_popovers(gui_data: &GuiData) {
);
});
let popover_select = gui_data.popovers.popover_select.clone();
let buttons_popover_select_one_newest = gui_data.popovers.buttons_popover_select_one_newest.clone();
let popover_select = gui_data.popovers_select.popover_select.clone();
let buttons_popover_select_one_newest = gui_data.popovers_select.buttons_popover_select_one_newest.clone();
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 |_| {
@ -711,8 +712,8 @@ pub fn connect_popovers(gui_data: &GuiData) {
);
});
let popover_select = gui_data.popovers.popover_select.clone();
let buttons_popover_select_custom = gui_data.popovers.buttons_popover_select_custom.clone();
let popover_select = gui_data.popovers_select.popover_select.clone();
let buttons_popover_select_custom = gui_data.popovers_select.buttons_popover_select_custom.clone();
let notebook_main = gui_data.main_notebook.notebook_main.clone();
let main_tree_views = gui_data.main_notebook.get_main_tree_views();
let window_main = gui_data.window_main.clone();
@ -733,8 +734,8 @@ pub fn connect_popovers(gui_data: &GuiData) {
);
});
let popover_select = gui_data.popovers.popover_select.clone();
let buttons_popover_unselect_custom = gui_data.popovers.buttons_popover_unselect_custom.clone();
let popover_select = gui_data.popovers_select.popover_select.clone();
let buttons_popover_unselect_custom = gui_data.popovers_select.buttons_popover_unselect_custom.clone();
let notebook_main = gui_data.main_notebook.notebook_main.clone();
let main_tree_views = gui_data.main_notebook.get_main_tree_views();
let window_main = gui_data.window_main.clone();
@ -755,8 +756,8 @@ pub fn connect_popovers(gui_data: &GuiData) {
);
});
let popover_select = gui_data.popovers.popover_select.clone();
let buttons_popover_select_all_images_except_biggest = gui_data.popovers.buttons_popover_select_all_images_except_biggest.clone();
let popover_select = gui_data.popovers_select.popover_select.clone();
let buttons_popover_select_all_images_except_biggest = gui_data.popovers_select.buttons_popover_select_all_images_except_biggest.clone();
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 |_| {
@ -775,8 +776,8 @@ pub fn connect_popovers(gui_data: &GuiData) {
);
});
let popover_select = gui_data.popovers.popover_select.clone();
let buttons_popover_select_all_images_except_smallest = gui_data.popovers.buttons_popover_select_all_images_except_smallest.clone();
let popover_select = gui_data.popovers_select.popover_select.clone();
let buttons_popover_select_all_images_except_smallest = gui_data.popovers_select.buttons_popover_select_all_images_except_smallest.clone();
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 |_| {

View file

@ -0,0 +1,210 @@
use gtk4::prelude::*;
use gtk4::{ListStore, TreeIter};
use std::fmt::Debug;
use crate::gui_structs::gui_data::GuiData;
use crate::help_functions::*;
use crate::notebook_info::NOTEBOOKS_INFO;
fn popover_sort_general<T>(popover: &gtk4::Popover, tree_view: &gtk4::TreeView, column_sort: i32, column_header: i32)
where
T: Ord + for<'b> glib::value::FromValue<'b> + 'static + Debug,
{
let model = get_list_store(tree_view);
if let Some(curr_iter) = model.iter_first() {
assert!(model.get::<bool>(&curr_iter, column_header));
assert!(model.iter_next(&curr_iter)); // Must be at least one item
loop {
let mut iters = Vec::new();
let mut all_have = false;
loop {
if model.get::<bool>(&curr_iter, column_header) {
assert!(model.iter_next(&curr_iter), "Empty header, this should not happens");
break;
}
iters.push(curr_iter);
if !model.iter_next(&curr_iter) {
all_have = true;
break;
}
}
if iters.len() == 1 {
continue; // Can be equal 1 in reference folders
}
sort_iters::<T>(&model, iters, column_sort);
if all_have {
break;
}
}
}
popover.popdown();
}
fn sort_iters<T>(model: &ListStore, mut iters: Vec<TreeIter>, column_sort: i32)
where
T: Ord + for<'b> glib::value::FromValue<'b> + 'static + Debug,
{
assert!(iters.len() >= 2);
loop {
let mut changed_item = false;
for idx in 0..(iters.len() - 1) {
if model.get::<T>(&iters[idx], column_sort) > model.get::<T>(&iters[idx + 1], column_sort) {
model.swap(&iters[idx], &iters[idx + 1]);
iters.swap(idx, idx + 1);
changed_item = true;
}
}
if !changed_item {
return;
}
}
}
pub fn connect_popover_sort(gui_data: &GuiData) {
let popover_sort = gui_data.popovers_sort.popover_sort.clone();
let buttons_popover_file_name = gui_data.popovers_sort.buttons_popover_sort_file_name.clone();
let notebook_main = gui_data.main_notebook.notebook_main.clone();
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 tree_view = &main_tree_views[nb_number as usize];
let nb_object = &NOTEBOOKS_INFO[nb_number as usize];
popover_sort_general::<String>(&popover_sort, tree_view, nb_object.column_name, nb_object.column_header.unwrap());
});
let popover_sort = gui_data.popovers_sort.popover_sort.clone();
let buttons_popover_sort_folder_name = gui_data.popovers_sort.buttons_popover_sort_folder_name.clone();
let notebook_main = gui_data.main_notebook.notebook_main.clone();
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 tree_view = &main_tree_views[nb_number as usize];
let nb_object = &NOTEBOOKS_INFO[nb_number as usize];
popover_sort_general::<String>(&popover_sort, tree_view, nb_object.column_path, nb_object.column_header.unwrap());
});
let popover_sort = gui_data.popovers_sort.popover_sort.clone();
let buttons_popover_sort_selection = gui_data.popovers_sort.buttons_popover_sort_selection.clone();
let notebook_main = gui_data.main_notebook.notebook_main.clone();
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 tree_view = &main_tree_views[nb_number as usize];
let nb_object = &NOTEBOOKS_INFO[nb_number as usize];
popover_sort_general::<bool>(&popover_sort, tree_view, nb_object.column_selection, nb_object.column_header.unwrap());
});
let popover_sort = gui_data.popovers_sort.popover_sort.clone();
let buttons_popover_sort_size = gui_data.popovers_sort.buttons_popover_sort_size.clone();
let notebook_main = gui_data.main_notebook.notebook_main.clone();
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 tree_view = &main_tree_views[nb_number as usize];
let nb_object = &NOTEBOOKS_INFO[nb_number as usize];
popover_sort_general::<u64>(&popover_sort, tree_view, nb_object.column_size_as_bytes.unwrap(), nb_object.column_header.unwrap());
});
}
#[cfg(test)]
mod test {
use crate::connect_things::connect_popovers_sort::{popover_sort_general, sort_iters};
use gtk4::prelude::*;
use gtk4::{Popover, TreeView};
#[gtk4::test]
fn test_sort_iters() {
let columns_types: &[glib::types::Type] = &[glib::types::Type::U32, glib::types::Type::STRING];
let list_store = gtk4::ListStore::new(columns_types);
let values_to_add: &[&[(u32, &dyn ToValue)]] = &[&[(0, &2), (1, &"AAA")], &[(0, &3), (1, &"CCC")], &[(0, &1), (1, &"BBB")]];
for i in values_to_add {
list_store.set(&list_store.append(), i);
}
let mut iters = Vec::new();
let iter = list_store.iter_first().unwrap();
iters.push(iter);
list_store.iter_next(&iter);
iters.push(iter);
list_store.iter_next(&iter);
iters.push(iter);
sort_iters::<String>(&list_store, iters, 1);
let expected = [(2, "AAA"), (1, "BBB"), (3, "CCC")];
let curr_iter = list_store.iter_first().unwrap();
for exp in expected {
let real_0 = list_store.get::<u32>(&curr_iter, 0);
assert_eq!(real_0, exp.0);
let real_1 = list_store.get::<String>(&curr_iter, 1);
assert_eq!(real_1, exp.1);
list_store.iter_next(&curr_iter);
}
}
#[gtk4::test]
pub fn test_popover_sort_general_simple() {
let columns_types: &[glib::types::Type] = &[glib::types::Type::BOOL, glib::types::Type::STRING];
let list_store = gtk4::ListStore::new(columns_types);
let tree_view = TreeView::builder().model(&list_store).build();
let popover = Popover::new();
let values_to_add: &[&[(u32, &dyn ToValue)]] = &[&[(0, &true), (1, &"DDD")], &[(0, &false), (1, &"CCC")], &[(0, &false), (1, &"BBB")]];
for i in values_to_add {
list_store.set(&list_store.append(), i);
}
popover_sort_general::<String>(&popover, &tree_view, 1, 0);
let expected = ["DDD", "BBB", "CCC"];
let curr_iter = list_store.iter_first().unwrap();
for exp in expected {
let real = list_store.get::<String>(&curr_iter, 1);
assert_eq!(real, exp);
list_store.iter_next(&curr_iter);
}
}
#[gtk4::test]
pub fn test_popover_sort_general() {
let columns_types: &[glib::types::Type] = &[glib::types::Type::BOOL, glib::types::Type::STRING];
let list_store = gtk4::ListStore::new(columns_types);
let tree_view = TreeView::builder().model(&list_store).build();
let popover = Popover::new();
let values_to_add: &[&[(u32, &dyn ToValue)]] = &[
&[(0, &true), (1, &"AAA")],
&[(0, &false), (1, &"CCC")],
&[(0, &false), (1, &"BBB")],
&[(0, &true), (1, &"TTT")],
&[(0, &false), (1, &"PPP")],
&[(0, &false), (1, &"AAA")],
&[(0, &true), (1, &"RRR")],
&[(0, &false), (1, &"WWW")],
&[(0, &false), (1, &"ZZZ")],
];
for i in values_to_add {
list_store.set(&list_store.append(), i);
}
popover_sort_general::<String>(&popover, &tree_view, 1, 0);
let expected = ["AAA", "BBB", "CCC", "TTT", "AAA", "PPP", "RRR", "WWW", "ZZZ"];
let curr_iter = list_store.iter_first().unwrap();
for exp in expected {
let real = list_store.get::<String>(&curr_iter, 1);
assert_eq!(real, exp);
list_store.iter_next(&curr_iter);
}
}
}

View file

@ -1,7 +1,7 @@
use std::path::PathBuf;
use gtk4::prelude::*;
use gtk4::{Orientation, ResponseType, TreeView, Window};
use gtk4::{FileChooserNative, Orientation, ResponseType, TreeView, Window};
#[cfg(target_family = "windows")]
use czkawka_core::common::Common;
@ -32,19 +32,19 @@ pub fn connect_selection_of_directories(gui_data: &GuiData) {
// Add included directory
{
let tree_view_included_directories = gui_data.upper_notebook.tree_view_included_directories.clone();
let window_main = gui_data.window_main.clone();
let buttons_add_included_directory = gui_data.upper_notebook.buttons_add_included_directory.clone();
let file_dialog_include_exclude_folder_selection = gui_data.file_dialog_include_exclude_folder_selection.clone();
buttons_add_included_directory.connect_clicked(move |_| {
add_chosen_directories(&window_main, &tree_view_included_directories, false);
add_chosen_directories(&file_dialog_include_exclude_folder_selection, &tree_view_included_directories, false);
});
}
// Add excluded directory
{
let tree_view_excluded_directories = gui_data.upper_notebook.tree_view_excluded_directories.clone();
let window_main = gui_data.window_main.clone();
let buttons_add_excluded_directory = gui_data.upper_notebook.buttons_add_excluded_directory.clone();
let file_dialog_include_exclude_folder_selection = gui_data.file_dialog_include_exclude_folder_selection.clone();
buttons_add_excluded_directory.connect_clicked(move |_| {
add_chosen_directories(&window_main, &tree_view_excluded_directories, true);
add_chosen_directories(&file_dialog_include_exclude_folder_selection, &tree_view_excluded_directories, true);
});
}
// Remove Excluded Folder
@ -79,28 +79,19 @@ pub fn connect_selection_of_directories(gui_data: &GuiData) {
}
}
fn add_chosen_directories(window_main: &Window, tree_view: &TreeView, excluded_items: bool) {
fn add_chosen_directories(file_dialog_include_exclude_folder_selection: &FileChooserNative, tree_view: &TreeView, excluded_items: bool) {
let folders_to = if excluded_items {
flg!("exclude_folders_dialog_title")
} else {
flg!("include_folders_dialog_title")
};
let file_chooser = gtk4::FileChooserDialog::builder()
.title(&folders_to)
.action(gtk4::FileChooserAction::SelectFolder)
.transient_for(window_main)
.modal(true)
.build();
file_chooser.add_button(&flg!("general_ok_button"), ResponseType::Ok);
file_chooser.add_button(&flg!("general_close_button"), ResponseType::Cancel);
file_chooser.set_select_multiple(true);
file_chooser.show();
file_dialog_include_exclude_folder_selection.show();
file_dialog_include_exclude_folder_selection.set_title(&folders_to);
let tree_view = tree_view.clone();
file_chooser.connect_response(move |file_chooser, response_type| {
if response_type == ResponseType::Ok {
file_dialog_include_exclude_folder_selection.connect_response(move |file_chooser, response_type| {
if response_type == ResponseType::Accept {
let mut folders: Vec<PathBuf> = Vec::new();
let g_files = file_chooser.files();
for index in 0..g_files.n_items() {
@ -130,13 +121,12 @@ fn add_chosen_directories(window_main: &Window, tree_view: &TreeView, excluded_i
}
}
}
file_chooser.close();
});
}
fn add_manually_directories(window_main: &Window, tree_view: &TreeView, excluded_items: bool) {
let dialog = gtk4::Dialog::builder()
.title(&flg!("include_manually_directories_dialog_title"))
.title(flg!("include_manually_directories_dialog_title"))
.transient_for(window_main)
.modal(true)
.build();

View file

@ -2,9 +2,8 @@ use std::collections::BTreeMap;
use std::default::Default;
use directories_next::ProjectDirs;
use gtk4::builders::LabelBuilder;
use gtk4::prelude::*;
use gtk4::{ResponseType, Window};
use gtk4::{Label, ResponseType, Window};
use image::imageops::FilterType;
use image_hasher::HashAlg;
@ -217,10 +216,10 @@ fn create_clear_cache_dialog(title_str: &str, window_settings: &Window) -> gtk4:
dialog.add_button(&flg!("general_ok_button"), ResponseType::Ok);
dialog.add_button(&flg!("general_close_button"), ResponseType::Cancel);
let label = LabelBuilder::new().label(&flg!("cache_clear_message_label_1")).build();
let label2 = LabelBuilder::new().label(&flg!("cache_clear_message_label_2")).build();
let label3 = LabelBuilder::new().label(&flg!("cache_clear_message_label_3")).build();
let label4 = LabelBuilder::new().label(&flg!("cache_clear_message_label_4")).build();
let label = Label::builder().label(flg!("cache_clear_message_label_1")).build();
let label2 = Label::builder().label(flg!("cache_clear_message_label_2")).build();
let label3 = Label::builder().label(flg!("cache_clear_message_label_3")).build();
let label4 = Label::builder().label(flg!("cache_clear_message_label_4")).build();
let internal_box = get_dialog_box_child(&dialog);
internal_box.append(&label);

View file

@ -6,12 +6,14 @@ pub mod connect_button_move;
pub mod connect_button_save;
pub mod connect_button_search;
pub mod connect_button_select;
pub mod connect_button_sort;
pub mod connect_button_stop;
pub mod connect_change_language;
pub mod connect_duplicate_buttons;
pub mod connect_header_buttons;
pub mod connect_notebook_tabs;
pub mod connect_popovers;
pub mod connect_popovers_select;
pub mod connect_popovers_sort;
pub mod connect_progress_window;
pub mod connect_selection_of_directories;
pub mod connect_settings;

View file

@ -1,6 +1,7 @@
use gtk4::prelude::*;
use gtk4::{GestureClick, Widget};
use crate::gui_structs::gui_data::CZK_ICON_SORT;
use crate::help_functions::{get_custom_label_from_widget, set_icon_of_button, BottomButtonsEnum};
use crate::{
flg, CZK_ICON_COMPARE, CZK_ICON_HARDLINK, CZK_ICON_HIDE_DOWN, CZK_ICON_HIDE_UP, CZK_ICON_MOVE, CZK_ICON_SAVE, CZK_ICON_SEARCH, CZK_ICON_SELECT, CZK_ICON_SYMLINK,
@ -17,19 +18,22 @@ pub struct GuiBottomButtons {
pub buttons_hardlink: gtk4::Button,
pub buttons_move: gtk4::Button,
pub buttons_compare: gtk4::Button,
pub buttons_sort: gtk4::MenuButton,
pub buttons_show_errors: gtk4::Button,
pub buttons_show_upper_notebook: gtk4::Button,
pub label_buttons_select: gtk4::Label,
pub label_buttons_sort: gtk4::Label,
pub buttons_names: [BottomButtonsEnum; 8],
pub buttons_array: [Widget; 8],
pub buttons_names: [BottomButtonsEnum; 9],
pub buttons_array: [Widget; 9],
pub gc_buttons_select: GestureClick,
pub gc_buttons_sort: GestureClick,
}
impl GuiBottomButtons {
pub fn create_from_builder(builder: &gtk4::Builder, popover_select: &gtk4::Popover) -> Self {
pub fn create_from_builder(builder: &gtk4::Builder, popover_select: &gtk4::Popover, popover_sort: &gtk4::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();
@ -38,15 +42,19 @@ impl GuiBottomButtons {
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 gc_buttons_select: GestureClick = GestureClick::new();
let gc_buttons_sort: GestureClick = GestureClick::new();
buttons_select.add_controller(&gc_buttons_select);
buttons_select.add_controller(gc_buttons_select.clone());
buttons_sort.add_controller(gc_buttons_sort.clone());
set_icon_of_button(&buttons_search, CZK_ICON_SEARCH);
set_icon_of_button(&buttons_select, CZK_ICON_SELECT);
@ -56,6 +64,7 @@ impl GuiBottomButtons {
set_icon_of_button(&buttons_hardlink, CZK_ICON_HARDLINK);
set_icon_of_button(&buttons_move, CZK_ICON_MOVE);
set_icon_of_button(&buttons_compare, CZK_ICON_COMPARE);
set_icon_of_button(&buttons_sort, CZK_ICON_SORT);
set_icon_of_button(&buttons_show_errors, CZK_ICON_HIDE_DOWN);
set_icon_of_button(&buttons_show_upper_notebook, CZK_ICON_HIDE_UP);
@ -68,6 +77,7 @@ impl GuiBottomButtons {
BottomButtonsEnum::Hardlink,
BottomButtonsEnum::Move,
BottomButtonsEnum::Compare,
BottomButtonsEnum::Sort,
];
let buttons_array = [
buttons_search.clone().upcast::<Widget>(),
@ -78,9 +88,11 @@ impl GuiBottomButtons {
buttons_hardlink.clone().upcast::<Widget>(),
buttons_move.clone().upcast::<Widget>(),
buttons_compare.clone().upcast::<Widget>(),
buttons_sort.clone().upcast::<Widget>(),
];
buttons_select.set_popover(Some(popover_select));
buttons_sort.set_popover(Some(popover_sort));
#[cfg(target_family = "windows")]
buttons_hardlink.set_sensitive(test_hardlinks());
@ -94,12 +106,15 @@ impl GuiBottomButtons {
buttons_hardlink,
buttons_move,
buttons_compare,
buttons_sort,
buttons_show_errors,
buttons_show_upper_notebook,
label_buttons_select,
label_buttons_sort,
buttons_names,
buttons_array,
gc_buttons_select,
gc_buttons_sort,
}
}
pub fn update_language(&self) {
@ -110,6 +125,7 @@ impl GuiBottomButtons {
get_custom_label_from_widget(&self.buttons_symlink.clone()).set_text(&flg!("bottom_symlink_button"));
get_custom_label_from_widget(&self.buttons_move.clone()).set_text(&flg!("bottom_move_button"));
get_custom_label_from_widget(&self.buttons_hardlink.clone()).set_text(&flg!("bottom_hardlink_button"));
self.label_buttons_sort.set_text(&flg!("bottom_sort_button"));
self.buttons_search.set_tooltip_text(Some(&flg!("bottom_search_button_tooltip")));
self.buttons_select.set_tooltip_text(Some(&flg!("bottom_select_button_tooltip")));
@ -117,6 +133,7 @@ impl GuiBottomButtons {
self.buttons_save.set_tooltip_text(Some(&flg!("bottom_save_button_tooltip")));
self.buttons_symlink.set_tooltip_text(Some(&flg!("bottom_symlink_button_tooltip")));
self.buttons_move.set_tooltip_text(Some(&flg!("bottom_move_button_tooltip")));
self.buttons_sort.set_tooltip_text(Some(&flg!("bottom_sort_button_tooltip")));
if self.buttons_hardlink.is_sensitive() {
self.buttons_hardlink.set_tooltip_text(Some(&flg!("bottom_hardlink_button_tooltip")));
} else {

View file

@ -5,7 +5,7 @@ use std::rc::Rc;
use crossbeam_channel::bounded;
use gdk4::gdk_pixbuf::Pixbuf;
use gtk4::prelude::*;
use gtk4::Builder;
use gtk4::{Builder, FileChooserNative};
use czkawka_core::bad_extensions::BadExtensions;
use czkawka_core::big_file::BigFile;
@ -25,7 +25,8 @@ use crate::gui_structs::gui_bottom_buttons::GuiBottomButtons;
use crate::gui_structs::gui_compare_images::GuiCompareImages;
use crate::gui_structs::gui_header::GuiHeader;
use crate::gui_structs::gui_main_notebook::GuiMainNotebook;
use crate::gui_structs::gui_popovers::GuiPopovers;
use crate::gui_structs::gui_popovers_select::GuiSelectPopovers;
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;
@ -33,25 +34,26 @@ use crate::help_functions::BottomButtonsEnum;
use crate::notebook_enums::*;
use crate::taskbar_progress::TaskbarProgress;
pub const ICON_ABOUT: &[u8; 4458] = include_bytes!("../../icons/icon_about.png");
pub const CZK_ICON_ADD: &[u8; 677] = include_bytes!("../../icons/czk_add.svg");
pub const CZK_ICON_COMPARE: &[u8; 5700] = include_bytes!("../../icons/czk_compare.svg");
pub const CZK_ICON_DELETE: &[u8; 489] = include_bytes!("../../icons/czk_delete.svg");
pub const CZK_ICON_HARDLINK: &[u8; 17326] = include_bytes!("../../icons/czk_hardlink.svg");
pub const CZK_ICON_HIDE_DOWN: &[u8; 3057] = include_bytes!("../../icons/czk_hide_down.svg");
pub const CZK_ICON_HIDE_UP: &[u8; 3310] = include_bytes!("../../icons/czk_hide_up.svg");
pub const CZK_ICON_INFO: &[u8; 3325] = include_bytes!("../../icons/czk_info.svg");
pub const CZK_ICON_LEFT: &[u8; 245] = include_bytes!("../../icons/czk_left.svg");
pub const CZK_ICON_MANUAL_ADD: &[u8; 677] = include_bytes!("../../icons/czk_manual_add.svg");
pub const CZK_ICON_MOVE: &[u8; 2535] = include_bytes!("../../icons/czk_move.svg");
pub const CZK_ICON_RIGHT: &[u8; 278] = include_bytes!("../../icons/czk_right.svg");
pub const CZK_ICON_SAVE: &[u8; 462] = include_bytes!("../../icons/czk_save.svg");
pub const CZK_ICON_SEARCH: &[u8; 1517] = include_bytes!("../../icons/czk_search.svg");
pub const CZK_ICON_SELECT: &[u8; 370] = include_bytes!("../../icons/czk_select.svg");
pub const CZK_ICON_SETTINGS: &[u8; 11677] = include_bytes!("../../icons/czk_settings.svg");
pub const CZK_ICON_STOP: &[u8; 618] = include_bytes!("../../icons/czk_stop.svg");
pub const CZK_ICON_SYMLINK: &[u8; 2455] = include_bytes!("../../icons/czk_symlink.svg");
pub const CZK_ICON_TRASH: &[u8; 709] = include_bytes!("../../icons/czk_trash.svg");
pub const ICON_ABOUT: &[u8] = include_bytes!("../../icons/icon_about.png");
pub const CZK_ICON_ADD: &[u8] = include_bytes!("../../icons/czk_add.svg");
pub const CZK_ICON_COMPARE: &[u8] = include_bytes!("../../icons/czk_compare.svg");
pub const CZK_ICON_DELETE: &[u8] = include_bytes!("../../icons/czk_delete.svg");
pub const CZK_ICON_HARDLINK: &[u8] = include_bytes!("../../icons/czk_hardlink.svg");
pub const CZK_ICON_HIDE_DOWN: &[u8] = include_bytes!("../../icons/czk_hide_down.svg");
pub const CZK_ICON_HIDE_UP: &[u8] = include_bytes!("../../icons/czk_hide_up.svg");
pub const CZK_ICON_INFO: &[u8] = include_bytes!("../../icons/czk_info.svg");
pub const CZK_ICON_LEFT: &[u8] = include_bytes!("../../icons/czk_left.svg");
pub const CZK_ICON_MANUAL_ADD: &[u8] = include_bytes!("../../icons/czk_manual_add.svg");
pub const CZK_ICON_MOVE: &[u8] = include_bytes!("../../icons/czk_move.svg");
pub const CZK_ICON_RIGHT: &[u8] = include_bytes!("../../icons/czk_right.svg");
pub const CZK_ICON_SAVE: &[u8] = include_bytes!("../../icons/czk_save.svg");
pub const CZK_ICON_SEARCH: &[u8] = include_bytes!("../../icons/czk_search.svg");
pub const CZK_ICON_SELECT: &[u8] = include_bytes!("../../icons/czk_select.svg");
pub const CZK_ICON_SETTINGS: &[u8] = include_bytes!("../../icons/czk_settings.svg");
pub const CZK_ICON_SORT: &[u8] = include_bytes!("../../icons/czk_sort.svg");
pub const CZK_ICON_STOP: &[u8] = include_bytes!("../../icons/czk_stop.svg");
pub const CZK_ICON_SYMLINK: &[u8] = include_bytes!("../../icons/czk_symlink.svg");
pub const CZK_ICON_TRASH: &[u8] = include_bytes!("../../icons/czk_trash.svg");
#[derive(Clone)]
pub struct GuiData {
@ -64,7 +66,8 @@ pub struct GuiData {
pub main_notebook: GuiMainNotebook,
pub upper_notebook: GuiUpperNotebook,
pub popovers: GuiPopovers,
pub popovers_select: GuiSelectPopovers,
pub popovers_sort: GuiSortPopovers,
pub bottom_buttons: GuiBottomButtons,
pub progress_window: GuiProgressDialog,
pub about: GuiAbout,
@ -72,6 +75,9 @@ pub struct GuiData {
pub header: GuiHeader,
pub compare_images: GuiCompareImages,
pub file_dialog_include_exclude_folder_selection: FileChooserNative,
pub file_dialog_move_to_folder: FileChooserNative,
// Taskbar state
pub taskbar_state: Rc<RefCell<TaskbarProgress>>,
@ -116,14 +122,15 @@ impl GuiData {
window_main.set_title(Some(&flg!("window_main_title")));
window_main.show();
let pixbuf = Pixbuf::from_read(std::io::BufReader::new(&ICON_ABOUT[..])).unwrap();
let pixbuf = Pixbuf::from_read(std::io::BufReader::new(ICON_ABOUT)).unwrap();
window_main.set_application(Some(application));
let main_notebook = GuiMainNotebook::create_from_builder(&builder);
let upper_notebook = GuiUpperNotebook::create_from_builder(&builder);
let popovers = GuiPopovers::create_from_builder();
let bottom_buttons = GuiBottomButtons::create_from_builder(&builder, &popovers.popover_select);
let popovers_select = GuiSelectPopovers::create_from_builder();
let popovers_sort = GuiSortPopovers::create_from_builder();
let bottom_buttons = GuiBottomButtons::create_from_builder(&builder, &popovers_select.popover_select, &popovers_sort.popover_sort);
let progress_window = GuiProgressDialog::create_from_builder(&window_main);
let about = GuiAbout::create_from_builder(&window_main, &pixbuf);
let header = GuiHeader::create_from_builder(&builder);
@ -148,9 +155,25 @@ impl GuiData {
temp_hashmap.insert(*button_name, false);
}
}
shared_buttons.borrow_mut().insert(i.clone(), temp_hashmap);
shared_buttons.borrow_mut().insert(*i, temp_hashmap);
}
// File Dialogs - Native file dialogs must exists all the time in opposite to normal dialog
let file_dialog_include_exclude_folder_selection = FileChooserNative::builder()
.action(gtk4::FileChooserAction::SelectFolder)
.transient_for(&window_main)
.select_multiple(true)
.modal(true)
.build();
let file_dialog_move_to_folder = FileChooserNative::builder()
.title(flg!("move_files_title_dialog"))
.action(gtk4::FileChooserAction::SelectFolder)
.transient_for(&window_main)
.select_multiple(false)
.modal(true)
.build();
// State of search results
let shared_duplication_state: Rc<RefCell<_>> = Rc::new(RefCell::new(DuplicateFinder::new()));
@ -184,13 +207,16 @@ impl GuiData {
window_main,
main_notebook,
upper_notebook,
popovers,
popovers_select,
popovers_sort,
bottom_buttons,
progress_window,
about,
settings,
header,
compare_images,
file_dialog_include_exclude_folder_selection,
file_dialog_move_to_folder,
taskbar_state,
shared_buttons,
shared_duplication_state,
@ -218,7 +244,8 @@ impl GuiData {
self.main_notebook.update_language();
self.upper_notebook.update_language();
self.popovers.update_language();
self.popovers_select.update_language();
self.popovers_sort.update_language();
self.bottom_buttons.update_language();
self.progress_window.update_language();
self.about.update_language();

View file

@ -153,50 +153,50 @@ impl GuiMainNotebook {
let tree_view_bad_extensions: TreeView = TreeView::new();
let evk_tree_view_duplicate_finder: EventControllerKey = EventControllerKey::new();
tree_view_duplicate_finder.add_controller(&evk_tree_view_duplicate_finder);
tree_view_duplicate_finder.add_controller(evk_tree_view_duplicate_finder.clone());
let evk_tree_view_empty_folder_finder: EventControllerKey = EventControllerKey::new();
tree_view_empty_folder_finder.add_controller(&evk_tree_view_empty_folder_finder);
tree_view_empty_folder_finder.add_controller(evk_tree_view_empty_folder_finder.clone());
let evk_tree_view_empty_files_finder: EventControllerKey = EventControllerKey::new();
tree_view_empty_files_finder.add_controller(&evk_tree_view_empty_files_finder);
tree_view_empty_files_finder.add_controller(evk_tree_view_empty_files_finder.clone());
let evk_tree_view_temporary_files_finder: EventControllerKey = EventControllerKey::new();
tree_view_temporary_files_finder.add_controller(&evk_tree_view_temporary_files_finder);
tree_view_temporary_files_finder.add_controller(evk_tree_view_temporary_files_finder.clone());
let evk_tree_view_big_files_finder: EventControllerKey = EventControllerKey::new();
tree_view_big_files_finder.add_controller(&evk_tree_view_big_files_finder);
tree_view_big_files_finder.add_controller(evk_tree_view_big_files_finder.clone());
let evk_tree_view_similar_images_finder: EventControllerKey = EventControllerKey::new();
tree_view_similar_images_finder.add_controller(&evk_tree_view_similar_images_finder);
tree_view_similar_images_finder.add_controller(evk_tree_view_similar_images_finder.clone());
let evk_tree_view_similar_videos_finder: EventControllerKey = EventControllerKey::new();
tree_view_similar_videos_finder.add_controller(&evk_tree_view_similar_videos_finder);
tree_view_similar_videos_finder.add_controller(evk_tree_view_similar_videos_finder.clone());
let evk_tree_view_same_music_finder: EventControllerKey = EventControllerKey::new();
tree_view_same_music_finder.add_controller(&evk_tree_view_same_music_finder);
tree_view_same_music_finder.add_controller(evk_tree_view_same_music_finder.clone());
let evk_tree_view_invalid_symlinks: EventControllerKey = EventControllerKey::new();
tree_view_invalid_symlinks.add_controller(&evk_tree_view_invalid_symlinks);
tree_view_invalid_symlinks.add_controller(evk_tree_view_invalid_symlinks.clone());
let evk_tree_view_broken_files: EventControllerKey = EventControllerKey::new();
tree_view_broken_files.add_controller(&evk_tree_view_broken_files);
tree_view_broken_files.add_controller(evk_tree_view_broken_files.clone());
let evk_tree_view_bad_extensions: EventControllerKey = EventControllerKey::new();
tree_view_bad_extensions.add_controller(&evk_tree_view_bad_extensions);
tree_view_bad_extensions.add_controller(evk_tree_view_bad_extensions.clone());
let gc_tree_view_duplicate_finder: GestureClick = GestureClick::new();
tree_view_duplicate_finder.add_controller(&gc_tree_view_duplicate_finder);
tree_view_duplicate_finder.add_controller(gc_tree_view_duplicate_finder.clone());
let gc_tree_view_empty_folder_finder: GestureClick = GestureClick::new();
tree_view_empty_folder_finder.add_controller(&gc_tree_view_empty_folder_finder);
tree_view_empty_folder_finder.add_controller(gc_tree_view_empty_folder_finder.clone());
let gc_tree_view_empty_files_finder: GestureClick = GestureClick::new();
tree_view_empty_files_finder.add_controller(&gc_tree_view_empty_files_finder);
tree_view_empty_files_finder.add_controller(gc_tree_view_empty_files_finder.clone());
let gc_tree_view_temporary_files_finder: GestureClick = GestureClick::new();
tree_view_temporary_files_finder.add_controller(&gc_tree_view_temporary_files_finder);
tree_view_temporary_files_finder.add_controller(gc_tree_view_temporary_files_finder.clone());
let gc_tree_view_big_files_finder: GestureClick = GestureClick::new();
tree_view_big_files_finder.add_controller(&gc_tree_view_big_files_finder);
tree_view_big_files_finder.add_controller(gc_tree_view_big_files_finder.clone());
let gc_tree_view_similar_images_finder: GestureClick = GestureClick::new();
tree_view_similar_images_finder.add_controller(&gc_tree_view_similar_images_finder);
tree_view_similar_images_finder.add_controller(gc_tree_view_similar_images_finder.clone());
let gc_tree_view_similar_videos_finder: GestureClick = GestureClick::new();
tree_view_similar_videos_finder.add_controller(&gc_tree_view_similar_videos_finder);
tree_view_similar_videos_finder.add_controller(gc_tree_view_similar_videos_finder.clone());
let gc_tree_view_same_music_finder: GestureClick = GestureClick::new();
tree_view_same_music_finder.add_controller(&gc_tree_view_same_music_finder);
tree_view_same_music_finder.add_controller(gc_tree_view_same_music_finder.clone());
let gc_tree_view_invalid_symlinks: GestureClick = GestureClick::new();
tree_view_invalid_symlinks.add_controller(&gc_tree_view_invalid_symlinks);
tree_view_invalid_symlinks.add_controller(gc_tree_view_invalid_symlinks.clone());
let gc_tree_view_broken_files: GestureClick = GestureClick::new();
tree_view_broken_files.add_controller(&gc_tree_view_broken_files);
tree_view_broken_files.add_controller(gc_tree_view_broken_files.clone());
let gc_tree_view_bad_extensions: GestureClick = GestureClick::new();
tree_view_bad_extensions.add_controller(&gc_tree_view_bad_extensions);
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();

View file

@ -4,7 +4,7 @@ use gtk4::Builder;
use crate::flg;
#[derive(Clone)]
pub struct GuiPopovers {
pub struct GuiSelectPopovers {
pub buttons_popover_select_all: gtk4::Button,
pub buttons_popover_unselect_all: gtk4::Button,
pub buttons_popover_reverse: gtk4::Button,
@ -29,7 +29,7 @@ pub struct GuiPopovers {
pub popover_right_click: gtk4::Popover,
}
impl GuiPopovers {
impl GuiSelectPopovers {
pub fn create_from_builder() -> Self {
let glade_src = include_str!("../../ui/popover_select.ui").to_string();
let builder = Builder::from_string(glade_src.as_str());

View file

@ -0,0 +1,46 @@
use gtk4::prelude::*;
use gtk4::Builder;
use crate::flg;
#[derive(Clone)]
pub struct GuiSortPopovers {
pub buttons_popover_sort_file_name: gtk4::Button,
pub buttons_popover_sort_folder_name: gtk4::Button,
pub buttons_popover_sort_full_name: gtk4::Button,
pub buttons_popover_sort_size: gtk4::Button,
pub buttons_popover_sort_selection: gtk4::Button,
pub popover_sort: gtk4::Popover,
}
impl GuiSortPopovers {
pub fn create_from_builder() -> Self {
let glade_src = include_str!("../../ui/popover_sort.ui").to_string();
let builder = Builder::from_string(glade_src.as_str());
let buttons_popover_sort_file_name: gtk4::Button = builder.object("buttons_popover_sort_file_name").unwrap();
let buttons_popover_sort_folder_name: gtk4::Button = builder.object("buttons_popover_sort_folder_name").unwrap();
let buttons_popover_sort_full_name: gtk4::Button = builder.object("buttons_popover_sort_full_name").unwrap();
let buttons_popover_sort_size: gtk4::Button = builder.object("buttons_popover_sort_size").unwrap();
let buttons_popover_sort_selection: gtk4::Button = builder.object("buttons_popover_sort_selection").unwrap();
let popover_sort: gtk4::Popover = builder.object("popover_sort").unwrap();
Self {
buttons_popover_sort_file_name,
buttons_popover_sort_folder_name,
buttons_popover_sort_full_name,
buttons_popover_sort_size,
buttons_popover_sort_selection,
popover_sort,
}
}
pub fn update_language(&self) {
self.buttons_popover_sort_file_name.set_label(&flg!("popover_sort_file_name"));
self.buttons_popover_sort_folder_name.set_label(&flg!("popover_sort_folder_name"));
self.buttons_popover_sort_full_name.set_label(&flg!("popover_sort_full_name"));
self.buttons_popover_sort_size.set_label(&flg!("popover_sort_size"));
self.buttons_popover_sort_selection.set_label(&flg!("popover_sort_selection"));
}
}

View file

@ -42,7 +42,7 @@ impl GuiProgressDialog {
let button_stop_in_dialog: gtk4::Button = builder.object("button_stop_in_dialog").unwrap();
let evk_button_stop_in_dialog = EventControllerKey::new();
button_stop_in_dialog.add_controller(&evk_button_stop_in_dialog);
button_stop_in_dialog.add_controller(evk_button_stop_in_dialog.clone());
set_icon_of_button(&button_stop_in_dialog, CZK_ICON_STOP);

View file

@ -54,14 +54,14 @@ impl GuiUpperNotebook {
let tree_view_excluded_directories: TreeView = TreeView::new();
let evk_tree_view_included_directories: EventControllerKey = EventControllerKey::new();
tree_view_included_directories.add_controller(&evk_tree_view_included_directories);
tree_view_included_directories.add_controller(evk_tree_view_included_directories.clone());
let evk_tree_view_excluded_directories: EventControllerKey = EventControllerKey::new();
tree_view_excluded_directories.add_controller(&evk_tree_view_excluded_directories);
tree_view_excluded_directories.add_controller(evk_tree_view_excluded_directories.clone());
let gc_tree_view_included_directories: GestureClick = GestureClick::new();
tree_view_included_directories.add_controller(&gc_tree_view_included_directories);
tree_view_included_directories.add_controller(gc_tree_view_included_directories.clone());
let gc_tree_view_excluded_directories: GestureClick = GestureClick::new();
tree_view_excluded_directories.add_controller(&gc_tree_view_excluded_directories);
tree_view_excluded_directories.add_controller(gc_tree_view_excluded_directories.clone());
let entry_allowed_extensions: gtk4::Entry = builder.object("entry_allowed_extensions").unwrap();
let entry_excluded_items: gtk4::Entry = builder.object("entry_excluded_items").unwrap();

View file

@ -4,7 +4,8 @@ mod gui_compare_images;
pub mod gui_data;
mod gui_header;
pub mod gui_main_notebook;
pub mod gui_popovers;
pub mod gui_popovers_select;
pub mod gui_popovers_sort;
mod gui_progress_dialog;
pub mod gui_settings;
pub mod gui_upper_notebook;

View file

@ -45,7 +45,7 @@ pub const KEY_SPACE: u32 = 65;
// pub const KEY_HOME: u32 = 115;
// pub const KEY_END: u32 = 110;
#[derive(Eq, PartialEq)]
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum PopoverTypes {
All,
Size,
@ -64,6 +64,7 @@ pub enum BottomButtonsEnum {
Hardlink,
Move,
Compare,
Sort,
}
pub enum Message {
@ -80,11 +81,13 @@ pub enum Message {
BadExtensions(BadExtensions),
}
#[derive(Clone, Copy)]
pub enum ColumnsDuplicates {
// Columns for duplicate treeview
ActivatableSelectButton = 0,
SelectionButton,
Size,
SizeAsBytes,
Name,
Path,
Modification,
@ -94,6 +97,7 @@ pub enum ColumnsDuplicates {
TextColor,
}
#[derive(Clone, Copy)]
pub enum ColumnsEmptyFolders {
// Columns for empty folder treeview
SelectionButton = 0,
@ -103,17 +107,20 @@ pub enum ColumnsEmptyFolders {
ModificationAsSecs,
}
#[derive(Clone, Copy)]
pub enum ColumnsIncludedDirectory {
// Columns for Included Directories in upper Notebook
Path = 0,
ReferenceButton,
}
#[derive(Clone, Copy)]
pub enum ColumnsExcludedDirectory {
// Columns for Excluded Directories in upper Notebook
Path = 0,
}
#[derive(Clone, Copy)]
pub enum ColumnsBigFiles {
SelectionButton = 0,
Size,
@ -124,6 +131,7 @@ pub enum ColumnsBigFiles {
ModificationAsSecs,
}
#[derive(Clone, Copy)]
pub enum ColumnsEmptyFiles {
SelectionButton = 0,
Name,
@ -132,6 +140,7 @@ pub enum ColumnsEmptyFiles {
ModificationAsSecs,
}
#[derive(Clone, Copy)]
pub enum ColumnsTemporaryFiles {
SelectionButton = 0,
Name,
@ -140,6 +149,7 @@ pub enum ColumnsTemporaryFiles {
ModificationAsSecs,
}
#[derive(Clone, Copy)]
pub enum ColumnsSimilarImages {
ActivatableSelectButton = 0,
SelectionButton,
@ -156,6 +166,7 @@ pub enum ColumnsSimilarImages {
TextColor,
}
#[derive(Clone, Copy)]
pub enum ColumnsSimilarVideos {
ActivatableSelectButton = 0,
SelectionButton,
@ -170,6 +181,7 @@ pub enum ColumnsSimilarVideos {
TextColor,
}
#[derive(Clone, Copy)]
pub enum ColumnsSameMusic {
ActivatableSelectButton = 0,
SelectionButton,
@ -191,6 +203,7 @@ pub enum ColumnsSameMusic {
TextColor,
}
#[derive(Clone, Copy)]
pub enum ColumnsInvalidSymlinks {
SelectionButton = 0,
Name,
@ -201,6 +214,7 @@ pub enum ColumnsInvalidSymlinks {
ModificationAsSecs,
}
#[derive(Clone, Copy)]
pub enum ColumnsBrokenFiles {
SelectionButton = 0,
Name,
@ -210,6 +224,7 @@ pub enum ColumnsBrokenFiles {
ModificationAsSecs,
}
#[derive(Clone, Copy)]
pub enum ColumnsBadExtensions {
SelectionButton = 0,
Name,

View file

@ -31,24 +31,11 @@ use crate::opening_selecting_records::*;
pub fn initialize_gui(gui_data: &mut GuiData) {
//// Initialize button
{
let buttons_search = gui_data.bottom_buttons.buttons_search.clone();
let buttons_save = gui_data.bottom_buttons.buttons_save.clone();
let buttons_delete = gui_data.bottom_buttons.buttons_delete.clone();
let buttons_select = gui_data.bottom_buttons.buttons_select.clone();
let buttons_symlink = gui_data.bottom_buttons.buttons_symlink.clone();
let buttons_hardlink = gui_data.bottom_buttons.buttons_hardlink.clone();
let buttons_move = gui_data.bottom_buttons.buttons_move.clone();
let buttons_compare = gui_data.bottom_buttons.buttons_compare.clone();
// Disable and show buttons - only search button should be visible
buttons_search.show();
buttons_save.hide();
buttons_delete.hide();
buttons_select.hide();
buttons_symlink.hide();
buttons_hardlink.hide();
buttons_move.hide();
buttons_compare.hide();
let buttons = &gui_data.bottom_buttons.buttons_array;
for button in buttons {
button.hide();
}
gui_data.bottom_buttons.buttons_search.show();
}
//// Initialize language combo box
{

View file

@ -26,7 +26,6 @@ use connect_things::connect_change_language::*;
use connect_things::connect_duplicate_buttons::connect_duplicate_combo_box;
use connect_things::connect_header_buttons::*;
use connect_things::connect_notebook_tabs::*;
use connect_things::connect_popovers::*;
use connect_things::connect_progress_window::*;
use connect_things::connect_selection_of_directories::*;
use connect_things::connect_settings::*;
@ -37,6 +36,9 @@ use czkawka_core::*;
use gui_structs::gui_data::*;
use crate::compute_results::*;
use crate::connect_things::connect_button_sort::connect_button_sort;
use crate::connect_things::connect_popovers_select::connect_popover_select;
use crate::connect_things::connect_popovers_sort::connect_popover_sort;
use crate::initialize_gui::*;
use crate::language_functions::LANGUAGES_ALL;
use crate::saving_loading::*;
@ -63,7 +65,7 @@ mod taskbar_progress_win;
mod tests;
fn main() {
let application = Application::new(None, ApplicationFlags::HANDLES_OPEN | ApplicationFlags::HANDLES_COMMAND_LINE);
let application = Application::new(None::<String>, ApplicationFlags::HANDLES_OPEN | ApplicationFlags::HANDLES_COMMAND_LINE);
application.connect_command_line(move |app, cmdline| {
build_ui(app, &cmdline.arguments());
0
@ -160,6 +162,7 @@ fn build_ui(application: &Application, arguments: &[OsString]) {
futures_sender_bad_extensions,
);
connect_button_select(&gui_data);
connect_button_sort(&gui_data);
connect_button_stop(&gui_data);
connect_button_hardlink_symlink(&gui_data);
connect_button_move(&gui_data);
@ -168,7 +171,8 @@ fn build_ui(application: &Application, arguments: &[OsString]) {
connect_duplicate_combo_box(&gui_data);
connect_notebook_tabs(&gui_data);
connect_selection_of_directories(&gui_data);
connect_popovers(&gui_data);
connect_popover_select(&gui_data);
connect_popover_sort(&gui_data);
connect_compute_results(&gui_data, glib_stop_receiver);
connect_progress_window(
&gui_data,

View file

@ -2,7 +2,7 @@ pub const NUMBER_OF_NOTEBOOK_MAIN_TABS: usize = 11;
// pub const NUMBER_OF_NOTEBOOK_UPPER_TABS: usize = 3;
// Needs to be updated when changed order of notebook tabs
#[derive(Eq, PartialEq, Hash, Clone, Debug)]
#[derive(Eq, PartialEq, Hash, Clone, Debug, Copy)]
pub enum NotebookMainEnum {
Duplicate = 0,
EmptyDirectories,
@ -50,7 +50,7 @@ pub fn get_all_main_tabs() -> [NotebookMainEnum; NUMBER_OF_NOTEBOOK_MAIN_TABS] {
]
}
#[derive(Eq, PartialEq, Hash, Clone, Debug)]
#[derive(Eq, PartialEq, Hash, Clone, Debug, Copy)]
pub enum NotebookUpperEnum {
IncludedDirectories = 0,
ExcludedDirectories,

View file

@ -22,20 +22,28 @@ pub struct NotebookObject {
pub static NOTEBOOKS_INFO: [NotebookObject; NUMBER_OF_NOTEBOOK_MAIN_TABS] = [
NotebookObject {
notebook_type: NotebookMainEnum::Duplicate,
available_modes: &[PopoverTypes::All, PopoverTypes::Reverse, PopoverTypes::Custom, PopoverTypes::Date],
available_modes: &[
PopoverTypes::All,
PopoverTypes::Reverse,
PopoverTypes::Custom,
PopoverTypes::Date,
PopoverTypes::Size,
PopoverTypes::All,
],
column_activatable_button: Some(ColumnsDuplicates::ActivatableSelectButton as i32),
column_path: ColumnsDuplicates::Path as i32,
column_name: ColumnsDuplicates::Name as i32,
column_selection: ColumnsDuplicates::SelectionButton as i32,
column_header: Some(ColumnsDuplicates::IsHeader as i32),
column_dimensions: None,
column_size: None, // Do not add, useless in hash and size mode
column_size_as_bytes: None, // Do not add, useless in hash and size mode
column_size: Some(ColumnsDuplicates::Size as i32), // Useless with duplicates by hash or size, but needed by sorting by name
column_size_as_bytes: Some(ColumnsDuplicates::SizeAsBytes as i32),
column_modification_as_secs: Some(ColumnsDuplicates::ModificationAsSecs as i32),
columns_types: &[
glib::types::Type::BOOL, // ActivatableSelectButton
glib::types::Type::BOOL, // SelectionButton
glib::types::Type::STRING, // Size
glib::types::Type::U64, // SizeAsBytes
glib::types::Type::STRING, // Name
glib::types::Type::STRING, // Path
glib::types::Type::STRING, // Modification

View file

@ -8,7 +8,7 @@ use std::{env, fs};
use czkawka_core::common::get_default_number_of_threads;
use directories_next::ProjectDirs;
use gtk4::prelude::*;
use gtk4::{ComboBoxText, ScrolledWindow, TextView};
use gtk4::{ComboBoxText, ScrolledWindow, TextView, TreeView};
use czkawka_core::common_dir_traversal::CheckingMethod;
use czkawka_core::similar_images::SIMILAR_VALUES;
@ -157,7 +157,7 @@ impl LoadSaveStruct {
if self.loaded_items.contains_key(&key) {
let item = self.loaded_items.get(&key).unwrap().clone().into_iter().filter(|e| !e.is_empty()).collect::<Vec<String>>();
return if item.len() == 1 {
let text = item[0].clone().trim().to_lowercase();
let text = item[0].trim().to_lowercase();
if text == "false" || text == "0" {
false
} else if text == "true" || text == "1" {
@ -199,7 +199,7 @@ impl LoadSaveStruct {
self.loaded_items.insert(key, vec![value.to_string()]);
}
pub fn save_list_store(&mut self, key: String, tree_view: &gtk4::TreeView, column_path: i32) {
pub fn save_list_store(&mut self, key: String, tree_view: &TreeView, column_path: i32) {
let mut vec_string = vec![];
let list_store = get_list_store(tree_view);
if let Some(iter) = list_store.iter_first() {
@ -214,7 +214,6 @@ impl LoadSaveStruct {
self.loaded_items.insert(key, vec_string);
}
//noinspection RsLift
pub fn open_save_file(&self, text_view_errors: &TextView, save_configuration: bool, manual_execution: bool) -> Option<(File, PathBuf)> {
if let Some(proj_dirs) = ProjectDirs::from("pl", "Qarmin", "Czkawka") {
// Lin: /home/username/.config/czkawka
@ -735,7 +734,7 @@ pub fn load_configuration(
let maximal_file_size: String = loaded_entries.get_integer_string(hashmap_ls.get(&LoadText::MaximalFileSize).unwrap().clone(), DEFAULT_MAXIMAL_FILE_SIZE.to_string());
let loading_at_start: bool = loaded_entries.get_bool(hashmap_ls.get(&LoadText::LoadAtStart).unwrap().clone(), DEFAULT_LOAD_AT_START);
let saving_at_exit: bool = loaded_entries.get_bool(hashmap_ls.get(&LoadText::SaveAtExit).unwrap().clone(), DEFAULT_SAVE_ON_EXIT);
let mut saving_at_exit: bool = loaded_entries.get_bool(hashmap_ls.get(&LoadText::SaveAtExit).unwrap().clone(), DEFAULT_SAVE_ON_EXIT);
let confirm_deletion: bool = loaded_entries.get_bool(hashmap_ls.get(&LoadText::ConfirmDeletionFiles).unwrap().clone(), DEFAULT_CONFIRM_DELETION);
let confirm_group_deletion: bool = loaded_entries.get_bool(hashmap_ls.get(&LoadText::ConfirmDeletionAllFilesInGroup).unwrap().clone(), DEFAULT_CONFIRM_GROUP_DELETION);
let show_previews_similar_images: bool = loaded_entries.get_bool(hashmap_ls.get(&LoadText::ImagePreviewImage).unwrap().clone(), DEFAULT_SHOW_IMAGE_PREVIEW);
@ -802,72 +801,69 @@ pub fn load_configuration(
let check_button_broken_files_audio = loaded_entries.get_object(hashmap_ls.get(&LoadText::BrokenFilesAudio).unwrap().clone(), DEFAULT_BROKEN_FILES_AUDIO);
let thread_number = loaded_entries.get_object(hashmap_ls.get(&LoadText::ThreadNumber).unwrap().clone(), DEFAULT_THREAD_NUMBER);
// Setting data
if manual_execution || loading_at_start {
{
// Handle here arguments that were added to app e.g. czkawka_gui /home --/home/roman
if loading_at_start && arguments.len() > 1 {
let iter_i = arguments.iter().skip(1);
let iter_e = iter_i.clone();
included_directories = iter_i
.filter_map(|e| {
let r = e.to_string_lossy().to_string();
if !r.starts_with("--") {
let path = Path::new(&r);
if !path.exists() {
return None;
}
match path.canonicalize() {
Ok(r) => Some(r.to_string_lossy().to_string()),
Err(_) => None,
}
} else {
None
let mut set_start_folders = false;
if !manual_execution {
// Handle here arguments that were added to app e.g. czkawka_gui /home --/home/roman
if arguments.len() > 1 {
let iter_i = arguments.iter().skip(1);
let iter_e = iter_i.clone();
let inc_dir = iter_i
.filter_map(|e| {
let r = e.to_string_lossy().to_string();
if !r.starts_with("--") {
let path = Path::new(&r);
if !path.exists() {
return None;
}
})
.collect::<Vec<_>>();
excluded_directories = iter_e
.filter_map(|e| {
let r = e.to_string_lossy().to_string();
if let Some(r) = r.strip_prefix("--") {
let path = Path::new(&r);
if !path.exists() {
return None;
}
match path.canonicalize() {
Ok(r) => Some(r.to_string_lossy().to_string()),
Err(_) => None,
}
} else {
None
match path.canonicalize() {
Ok(r) => Some(r.to_string_lossy().to_string()),
Err(_) => None,
}
})
.collect::<Vec<_>>();
}
} else {
None
}
})
.collect::<Vec<_>>();
let exc_dir = iter_e
.filter_map(|e| {
let r = e.to_string_lossy().to_string();
if let Some(r) = r.strip_prefix("--") {
let path = Path::new(&r);
if !path.exists() {
return None;
}
match path.canonicalize() {
Ok(r) => Some(r.to_string_lossy().to_string()),
Err(_) => None,
}
} else {
None
}
})
.collect::<Vec<_>>();
// Include Directories
let tree_view_included_directories = upper_notebook.tree_view_included_directories.clone();
let list_store = get_list_store(&tree_view_included_directories);
list_store.clear();
for directory in included_directories {
let values: [(u32, &dyn ToValue); 2] = [
(ColumnsIncludedDirectory::Path as u32, &directory),
(ColumnsIncludedDirectory::ReferenceButton as u32, &false),
];
list_store.set(&list_store.append(), &values);
}
//// Exclude Directories
let tree_view_excluded_directories = upper_notebook.tree_view_excluded_directories.clone();
let list_store = get_list_store(&tree_view_excluded_directories);
list_store.clear();
for directory in excluded_directories {
let values: [(u32, &dyn ToValue); 1] = [(ColumnsExcludedDirectory::Path as u32, &directory)];
list_store.set(&list_store.append(), &values);
if inc_dir.is_empty() {
println!("Arguments {arguments:?} should contains at least one directory to include");
} else {
included_directories = inc_dir;
excluded_directories = exc_dir;
saving_at_exit = false;
set_start_folders = true;
}
}
}
if manual_execution || loading_at_start || set_start_folders {
set_directories(
&upper_notebook.tree_view_included_directories,
&upper_notebook.tree_view_excluded_directories,
&included_directories,
&excluded_directories,
);
}
// Setting data
if loading_at_start || manual_execution {
//// Language ComboBoxText
{
for (index, lang) in LANGUAGES_ALL.iter().enumerate() {
@ -966,6 +962,29 @@ pub fn load_configuration(
}
}
fn set_directories(tree_view_included_directories: &TreeView, tree_view_excluded_directories: &TreeView, included_directories: &[String], excluded_directories: &[String]) {
// Include Directories
let list_store = get_list_store(tree_view_included_directories);
list_store.clear();
for directory in included_directories {
let values: [(u32, &dyn ToValue); 2] = [
(ColumnsIncludedDirectory::Path as u32, &directory),
(ColumnsIncludedDirectory::ReferenceButton as u32, &false),
];
list_store.set(&list_store.append(), &values);
}
//// Exclude Directories
let list_store = get_list_store(tree_view_excluded_directories);
list_store.clear();
for directory in excluded_directories {
let values: [(u32, &dyn ToValue); 1] = [(ColumnsExcludedDirectory::Path as u32, &directory)];
list_store.set(&list_store.append(), &values);
}
}
/// Function do not allow to set invalid index to combobox because this would cause to show empty value and function would crash
fn save_proper_value_to_combo_box(combo_box: &ComboBoxText, what_to_save: u32) {
combo_box.set_active(Some(what_to_save));

View file

@ -8,7 +8,8 @@
(6,None,"popover_right_click.ui","popover_right_click.ui",None,None,None,None,None,None),
(7,None,"popover_select.ui","popover_select.ui",None,None,None,None,None,None),
(8,None,"progress.ui","progress.ui",None,None,None,None,None,None),
(9,None,"settings.ui","settings.ui",None,None,None,None,None,None)
(9,None,"settings.ui","settings.ui",None,None,None,None,None,None),
(10,None,"popover_sort.ui","popover_sort.ui",None,None,None,None,None,None)
</ui>
<ui_library>
(3,"gtk","4.0",None),
@ -194,27 +195,27 @@
(5,190,"GtkBox",None,189,None,None,None,None),
(5,191,"GtkImage",None,190,None,None,None,None),
(5,192,"GtkLabel","label_buttons_select",190,None,None,None,1),
(5,193,"GtkButton","buttons_compare",188,None,None,None,1),
(5,193,"GtkButton","buttons_compare",188,None,None,None,2),
(5,194,"GtkBox",None,193,None,None,None,None),
(5,195,"GtkImage",None,194,None,None,None,None),
(5,196,"GtkLabel",None,194,None,None,None,1),
(5,197,"GtkButton","buttons_delete",188,None,None,None,2),
(5,197,"GtkButton","buttons_delete",188,None,None,None,3),
(5,198,"GtkBox",None,197,None,None,None,None),
(5,199,"GtkImage",None,198,None,None,None,None),
(5,200,"GtkLabel",None,198,None,None,None,1),
(5,201,"GtkButton","buttons_move",188,None,None,None,3),
(5,201,"GtkButton","buttons_move",188,None,None,None,4),
(5,202,"GtkBox",None,201,None,None,None,None),
(5,203,"GtkImage",None,202,None,None,None,None),
(5,204,"GtkLabel",None,202,None,None,None,1),
(5,205,"GtkButton","buttons_save",188,None,None,None,4),
(5,205,"GtkButton","buttons_save",188,None,None,None,5),
(5,206,"GtkBox",None,205,None,None,None,None),
(5,207,"GtkImage",None,206,None,None,None,None),
(5,208,"GtkLabel",None,206,None,None,None,1),
(5,209,"GtkButton","buttons_symlink",188,None,None,None,5),
(5,209,"GtkButton","buttons_symlink",188,None,None,None,6),
(5,210,"GtkBox",None,209,None,None,None,None),
(5,211,"GtkImage",None,210,None,None,None,None),
(5,212,"GtkLabel",None,210,None,None,None,1),
(5,213,"GtkButton","buttons_hardlink",188,None,None,None,6),
(5,213,"GtkButton","buttons_hardlink",188,None,None,None,7),
(5,214,"GtkBox",None,213,None,None,None,None),
(5,215,"GtkImage",None,214,None,None,None,None),
(5,216,"GtkLabel",None,214,None,None,None,1),
@ -230,6 +231,10 @@
(5,226,"GtkCheckButton","check_button_broken_files_pdf",224,None,None,None,1),
(5,227,"GtkCheckButton","check_button_broken_files_archive",224,None,None,None,2),
(5,228,"GtkCheckButton","check_button_broken_files_image",224,None,None,None,3),
(5,229,"GtkMenuButton","buttons_sort",188,None,None,None,1),
(5,230,"GtkBox",None,229,None,None,None,None),
(5,231,"GtkImage",None,230,None,None,None,None),
(5,232,"GtkLabel","label_buttons_sort",230,None,None,None,1),
(6,1,"GtkPopover","popover_right_click",None,None,None,None,None),
(6,2,"GtkBox",None,1,None,None,None,None),
(6,3,"GtkButton","buttons_popover_right_click_open_file",2,None,None,None,None),
@ -318,7 +323,14 @@
(9,56,"GtkBox",None,9,None,None,None,11),
(9,57,"GtkLabel","label_settings_number_of_threads",56,None,None,None,None),
(9,58,"GtkScale","scale_settings_number_of_threads",56,None,None,None,1),
(9,59,"GtkLabel","label_restart_needed",8,None,None,None,1)
(9,59,"GtkLabel","label_restart_needed",8,None,None,None,1),
(10,1,"GtkPopover","popover_sort",None,None,None,None,None),
(10,2,"GtkBox",None,1,None,None,None,None),
(10,3,"GtkButton","buttons_popover_sort_file_name",2,None,None,None,None),
(10,4,"GtkButton","buttons_popover_sort_folder_name",2,None,None,None,1),
(10,5,"GtkButton","buttons_popover_sort_full_name",2,None,None,None,2),
(10,6,"GtkButton","buttons_popover_sort_size",2,None,None,None,3),
(10,7,"GtkButton","buttons_popover_sort_selection",2,None,None,None,4)
</object>
<object_property>
(3,1,"GtkAboutDialog","comments","2020 - 2022 Rafał Mikrut(qarmin)\n\nThis program is free to use and will always be.\n",1,None,None,None,None),
@ -746,6 +758,13 @@
(5,227,"GtkCheckButton","label","Archive",None,None,None,None,None),
(5,228,"GtkCheckButton","active","True",None,None,None,None,None),
(5,228,"GtkCheckButton","label","Image",None,None,None,None,None),
(5,229,"GtkWidget","focus-on-click","0",None,None,None,None,None),
(5,229,"GtkWidget","focusable","1",None,None,None,None,None),
(5,229,"GtkWidget","receives-default","1",None,None,None,None,None),
(5,230,"GtkBox","spacing","2",None,None,None,None,None),
(5,230,"GtkWidget","halign","center",None,None,None,None,None),
(5,231,"GtkImage","icon-name","image-missing",None,None,None,None,None),
(5,232,"GtkLabel","label","SortMenu",None,None,None,None,None),
(6,1,"GtkPopover","child",None,None,None,None,None,2),
(6,1,"GtkPopover","position","left",None,None,None,None,None),
(6,2,"GtkOrientable","orientation","vertical",None,None,None,None,None),
@ -969,7 +988,25 @@
(9,58,"GtkWidget","hexpand","1",None,None,None,None,None),
(9,59,"GtkAccessible","accessible-role","menu-item-checkbox",None,None,None,None,None),
(9,59,"GtkWidget","margin-bottom","4",None,None,None,None,None),
(9,59,"GtkWidget","margin-top","5",None,None,None,None,None)
(9,59,"GtkWidget","margin-top","5",None,None,None,None,None),
(10,1,"GtkPopover","child",None,None,None,None,None,2),
(10,1,"GtkPopover","position","top",None,None,None,None,None),
(10,2,"GtkOrientable","orientation","vertical",None,None,None,None,None),
(10,3,"GtkButton","label","File name",None,None,None,None,None),
(10,3,"GtkWidget","focusable","1",None,None,None,None,None),
(10,3,"GtkWidget","receives-default","1",None,None,None,None,None),
(10,4,"GtkButton","label","Folder name",None,None,None,None,None),
(10,4,"GtkWidget","focusable","1",None,None,None,None,None),
(10,4,"GtkWidget","receives-default","1",None,None,None,None,None),
(10,5,"GtkButton","label","Full name",None,None,None,None,None),
(10,5,"GtkWidget","focusable","1",None,None,None,None,None),
(10,5,"GtkWidget","receives-default","1",None,None,None,None,None),
(10,6,"GtkButton","label","Size",None,None,None,None,None),
(10,6,"GtkWidget","focusable","1",None,None,None,None,None),
(10,6,"GtkWidget","receives-default","1",None,None,None,None,None),
(10,7,"GtkButton","label","Selection",None,None,None,None,None),
(10,7,"GtkWidget","focusable","1",None,None,None,None,None),
(10,7,"GtkWidget","receives-default","1",None,None,None,None,None)
</object_property>
<object_layout_property>
(8,17,18,"GtkGridLayoutChild","column","0",None,None,None,None),

View file

@ -900,6 +900,29 @@
</child>
</object>
</child>
<child>
<object class="GtkMenuButton" id="buttons_sort">
<property name="focus-on-click">0</property>
<property name="focusable">1</property>
<property name="receives-default">1</property>
<child>
<object class="GtkBox">
<property name="halign">center</property>
<property name="spacing">2</property>
<child>
<object class="GtkImage">
<property name="icon-name">image-missing</property>
</object>
</child>
<child>
<object class="GtkLabel" id="label_buttons_sort">
<property name="label">SortMenu</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkButton" id="buttons_compare">
<property name="focusable">1</property>

View file

@ -0,0 +1,49 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Created with Cambalache 0.10.3 -->
<interface>
<!-- interface-name popover_sort.ui -->
<requires lib="gtk" version="4.6"/>
<object class="GtkPopover" id="popover_sort">
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkButton" id="buttons_popover_sort_file_name">
<property name="focusable">1</property>
<property name="label">File name</property>
<property name="receives-default">1</property>
</object>
</child>
<child>
<object class="GtkButton" id="buttons_popover_sort_folder_name">
<property name="focusable">1</property>
<property name="label">Folder name</property>
<property name="receives-default">1</property>
</object>
</child>
<child>
<object class="GtkButton" id="buttons_popover_sort_full_name">
<property name="focusable">1</property>
<property name="label">Full name</property>
<property name="receives-default">1</property>
</object>
</child>
<child>
<object class="GtkButton" id="buttons_popover_sort_size">
<property name="focusable">1</property>
<property name="label">Size</property>
<property name="receives-default">1</property>
</object>
</child>
<child>
<object class="GtkButton" id="buttons_popover_sort_selection">
<property name="focusable">1</property>
<property name="label">Selection</property>
<property name="receives-default">1</property>
</object>
</child>
</object>
</property>
<property name="position">top</property>
</object>
</interface>

View file

@ -9,10 +9,10 @@ FFmpeg is not included here because it is not needed to build - it is dynamicall
Support for heif images is optional and require to install libheif library.
| Program | Min | What for |
|---------|--------|-------------------------------------------------------------------------------|
| Rust | 1.65.0 | Czkawka, aims to support the latest available version of Rust on Ubuntu 22.04 |
| GTK | 4.6 | Only for the `GTK` backend |
| Program | Min | What for |
|---------|--------|--------------------------------------------------------------------------------------|
| Rust | 1.65.0 | The minimum version of rust does not depend on anything, so it can change frequently |
| GTK | 4.6 | Only for the `GTK` backend |
#### Debian / Ubuntu
```shell