1
0
Fork 0
mirror of synced 2024-04-28 17:42:26 +12:00

Select things by checkbox (#392)

This commit is contained in:
Rafał Mikrut 2021-07-16 06:51:54 +02:00 committed by GitHub
parent 45707d54c7
commit bb2fea2b92
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 1148 additions and 743 deletions

204
Cargo.lock generated
View file

@ -47,9 +47,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.40"
version = "1.0.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b"
checksum = "595d3cfa7a60d4555cb5067b99f07142a08ea778de5cf993f7b75c7d8fabc486"
[[package]]
name = "arrayref"
@ -177,15 +177,15 @@ dependencies = [
[[package]]
name = "bumpalo"
version = "3.6.1"
version = "3.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe"
checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631"
[[package]]
name = "bytemuck"
version = "1.5.1"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bed57e2090563b83ba8f83366628ce535a7584c9afa4c9fc0612a03925c6df58"
checksum = "9966d2ab714d0f785dbac0a0396251a35280aeb42413281617d0209ab4898435"
[[package]]
name = "byteorder"
@ -222,9 +222,9 @@ dependencies = [
[[package]]
name = "cairo-rs"
version = "0.14.0"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d32eecb1e806433cf68063c4548bbdc15cc56d35db19d685ab60909c4c85206"
checksum = "a408c13bbc04c3337b94194c1a4d04067097439b79dbc1dcbceba299d828b9ea"
dependencies = [
"bitflags",
"cairo-sys-rs",
@ -246,9 +246,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.0.67"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2"
dependencies = [
"jobserver",
]
@ -342,9 +342,9 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]]
name = "combine"
version = "4.5.2"
version = "4.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc4369b5e4c0cddf64ad8981c0111e7df4f7078f4d6ba98fb31f2e17c4c57b7e"
checksum = "a2d47c1b11006b87e492b53b313bb699ce60e16613c4dddaa91f8f7c220ab2fa"
dependencies = [
"bytes",
"memchr",
@ -438,9 +438,9 @@ dependencies = [
[[package]]
name = "crossbeam-epoch"
version = "0.9.4"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52fb27eab85b17fbb9f6fd667089e07d6a2eb8743d02639ee7f6a7a7729c9c94"
checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd"
dependencies = [
"cfg-if 1.0.0",
"crossbeam-utils",
@ -451,11 +451,10 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
version = "0.8.4"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4feb231f0d4d6af81aed15928e58ecf5816aa62a2393e2c82f46973e92a9a278"
checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
dependencies = [
"autocfg",
"cfg-if 1.0.0",
"lazy_static",
]
@ -804,9 +803,9 @@ dependencies = [
[[package]]
name = "getrandom"
version = "0.2.2"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
dependencies = [
"cfg-if 1.0.0",
"libc",
@ -855,9 +854,9 @@ dependencies = [
[[package]]
name = "glib"
version = "0.14.0"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0028bbfd270d0778540294abca11141d59cb474da4c1f61ca1e11f579c49247"
checksum = "dbecad7a3a898ee749d491ce2ae0decb0bce9e736f9747bc49159b1cea5d37f4"
dependencies = [
"bitflags",
"futures-channel",
@ -874,9 +873,9 @@ dependencies = [
[[package]]
name = "glib-macros"
version = "0.14.0"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9eb7bdf41972a6f6dab5d72c23d22789f400059a43ba0d72b4bb2f8664d946a9"
checksum = "2aad66361f66796bfc73f530c51ef123970eb895ffba991a234fcf7bea89e518"
dependencies = [
"anyhow",
"heck",
@ -978,18 +977,18 @@ checksum = "65043da274378d68241eb9a8f8f8aa54e349136f7b8e12f63e3ef44043cc30e1"
[[package]]
name = "heck"
version = "0.3.2"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac"
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "hermit-abi"
version = "0.1.18"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
@ -1063,9 +1062,9 @@ dependencies = [
[[package]]
name = "instant"
version = "0.1.9"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d"
dependencies = [
"cfg-if 1.0.0",
]
@ -1119,9 +1118,9 @@ dependencies = [
[[package]]
name = "js-sys"
version = "0.3.50"
version = "0.3.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d99f9e3e84b8f67f846ef5b4cbbc3b1c29f6c759fcbce6f01aa0e73d932a24c"
checksum = "83bdfbace3a0e81a4253f73b49e960b053e396a11012cbd49b9b74d6a2b67062"
dependencies = [
"wasm-bindgen",
]
@ -1151,9 +1150,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.94"
version = "0.2.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e"
checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
[[package]]
name = "libloading"
@ -1200,9 +1199,9 @@ checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
[[package]]
name = "memoffset"
version = "0.6.3"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f83fb6581e8ed1f85fd45c116db8405483899489e38406156c25eb743554361d"
checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
dependencies = [
"autocfg",
]
@ -1414,9 +1413,9 @@ dependencies = [
[[package]]
name = "num_enum"
version = "0.5.1"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "226b45a5c2ac4dd696ed30fa6b94b057ad909c7b7fc2e0d0808192bced894066"
checksum = "e5adf0198d427ee515335639f275e806ca01acf9f07d7cf14bb36a10532a6169"
dependencies = [
"derivative",
"num_enum_derive",
@ -1424,11 +1423,11 @@ dependencies = [
[[package]]
name = "num_enum_derive"
version = "0.5.1"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c0fd9eba1d5db0994a239e09c1be402d35622277e35468ba891aa5e3188ce7e"
checksum = "b1def5a3f69d4707d8a040b12785b98029a39e8c610ae685c7f6265669767482"
dependencies = [
"proc-macro-crate 0.1.5",
"proc-macro-crate 1.0.0",
"proc-macro2",
"quote",
"syn",
@ -1436,9 +1435,9 @@ dependencies = [
[[package]]
name = "oboe"
version = "0.4.1"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cfb2390bddb9546c0f7448fd1d2abdd39e6075206f960991eb28c7fa7f126c4"
checksum = "dfa187b38ae20374617b7ad418034ed3dc90ac980181d211518bd03537ae8f8d"
dependencies = [
"jni",
"ndk",
@ -1450,9 +1449,9 @@ dependencies = [
[[package]]
name = "oboe-sys"
version = "0.4.0"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe069264d082fc820dfa172f79be3f2e088ecfece9b1c47b0c9fd838d2bef103"
checksum = "b88e64835aa3f579c08d182526dc34e3907343d5b97e87b71a40ba5bca7aca9e"
dependencies = [
"cc",
]
@ -1468,9 +1467,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.7.2"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
[[package]]
name = "open"
@ -1549,9 +1548,9 @@ dependencies = [
[[package]]
name = "pin-project-lite"
version = "0.2.6"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905"
checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443"
[[package]]
name = "pin-utils"
@ -1640,9 +1639,9 @@ checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
[[package]]
name = "proc-macro2"
version = "1.0.26"
version = "1.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038"
dependencies = [
"unicode-xid",
]
@ -1658,9 +1657,9 @@ dependencies = [
[[package]]
name = "rand"
version = "0.8.3"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
dependencies = [
"libc",
"rand_chacha",
@ -1670,9 +1669,9 @@ dependencies = [
[[package]]
name = "rand_chacha"
version = "0.3.0"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
@ -1680,18 +1679,18 @@ dependencies = [
[[package]]
name = "rand_core"
version = "0.6.2"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
dependencies = [
"getrandom",
]
[[package]]
name = "rand_hc"
version = "0.3.0"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
dependencies = [
"rand_core",
]
@ -1723,9 +1722,9 @@ dependencies = [
[[package]]
name = "redox_syscall"
version = "0.2.8"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc"
checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee"
dependencies = [
"bitflags",
]
@ -1742,9 +1741,9 @@ dependencies = [
[[package]]
name = "regex"
version = "1.5.3"
version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce5f1ceb7f74abbce32601642fcf8e8508a8a8991e0621c7d750295b9095702b"
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
dependencies = [
"regex-syntax",
]
@ -1855,18 +1854,18 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.125"
version = "1.0.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.125"
version = "1.0.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43"
dependencies = [
"proc-macro2",
"quote",
@ -1928,9 +1927,9 @@ checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
[[package]]
name = "structopt"
version = "0.3.21"
version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5277acd7ee46e63e5168a80734c9f6ee81b1367a7d8772a2d765df2a3705d28c"
checksum = "69b041cdcb67226aca307e6e7be44c8806423d83e018bd662360a93dabce4d71"
dependencies = [
"clap",
"lazy_static",
@ -1939,9 +1938,9 @@ dependencies = [
[[package]]
name = "structopt-derive"
version = "0.4.14"
version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ba9cdfda491b814720b6b06e0cac513d922fc407582032e8706e9f137976f90"
checksum = "7813934aecf5f51a54775e00068c237de98489463968231a51746bbbc03f9c10"
dependencies = [
"heck",
"proc-macro-error",
@ -1952,15 +1951,15 @@ dependencies = [
[[package]]
name = "strum"
version = "0.20.0"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7318c509b5ba57f18533982607f24070a55d353e90d4cae30c467cdb2ad5ac5c"
checksum = "aaf86bbcfd1fa9670b7a129f64fc0c9fcbbfe4f1bc4210e9e98fe71ffc12cde2"
[[package]]
name = "strum_macros"
version = "0.20.1"
version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee8bc6b87a5112aeeab1f4a9f7ab634fe6cbefc4850006df31267f4cfb9e3149"
checksum = "d06aaeeee809dbc59eb4556183dd927df67db1540de5be8d3ec0b6636358a5ec"
dependencies = [
"heck",
"proc-macro2",
@ -1970,15 +1969,15 @@ dependencies = [
[[package]]
name = "subtle"
version = "2.4.0"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2"
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]]
name = "syn"
version = "1.0.72"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82"
checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7"
dependencies = [
"proc-macro2",
"quote",
@ -1987,9 +1986,9 @@ dependencies = [
[[package]]
name = "system-deps"
version = "3.1.1"
version = "3.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c248107ad7bc1ac07066a4d003cae9e9a7bc2e27d3418f7a9cdcdc8699dbea70"
checksum = "7ab7dbd121ce66af2176147a48c7e01aaf1f001837a18a7cf4317858606bbdf8"
dependencies = [
"anyhow",
"cfg-expr",
@ -2028,18 +2027,18 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.24"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e"
checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.24"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745"
dependencies = [
"proc-macro2",
"quote",
@ -2059,11 +2058,12 @@ dependencies = [
[[package]]
name = "time"
version = "0.1.43"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
dependencies = [
"libc",
"wasi",
"winapi",
]
@ -2130,9 +2130,9 @@ checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
[[package]]
name = "unicode-segmentation"
version = "1.7.1"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
[[package]]
name = "unicode-width"
@ -2177,15 +2177,15 @@ dependencies = [
[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]]
name = "wasm-bindgen"
version = "0.2.73"
version = "0.2.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83240549659d187488f91f33c0f8547cbfef0b2088bc470c116d1d260ef623d9"
checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd"
dependencies = [
"cfg-if 1.0.0",
"wasm-bindgen-macro",
@ -2193,9 +2193,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.73"
version = "0.2.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae70622411ca953215ca6d06d3ebeb1e915f0f6613e3b495122878d7ebec7dae"
checksum = "3b33f6a0694ccfea53d94db8b2ed1c3a8a4c86dd936b13b9f0a15ec4a451b900"
dependencies = [
"bumpalo",
"lazy_static",
@ -2208,9 +2208,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.73"
version = "0.2.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e734d91443f177bfdb41969de821e15c516931c3c3db3d318fa1b68975d0f6f"
checksum = "088169ca61430fe1e58b8096c24975251700e7b1f6fd91cc9d59b04fb9b18bd4"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@ -2218,9 +2218,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.73"
version = "0.2.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d53739ff08c8a68b0fdbcd54c372b8ab800b1449ab3c9d706503bc7dd1621b2c"
checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97"
dependencies = [
"proc-macro2",
"quote",
@ -2231,15 +2231,15 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.73"
version = "0.2.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9a543ae66aa233d14bb765ed9af4a33e81b8b58d1584cf1b47ff8cd0b9e4489"
checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f"
[[package]]
name = "web-sys"
version = "0.3.50"
version = "0.3.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a905d57e488fec8861446d3393670fb50d27a262344013181c2cdf9fff5481be"
checksum = "e828417b379f3df7111d3a2a9e5753706cae29c41f7c4029ee9fd77f3e09e582"
dependencies = [
"js-sys",
"wasm-bindgen",

View file

@ -115,8 +115,14 @@ Bleachbit is a master at finding and removing temporary files, while Czkawka onl
| Cache support | • | | • | |
| In active development | Yes | No | Yes | Yes |
## Other apps
There are many similar applications to Czkawka on the Internet, which do some things better and some things worse.
- [DupeGuru](https://github.com/arsenetar/dupeguru) - A lot of options to customize
- [FSlint](https://github.com/pixelb/fslint) - A little outdated, but have a lot of helpful tools
- [Fclones](https://github.com/pkolaczk/fclones) - One of the fastest tools to find duplicates, but only in CLI
## Contributions
Contributions to this repository are welcome.
Contributions to this repository are welcome.
You can help by creating:
- Bug reports - memory leaks, unexpected behavior, crashes
@ -132,7 +138,7 @@ You can also help by doing different things:
- Recommending it to others
## Name
Czkawka is a Polish word which means _hiccup_.
Czkawka is a Polish word which means _hiccup_.
I chose this name because I wanted to hear people speaking other languages pronounce it, so feel free to spell it the way you want.

View file

@ -36,49 +36,122 @@ pub fn connect_button_delete(gui_data: &GuiData) {
match to_notebook_main_enum(notebook_main.current_page().unwrap()) {
NotebookMainEnum::Duplicate => {
if !check_button_settings_confirm_group_deletion.is_active() || !check_if_deleting_all_files_in_group(&tree_view_duplicate_finder.clone(), ColumnsDuplicates::Color as i32, &window_main, &check_button_settings_confirm_group_deletion) {
tree_remove(&tree_view_duplicate_finder.clone(), ColumnsDuplicates::Name as i32, ColumnsDuplicates::Path as i32, ColumnsDuplicates::Color as i32, &gui_data);
if !check_button_settings_confirm_group_deletion.is_active()
|| !check_if_deleting_all_files_in_group(
&tree_view_duplicate_finder.clone(),
ColumnsDuplicates::Color as i32,
ColumnsDuplicates::ActiveSelectButton as i32,
&window_main,
&check_button_settings_confirm_group_deletion,
)
{
tree_remove(
&tree_view_duplicate_finder.clone(),
ColumnsDuplicates::Name as i32,
ColumnsDuplicates::Path as i32,
ColumnsDuplicates::Color as i32,
ColumnsDuplicates::ActiveSelectButton as i32,
&gui_data,
);
}
}
NotebookMainEnum::EmptyDirectories => {
empty_folder_remover(&tree_view_empty_folder_finder.clone(), ColumnsEmptyFolders::Name as i32, ColumnsEmptyFolders::Path as i32, &gui_data);
empty_folder_remover(
&tree_view_empty_folder_finder.clone(),
ColumnsEmptyFolders::Name as i32,
ColumnsEmptyFolders::Path as i32,
ColumnsEmptyFolders::ActiveSelectButton as i32,
&gui_data,
);
}
NotebookMainEnum::EmptyFiles => {
basic_remove(&tree_view_empty_files_finder.clone(), ColumnsEmptyFiles::Name as i32, ColumnsEmptyFiles::Path as i32, &gui_data);
basic_remove(
&tree_view_empty_files_finder.clone(),
ColumnsEmptyFiles::Name as i32,
ColumnsEmptyFiles::Path as i32,
ColumnsEmptyFiles::ActiveSelectButton as i32,
&gui_data,
);
}
NotebookMainEnum::Temporary => {
basic_remove(&tree_view_temporary_files_finder.clone(), ColumnsTemporaryFiles::Name as i32, ColumnsTemporaryFiles::Path as i32, &gui_data);
basic_remove(
&tree_view_temporary_files_finder.clone(),
ColumnsTemporaryFiles::Name as i32,
ColumnsTemporaryFiles::Path as i32,
ColumnsTemporaryFiles::ActiveSelectButton as i32,
&gui_data,
);
}
NotebookMainEnum::BigFiles => {
basic_remove(&tree_view_big_files_finder.clone(), ColumnsBigFiles::Name as i32, ColumnsBigFiles::Path as i32, &gui_data);
basic_remove(&tree_view_big_files_finder.clone(), ColumnsBigFiles::Name as i32, ColumnsBigFiles::Path as i32, ColumnsBigFiles::ActiveSelectButton as i32, &gui_data);
}
NotebookMainEnum::SimilarImages => {
if !check_button_settings_confirm_group_deletion.is_active()
|| !check_if_deleting_all_files_in_group(&tree_view_similar_images_finder.clone(), ColumnsSimilarImages::Color as i32, &window_main, &check_button_settings_confirm_group_deletion)
|| !check_if_deleting_all_files_in_group(
&tree_view_similar_images_finder.clone(),
ColumnsSimilarImages::Color as i32,
ColumnsSimilarImages::ActiveSelectButton as i32,
&window_main,
&check_button_settings_confirm_group_deletion,
)
{
tree_remove(
&tree_view_similar_images_finder.clone(),
ColumnsSimilarImages::Name as i32,
ColumnsSimilarImages::Path as i32,
ColumnsSimilarImages::Color as i32,
ColumnsSimilarImages::ActiveSelectButton as i32,
&gui_data,
);
image_preview_similar_images.hide();
}
}
NotebookMainEnum::Zeroed => {
basic_remove(&tree_view_zeroed_files_finder.clone(), ColumnsZeroedFiles::Name as i32, ColumnsZeroedFiles::Path as i32, &gui_data);
basic_remove(
&tree_view_zeroed_files_finder.clone(),
ColumnsZeroedFiles::Name as i32,
ColumnsZeroedFiles::Path as i32,
ColumnsZeroedFiles::ActiveSelectButton as i32,
&gui_data,
);
}
NotebookMainEnum::SameMusic => {
if !check_button_settings_confirm_group_deletion.is_active() || !check_if_deleting_all_files_in_group(&tree_view_same_music_finder.clone(), ColumnsSameMusic::Color as i32, &window_main, &check_button_settings_confirm_group_deletion) {
tree_remove(&tree_view_same_music_finder.clone(), ColumnsSameMusic::Name as i32, ColumnsSameMusic::Path as i32, ColumnsSameMusic::Color as i32, &gui_data);
if !check_button_settings_confirm_group_deletion.is_active()
|| !check_if_deleting_all_files_in_group(
&tree_view_same_music_finder.clone(),
ColumnsSameMusic::Color as i32,
ColumnsSameMusic::ActiveSelectButton as i32,
&window_main,
&check_button_settings_confirm_group_deletion,
)
{
tree_remove(
&tree_view_same_music_finder.clone(),
ColumnsSameMusic::Name as i32,
ColumnsSameMusic::Path as i32,
ColumnsSameMusic::Color as i32,
ColumnsSameMusic::ActiveSelectButton as i32,
&gui_data,
);
}
}
NotebookMainEnum::Symlinks => {
basic_remove(&tree_view_invalid_symlinks.clone(), ColumnsInvalidSymlinks::Name as i32, ColumnsInvalidSymlinks::Path as i32, &gui_data);
basic_remove(
&tree_view_invalid_symlinks.clone(),
ColumnsInvalidSymlinks::Name as i32,
ColumnsInvalidSymlinks::Path as i32,
ColumnsInvalidSymlinks::ActiveSelectButton as i32,
&gui_data,
);
}
NotebookMainEnum::BrokenFiles => {
basic_remove(&tree_view_broken_files.clone(), ColumnsBrokenFiles::Name as i32, ColumnsBrokenFiles::Path as i32, &gui_data);
basic_remove(
&tree_view_broken_files.clone(),
ColumnsBrokenFiles::Name as i32,
ColumnsBrokenFiles::Path as i32,
ColumnsInvalidSymlinks::ActiveSelectButton as i32,
&gui_data,
);
}
}
});
@ -127,39 +200,28 @@ pub fn check_if_can_delete_files(check_button_settings_confirm_deletion: &gtk::C
true
}
pub fn check_if_deleting_all_files_in_group(tree_view: &gtk::TreeView, column_color: i32, window_main: &gtk::Window, check_button_settings_confirm_group_deletion: &gtk::CheckButton) -> bool {
let selection = tree_view.selection();
let (selection_rows, tree_model) = selection.selected_rows();
if selection_rows.is_empty() {
return false;
}
let mut current_selected_row = 0;
pub fn check_if_deleting_all_files_in_group(tree_view: &gtk::TreeView, column_color: i32, column_selection: i32, window_main: &gtk::Window, check_button_settings_confirm_group_deletion: &gtk::CheckButton) -> bool {
let model = get_list_store(&tree_view);
let mut selected_all_records: bool = true;
if let Some(first_iter) = tree_model.iter_first() {
let current_iter = first_iter;
if tree_model.value(&current_iter, column_color).get::<String>().unwrap() != HEADER_ROW_COLOR {
panic!("First element, should be a header"); // First element should be header
};
if let Some(iter) = model.iter_first() {
assert_eq!(model.value(&iter, column_color).get::<String>().unwrap(), HEADER_ROW_COLOR); // First element should be header
loop {
if !tree_model.iter_next(&current_iter) {
if selected_all_records {
break;
}
if !model.iter_next(&iter) {
break;
}
if tree_model.value(&current_iter, column_color).get::<String>().unwrap() == HEADER_ROW_COLOR {
if model.value(&iter, column_color).get::<String>().unwrap() == HEADER_ROW_COLOR {
if selected_all_records {
break;
}
} else if current_selected_row != selection_rows.len() && selection_rows[current_selected_row] == tree_model.path(&current_iter).unwrap() {
current_selected_row += 1;
selected_all_records = true;
} else {
selected_all_records = false;
if !model.value(&iter, column_selection).get::<bool>().unwrap() {
selected_all_records = false;
}
}
}
} else {
@ -217,24 +279,33 @@ pub fn check_if_deleting_all_files_in_group(tree_view: &gtk::TreeView, column_co
false
}
pub fn empty_folder_remover(tree_view: &gtk::TreeView, column_file_name: i32, column_path: i32, gui_data: &GuiData) {
pub fn empty_folder_remover(tree_view: &gtk::TreeView, column_file_name: i32, column_path: i32, column_selection: i32, gui_data: &GuiData) {
let text_view_errors = gui_data.text_view_errors.clone();
let use_trash = gui_data.settings.check_button_settings_use_trash.clone().is_active();
let selection = tree_view.selection();
let model = get_list_store(&tree_view);
let (selection_rows, tree_model) = selection.selected_rows();
if selection_rows.is_empty() {
return;
let mut selected_rows = Vec::new();
if let Some(iter) = model.iter_first() {
loop {
if model.value(&iter, column_selection).get::<bool>().unwrap() {
selected_rows.push(model.path(&iter).unwrap());
}
if !model.iter_next(&iter) {
break;
}
}
}
let list_store = get_list_store(&tree_view);
let mut messages: String = "".to_string();
// Must be deleted from end to start, because when deleting entries, TreePath(and also TreeIter) will points to invalid data
for tree_path in selection_rows.iter().rev() {
let name = tree_model.value(&tree_model.iter(tree_path).unwrap(), column_file_name).get::<String>().unwrap();
let path = tree_model.value(&tree_model.iter(tree_path).unwrap(), column_path).get::<String>().unwrap();
for tree_path in selected_rows.iter().rev() {
let iter = model.iter(tree_path).unwrap();
let name = model.value(&iter, column_file_name).get::<String>().unwrap();
let path = model.value(&iter, column_path).get::<String>().unwrap();
// We must check if folder is really empty or contains only other empty folders
let mut error_happened = false;
@ -288,14 +359,14 @@ pub fn empty_folder_remover(tree_view: &gtk::TreeView, column_file_name: i32, co
if !use_trash {
match fs::remove_dir_all(format!("{}/{}", path, name)) {
Ok(_) => {
list_store.remove(&list_store.iter(tree_path).unwrap());
model.remove(&iter);
}
Err(_) => error_happened = true,
}
} else {
match trash::delete(format!("{}/{}", path, name)) {
Ok(_) => {
list_store.remove(&list_store.iter(tree_path).unwrap());
model.remove(&iter);
}
Err(_) => error_happened = true,
}
@ -307,39 +378,48 @@ pub fn empty_folder_remover(tree_view: &gtk::TreeView, column_file_name: i32, co
}
text_view_errors.buffer().unwrap().set_text(messages.as_str());
selection.unselect_all();
}
pub fn basic_remove(tree_view: &gtk::TreeView, column_file_name: i32, column_path: i32, gui_data: &GuiData) {
pub fn basic_remove(tree_view: &gtk::TreeView, column_file_name: i32, column_path: i32, column_selection: i32, gui_data: &GuiData) {
let text_view_errors = gui_data.text_view_errors.clone();
let use_trash = gui_data.settings.check_button_settings_use_trash.clone().is_active();
let selection = tree_view.selection();
let (selection_rows, tree_model) = selection.selected_rows();
if selection_rows.is_empty() {
return;
}
let list_store = get_list_store(&tree_view);
let model = get_list_store(&tree_view);
let mut messages: String = "".to_string();
let mut selection_rows = Vec::new();
if let Some(iter) = model.iter_first() {
loop {
if model.value(&iter, column_selection).get::<bool>().unwrap() {
selection_rows.push(model.path(&iter).unwrap());
}
if !model.iter_next(&iter) {
break;
}
}
}
// Must be deleted from end to start, because when deleting entries, TreePath(and also TreeIter) will points to invalid data
for tree_path in selection_rows.iter().rev() {
let name = tree_model.value(&tree_model.iter(tree_path).unwrap(), column_file_name).get::<String>().unwrap();
let path = tree_model.value(&tree_model.iter(tree_path).unwrap(), column_path).get::<String>().unwrap();
let iter = model.iter(tree_path).unwrap();
let name = model.value(&iter, column_file_name).get::<String>().unwrap();
let path = model.value(&iter, column_path).get::<String>().unwrap();
if !use_trash {
match fs::remove_file(format!("{}/{}", path, name)) {
Ok(_) => {
list_store.remove(&list_store.iter(tree_path).unwrap());
model.remove(&iter);
}
Err(_) => messages += format!("Failed to remove file {}/{} because file doesn't exists or you don't have permissions.\n", path, name).as_str(),
}
} else {
match trash::delete(format!("{}/{}", path, name)) {
Ok(_) => {
list_store.remove(&list_store.iter(tree_path).unwrap());
model.remove(&iter);
}
Err(_) => messages += format!("Failed to remove file {}/{} because file doesn't exists or you don't have permissions.\n", path, name).as_str(),
}
@ -347,33 +427,45 @@ pub fn basic_remove(tree_view: &gtk::TreeView, column_file_name: i32, column_pat
}
text_view_errors.buffer().unwrap().set_text(messages.as_str());
selection.unselect_all();
}
// Remove all occurrences - remove every element which have same path and name as even non selected ones
pub fn tree_remove(tree_view: &gtk::TreeView, column_file_name: i32, column_path: i32, column_color: i32, gui_data: &GuiData) {
pub fn tree_remove(tree_view: &gtk::TreeView, column_file_name: i32, column_path: i32, column_color: i32, column_selection: i32, gui_data: &GuiData) {
let text_view_errors = gui_data.text_view_errors.clone();
let use_trash = gui_data.settings.check_button_settings_use_trash.clone().is_active();
let selection = tree_view.selection();
let (selection_rows, tree_model) = selection.selected_rows();
if selection_rows.is_empty() {
return;
}
let list_store = get_list_store(&tree_view);
let model = get_list_store(&tree_view);
let mut messages: String = "".to_string();
let mut vec_path_to_delete: Vec<(String, String)> = Vec::new();
let mut map_with_path_to_delete: BTreeMap<String, Vec<String>> = Default::default(); // BTreeMap<Path,Vec<FileName>>
let mut selection_rows = Vec::new();
if let Some(iter) = model.iter_first() {
loop {
if model.value(&iter, column_selection).get::<bool>().unwrap() {
// TODO, this maybe isn't required if we will be sure that any header cannot be selected
if model.value(&iter, column_color).get::<String>().unwrap() == MAIN_ROW_COLOR {
selection_rows.push(model.path(&iter).unwrap());
}
}
if !model.iter_next(&iter) {
break;
}
}
}
// Save to variable paths of files, and remove it when not removing all occurrences.
for tree_path in selection_rows.iter().rev() {
let file_name = tree_model.value(&tree_model.iter(tree_path).unwrap(), column_file_name).get::<String>().unwrap();
let path = tree_model.value(&tree_model.iter(tree_path).unwrap(), column_path).get::<String>().unwrap();
let iter = model.iter(tree_path).unwrap();
list_store.remove(&list_store.iter(tree_path).unwrap());
let file_name = model.value(&iter, column_file_name).get::<String>().unwrap();
let path = model.value(&iter, column_path).get::<String>().unwrap();
model.remove(&iter);
map_with_path_to_delete.entry(path.clone()).or_insert_with(Vec::new);
map_with_path_to_delete.get_mut(path.as_str()).unwrap().push(file_name);
@ -405,74 +497,73 @@ pub fn tree_remove(tree_view: &gtk::TreeView, column_file_name: i32, column_path
}
// Remove only child from header
if let Some(first_iter) = list_store.iter_first() {
if let Some(first_iter) = model.iter_first() {
let mut vec_tree_path_to_delete: Vec<gtk::TreePath> = Vec::new();
let mut current_iter = first_iter;
if tree_model.value(&current_iter, column_color).get::<String>().unwrap() != HEADER_ROW_COLOR {
if model.value(&current_iter, column_color).get::<String>().unwrap() != HEADER_ROW_COLOR {
panic!("First deleted element, should be a header"); // First element should be header
};
let mut next_iter;
let mut next_next_iter;
'main: loop {
if tree_model.value(&current_iter, column_color).get::<String>().unwrap() != HEADER_ROW_COLOR {
if model.value(&current_iter, column_color).get::<String>().unwrap() != HEADER_ROW_COLOR {
panic!("First deleted element, should be a header"); // First element should be header
};
next_iter = current_iter.clone();
if !list_store.iter_next(&next_iter) {
if !model.iter_next(&next_iter) {
// There is only single header left (H1 -> END) -> (NOTHING)
vec_tree_path_to_delete.push(list_store.path(&current_iter).unwrap());
vec_tree_path_to_delete.push(model.path(&current_iter).unwrap());
break 'main;
}
if tree_model.value(&next_iter, column_color).get::<String>().unwrap() == HEADER_ROW_COLOR {
if model.value(&next_iter, column_color).get::<String>().unwrap() == HEADER_ROW_COLOR {
// There are two headers each others(we remove just first) -> (H1 -> H2) -> (H2)
vec_tree_path_to_delete.push(list_store.path(&current_iter).unwrap());
vec_tree_path_to_delete.push(model.path(&current_iter).unwrap());
current_iter = next_iter.clone();
continue 'main;
}
next_next_iter = next_iter.clone();
if !list_store.iter_next(&next_next_iter) {
if !model.iter_next(&next_next_iter) {
// There is only one child of header left, so we remove it with header (H1 -> C1 -> END) -> (NOTHING)
vec_tree_path_to_delete.push(list_store.path(&current_iter).unwrap());
vec_tree_path_to_delete.push(list_store.path(&next_iter).unwrap());
vec_tree_path_to_delete.push(model.path(&current_iter).unwrap());
vec_tree_path_to_delete.push(model.path(&next_iter).unwrap());
break 'main;
}
if tree_model.value(&next_next_iter, column_color).get::<String>().unwrap() == HEADER_ROW_COLOR {
if model.value(&next_next_iter, column_color).get::<String>().unwrap() == HEADER_ROW_COLOR {
// One child between two headers, we can remove them (H1 -> C1 -> H2) -> (H2)
vec_tree_path_to_delete.push(list_store.path(&current_iter).unwrap());
vec_tree_path_to_delete.push(list_store.path(&next_iter).unwrap());
vec_tree_path_to_delete.push(model.path(&current_iter).unwrap());
vec_tree_path_to_delete.push(model.path(&next_iter).unwrap());
current_iter = next_next_iter.clone();
continue 'main;
}
loop {
// (H1 -> C1 -> C2 -> Cn -> END) -> (NO CHANGE, BECAUSE IS GOOD)
if !list_store.iter_next(&next_next_iter) {
if !model.iter_next(&next_next_iter) {
break 'main;
}
// Move to next header
if tree_model.value(&next_next_iter, column_color).get::<String>().unwrap() == HEADER_ROW_COLOR {
if model.value(&next_next_iter, column_color).get::<String>().unwrap() == HEADER_ROW_COLOR {
current_iter = next_next_iter.clone();
continue 'main;
}
}
}
for tree_path in vec_tree_path_to_delete.iter().rev() {
list_store.remove(&list_store.iter(&tree_path).unwrap());
model.remove(&model.iter(&tree_path).unwrap());
}
}
// Last step, remove orphan header if exists
if let Some(iter) = list_store.iter_first() {
if !list_store.iter_next(&iter) {
list_store.clear();
if let Some(iter) = model.iter_first() {
if !model.iter_next(&iter) {
model.clear();
}
}
text_view_errors.buffer().unwrap().set_text(messages.as_str());
selection.unselect_all();
}

View file

@ -16,20 +16,18 @@ pub fn connect_button_select(gui_data: &GuiData) {
// let mode = ["all", "image_size", "reverse", "custom", "date"];
let mut hashmap: HashMap<NotebookMainEnum, Vec<&str>> = Default::default();
{
{
// Remember to update connect_popovers file, because this data are connected to each others
hashmap.insert(NotebookMainEnum::SimilarImages, vec!["all", "image_size", "reverse", "custom", "date"]);
hashmap.insert(NotebookMainEnum::Duplicate, vec!["all", "reverse", "custom", "date"]);
hashmap.insert(NotebookMainEnum::SameMusic, vec!["all", "reverse", "custom", "date"]);
// Remember to update connect_popovers file, because this data are connected to each others
hashmap.insert(NotebookMainEnum::SimilarImages, vec!["all", "image_size", "reverse", "custom", "date"]);
hashmap.insert(NotebookMainEnum::Duplicate, vec!["all", "reverse", "custom", "date"]);
hashmap.insert(NotebookMainEnum::SameMusic, vec!["all", "reverse", "custom", "date"]);
hashmap.insert(NotebookMainEnum::EmptyFiles, vec!["all", "reverse", "custom"]);
hashmap.insert(NotebookMainEnum::EmptyDirectories, vec!["all", "reverse", "custom"]);
hashmap.insert(NotebookMainEnum::BigFiles, vec!["all", "reverse", "custom"]);
hashmap.insert(NotebookMainEnum::Symlinks, vec!["all", "reverse", "custom"]);
hashmap.insert(NotebookMainEnum::Zeroed, vec!["all", "reverse", "custom"]);
hashmap.insert(NotebookMainEnum::Temporary, vec!["all", "reverse", "custom"]);
hashmap.insert(NotebookMainEnum::BrokenFiles, vec!["all", "reverse", "custom"]);
}
hashmap.insert(NotebookMainEnum::EmptyFiles, vec!["all", "reverse", "custom"]);
hashmap.insert(NotebookMainEnum::EmptyDirectories, vec!["all", "reverse", "custom"]);
hashmap.insert(NotebookMainEnum::BigFiles, vec!["all", "reverse", "custom"]);
hashmap.insert(NotebookMainEnum::Symlinks, vec!["all", "reverse", "custom"]);
hashmap.insert(NotebookMainEnum::Zeroed, vec!["all", "reverse", "custom"]);
hashmap.insert(NotebookMainEnum::Temporary, vec!["all", "reverse", "custom"]);
hashmap.insert(NotebookMainEnum::BrokenFiles, vec!["all", "reverse", "custom"]);
}
let gui_data = gui_data.clone();

View file

@ -114,25 +114,29 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
vector.clone()
};
let values: [(u32, &dyn ToValue); 6] = [
(0, &name),
(1, (&(format!("{} results", vector.len())))),
(2, (&"".to_string())), // No text in 3 column
(3, (&(0))), // Not used here
(4, &(HEADER_ROW_COLOR.to_string())),
(5, &(TEXT_COLOR.to_string())),
let values: [(u32, &dyn ToValue); 8] = [
(0, &false),
(1, &false),
(2, &name),
(3, (&(format!("{} results", vector.len())))),
(4, (&"".to_string())), // No text in 3 column
(5, (&(0))), // Not used here
(6, &(HEADER_ROW_COLOR.to_string())),
(7, &(TEXT_COLOR.to_string())),
];
list_store.set(&list_store.append(), &values);
for entry in vector {
let (directory, file) = split_path(&entry.path);
let values: [(u32, &dyn ToValue); 6] = [
(0, &file),
(1, &directory),
(2, &(format!("{} - ({})", NaiveDateTime::from_timestamp(entry.modified_date as i64, 0).to_string(), entry.size.file_size(options::BINARY).unwrap()))),
(3, &(entry.modified_date)),
(4, &(MAIN_ROW_COLOR.to_string())),
(5, &(TEXT_COLOR.to_string())),
let values: [(u32, &dyn ToValue); 8] = [
(0, &true),
(1, &false),
(2, &file),
(3, &directory),
(4, &(format!("{} - ({})", NaiveDateTime::from_timestamp(entry.modified_date as i64, 0).to_string(), entry.size.file_size(options::BINARY).unwrap()))),
(5, &(entry.modified_date)),
(6, &(MAIN_ROW_COLOR.to_string())),
(7, &(TEXT_COLOR.to_string())),
];
list_store.set(&list_store.append(), &values);
}
@ -155,29 +159,33 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
vector.clone()
};
let values: [(u32, &dyn ToValue); 6] = [
(0, &(format!("{} x {} ({} bytes)", vector.len(), size.file_size(options::BINARY).unwrap(), size))),
let values: [(u32, &dyn ToValue); 8] = [
(0, &false),
(1, &false),
(2, &(format!("{} x {} ({} bytes)", vector.len(), size.file_size(options::BINARY).unwrap(), size))),
(
1,
3,
&(format!("{} ({} bytes) lost", ((vector.len() - 1) as u64 * *size as u64).file_size(options::BINARY).unwrap(), (vector.len() - 1) as u64 * *size as u64)),
),
(2, &"".to_string()), // No text in 3 column
(3, &(0)),
(4, &(HEADER_ROW_COLOR.to_string())),
(5, &(TEXT_COLOR.to_string())),
(4, &"".to_string()), // No text in 3 column
(5, &(0)),
(6, &(HEADER_ROW_COLOR.to_string())),
(7, &(TEXT_COLOR.to_string())),
];
list_store.set(&list_store.append(), &values);
for entry in vector {
let (directory, file) = split_path(&entry.path);
let values: [(u32, &dyn ToValue); 6] = [
(0, &file),
(1, &directory),
(2, &(NaiveDateTime::from_timestamp(entry.modified_date as i64, 0).to_string())),
(3, &(entry.modified_date)),
(4, &(MAIN_ROW_COLOR.to_string())),
(5, &(TEXT_COLOR.to_string())),
let values: [(u32, &dyn ToValue); 8] = [
(0, &true),
(1, &false),
(2, &file),
(3, &directory),
(4, &(NaiveDateTime::from_timestamp(entry.modified_date as i64, 0).to_string())),
(5, &(entry.modified_date)),
(6, &(MAIN_ROW_COLOR.to_string())),
(7, &(TEXT_COLOR.to_string())),
];
list_store.set(&list_store.append(), &values);
@ -200,28 +208,32 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
} else {
vector.clone()
};
let values: [(u32, &dyn ToValue); 6] = [
(0, &(format!("{} x {} ({} bytes)", vector.len(), size.file_size(options::BINARY).unwrap(), size))),
let values: [(u32, &dyn ToValue); 8] = [
(0, &false),
(1, &false),
(2, &(format!("{} x {} ({} bytes)", vector.len(), size.file_size(options::BINARY).unwrap(), size))),
(
1,
3,
&(format!("{} ({} bytes) lost", ((vector.len() - 1) as u64 * *size as u64).file_size(options::BINARY).unwrap(), (vector.len() - 1) as u64 * *size as u64)),
),
(2, &"".to_string()), // No text in 3 column
(3, &(0)), // Not used here
(4, &(HEADER_ROW_COLOR.to_string())),
(5, &(TEXT_COLOR.to_string())),
(4, &"".to_string()), // No text in 3 column
(5, &(0)), // Not used here
(6, &(HEADER_ROW_COLOR.to_string())),
(7, &(TEXT_COLOR.to_string())),
];
list_store.set(&list_store.append(), &values);
for entry in vector {
let (directory, file) = split_path(&entry.path);
let values: [(u32, &dyn ToValue); 6] = [
(0, &file),
(1, &directory),
(2, &(NaiveDateTime::from_timestamp(entry.modified_date as i64, 0).to_string())),
(3, &(entry.modified_date)),
(4, &(MAIN_ROW_COLOR.to_string())),
(5, &(TEXT_COLOR.to_string())),
let values: [(u32, &dyn ToValue); 8] = [
(0, &true),
(1, &false),
(2, &file),
(3, &directory),
(4, &(NaiveDateTime::from_timestamp(entry.modified_date as i64, 0).to_string())),
(5, &(entry.modified_date)),
(6, &(MAIN_ROW_COLOR.to_string())),
(7, &(TEXT_COLOR.to_string())),
];
list_store.set(&list_store.append(), &values);
}
@ -281,7 +293,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); 3] = [(0, &file), (1, &directory), (2, &(NaiveDateTime::from_timestamp(hashmap.get(&path).unwrap().modified_date as i64, 0).to_string()))];
let values: [(u32, &dyn ToValue); 4] = [(0, &false), (1, &file), (2, &directory), (3, &(NaiveDateTime::from_timestamp(hashmap.get(&path).unwrap().modified_date as i64, 0).to_string()))];
list_store.set(&list_store.append(), &values);
}
print_text_messages_to_text_view(text_messages, &text_view_errors);
@ -330,7 +342,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); 3] = [(0, &file), (1, &directory), (2, &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string()))];
let values: [(u32, &dyn ToValue); 4] = [(0, &false), (1, &file), (2, &directory), (3, &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string()))];
list_store.set(&list_store.append(), &values);
}
print_text_messages_to_text_view(text_messages, &text_view_errors);
@ -378,11 +390,12 @@ 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); 4] = [
(0, &(format!("{} ({} bytes)", size.file_size(options::BINARY).unwrap(), size))),
(1, &file),
(2, &directory),
(3, &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string())),
let values: [(u32, &dyn ToValue); 5] = [
(0, &false),
(1, &(format!("{} ({} bytes)", size.file_size(options::BINARY).unwrap(), size))),
(2, &file),
(3, &directory),
(4, &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string())),
];
list_store.set(&list_store.append(), &values);
}
@ -433,7 +446,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); 3] = [(0, &file), (1, &directory), (2, &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string()))];
let values: [(u32, &dyn ToValue); 4] = [(0, &false), (1, &file), (2, &directory), (3, &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string()))];
list_store.set(&list_store.append(), &values);
}
print_text_messages_to_text_view(text_messages, &text_view_errors);
@ -487,34 +500,38 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
};
// Header
let values: [(u32, &dyn ToValue); 10] = [
(0, &"".to_string()),
(1, &"".to_string()),
(2, &(0)),
let values: [(u32, &dyn ToValue); 12] = [
(0, &false),
(1, &false),
(2, &"".to_string()),
(3, &"".to_string()),
(4, &"".to_string()),
(4, &(0)),
(5, &"".to_string()),
(6, &"".to_string()),
(7, &(0)),
(8, &(HEADER_ROW_COLOR.to_string())),
(9, &(TEXT_COLOR.to_string())),
(7, &"".to_string()),
(8, &"".to_string()),
(9, &(0)),
(10, &(HEADER_ROW_COLOR.to_string())),
(11, &(TEXT_COLOR.to_string())),
];
list_store.set(&list_store.append(), &values);
// Meat
for file_entry in vec_file_entry.iter() {
let (directory, file) = split_path(&file_entry.path);
let values: [(u32, &dyn ToValue); 10] = [
(0, &(get_text_from_similarity(&file_entry.similarity).to_string())),
(1, &file_entry.size.file_size(options::BINARY).unwrap()),
(2, &file_entry.size),
(3, &file_entry.dimensions),
(4, &file),
(5, &directory),
(6, &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string())),
(7, &(file_entry.modified_date)),
(8, &(MAIN_ROW_COLOR.to_string())),
(9, &(TEXT_COLOR.to_string())),
let values: [(u32, &dyn ToValue); 12] = [
(0, &true),
(1, &false),
(2, &(get_text_from_similarity(&file_entry.similarity).to_string())),
(3, &file_entry.size.file_size(options::BINARY).unwrap()),
(4, &file_entry.size),
(5, &file_entry.dimensions),
(6, &file),
(7, &directory),
(8, &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string())),
(9, &(file_entry.modified_date)),
(10, &(MAIN_ROW_COLOR.to_string())),
(11, &(TEXT_COLOR.to_string())),
];
list_store.set(&list_store.append(), &values);
}
@ -570,12 +587,13 @@ 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] = [
(0, &(file_entry.size.file_size(options::BINARY).unwrap())),
(1, &(file_entry.size)),
(2, &file),
(3, &directory),
(4, &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string())),
let values: [(u32, &dyn ToValue); 6] = [
(0, &false),
(1, &(file_entry.size.file_size(options::BINARY).unwrap())),
(2, &(file_entry.size)),
(3, &file),
(4, &directory),
(5, &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string())),
];
list_store.set(&list_store.append(), &values);
}
@ -639,68 +657,72 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
vec_file_entry.clone()
};
let values: [(u32, &dyn ToValue); 13] = [
(0, &"".to_string()),
(1, &(0)),
let values: [(u32, &dyn ToValue); 15] = [
(0, &false),
(1, &false),
(2, &"".to_string()),
(3, &"".to_string()),
(3, &(0)),
(4, &"".to_string()),
(5, &"".to_string()),
(
4,
6,
&(match is_title {
true => text.clone(),
false => "".to_string(),
}),
),
(
5,
7,
&(match is_artist {
true => text.clone(),
false => "".to_string(),
}),
),
(
6,
8,
&(match is_album_title {
true => text.clone(),
false => "".to_string(),
}),
),
(
7,
9,
&(match is_album_artist {
true => text.clone(),
false => "".to_string(),
}),
),
(
8,
10,
&(match is_year {
true => text.clone(),
false => "".to_string(),
}),
),
(9, &"".to_string()),
(10, &(0)),
(11, &(HEADER_ROW_COLOR.to_string())),
(12, &(TEXT_COLOR.to_string())),
(11, &"".to_string()),
(12, &(0)),
(13, &(HEADER_ROW_COLOR.to_string())),
(14, &(TEXT_COLOR.to_string())),
];
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); 13] = [
(0, &file_entry.size.file_size(options::BINARY).unwrap()),
(1, &file_entry.size),
(2, &file),
(3, &directory),
(4, &file_entry.title),
(5, &file_entry.artist),
(6, &file_entry.album_title),
(7, &file_entry.album_artist),
(8, &file_entry.year.to_string()),
(9, &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string())),
(10, &(file_entry.modified_date)),
(11, &(MAIN_ROW_COLOR.to_string())),
(12, &(TEXT_COLOR.to_string())),
let values: [(u32, &dyn ToValue); 15] = [
(0, &true),
(1, &false),
(2, &file_entry.size.file_size(options::BINARY).unwrap()),
(3, &file_entry.size),
(4, &file),
(5, &directory),
(6, &file_entry.title),
(7, &file_entry.artist),
(8, &file_entry.album_title),
(9, &file_entry.album_artist),
(10, &file_entry.year.to_string()),
(11, &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string())),
(12, &(file_entry.modified_date)),
(13, &(MAIN_ROW_COLOR.to_string())),
(14, &(TEXT_COLOR.to_string())),
];
list_store.set(&list_store.append(), &values);
}
@ -756,12 +778,13 @@ pub fn connect_compute_results(gui_data: &GuiData, glib_stop_receiver: Receiver<
for file_entry in vector {
let (directory, file) = split_path(&file_entry.symlink_path);
let values: [(u32, &dyn ToValue); 5] = [
(0, &file),
(1, &directory),
(2, &file_entry.destination_path.to_string_lossy().to_string()),
(3, &get_text_from_invalid_symlink_cause(&file_entry.type_of_error)),
(4, &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string())),
let values: [(u32, &dyn ToValue); 6] = [
(0, &false),
(1, &file),
(2, &directory),
(3, &file_entry.destination_path.to_string_lossy().to_string()),
(4, &get_text_from_invalid_symlink_cause(&file_entry.type_of_error)),
(5, &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string())),
];
list_store.set(&list_store.append(), &values);
}
@ -811,7 +834,13 @@ 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); 4] = [(0, &file), (1, &directory), (2, &file_entry.error_string), (3, &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string()))];
let values: [(u32, &dyn ToValue); 5] = [
(0, &false),
(1, &file),
(2, &directory),
(3, &file_entry.error_string),
(4, &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string())),
];
list_store.set(&list_store.append(), &values);
}
print_text_messages_to_text_view(text_messages, &text_view_errors);

File diff suppressed because it is too large Load diff

View file

@ -3,6 +3,27 @@ use gtk::prelude::*;
use gtk::TreeViewColumn;
pub fn create_tree_view_duplicates(tree_view: &mut gtk::TreeView) {
let model = get_list_store(tree_view);
let renderer = gtk::CellRendererToggle::new();
renderer.connect_toggled(move |_r, path| {
let iter = model.iter(&path).unwrap();
let mut fixed = model
.value(&iter, ColumnsDuplicates::ActiveSelectButton as i32)
.get::<bool>()
.unwrap_or_else(|err| panic!("ListStore value missing at path {}: {}", path, err));
fixed = !fixed;
model.set_value(&iter, ColumnsDuplicates::ActiveSelectButton as u32, &fixed.to_value());
});
let column = gtk::TreeViewColumn::new();
column.pack_start(&renderer, true);
column.set_resizable(false);
column.set_fixed_width(30);
column.add_attribute(&renderer, "visible", ColumnsDuplicates::VisibleSelectButton as i32);
column.add_attribute(&renderer, "active", ColumnsDuplicates::ActiveSelectButton as i32);
column.add_attribute(&renderer, "cell-background", ColumnsDuplicates::Color as i32);
tree_view.append_column(&column);
let renderer = gtk::CellRendererText::new();
let column: gtk::TreeViewColumn = TreeViewColumn::new();
column.pack_start(&renderer, true);
@ -40,6 +61,25 @@ pub fn create_tree_view_duplicates(tree_view: &mut gtk::TreeView) {
}
pub fn create_tree_view_empty_folders(tree_view: &mut gtk::TreeView) {
let model = get_list_store(tree_view);
let renderer = gtk::CellRendererToggle::new();
renderer.connect_toggled(move |_r, path| {
let iter = model.iter(&path).unwrap();
let mut fixed = model
.value(&iter, ColumnsEmptyFolders::ActiveSelectButton as i32)
.get::<bool>()
.unwrap_or_else(|err| panic!("ListStore value missing at path {}: {}", path, err));
fixed = !fixed;
model.set_value(&iter, ColumnsEmptyFolders::ActiveSelectButton as u32, &fixed.to_value());
});
let column = gtk::TreeViewColumn::new();
column.pack_start(&renderer, true);
column.set_resizable(false);
column.set_fixed_width(30);
column.add_attribute(&renderer, "active", ColumnsEmptyFolders::ActiveSelectButton as i32);
tree_view.append_column(&column);
let renderer = gtk::CellRendererText::new();
let column: gtk::TreeViewColumn = TreeViewColumn::new();
column.pack_start(&renderer, true);
@ -71,6 +111,25 @@ pub fn create_tree_view_empty_folders(tree_view: &mut gtk::TreeView) {
}
pub fn create_tree_view_big_files(tree_view: &mut gtk::TreeView) {
let model = get_list_store(tree_view);
let renderer = gtk::CellRendererToggle::new();
renderer.connect_toggled(move |_r, path| {
let iter = model.iter(&path).unwrap();
let mut fixed = model
.value(&iter, ColumnsBigFiles::ActiveSelectButton as i32)
.get::<bool>()
.unwrap_or_else(|err| panic!("ListStore value missing at path {}: {}", path, err));
fixed = !fixed;
model.set_value(&iter, ColumnsBigFiles::ActiveSelectButton as u32, &fixed.to_value());
});
let column = gtk::TreeViewColumn::new();
column.pack_start(&renderer, true);
column.set_resizable(false);
column.set_fixed_width(30);
column.add_attribute(&renderer, "active", ColumnsBigFiles::ActiveSelectButton as i32);
tree_view.append_column(&column);
let renderer = gtk::CellRendererText::new();
let column: gtk::TreeViewColumn = TreeViewColumn::new();
column.pack_start(&renderer, true);
@ -111,6 +170,25 @@ pub fn create_tree_view_big_files(tree_view: &mut gtk::TreeView) {
}
pub fn create_tree_view_temporary_files(tree_view: &mut gtk::TreeView) {
let model = get_list_store(tree_view);
let renderer = gtk::CellRendererToggle::new();
renderer.connect_toggled(move |_r, path| {
let iter = model.iter(&path).unwrap();
let mut fixed = model
.value(&iter, ColumnsTemporaryFiles::ActiveSelectButton as i32)
.get::<bool>()
.unwrap_or_else(|err| panic!("ListStore value missing at path {}: {}", path, err));
fixed = !fixed;
model.set_value(&iter, ColumnsTemporaryFiles::ActiveSelectButton as u32, &fixed.to_value());
});
let column = gtk::TreeViewColumn::new();
column.pack_start(&renderer, true);
column.set_resizable(false);
column.set_fixed_width(30);
column.add_attribute(&renderer, "active", ColumnsTemporaryFiles::ActiveSelectButton as i32);
tree_view.append_column(&column);
let renderer = gtk::CellRendererText::new();
let column: gtk::TreeViewColumn = TreeViewColumn::new();
column.pack_start(&renderer, true);
@ -142,6 +220,25 @@ pub fn create_tree_view_temporary_files(tree_view: &mut gtk::TreeView) {
}
pub fn create_tree_view_empty_files(tree_view: &mut gtk::TreeView) {
let model = get_list_store(tree_view);
let renderer = gtk::CellRendererToggle::new();
renderer.connect_toggled(move |_r, path| {
let iter = model.iter(&path).unwrap();
let mut fixed = model
.value(&iter, ColumnsEmptyFiles::ActiveSelectButton as i32)
.get::<bool>()
.unwrap_or_else(|err| panic!("ListStore value missing at path {}: {}", path, err));
fixed = !fixed;
model.set_value(&iter, ColumnsEmptyFiles::ActiveSelectButton as u32, &fixed.to_value());
});
let column = gtk::TreeViewColumn::new();
column.pack_start(&renderer, true);
column.set_resizable(false);
column.set_fixed_width(30);
column.add_attribute(&renderer, "active", ColumnsEmptyFiles::ActiveSelectButton as i32);
tree_view.append_column(&column);
let renderer = gtk::CellRendererText::new();
let column: gtk::TreeViewColumn = TreeViewColumn::new();
column.pack_start(&renderer, true);
@ -173,6 +270,27 @@ pub fn create_tree_view_empty_files(tree_view: &mut gtk::TreeView) {
}
pub fn create_tree_view_similar_images(tree_view: &mut gtk::TreeView) {
let model = get_list_store(tree_view);
let renderer = gtk::CellRendererToggle::new();
renderer.connect_toggled(move |_r, path| {
let iter = model.iter(&path).unwrap();
let mut fixed = model
.value(&iter, ColumnsSimilarImages::ActiveSelectButton as i32)
.get::<bool>()
.unwrap_or_else(|err| panic!("ListStore value missing at path {}: {}", path, err));
fixed = !fixed;
model.set_value(&iter, ColumnsSimilarImages::ActiveSelectButton as u32, &fixed.to_value());
});
let column = gtk::TreeViewColumn::new();
column.pack_start(&renderer, true);
column.set_resizable(false);
column.set_fixed_width(30);
column.add_attribute(&renderer, "visible", ColumnsSimilarImages::VisibleSelectButton as i32);
column.add_attribute(&renderer, "active", ColumnsSimilarImages::ActiveSelectButton as i32);
column.add_attribute(&renderer, "cell-background", ColumnsSimilarImages::Color as i32);
tree_view.append_column(&column);
let renderer = gtk::CellRendererText::new();
let column: gtk::TreeViewColumn = TreeViewColumn::new();
column.pack_start(&renderer, true);
@ -253,6 +371,25 @@ pub fn create_tree_view_directories(tree_view: &mut gtk::TreeView) {
}
pub fn create_tree_view_zeroed_files(tree_view: &mut gtk::TreeView) {
let model = get_list_store(tree_view);
let renderer = gtk::CellRendererToggle::new();
renderer.connect_toggled(move |_r, path| {
let iter = model.iter(&path).unwrap();
let mut fixed = model
.value(&iter, ColumnsZeroedFiles::ActiveSelectButton as i32)
.get::<bool>()
.unwrap_or_else(|err| panic!("ListStore value missing at path {}: {}", path, err));
fixed = !fixed;
model.set_value(&iter, ColumnsZeroedFiles::ActiveSelectButton as u32, &fixed.to_value());
});
let column = gtk::TreeViewColumn::new();
column.pack_start(&renderer, true);
column.set_resizable(false);
column.set_fixed_width(30);
column.add_attribute(&renderer, "active", ColumnsZeroedFiles::ActiveSelectButton as i32);
tree_view.append_column(&column);
let renderer = gtk::CellRendererText::new();
let column: gtk::TreeViewColumn = TreeViewColumn::new();
column.pack_start(&renderer, true);
@ -293,6 +430,27 @@ pub fn create_tree_view_zeroed_files(tree_view: &mut gtk::TreeView) {
}
pub fn create_tree_view_same_music(tree_view: &mut gtk::TreeView) {
let model = get_list_store(tree_view);
let renderer = gtk::CellRendererToggle::new();
renderer.connect_toggled(move |_r, path| {
let iter = model.iter(&path).unwrap();
let mut fixed = model
.value(&iter, ColumnsSameMusic::ActiveSelectButton as i32)
.get::<bool>()
.unwrap_or_else(|err| panic!("ListStore value missing at path {}: {}", path, err));
fixed = !fixed;
model.set_value(&iter, ColumnsSameMusic::ActiveSelectButton as u32, &fixed.to_value());
});
let column = gtk::TreeViewColumn::new();
column.pack_start(&renderer, true);
column.set_resizable(false);
column.set_fixed_width(30);
column.add_attribute(&renderer, "visible", ColumnsSameMusic::VisibleSelectButton as i32);
column.add_attribute(&renderer, "active", ColumnsSameMusic::ActiveSelectButton as i32);
column.add_attribute(&renderer, "cell-background", ColumnsSameMusic::Color as i32);
tree_view.append_column(&column);
let renderer = gtk::CellRendererText::new();
let column: gtk::TreeViewColumn = TreeViewColumn::new();
column.pack_start(&renderer, true);
@ -396,6 +554,25 @@ pub fn create_tree_view_same_music(tree_view: &mut gtk::TreeView) {
}
pub fn create_tree_view_invalid_symlinks(tree_view: &mut gtk::TreeView) {
let model = get_list_store(tree_view);
let renderer = gtk::CellRendererToggle::new();
renderer.connect_toggled(move |_r, path| {
let iter = model.iter(&path).unwrap();
let mut fixed = model
.value(&iter, ColumnsInvalidSymlinks::ActiveSelectButton as i32)
.get::<bool>()
.unwrap_or_else(|err| panic!("ListStore value missing at path {}: {}", path, err));
fixed = !fixed;
model.set_value(&iter, ColumnsInvalidSymlinks::ActiveSelectButton as u32, &fixed.to_value());
});
let column = gtk::TreeViewColumn::new();
column.pack_start(&renderer, true);
column.set_resizable(false);
column.set_fixed_width(30);
column.add_attribute(&renderer, "active", ColumnsInvalidSymlinks::ActiveSelectButton as i32);
tree_view.append_column(&column);
let renderer = gtk::CellRendererText::new();
let column: gtk::TreeViewColumn = TreeViewColumn::new();
column.pack_start(&renderer, true);
@ -445,6 +622,25 @@ pub fn create_tree_view_invalid_symlinks(tree_view: &mut gtk::TreeView) {
}
pub fn create_tree_view_broken_files(tree_view: &mut gtk::TreeView) {
let model = get_list_store(tree_view);
let renderer = gtk::CellRendererToggle::new();
renderer.connect_toggled(move |_r, path| {
let iter = model.iter(&path).unwrap();
let mut fixed = model
.value(&iter, ColumnsBrokenFiles::ActiveSelectButton as i32)
.get::<bool>()
.unwrap_or_else(|err| panic!("ListStore value missing at path {}: {}", path, err));
fixed = !fixed;
model.set_value(&iter, ColumnsBrokenFiles::ActiveSelectButton as u32, &fixed.to_value());
});
let column = gtk::TreeViewColumn::new();
column.pack_start(&renderer, true);
column.set_resizable(false);
column.set_fixed_width(30);
column.add_attribute(&renderer, "active", ColumnsBrokenFiles::ActiveSelectButton as i32);
tree_view.append_column(&column);
let renderer = gtk::CellRendererText::new();
let column: gtk::TreeViewColumn = TreeViewColumn::new();
column.pack_start(&renderer, true);

View file

@ -28,9 +28,12 @@ pub enum Message {
BrokenFiles(BrokenFiles),
}
#[derive(Debug)]
pub enum ColumnsDuplicates {
// Columns for duplicate treeview
Name = 0,
VisibleSelectButton = 0,
ActiveSelectButton,
Name,
Path,
Modification,
ModificationAsSecs,
@ -40,7 +43,8 @@ pub enum ColumnsDuplicates {
pub enum ColumnsEmptyFolders {
// Columns for empty folder treeview
Name = 0,
ActiveSelectButton = 0,
Name,
Path,
Modification,
}
@ -49,23 +53,28 @@ pub enum ColumnsDirectory {
Path = 0,
}
pub enum ColumnsBigFiles {
Size = 0,
ActiveSelectButton = 0,
Size,
Name,
Path,
Modification,
}
pub enum ColumnsEmptyFiles {
Name = 0,
ActiveSelectButton = 0,
Name,
Path,
Modification,
}
pub enum ColumnsTemporaryFiles {
Name = 0,
ActiveSelectButton = 0,
Name,
Path,
Modification,
}
pub enum ColumnsSimilarImages {
Similarity = 0,
VisibleSelectButton = 0,
ActiveSelectButton,
Similarity,
Size,
SizeAsBytes,
Dimensions,
@ -77,14 +86,17 @@ pub enum ColumnsSimilarImages {
TextColor,
}
pub enum ColumnsZeroedFiles {
Size = 0,
ActiveSelectButton = 0,
Size,
SizeAsBytes,
Name,
Path,
Modification,
}
pub enum ColumnsSameMusic {
Size = 0,
VisibleSelectButton = 0,
ActiveSelectButton,
Size,
SizeAsBytes,
Name,
Path,
@ -99,7 +111,8 @@ pub enum ColumnsSameMusic {
TextColor,
}
pub enum ColumnsInvalidSymlinks {
Name = 0,
ActiveSelectButton = 0,
Name,
Path,
DestinationPath,
TypeOfError,
@ -107,7 +120,8 @@ pub enum ColumnsInvalidSymlinks {
}
pub enum ColumnsBrokenFiles {
Name = 0,
ActiveSelectButton = 0,
Name,
Path,
ErrorType,
Modification,

View file

@ -52,7 +52,9 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
{
// Duplicate Files
{
let col_types: [glib::types::Type; 6] = [
let col_types: [glib::types::Type; 8] = [
glib::types::Type::BOOL,
glib::types::Type::BOOL,
glib::types::Type::STRING,
glib::types::Type::STRING,
glib::types::Type::STRING,
@ -93,11 +95,24 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
return gtk::Inhibit(false);
}
if gui_data.settings.check_button_settings_confirm_group_deletion.is_active()
&& check_if_deleting_all_files_in_group(&tree_view.clone(), ColumnsDuplicates::Color as i32, &gui_data.window_main, &gui_data.settings.check_button_settings_confirm_group_deletion)
&& check_if_deleting_all_files_in_group(
&tree_view.clone(),
ColumnsDuplicates::Color as i32,
ColumnsDuplicates::ActiveSelectButton as i32,
&gui_data.window_main,
&gui_data.settings.check_button_settings_confirm_group_deletion,
)
{
return gtk::Inhibit(false);
}
tree_remove(&tree_view, ColumnsDuplicates::Name as i32, ColumnsDuplicates::Path as i32, ColumnsDuplicates::Color as i32, &gui_data);
tree_remove(
&tree_view,
ColumnsDuplicates::Name as i32,
ColumnsDuplicates::Path as i32,
ColumnsDuplicates::Color as i32,
ColumnsDuplicates::ActiveSelectButton as i32,
&gui_data,
);
}
}
gtk::Inhibit(false)
@ -105,7 +120,7 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
}
// Empty Folders
{
let col_types: [glib::types::Type; 3] = [glib::types::Type::STRING, glib::types::Type::STRING, glib::types::Type::STRING];
let col_types: [glib::types::Type; 4] = [glib::types::Type::BOOL, glib::types::Type::STRING, glib::types::Type::STRING, glib::types::Type::STRING];
let list_store: gtk::ListStore = gtk::ListStore::new(&col_types);
let mut tree_view: gtk::TreeView = TreeView::with_model(&list_store);
@ -126,7 +141,7 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
if let Some(button_number) = e.keycode() {
// Handle delete button
if button_number == 119 {
empty_folder_remover(&tree_view, ColumnsEmptyFolders::Name as i32, ColumnsEmptyFolders::Path as i32, &gui_data);
empty_folder_remover(&tree_view, ColumnsEmptyFolders::Name as i32, ColumnsEmptyFolders::Path as i32, ColumnsEmptyFolders::ActiveSelectButton as i32, &gui_data);
}
}
gtk::Inhibit(false)
@ -134,7 +149,7 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
}
// Empty Files
{
let col_types: [glib::types::Type; 3] = [glib::types::Type::STRING, glib::types::Type::STRING, glib::types::Type::STRING];
let col_types: [glib::types::Type; 4] = [glib::types::Type::BOOL, glib::types::Type::STRING, glib::types::Type::STRING, glib::types::Type::STRING];
let list_store: gtk::ListStore = gtk::ListStore::new(&col_types);
let mut tree_view: gtk::TreeView = TreeView::with_model(&list_store);
@ -155,7 +170,7 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
if let Some(button_number) = e.keycode() {
// Handle delete button
if button_number == 119 {
basic_remove(&tree_view, ColumnsEmptyFiles::Name as i32, ColumnsEmptyFiles::Path as i32, &gui_data);
basic_remove(&tree_view, ColumnsEmptyFiles::Name as i32, ColumnsEmptyFiles::Path as i32, ColumnsEmptyFiles::ActiveSelectButton as i32, &gui_data);
}
}
gtk::Inhibit(false)
@ -163,7 +178,7 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
}
// Temporary Files
{
let col_types: [glib::types::Type; 3] = [glib::types::Type::STRING, glib::types::Type::STRING, glib::types::Type::STRING];
let col_types: [glib::types::Type; 4] = [glib::types::Type::BOOL, glib::types::Type::STRING, glib::types::Type::STRING, glib::types::Type::STRING];
let list_store: gtk::ListStore = gtk::ListStore::new(&col_types);
let mut tree_view: gtk::TreeView = TreeView::with_model(&list_store);
@ -184,7 +199,7 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
if let Some(button_number) = e.keycode() {
// Handle delete button
if button_number == 119 {
basic_remove(&tree_view, ColumnsTemporaryFiles::Name as i32, ColumnsTemporaryFiles::Path as i32, &gui_data);
basic_remove(&tree_view, ColumnsTemporaryFiles::Name as i32, ColumnsTemporaryFiles::Path as i32, ColumnsTemporaryFiles::ActiveSelectButton as i32, &gui_data);
}
}
gtk::Inhibit(false)
@ -192,7 +207,7 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
}
// Big Files
{
let col_types: [glib::types::Type; 4] = [glib::types::Type::STRING, glib::types::Type::STRING, glib::types::Type::STRING, glib::types::Type::STRING];
let col_types: [glib::types::Type; 5] = [glib::types::Type::BOOL, glib::types::Type::STRING, glib::types::Type::STRING, glib::types::Type::STRING, glib::types::Type::STRING];
let list_store: gtk::ListStore = gtk::ListStore::new(&col_types);
let mut tree_view: gtk::TreeView = TreeView::with_model(&list_store);
@ -213,7 +228,7 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
if let Some(button_number) = e.keycode() {
// Handle delete button
if button_number == 119 {
basic_remove(&tree_view, ColumnsBigFiles::Name as i32, ColumnsBigFiles::Path as i32, &gui_data);
basic_remove(&tree_view, ColumnsBigFiles::Name as i32, ColumnsBigFiles::Path as i32, ColumnsBigFiles::ActiveSelectButton as i32, &gui_data);
}
}
gtk::Inhibit(false)
@ -224,7 +239,9 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
let image_preview_similar_images_clone = image_preview_similar_images.clone();
image_preview_similar_images.hide();
let col_types: [glib::types::Type; 10] = [
let col_types: [glib::types::Type; 12] = [
glib::types::Type::BOOL,
glib::types::Type::BOOL,
glib::types::Type::STRING,
glib::types::Type::STRING,
glib::types::Type::U64,
@ -271,11 +288,24 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
return gtk::Inhibit(false);
}
if gui_data.settings.check_button_settings_confirm_group_deletion.is_active()
&& check_if_deleting_all_files_in_group(&tree_view.clone(), ColumnsSimilarImages::Color as i32, &gui_data.window_main, &gui_data.settings.check_button_settings_confirm_group_deletion)
&& check_if_deleting_all_files_in_group(
&tree_view.clone(),
ColumnsSimilarImages::Color as i32,
ColumnsSimilarImages::ActiveSelectButton as i32,
&gui_data.window_main,
&gui_data.settings.check_button_settings_confirm_group_deletion,
)
{
return gtk::Inhibit(false);
}
tree_remove(&tree_view, ColumnsSimilarImages::Name as i32, ColumnsSimilarImages::Path as i32, ColumnsSimilarImages::Color as i32, &gui_data);
tree_remove(
&tree_view,
ColumnsSimilarImages::Name as i32,
ColumnsSimilarImages::Path as i32,
ColumnsSimilarImages::Color as i32,
ColumnsSimilarImages::ActiveSelectButton as i32,
&gui_data,
);
image_preview_similar_images_clone.hide();
}
}
@ -285,7 +315,14 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
}
// Zeroed Files
{
let col_types: [glib::types::Type; 5] = [glib::types::Type::STRING, glib::types::Type::U64, glib::types::Type::STRING, glib::types::Type::STRING, glib::types::Type::STRING];
let col_types: [glib::types::Type; 6] = [
glib::types::Type::BOOL,
glib::types::Type::STRING,
glib::types::Type::U64,
glib::types::Type::STRING,
glib::types::Type::STRING,
glib::types::Type::STRING,
];
let list_store: gtk::ListStore = gtk::ListStore::new(&col_types);
let mut tree_view: gtk::TreeView = TreeView::with_model(&list_store);
@ -306,7 +343,7 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
if let Some(button_number) = e.keycode() {
// Handle delete button
if button_number == 119 {
basic_remove(&tree_view, ColumnsZeroedFiles::Name as i32, ColumnsZeroedFiles::Path as i32, &gui_data);
basic_remove(&tree_view, ColumnsZeroedFiles::Name as i32, ColumnsZeroedFiles::Path as i32, ColumnsZeroedFiles::ActiveSelectButton as i32, &gui_data);
}
}
gtk::Inhibit(false)
@ -314,7 +351,9 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
}
// Same Music
{
let col_types: [glib::types::Type; 13] = [
let col_types: [glib::types::Type; 15] = [
glib::types::Type::BOOL,
glib::types::Type::BOOL,
glib::types::Type::STRING,
glib::types::Type::U64,
glib::types::Type::STRING,
@ -357,11 +396,24 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
return gtk::Inhibit(false);
}
if gui_data.settings.check_button_settings_confirm_group_deletion.is_active()
&& check_if_deleting_all_files_in_group(&tree_view.clone(), ColumnsSameMusic::Color as i32, &gui_data.window_main, &gui_data.settings.check_button_settings_confirm_group_deletion)
&& check_if_deleting_all_files_in_group(
&tree_view.clone(),
ColumnsSameMusic::Color as i32,
ColumnsSameMusic::ActiveSelectButton as i32,
&gui_data.window_main,
&gui_data.settings.check_button_settings_confirm_group_deletion,
)
{
return gtk::Inhibit(false);
}
tree_remove(&tree_view, ColumnsSameMusic::Name as i32, ColumnsSameMusic::Path as i32, ColumnsSameMusic::Color as i32, &gui_data);
tree_remove(
&tree_view,
ColumnsSameMusic::Name as i32,
ColumnsSameMusic::Path as i32,
ColumnsSameMusic::Color as i32,
ColumnsSameMusic::ActiveSelectButton as i32,
&gui_data,
);
}
}
gtk::Inhibit(false)
@ -369,7 +421,14 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
}
// Invalid Symlinks
{
let col_types: [glib::types::Type; 5] = [glib::types::Type::STRING, glib::types::Type::STRING, glib::types::Type::STRING, glib::types::Type::STRING, glib::types::Type::STRING];
let col_types: [glib::types::Type; 6] = [
glib::types::Type::BOOL,
glib::types::Type::STRING,
glib::types::Type::STRING,
glib::types::Type::STRING,
glib::types::Type::STRING,
glib::types::Type::STRING,
];
let list_store: gtk::ListStore = gtk::ListStore::new(&col_types);
let mut tree_view: gtk::TreeView = TreeView::with_model(&list_store);
@ -390,7 +449,7 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
if let Some(button_number) = e.keycode() {
// Handle delete button
if button_number == 119 {
basic_remove(&tree_view, ColumnsInvalidSymlinks::Name as i32, ColumnsInvalidSymlinks::Path as i32, &gui_data);
basic_remove(&tree_view, ColumnsInvalidSymlinks::Name as i32, ColumnsInvalidSymlinks::Path as i32, ColumnsInvalidSymlinks::ActiveSelectButton as i32, &gui_data);
}
}
gtk::Inhibit(false)
@ -398,7 +457,7 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
}
// Broken Files
{
let col_types: [glib::types::Type; 4] = [glib::types::Type::STRING, glib::types::Type::STRING, glib::types::Type::STRING, glib::types::Type::STRING];
let col_types: [glib::types::Type; 5] = [glib::types::Type::BOOL, glib::types::Type::STRING, glib::types::Type::STRING, glib::types::Type::STRING, glib::types::Type::STRING];
let list_store: gtk::ListStore = gtk::ListStore::new(&col_types);
let mut tree_view: gtk::TreeView = TreeView::with_model(&list_store);
@ -419,7 +478,7 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
if let Some(button_number) = e.keycode() {
// Handle delete button
if button_number == 119 {
basic_remove(&tree_view, ColumnsBrokenFiles::Name as i32, ColumnsBrokenFiles::Path as i32, &gui_data);
basic_remove(&tree_view, ColumnsBrokenFiles::Name as i32, ColumnsBrokenFiles::Path as i32, ColumnsBrokenFiles::ActiveSelectButton as i32, &gui_data);
}
}
gtk::Inhibit(false)

View file

@ -1,5 +1,6 @@
// Remove console window in Windows OS
#![windows_subsystem = "windows"]
#![allow(clippy::collapsible_else_if)]
mod connect_about_buttons;
mod connect_button_delete;

View file

@ -3,7 +3,7 @@
- [GUI](#gui-gtk)
- [CLI](#cli)
- [Config / Cache files](#configcache-files)
- [Tips and tricks](#tips-and-tricks)
- [Tips, tricks and known bugs](#tips-tricks-and-known-bugs)
- [Tools](#tools)
Czkawka for now contains two independent frontends - the terminal and graphical interface which share the core module.
@ -15,7 +15,7 @@ This code also has good support for multi-threading.
### GUI overview
The GUI is built from different pieces:
- Red - Program settings, contains info about included/excluded directories which user may want to check. Also, there is a tab with allowed extensions, which allows users to choose which type of files they want to check. Next category is Excluded items, which allows to discard specific path by using `*` wildcard - so `/home/*` means that e.g. `/home/rafal/` will be ignored but not `/home/czkawka/`. The last one is settings tab which allows to save configuration of the program, reset and load it when needed.
- Red - Program settings, contains info about included/excluded directories which user may want to check. Also, there is a tab with allowed extensions, which allows users to choose which type of files they want to check. Next category is Excluded items, which allows to discard specific path by using `*` wildcard - so `/home/ra*` means that e.g. `/home/rafal/` will be ignored but not `/home/czkawka/`. The last one is settings tab which allows to save configuration of the program, reset and load it when needed.
- Green - This allows to choose which tool we want to use.
- Blue - Here are settings for the current tool, which we want/need to configure
- Pink - Window in which results of searching are printed
@ -85,12 +85,19 @@ Linux - `/home/username/.cache/czkawka`
Mac - `/Users/Username/Library/Caches/pl.Qarmin.Czkawka`
Windows - `C:\Users\Username\AppData\Local\Qarmin\Czkawka\cache`
## Tips and Tricks
## Tips, Tricks and Known Bugs
- **Manually adding multiple directories**
You can manually edit config file `czkawka_gui_config.txt` and add/remove/change directories as you want. After setting required values, configuration must be loaded to Czkawka.
- **Slow checking of little number similar images**
If you checked before a large number of images (several tens of thousands) and they are still present on the disk, then the required information about all of them is loaded from and saved to the cache, even if you are working with only few image files. You can rename cache file `cache_similar_image.txt`(to be able to use it again) or delete it - cache will then regenerate but with smaller number of entries and this way it should load and save a lot of faster.
- **Not all columns are visible**
For now it is possible that some columns will not be visible when some are too wide. There are 2 workarounds for now
- View can be scrolled via horizontal scroll bar
- Size of other columns can be slimmed
This is handled via https://github.com/qarmin/czkawka/issues/169
![AA](https://user-images.githubusercontent.com/41945903/125684641-728e264a-34ab-41b1-9853-ab45dc25551f.png)
# Tools