diff --git a/.gitignore b/.gitignore index 26b6664..142a702 100644 --- a/.gitignore +++ b/.gitignore @@ -1,16 +1,15 @@ -target/ -build/ -_build/ -builddir/ -build-aux/app -.flatpak-builder -src/config.rs +/target/ +/build/ +/_build/ +/builddir/ +/build-aux/app +/build-aux/.flatpak-builder/ +/src/config.rs *.ui.in~ *.ui~ -.json~ -.flatpak/ -vendor -flatpak_app -libs +/.flatpak/ +/vendor +/.vscode +.flatpak-builder/ *.AppImage diff --git a/Cargo.lock b/Cargo.lock index fc30a09..4101e25 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] @@ -18,10 +18,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] -name = "anyhow" -version = "1.0.71" +name = "aho-corasick" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" + +[[package]] +name = "async-trait" +version = "0.1.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.51", +] [[package]] name = "autocfg" @@ -31,9 +51,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.68" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", @@ -51,29 +71,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] -name = "bytes" -version = "1.4.0" +name = "block" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "bumpalo" +version = "3.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b" [[package]] name = "cairo-rs" -version = "0.15.12" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c76ee391b03d35510d9fa917357c7f1855bd9a6659c95a1b392e33f49b3369bc" +checksum = "ab3603c4028a5e368d09b51c8b624b9a46edcd7c3778284077a6125af73c9f0a" dependencies = [ "bitflags", "cairo-sys-rs", "glib", "libc", + "once_cell", "thiserror", ] [[package]] name = "cairo-sys-rs" -version = "0.15.1" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c55d429bef56ac9172d25fecb85dc8068307d17acd74b377866b7a1ef25d3c8" +checksum = "691d0c66b1fb4881be80a760cb8fe76ea97218312f9dfe2c9cc0f496ca279cb1" dependencies = [ "glib-sys", "libc", @@ -82,15 +109,15 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.79" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc" [[package]] name = "cfg-expr" -version = "0.15.3" +version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "215c0072ecc28f92eeb0eea38ba63ddfcb65c2828c46311d646f1a3ff5f9841c" +checksum = "fa50868b64a9a6fda9d593ce778849ea8715cd2a3d2cc17ffdb4a2f2f2f1961d" dependencies = [ "smallvec", "target-lexicon", @@ -119,12 +146,16 @@ dependencies = [ ] [[package]] -name = "fragile" -version = "1.2.2" +name = "flume" +version = "0.10.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7464c5c4a3f014d9b2ec4073650e5c06596f385060af740fc45ad5a19f959e8" +checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577" dependencies = [ - "fragile 2.0.0", + "futures-core", + "futures-sink", + "nanorand", + "pin-project", + "spin", ] [[package]] @@ -134,25 +165,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" [[package]] -name = "futures-channel" -version = "0.3.28" +name = "futures" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", + "futures-sink", ] [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -161,24 +208,46 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.51", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ + "futures-channel", "futures-core", + "futures-io", + "futures-macro", + "futures-sink", "futures-task", + "memchr", "pin-project-lite", "pin-utils", "slab", @@ -186,22 +255,23 @@ dependencies = [ [[package]] name = "gdk-pixbuf" -version = "0.15.11" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad38dd9cc8b099cceecdf41375bb6d481b1b5a7cd5cd603e10a69a9383f8619a" +checksum = "695d6bc846438c5708b07007537b9274d883373dd30858ca881d7d71b5540717" dependencies = [ "bitflags", "gdk-pixbuf-sys", "gio", "glib", "libc", + "once_cell", ] [[package]] name = "gdk-pixbuf-sys" -version = "0.15.10" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "140b2f5378256527150350a8346dbdb08fadc13453a7a2d73aecd5fab3c402a7" +checksum = "9285ec3c113c66d7d0ab5676599176f1f42f4944ca1b581852215bf5694870cb" dependencies = [ "gio-sys", "glib-sys", @@ -212,9 +282,9 @@ dependencies = [ [[package]] name = "gdk4" -version = "0.4.8" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fabb7cf843c26b085a5d68abb95d0c0bf27a9ae2eeff9c4adb503a1eb580876" +checksum = "c3abf96408a26e3eddf881a7f893a1e111767137136e347745e8ea6ed12731ff" dependencies = [ "bitflags", "cairo-rs", @@ -228,9 +298,9 @@ dependencies = [ [[package]] name = "gdk4-sys" -version = "0.4.8" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efe7dcb44f5c00aeabff3f69abfc5673de46559070f89bd3fbb7b66485d9cef2" +checksum = "1bc92aa1608c089c49393d014c38ac0390d01e4841e1fedaa75dbcef77aaed64" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", @@ -244,33 +314,69 @@ dependencies = [ ] [[package]] -name = "gimli" -version = "0.27.3" +name = "getrandom" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "gettext-rs" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e49ea8a8fad198aaa1f9655a2524b64b70eb06b2f3ff37da407566c93054f364" +dependencies = [ + "gettext-sys", + "locale_config", +] + +[[package]] +name = "gettext-sys" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c63ce2e00f56a206778276704bbe38564c8695249fdc8f354b4ef71c57c3839d" +dependencies = [ + "cc", + "temp-dir", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "gio" -version = "0.15.12" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68fdbc90312d462781a395f7a16d96a2b379bb6ef8cd6310a2df272771c4283b" +checksum = "a6973e92937cf98689b6a054a9e56c657ed4ff76de925e36fc331a15f0c5d30a" dependencies = [ "bitflags", "futures-channel", "futures-core", "futures-io", + "futures-util", "gio-sys", "glib", "libc", "once_cell", + "pin-project-lite", + "smallvec", "thiserror", ] [[package]] name = "gio-sys" -version = "0.15.10" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32157a475271e2c4a023382e9cab31c4584ee30a97da41d3c4e9fdd605abcf8d" +checksum = "0ccf87c30a12c469b6d958950f6a9c09f2be20b7773f7e70d20b867fdf2628c3" dependencies = [ "glib-sys", "gobject-sys", @@ -281,19 +387,22 @@ dependencies = [ [[package]] name = "glib" -version = "0.15.12" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edb0306fbad0ab5428b0ca674a23893db909a98582969c9b537be4ced78c505d" +checksum = "d3fad45ba8d4d2cea612b432717e834f48031cd8853c8aaf43b2c79fec8d144b" dependencies = [ "bitflags", "futures-channel", "futures-core", "futures-executor", "futures-task", + "futures-util", + "gio-sys", "glib-macros", "glib-sys", "gobject-sys", "libc", + "memchr", "once_cell", "smallvec", "thiserror", @@ -301,9 +410,9 @@ dependencies = [ [[package]] name = "glib-macros" -version = "0.15.13" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10c6ae9f6fa26f4fb2ac16b528d138d971ead56141de489f8111e259b9df3c4a" +checksum = "eca5c79337338391f1ab8058d6698125034ce8ef31b72a442437fa6c8580de26" dependencies = [ "anyhow", "heck", @@ -316,9 +425,9 @@ dependencies = [ [[package]] name = "glib-sys" -version = "0.15.10" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef4b192f8e65e9cf76cbf4ea71fa8e3be4a0e18ffe3d68b8da6836974cc5bad4" +checksum = "d80aa6ea7bba0baac79222204aa786a6293078c210abe69ef1336911d4bdc4f0" dependencies = [ "libc", "system-deps", @@ -326,9 +435,9 @@ dependencies = [ [[package]] name = "gobject-sys" -version = "0.15.10" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d57ce44246becd17153bd035ab4d32cfee096a657fc01f2231c9278378d1e0a" +checksum = "cd34c3317740a6358ec04572c1bcfd3ac0b5b6529275fae255b237b314bb8062" dependencies = [ "glib-sys", "libc", @@ -337,9 +446,9 @@ dependencies = [ [[package]] name = "graphene-rs" -version = "0.15.1" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c54f9fbbeefdb62c99f892dfca35f83991e2cb5b46a8dc2a715e58612f85570" +checksum = "def4bb01265b59ed548b05455040d272d989b3012c42d4c1bbd39083cb9b40d9" dependencies = [ "glib", "graphene-sys", @@ -348,9 +457,9 @@ dependencies = [ [[package]] name = "graphene-sys" -version = "0.15.10" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa691fc7337ba1df599afb55c3bcb85c04f1b3f17362570e9bb0ff0d1bc3028a" +checksum = "1856fc817e6a6675e36cea0bd9a3afe296f5d9709d1e2d3182803ac77f0ab21d" dependencies = [ "glib-sys", "libc", @@ -360,9 +469,9 @@ dependencies = [ [[package]] name = "gsk4" -version = "0.4.8" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05e9020d333280b3aa38d496495bfa9b50712eebf1ad63f0ec5bcddb5eb61be4" +checksum = "6f01ef44fa7cac15e2da9978529383e6bee03e570ba5bf7036b4c10a15cc3a3c" dependencies = [ "bitflags", "cairo-rs", @@ -376,9 +485,9 @@ dependencies = [ [[package]] name = "gsk4-sys" -version = "0.4.8" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7add39ccf60078508c838643a2dcc91f045c46ed63b5ea6ab701b2e25bda3fea" +checksum = "c07a84fb4dcf1323d29435aa85e2f5f58bef564342bef06775ec7bd0da1f01b0" dependencies = [ "cairo-sys-rs", "gdk4-sys", @@ -392,9 +501,9 @@ dependencies = [ [[package]] name = "gtk4" -version = "0.4.9" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e8ae5aef2793bc3551b5e5e3fa062a5de54bb1eccf10dfa4effe9e4384fbbbc" +checksum = "b28a32a04cd75cef14a0983f8b0c669e0fe152a0a7725accdeb594e2c764c88b" dependencies = [ "bitflags", "cairo-rs", @@ -415,24 +524,23 @@ dependencies = [ [[package]] name = "gtk4-macros" -version = "0.4.10" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aba0b544e91a753068e279e99d34e9624b8cfd26282167024c8a5773b8a826c" +checksum = "6a4d6b61570f76d3ee542d984da443b1cd69b6105264c61afec3abed08c2500f" dependencies = [ "anyhow", "proc-macro-crate", "proc-macro-error", "proc-macro2", - "quick-xml", "quote", "syn 1.0.109", ] [[package]] name = "gtk4-sys" -version = "0.4.8" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bc8006eea634b7c72da3ff79e24606e45f21b3b832a3c5a1f543f5f97eb0f63" +checksum = "5f8283f707b07e019e76c7f2934bdd4180c277e08aa93f4c0d8dd07b7a34e22f" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", @@ -449,9 +557,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" [[package]] name = "heck" @@ -461,32 +569,42 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "379dada1584ad501b383485dd706b8afb7a70fcbc7f4da7d780638a5a6124a60" [[package]] name = "indexmap" -version = "2.0.0" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" dependencies = [ "equivalent", "hashbrown", ] [[package]] -name = "itoa" -version = "1.0.8" +name = "js-sys" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a" +checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libadwaita" -version = "0.1.1" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ae453d28e3b91f03749f02b1531e8cfe315a1d0762b77a61797d2ab80bb87d" +checksum = "1ab9c0843f9f23ff25634df2743690c3a1faffe0a190e60c490878517eb81abf" dependencies = [ + "bitflags", "gdk-pixbuf", "gdk4", "gio", @@ -494,15 +612,14 @@ dependencies = [ "gtk4", "libadwaita-sys", "libc", - "once_cell", "pango", ] [[package]] name = "libadwaita-sys" -version = "0.1.0" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f18b6ac4cadd252a89f5cba0a5a4e99836131795d6fad37b859ac79e8cb7d2c8" +checksum = "4231cb2499a9f0c4cdfa4885414b33e39901ddcac61150bc0bb4ff8a57ede404" dependencies = [ "gdk4-sys", "gio-sys", @@ -510,20 +627,34 @@ dependencies = [ "gobject-sys", "gtk4-sys", "libc", + "pango-sys", "system-deps", ] [[package]] name = "libc" -version = "0.2.147" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "locale_config" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d2c35b16f4483f6c26f0e4e9550717a2f6575bcd6f12a53ff0c490a94a6934" +dependencies = [ + "lazy_static", + "objc", + "objc-foundation", + "regex", + "winapi", +] [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -531,15 +662,24 @@ dependencies = [ [[package]] name = "log" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memoffset" @@ -552,22 +692,30 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] [[package]] -name = "mio" -version = "0.8.8" +name = "nanorand" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" dependencies = [ - "libc", - "wasi", - "windows-sys", + "getrandom", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", ] [[package]] @@ -581,27 +729,63 @@ dependencies = [ ] [[package]] -name = "object" -version = "0.31.1" +name = "objc" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "objc-foundation" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" +dependencies = [ + "block", + "objc", + "objc_id", +] + +[[package]] +name = "objc_id" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +dependencies = [ + "objc", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "pango" -version = "0.15.10" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e4045548659aee5313bde6c582b0d83a627b7904dd20dc2d9ef0895d414e4f" +checksum = "35be456fc620e61f62dff7ff70fbd54dcbaf0a4b920c0f16de1107c47d921d48" dependencies = [ "bitflags", + "gio", "glib", "libc", "once_cell", @@ -610,9 +794,9 @@ dependencies = [ [[package]] name = "pango-sys" -version = "0.15.10" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2a00081cde4661982ed91d80ef437c20eacaf6aa1a5962c0279ae194662c3aa" +checksum = "3da69f9f3850b0d8990d462f8c709561975e95f689c1cdf0fecdebde78b35195" dependencies = [ "glib-sys", "gobject-sys", @@ -621,33 +805,30 @@ dependencies = [ ] [[package]] -name = "parking_lot" -version = "0.12.1" +name = "pin-project" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" dependencies = [ - "lock_api", - "parking_lot_core", + "pin-project-internal", ] [[package]] -name = "parking_lot_core" -version = "0.9.8" +name = "pin-project-internal" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets", + "proc-macro2", + "quote", + "syn 2.0.51", ] [[package]] name = "pin-project-lite" -version = "0.2.10" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -657,9 +838,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "proc-macro-crate" @@ -668,7 +849,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ "once_cell", - "toml_edit", + "toml_edit 0.19.15", ] [[package]] @@ -697,64 +878,78 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.64" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] -[[package]] -name = "quick-xml" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8533f14c8382aaad0d592c812ac3b826162128b65662331e1127b45c3d18536b" -dependencies = [ - "memchr", -] - [[package]] name = "quote" -version = "1.0.29" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] [[package]] -name = "redox_syscall" -version = "0.3.5" +name = "regex" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ - "bitflags", + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", ] [[package]] -name = "relm4" -version = "0.4.4" +name = "regex-automata" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e737555426b35a18e9f6fa8d291ce858d358504d441d1e0a7b06ce6c905cc63" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" dependencies = [ - "fragile 1.2.2", - "futures-core", + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "relm4" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c16f3fad883034773b7f5af4d7e865532b8f3641e5a8bab2a34561a8d960d81" +dependencies = [ + "async-trait", + "flume", + "fragile", + "futures", "gtk4", "libadwaita", - "log", "once_cell", "relm4-macros", + "tokio", + "tracing", ] [[package]] name = "relm4-macros" -version = "0.4.4" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7136d9b9b97dc87198c619587de7bd61aca5ec4bec58a7167404c1edf750a490" +checksum = "9340e2553c0a184a80a0bfa1dcf73c47f3d48933aa6be90724b202f9fbd24735" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.51", ] [[package]] @@ -772,96 +967,78 @@ dependencies = [ "semver", ] -[[package]] -name = "ryu" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9" - [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.17" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.171" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.171" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", -] - -[[package]] -name = "serde_json" -version = "1.0.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5062a995d481b2308b6064e9af76011f2921c35f97b0468811ed9f6cd91dfed" -dependencies = [ - "itoa", - "ryu", - "serde", + "syn 2.0.51", ] [[package]] name = "serde_spanned" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" dependencies = [ "serde", ] [[package]] -name = "signal-hook-registry" -version = "1.4.1" +name = "sharded-slab" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ - "libc", + "lazy_static", ] [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] [[package]] name = "smallvec" -version = "1.11.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] -name = "socket2" -version = "0.4.9" +name = "spin" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" dependencies = [ - "libc", - "winapi", + "lock_api", ] [[package]] @@ -877,9 +1054,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.26" +version = "2.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970" +checksum = "6ab617d94515e94ae53b8406c628598680aa0c9587474ecbe58188f7b345d66c" dependencies = [ "proc-macro2", "quote", @@ -888,9 +1065,9 @@ dependencies = [ [[package]] name = "system-deps" -version = "6.1.1" +version = "6.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30c2de8a4d8f4b823d634affc9cd2a74ec98c53a756f317e529a48046cbf71f3" +checksum = "2a2d580ff6a20c55dfb86be5f9c238f67835d0e81cbdea8bf5680e0897320331" dependencies = [ "cfg-expr", "heck", @@ -901,110 +1078,180 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.9" +version = "0.12.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df8e77cb757a61f51b947ec4a7e3646efd825b73561db1c232a8ccb639e611a0" +checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" + +[[package]] +name = "temp-dir" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd16aa9ffe15fe021c6ee3766772132c6e98dfa395a167e16864f61a9cfb71d6" [[package]] name = "thiserror" -version = "1.0.43" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" +checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.43" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" +checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.51", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", ] [[package]] name = "tokio" -version = "1.29.1" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" dependencies = [ - "autocfg", "backtrace", - "bytes", - "libc", - "mio", "num_cpus", - "parking_lot", "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys", -] - -[[package]] -name = "tokio-macros" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.26", ] [[package]] name = "toml" -version = "0.7.6" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" +checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.22.6", ] [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.19.14" +version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c1b5fd4128cc8d3e0cb74d4ed9a9cc7c7284becd4df68f5f940e1ad123606f6" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.6.2", ] [[package]] -name = "toolbxtuner" +name = "toolbox-tuner" version = "0.0.1" dependencies = [ + "gettext-rs", "relm4", - "serde", - "serde_json", - "tokio", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.51", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", ] [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "version-compare" @@ -1024,6 +1271,60 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.51", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.51", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" + [[package]] name = "winapi" version = "0.3.9" @@ -1046,77 +1347,20 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.48.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" - [[package]] name = "winnow" -version = "0.5.0" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fac9742fd1ad1bd9643b991319f72dd031016d44b77039a26977eb667141e7" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a4191c47f15cc3ec71fcb4913cb83d58def65dd3787610213c649283b5ce178" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 07bb28a..325cf6f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,21 +1,15 @@ [package] -name = "toolbxtuner" +name = "toolbox-tuner" version = "0.0.1" authors = ["Hannes Kuchelmeister "] edition = "2021" +publish = false -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[profile.release] +lto = true [dependencies] -relm4 = {version="0.4", features = ["libadwaita", "macros"]} -tokio = { version = "1", features = ["full"] } -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" - -[package.metadata.appimage] -auto_link = true -auto_link_exclude_list = [ - "libc.so*", - "libdl.so*", - "libpthread.so*", -] +gettext-rs = { version = "0.7", features = ["gettext-system"] } +tracing = "0.1" +tracing-subscriber = "0.3" +relm4 = { version = "0.6.0", features = ["libadwaita", "gnome_44"] } diff --git a/build-aux/dist-vendor.sh b/build-aux/dist-vendor.sh old mode 100755 new mode 100644 diff --git a/build-aux/org.kuchelmeister.ToolboxTuner.Devel.json b/build-aux/org.kuchelmeister.ToolboxTuner.Devel.json new file mode 100644 index 0000000..9ce4cd4 --- /dev/null +++ b/build-aux/org.kuchelmeister.ToolboxTuner.Devel.json @@ -0,0 +1,54 @@ +{ + "id": "org.kuchelmeister.ToolboxTuner.Devel", + "runtime": "org.gnome.Platform", + "runtime-version": "44", + "sdk": "org.gnome.Sdk", + "sdk-extensions": [ + "org.freedesktop.Sdk.Extension.rust-stable", + "org.freedesktop.Sdk.Extension.llvm15" + ], + "command": "toolbox-tuner", + "finish-args": [ + "--share=ipc", + "--socket=fallback-x11", + "--socket=wayland", + "--device=dri", + "--env=RUST_LOG=toolbox_tuner=debug", + "--env=G_MESSAGES_DEBUG=none", + "--env=RUST_BACKTRACE=1" + ], + "build-options": { + "append-path": "/usr/lib/sdk/rust-stable/bin:/usr/lib/sdk/llvm15/bin", + "prepend-ld-library-path": "/usr/lib/sdk/llvm15/lib", + "build-args": [ + "--share=network" + ], + "env": { + "CARGO_REGISTRIES_CRATES_IO_PROTOCOL": "sparse", + "CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER": "clang", + "CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUSTFLAGS": "-C link-arg=-fuse-ld=/usr/lib/sdk/rust-stable/bin/mold", + "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER": "clang", + "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUSTFLAGS": "-C link-arg=-fuse-ld=/usr/lib/sdk/rust-stable/bin/mold" + }, + "test-args": [ + "--socket=x11", + "--share=network" + ] + }, + "modules": [ + { + "name": "toolbox-tuner", + "buildsystem": "meson", + "run-tests": true, + "config-opts": [ + "-Dprofile=development" + ], + "sources": [ + { + "type": "dir", + "path": "../" + } + ] + } + ] +} diff --git a/build-aux/org.kuchelmeister.ToolbxTuner.Devel.json b/build-aux/org.kuchelmeister.ToolbxTuner.Devel.json deleted file mode 100644 index eb9b43c..0000000 --- a/build-aux/org.kuchelmeister.ToolbxTuner.Devel.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "id": "org.kuchelmeister.ToolbxTuner.Devel", - "runtime": "org.gnome.Platform", - "runtime-version": "42", - "sdk": "org.gnome.Sdk", - "sdk-extensions": [ - "org.freedesktop.Sdk.Extension.rust-stable" - ], - "command": "toolbxtuner", - "finish-args": [ - "--talk-name=org.freedesktop.Flatpak", - "--socket=fallback-x11", - "--socket=wayland", - "--device=dri", - "--env=RUST_LOG=toolbxtuner=debug", - "--env=G_MESSAGES_DEBUG=none", - "--env=RUST_BACKTRACE=1", - "--share=ipc" - ], - "build-options": { - "append-path": "/usr/lib/sdk/rust-stable/bin", - "build-args": [ - "--share=network" - ], - "test-args": [ - "--socket=x11", - "--share=network" - ] - }, - "modules": [ - { - "name": "toolbxtuner", - "buildsystem": "meson", - "run-tests": true, - "config-opts": [ - "-Dprofile=development" - ], - "sources": [ - { - "type": "dir", - "path": "../" - } - ] - } - ] -} diff --git a/containers/Containerfile b/containers/Containerfile deleted file mode 100644 index af6867f..0000000 --- a/containers/Containerfile +++ /dev/null @@ -1,17 +0,0 @@ -FROM quay.io/podman/stable - -ENV RUST_VERSION=1.61.0 -ENV HOME=/home/root - -RUN dnf install gtk4-devel gcc libadwaita-devel -y -RUN dnf install toolbox -y - -RUN curl https://sh.rustup.rs -sSf | sh -s -- -y -RUN . $HOME/.cargo/env -ENV PATH=/home/root/.cargo/bin:$PATH -RUN rustup install ${RUST_VERSION} - -WORKDIR /mnt - -CMD cargo test - diff --git a/containers/docker-compose.test.yml b/containers/docker-compose.test.yml deleted file mode 100644 index fabdb76..0000000 --- a/containers/docker-compose.test.yml +++ /dev/null @@ -1,10 +0,0 @@ -version: "3" -services: - toolbx-tuner-tests: - build: . - privileged: true - volumes: - - ..:/mnt:z - security_opt: - - label=disable - diff --git a/containers/docker-compose.yml b/containers/docker-compose.yml deleted file mode 100644 index 82694e5..0000000 --- a/containers/docker-compose.yml +++ /dev/null @@ -1,8 +0,0 @@ -version: "3" -services: - gtk4-rs: - image: ghcr.io/13hannes11/gtk4-rs-docker:latest-appimage - volumes: - - ..:/mnt:z - command: sh -c "cargo appimage" - diff --git a/data/icons/org.kuchelmeister.ToolbxTuner-symbolic.svg b/data/icons/org.kuchelmeister.ToolboxTuner-symbolic.svg similarity index 100% rename from data/icons/org.kuchelmeister.ToolbxTuner-symbolic.svg rename to data/icons/org.kuchelmeister.ToolboxTuner-symbolic.svg diff --git a/data/icons/org.kuchelmeister.ToolbxTuner.Devel.svg b/data/icons/org.kuchelmeister.ToolboxTuner.Devel.svg similarity index 100% rename from data/icons/org.kuchelmeister.ToolbxTuner.Devel.svg rename to data/icons/org.kuchelmeister.ToolboxTuner.Devel.svg diff --git a/data/icons/org.kuchelmeister.ToolbxTuner.Source.svg b/data/icons/org.kuchelmeister.ToolboxTuner.Source.svg similarity index 100% rename from data/icons/org.kuchelmeister.ToolbxTuner.Source.svg rename to data/icons/org.kuchelmeister.ToolboxTuner.Source.svg diff --git a/data/icons/org.kuchelmeister.ToolbxTuner.svg b/data/icons/org.kuchelmeister.ToolboxTuner.svg similarity index 100% rename from data/icons/org.kuchelmeister.ToolbxTuner.svg rename to data/icons/org.kuchelmeister.ToolboxTuner.svg diff --git a/data/meson.build b/data/meson.build index 05dec0c..5643b60 100644 --- a/data/meson.build +++ b/data/meson.build @@ -65,7 +65,7 @@ configure_file( install_dir: datadir / 'glib-2.0' / 'schemas' ) -# Validate GSchema +# Validata GSchema if glib_compile_schemas.found() test( 'validate-gschema', glib_compile_schemas, diff --git a/data/org.kuchelmeister.ToolbxTuner.desktop.in.in b/data/org.kuchelmeister.ToolboxTuner.desktop.in.in similarity index 66% rename from data/org.kuchelmeister.ToolbxTuner.desktop.in.in rename to data/org.kuchelmeister.ToolboxTuner.desktop.in.in index f0de095..e02d0a8 100644 --- a/data/org.kuchelmeister.ToolbxTuner.desktop.in.in +++ b/data/org.kuchelmeister.ToolboxTuner.desktop.in.in @@ -1,12 +1,12 @@ [Desktop Entry] -Name=Toolbx Tuner -Comment=Manage and enhance your toolbxes (containertoolboxes) -Exec=toolbxtuner -Terminal=false +Name=Toolbox Tuner +Comment=Manage and enhance your toolboxes (containertoolboxes) Type=Application +Exec=toolbox-tuner +Terminal=false Categories=Utility; # Translators: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! -Keywords=Gnome;GTK;Container;Toolbx;Podman;Toolbox;Fedora;Silvervblue; +Keywords=Gnome;GTK;Container;Podman;Toolbox;Fedora;Silvervblue; # Translators: Do NOT translate or transliterate this text (this is an icon file name)! Icon=@icon@ StartupNotify=true diff --git a/data/org.kuchelmeister.ToolboxTuner.gschema.xml.in b/data/org.kuchelmeister.ToolboxTuner.gschema.xml.in new file mode 100644 index 0000000..4fd4593 --- /dev/null +++ b/data/org.kuchelmeister.ToolboxTuner.gschema.xml.in @@ -0,0 +1,17 @@ + + + + + 600 + Window width + + + 400 + Window height + + + false + Window maximized state + + + diff --git a/data/org.kuchelmeister.ToolbxTuner.metainfo.xml.in.in b/data/org.kuchelmeister.ToolboxTuner.metainfo.xml.in.in similarity index 82% rename from data/org.kuchelmeister.ToolbxTuner.metainfo.xml.in.in rename to data/org.kuchelmeister.ToolboxTuner.metainfo.xml.in.in index 726ff30..ae187f0 100644 --- a/data/org.kuchelmeister.ToolbxTuner.metainfo.xml.in.in +++ b/data/org.kuchelmeister.ToolboxTuner.metainfo.xml.in.in @@ -1,5 +1,5 @@ - + @app-id@ CC0 @@ -9,19 +9,23 @@

An application to manage and enhance your containertoolboxes.

- + Main application window showing multiple toolboxes https://media.githubusercontent.com/media/13hannes11/toolbx-tuner/main/data/resources/screenshots/main_light.png - + Main application window in dark mode https://media.githubusercontent.com/media/13hannes11/toolbx-tuner/main/data/resources/screenshots/main_dark.png - + + #a3f6f1 + #60ada6 + + - + https://github.com/13hannes11/toolbx-tuner https://github.com/13hannes11/toolbx-tuner/issues/ @@ -30,3 +34,4 @@ @gettext-package@ @app-id@.desktop
+ diff --git a/data/org.kuchelmeister.ToolbxTuner.gschema.xml.in b/data/org.kuchelmeister.ToolbxTuner.gschema.xml.in deleted file mode 100644 index e6418dc..0000000 --- a/data/org.kuchelmeister.ToolbxTuner.gschema.xml.in +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/data/resources/resources.gresource.xml b/data/resources/resources.gresource.xml index 7bc4c8a..a28ee95 100644 --- a/data/resources/resources.gresource.xml +++ b/data/resources/resources.gresource.xml @@ -1,6 +1,8 @@ - + + ui/shortcuts.ui + style.css diff --git a/data/resources/style.css b/data/resources/style.css index e69de29..35ffd40 100644 --- a/data/resources/style.css +++ b/data/resources/style.css @@ -0,0 +1,4 @@ +.title-header{ + font-size: 36px; + font-weight: bold; +} \ No newline at end of file diff --git a/data/resources/ui/shortcuts.ui b/data/resources/ui/shortcuts.ui new file mode 100644 index 0000000..ef12f02 --- /dev/null +++ b/data/resources/ui/shortcuts.ui @@ -0,0 +1,29 @@ + + + + True + + + shortcuts + 10 + + + General + + + Show Shortcuts + win.show-help-overlay + + + + + Quit + app.quit + + + + + + + + diff --git a/hooks/pre-commit.hook b/hooks/pre-commit.hook old mode 100755 new mode 100644 index cc44705..464590e --- a/hooks/pre-commit.hook +++ b/hooks/pre-commit.hook @@ -2,16 +2,16 @@ # Source: https://gitlab.gnome.org/GNOME/fractal/blob/master/hooks/pre-commit.hook install_rustfmt() { - if ! which rustup &> /dev/null; then + if ! which rustup >/dev/null 2>&1; then curl https://sh.rustup.rs -sSf | sh -s -- -y export PATH=$PATH:$HOME/.cargo/bin - if ! which rustup &> /dev/null; then + if ! which rustup >/dev/null 2>&1; then echo "Failed to install rustup. Performing the commit without style checking." exit 0 fi fi - if ! rustup component list|grep rustfmt &> /dev/null; then + if ! rustup component list|grep rustfmt >/dev/null 2>&1; then echo "Installing rustfmt…" rustup component add rustfmt fi @@ -34,11 +34,11 @@ if ! which cargo >/dev/null 2>&1 || ! cargo fmt --help >/dev/null 2>&1; then echo "" while true do - echo -n "Install rustfmt via rustup? [y/n/Q]: "; read yn < /dev/tty + printf "%s" "Install rustfmt via rustup? [y/n/Q]: "; read yn < /dev/tty case $yn in [Yy]* ) install_rustfmt; break;; [Nn]* ) echo "Performing commit."; exit 0;; - [Qq]* | "" ) echo "Aborting commit."; exit -1 >/dev/null 2>&1;; + [Qq]* | "" ) echo "Aborting commit."; exit 1 >/dev/null 2>&1;; * ) echo "Invalid input";; esac done @@ -51,7 +51,7 @@ if test $? != 0; then echo "--Checking style fail--" echo "Please fix the above issues, either manually or by running: cargo fmt --all" - exit -1 + exit 1 else echo "--Checking style pass--" fi diff --git a/meson.build b/meson.build index 4e0aa99..f0086df 100644 --- a/meson.build +++ b/meson.build @@ -1,15 +1,15 @@ project( - 'toolbxtuner', + 'toolbox-tuner', 'rust', version: '0.0.1', meson_version: '>= 0.59', - license: 'GPL-3', + # license: 'MIT', ) i18n = import('i18n') gnome = import('gnome') -base_id = 'org.kuchelmeister.ToolbxTuner' +base_id = 'org.kuchelmeister.ToolboxTuner' dependency('glib-2.0', version: '>= 2.66') dependency('gio-2.0', version: '>= 2.66') @@ -35,7 +35,7 @@ gettext_package = meson.project_name() if get_option('profile') == 'development' profile = 'Devel' - vcs_tag = run_command('git', 'rev-parse', '--short', 'HEAD').stdout().strip() + vcs_tag = run_command('git', 'rev-parse', '--short', 'HEAD', check: false).stdout().strip() if vcs_tag == '' version_suffix = '-devel' else @@ -57,7 +57,7 @@ meson.add_dist_script( if get_option('profile') == 'development' # Setup pre-commit hook for ensuring coding style is always consistent message('Setting up git pre-commit hook..') - run_command('cp', '-f', 'hooks/pre-commit.hook', '.git/hooks/pre-commit') + run_command('cp', '-f', 'hooks/pre-commit.hook', '.git/hooks/pre-commit', check: false) endif subdir('data') diff --git a/meson_options.txt b/meson_options.txt index 568f4ac..f882783 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -3,9 +3,8 @@ option( type: 'combo', choices: [ 'default', - 'flathub', 'development' ], value: 'default', - description: 'The build profile for Toolbx Tuner. One of "default" or "development".' + description: 'The build profile for Toolbox Tuner. One of "default" or "development".' ) diff --git a/po/POTFILES.in b/po/POTFILES.in index 83bf505..00c689c 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,4 +1,6 @@ -data/org.kuchelmeister.ToolbxTuner.desktop.in.in -data/org.kuchelmeister.ToolbxTuner.gschema.xml.in -data/org.kuchelmeister.ToolbxTuner.metainfo.xml.in.in +data/org.kuchelmeister.ToolboxTuner.desktop.in.in +data/org.kuchelmeister.ToolboxTuner.gschema.xml.in +data/org.kuchelmeister.ToolboxTuner.metainfo.xml.in.in +data/resources/ui/shortcuts.ui +data/resources/ui/window.ui src/application.rs diff --git a/src/app.rs b/src/app.rs new file mode 100644 index 0000000..043ac57 --- /dev/null +++ b/src/app.rs @@ -0,0 +1,166 @@ +use relm4::{ + actions::{RelmAction, RelmActionGroup}, + adw, gtk, main_application, Component, ComponentController, ComponentParts, ComponentSender, + Controller, SimpleComponent, +}; + +use gtk::prelude::{ + ApplicationExt, ApplicationWindowExt, GtkWindowExt, OrientableExt, SettingsExt, WidgetExt, +}; +use gtk::{gio, glib}; + +use crate::config::{APP_ID, PROFILE}; +use crate::modals::about::AboutDialog; + +pub(super) struct App { + about_dialog: Controller, +} + +#[derive(Debug)] +pub(super) enum AppMsg { + Quit, +} + +relm4::new_action_group!(pub(super) WindowActionGroup, "win"); +//relm4::new_stateless_action!(PreferencesAction, WindowActionGroup, "preferences"); +relm4::new_stateless_action!(pub(super) ShortcutsAction, WindowActionGroup, "show-help-overlay"); +relm4::new_stateless_action!(AboutAction, WindowActionGroup, "about"); + +#[relm4::component(pub)] +impl SimpleComponent for App { + type Init = (); + type Input = AppMsg; + type Output = (); + type Widgets = AppWidgets; + + menu! { + primary_menu: { + section! { + //"_Preferences" => PreferencesAction, + "_Keyboard" => ShortcutsAction, + "_About Toolbox Tuner" => AboutAction, + } + } + } + + view! { + main_window = adw::ApplicationWindow::new(&main_application()) { + connect_close_request[sender] => move |_| { + sender.input(AppMsg::Quit); + gtk::Inhibit(true) + }, + + #[wrap(Some)] + set_help_overlay: shortcuts = >k::Builder::from_resource( + "/org/kuchelmeister/ToolboxTuner/gtk/help-overlay.ui" + ) + .object::("help_overlay") + .unwrap() -> gtk::ShortcutsWindow { + set_transient_for: Some(&main_window), + set_application: Some(&main_application()), + }, + + add_css_class?: if PROFILE == "Devel" { + Some("devel") + } else { + None + }, + + gtk::Box { + set_orientation: gtk::Orientation::Vertical, + + adw::HeaderBar { + pack_end = >k::MenuButton { + set_icon_name: "open-menu-symbolic", + set_menu_model: Some(&primary_menu), + } + }, + + gtk::Label { + set_label: "Hello world!", + add_css_class: "title-header", + set_vexpand: true, + } + } + + } + } + + fn init( + _init: Self::Init, + root: &Self::Root, + sender: ComponentSender, + ) -> ComponentParts { + let about_dialog = AboutDialog::builder() + .transient_for(root) + .launch(()) + .detach(); + + let model = Self { about_dialog }; + + let widgets = view_output!(); + + let mut actions = RelmActionGroup::::new(); + + let shortcuts_action = { + let shortcuts = widgets.shortcuts.clone(); + RelmAction::::new_stateless(move |_| { + shortcuts.present(); + }) + }; + + let about_action = { + let sender = model.about_dialog.sender().clone(); + RelmAction::::new_stateless(move |_| { + sender.send(()).unwrap(); + }) + }; + + actions.add_action(shortcuts_action); + actions.add_action(about_action); + actions.register_for_widget(&widgets.main_window); + + widgets.load_window_size(); + + ComponentParts { model, widgets } + } + + fn update(&mut self, message: Self::Input, _sender: ComponentSender) { + match message { + AppMsg::Quit => main_application().quit(), + } + } + + fn shutdown(&mut self, widgets: &mut Self::Widgets, _output: relm4::Sender) { + widgets.save_window_size().unwrap(); + } +} + +impl AppWidgets { + fn save_window_size(&self) -> Result<(), glib::BoolError> { + let settings = gio::Settings::new(APP_ID); + let (width, height) = self.main_window.default_size(); + + settings.set_int("window-width", width)?; + settings.set_int("window-height", height)?; + + settings.set_boolean("is-maximized", self.main_window.is_maximized())?; + + Ok(()) + } + + fn load_window_size(&self) { + let settings = gio::Settings::new(APP_ID); + + let width = settings.int("window-width"); + let height = settings.int("window-height"); + let is_maximized = settings.boolean("is-maximized"); + + self.main_window.set_default_size(width, height); + + if is_maximized { + self.main_window.maximize(); + } + } +} + diff --git a/src/config.rs.in b/src/config.rs.in index 699897f..0c1c0f6 100644 --- a/src/config.rs.in +++ b/src/config.rs.in @@ -1,6 +1,7 @@ pub const APP_ID: &str = @APP_ID@; pub const GETTEXT_PACKAGE: &str = @GETTEXT_PACKAGE@; pub const LOCALEDIR: &str = @LOCALEDIR@; +#[allow(unused)] pub const PKGDATADIR: &str = @PKGDATADIR@; pub const PROFILE: &str = @PROFILE@; pub const RESOURCES_FILE: &str = concat!(@PKGDATADIR@, "/resources.gresource"); diff --git a/src/main.rs b/src/main.rs index f73f759..f2739fa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,17 +1,47 @@ -use std::collections::VecDeque; +#[rustfmt::skip] +mod config; +mod app; +mod modals; +mod setup; -use relm4::gtk::{Application, ApplicationWindow}; -use relm4::{factory::FactoryVecDeque, RelmApp}; -use ui::app::model::AppModel; -use util::toolbx::ToolbxContainer; +use gtk::prelude::ApplicationExt; +use relm4::{ + actions::{AccelsPlus, RelmAction, RelmActionGroup}, + gtk, main_application, RelmApp, +}; -mod ui; -mod util; +use app::App; +use setup::setup; + +relm4::new_action_group!(AppActionGroup, "app"); +relm4::new_stateless_action!(QuitAction, AppActionGroup, "quit"); fn main() { - let mut model = AppModel { - toolboxes: FactoryVecDeque::new(), + // Enable logging + tracing_subscriber::fmt() + .with_span_events(tracing_subscriber::fmt::format::FmtSpan::FULL) + .with_max_level(tracing::Level::INFO) + .init(); + + setup(); + + let app = main_application(); + app.set_resource_base_path(Some("/org/kuchelmeister/ToolboxTuner/")); + + let mut actions = RelmActionGroup::::new(); + + let quit_action = { + let app = app.clone(); + RelmAction::::new_stateless(move |_| { + app.quit(); + }) }; - let app = RelmApp::new(model); - app.run(); + actions.add_action(quit_action); + actions.register_for_main_application(); + + app.set_accelerators_for_action::(&["q"]); + + let app = RelmApp::from_app(app); + + app.run::(()); } diff --git a/src/meson.build b/src/meson.build index 4f94a86..d99036d 100644 --- a/src/meson.build +++ b/src/meson.build @@ -25,20 +25,13 @@ if get_option('profile') == 'default' cargo_options += [ '--release' ] rust_target = 'release' message('Building in release mode') - cargo_env = [ 'CARGO_HOME=' + meson.project_build_root() / 'cargo-home' ] -endif -if get_option('profile') == 'flathub' - cargo_options += [ '--release', '--offline' ] - rust_target = 'release' - message('Building in flathub release mode') - cargo_env = [ 'CARGO_HOME=/run/build/toolbx-tuner/cargo' ] -endif -if get_option('profile') == 'development' +else rust_target = 'debug' message('Building in debug mode') - cargo_env = [ 'CARGO_HOME=' + meson.project_build_root() / 'cargo-home' ] endif +cargo_env = [ 'CARGO_HOME=' + meson.project_build_root() / 'cargo-home' ] + cargo_build = custom_target( 'cargo-build', build_by_default: true, diff --git a/src/modals/about.rs b/src/modals/about.rs new file mode 100644 index 0000000..d3f070e --- /dev/null +++ b/src/modals/about.rs @@ -0,0 +1,50 @@ +use gtk::prelude::GtkWindowExt; +use relm4::{adw, gtk, ComponentParts, ComponentSender, SimpleComponent}; + +use crate::config::{APP_ID, VERSION}; + +pub struct AboutDialog {} + +impl SimpleComponent for AboutDialog { + type Init = (); + type Widgets = adw::AboutWindow; + type Input = (); + type Output = (); + type Root = adw::AboutWindow; + + fn init_root() -> Self::Root { + adw::AboutWindow::builder() + .application_icon(APP_ID) + // Insert your license of choice here + .license_type(gtk::License::Lgpl30) + // Insert your website here + .website("https://github.com/13hannes11/toolbox-tuner") + // Insert your Issues page + .issue_url("https://github.com/13hannes11/toolbox-tuner/issues") + // Insert your application name here + .application_name("Toolbox Tuner") + .version(VERSION) + .translator_credits("translator-credits") + .copyright("© 2022-2024 Hannes Kuchelmeister") + .developers(vec!["Hannes Kuchelmeister"]) + .designers(vec!["Hannes Kuchelmeister"]) + .build() + } + + fn init( + _: Self::Init, + root: &Self::Root, + _sender: ComponentSender, + ) -> ComponentParts { + let model = Self {}; + + let widgets = root.clone(); + widgets.set_hide_on_close(true); + ComponentParts { model, widgets } + } + + fn update_view(&self, dialog: &mut Self::Widgets, _sender: ComponentSender) { + dialog.present(); + } +} + diff --git a/src/modals/mod.rs b/src/modals/mod.rs new file mode 100644 index 0000000..ced7521 --- /dev/null +++ b/src/modals/mod.rs @@ -0,0 +1 @@ +pub mod about; diff --git a/src/setup.rs b/src/setup.rs new file mode 100644 index 0000000..2bff9a2 --- /dev/null +++ b/src/setup.rs @@ -0,0 +1,39 @@ +use relm4::gtk; + +use gettextrs::{gettext, LocaleCategory}; +use gtk::{gio, glib}; + +use crate::config::{APP_ID, GETTEXT_PACKAGE, LOCALEDIR, RESOURCES_FILE}; + +pub fn setup() { + // Initialize GTK + gtk::init().unwrap(); + + setup_gettext(); + + glib::set_application_name(&gettext("Toolbox Tuner")); + + let res = gio::Resource::load(RESOURCES_FILE).expect("Could not load gresource file"); + gio::resources_register(&res); + + setup_css(&res); + + gtk::Window::set_default_icon_name(APP_ID); +} + +fn setup_gettext() { + // Prepare i18n + gettextrs::setlocale(LocaleCategory::LcAll, ""); + gettextrs::bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR).expect("Unable to bind the text domain"); + gettextrs::textdomain(GETTEXT_PACKAGE).expect("Unable to switch to the text domain"); +} + +fn setup_css(res: &gio::Resource) { + let data = res + .lookup_data( + "/org/kuchelmeister/ToolboxTuner/style.css", + gio::ResourceLookupFlags::NONE, + ) + .unwrap(); + relm4::set_global_css(&glib::GString::from_utf8_checked(data.to_vec()).unwrap()); +} diff --git a/src/ui.rs b/src/ui.rs deleted file mode 100644 index d47ef01..0000000 --- a/src/ui.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod app; -pub mod components; -pub mod ui_strings; diff --git a/src/ui/app.rs b/src/ui/app.rs deleted file mode 100644 index caa508a..0000000 --- a/src/ui/app.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub mod messages; -pub mod model; -pub mod toolbox_list; -pub mod update; -pub mod widgets; -pub mod workers; diff --git a/src/ui/app/messages.rs b/src/ui/app/messages.rs deleted file mode 100644 index cc23db8..0000000 --- a/src/ui/app/messages.rs +++ /dev/null @@ -1,12 +0,0 @@ -use relm4::factory::DynamicIndex; - -use crate::util::toolbx::ToolbxContainer; - -use super::model::ToolbxEntry; - -pub enum AppMsg { - ToolbxListUpdate(Vec), - ToolbxContainerToggleStartStop(DynamicIndex), - OpenToolbxTerminal(DynamicIndex), - ToolbxContainerChanged(DynamicIndex, ToolbxEntry), -} diff --git a/src/ui/app/model.rs b/src/ui/app/model.rs deleted file mode 100644 index 9468c33..0000000 --- a/src/ui/app/model.rs +++ /dev/null @@ -1,65 +0,0 @@ -use relm4::{factory::FactoryVecDeque, Model}; - -use crate::{ui::components::AppComponents, util::toolbx::ToolbxContainer}; - -use super::{messages::AppMsg, widgets::AppWidgets}; - -#[derive(Debug, Clone)] -pub struct ToolbxEntry { - pub toolbx_container: ToolbxContainer, - pub changing_status: bool, - // TODO: settings -} - -impl ToolbxEntry { - pub fn update_container(&mut self, container: ToolbxContainer) { - std::mem::replace::(&mut self.toolbx_container, container); - } - pub fn update_entry(&mut self, container: ToolbxEntry) { - std::mem::replace::( - &mut self.toolbx_container, - container.toolbx_container, - ); - self.changing_status = container.changing_status; - } -} - -pub struct AppModel { - pub toolboxes: FactoryVecDeque, -} - -impl Model for AppModel { - type Msg = AppMsg; - type Widgets = AppWidgets; - type Components = AppComponents; -} - -impl AppModel { - pub fn update_toolbxes(&mut self, toolbox_iter: I) - where - I: Iterator, - { - // Update each toolbx entry if there were changes to it - // TODO: deal with the removal of toolboxes - for tbx_update in toolbox_iter { - println!("name: {}", tbx_update.name); - let mut exists = false; - for (index, tbx_entry) in self.toolboxes.iter().enumerate() { - if tbx_update.name == tbx_entry.toolbx_container.name { - self.toolboxes - .get_mut(index) - .map(|x| x.update_container(tbx_update.clone())); - exists = true; - break; - } - } - if !exists { - println!("{}", tbx_update.name); - self.toolboxes.push_back(ToolbxEntry { - toolbx_container: tbx_update, - changing_status: false, - }) - } - } - } -} diff --git a/src/ui/app/toolbox_list.rs b/src/ui/app/toolbox_list.rs deleted file mode 100644 index 63f8b03..0000000 --- a/src/ui/app/toolbox_list.rs +++ /dev/null @@ -1,165 +0,0 @@ -use relm4::{ - adw::{ - self, - prelude::{BoxExt, ButtonExt, WidgetExt}, - traits::{ActionRowExt, PreferencesRowExt}, - }, - factory::{DynamicIndex, FactoryPrototype, FactoryVecDeque}, - gtk, send, view, Sender, -}; - -use crate::{ - ui::ui_strings::{ - APP_ICON, APP_TOOLTIP, SETTINGS_ICON, SETTINGS_TOOLTIP, SHUTDOWN_ICON, SHUTDOWN_TOOLTIP, - START_ICON, START_TOOLTIP, TERMINAL_ICON, TERMINAL_TOOLTIP, UPDATE_ICON, UPDATE_TOOLTIP, - }, - util::toolbx::ToolbxStatus, -}; - -use super::{messages::AppMsg, model::ToolbxEntry}; - -#[derive(Debug)] -pub struct FactoryWidgets { - pub action_row: adw::ActionRow, - status_button: gtk::Button, - status_spinner: gtk::Spinner, -} - -impl FactoryPrototype for ToolbxEntry { - type Factory = FactoryVecDeque; - type Widgets = FactoryWidgets; - type Root = adw::ActionRow; - type View = gtk::ListBox; - type Msg = AppMsg; - - fn init_view(&self, key: &DynamicIndex, sender: Sender) -> Self::Widgets { - let index_terminal = key.clone(); - let index_settings = key.clone(); - - view! { - suffix_box = >k::Box{ - append = >k::AspectFrame{ - set_ratio: 1.0, - set_child = Some(>k::Button::from_icon_name(TERMINAL_ICON)) { - set_margin_start: 10, - set_margin_top: 10, - set_margin_bottom: 10, - set_tooltip_text: Some(TERMINAL_TOOLTIP), - set_css_classes: &["flat"], - connect_clicked(sender) => move |btn| { - send!(sender, AppMsg::OpenToolbxTerminal(index_terminal.clone())); - }, - } - }, - } - }; - let mut status_button_tooltip = START_TOOLTIP; - let mut status_button_icon = START_ICON; - - match self.toolbx_container.status { - ToolbxStatus::Running => { - status_button_tooltip = SHUTDOWN_TOOLTIP; - status_button_icon = SHUTDOWN_ICON; - } - _ => { - status_button_tooltip = START_TOOLTIP; - status_button_icon = START_ICON; - } - } - - let subtitle = format!( - "created {}\n{}", - self.toolbx_container.created, self.toolbx_container.image - ); - - let index = key.clone(); - - view! { - status_spinner = >k::Spinner { - set_margin_top: 10, - set_margin_bottom: 10, - set_tooltip_text: Some(status_button_tooltip), - set_css_classes: &["circular"], - - } - }; - //status_spinner.start(); - - view! { - status_button = >k::Button::from_icon_name(status_button_icon) { - set_margin_top: 10, - set_margin_bottom: 10, - set_tooltip_text: Some(status_button_tooltip), - set_css_classes: &["circular"], - connect_clicked(sender) => move |btn| { - // Disable button - btn.set_sensitive(false); - send!(sender, AppMsg::ToolbxContainerToggleStartStop(index.clone())); - }, - } - }; - - view! { - action_row = &adw::ActionRow { - set_title: &self.toolbx_container.name, - set_subtitle: subtitle.as_str(), - add_prefix = >k::Box { - append = >k::AspectFrame{ - set_ratio: 1.0, - set_child: Some(&status_button), - } - }, - add_suffix: &suffix_box, - } - - }; - FactoryWidgets { - action_row, - status_button, - status_spinner, - } - } - - fn view( - &self, - key: &>::Key, - widgets: &Self::Widgets, - ) { - println!("updated {}", key.current_index()); - - // fixme: IDEALY this is would be done with message handling and only if the request actually is done - - if self.changing_status { - widgets.status_button.set_sensitive(false); - widgets - .status_button - .set_child(Some(&widgets.status_spinner)); - widgets.status_spinner.start(); - } else { - match self.toolbx_container.status { - ToolbxStatus::Running => { - widgets.status_button.set_icon_name(SHUTDOWN_ICON); - widgets - .status_button - .set_tooltip_text(Some(SHUTDOWN_TOOLTIP)); - } - _ => { - widgets.status_button.set_icon_name(START_ICON); - widgets.status_button.set_tooltip_text(Some(START_TOOLTIP)); - } - } - widgets.status_button.set_sensitive(true); - widgets.status_spinner.stop(); - } - } - - fn root_widget(widgets: &Self::Widgets) -> &Self::Root { - &widgets.action_row - } - - fn position( - &self, - key: &>::Key, - ) -> >::Position { - } -} diff --git a/src/ui/app/update.rs b/src/ui/app/update.rs deleted file mode 100644 index 6e12c80..0000000 --- a/src/ui/app/update.rs +++ /dev/null @@ -1,72 +0,0 @@ -use std::process::Command; - -use relm4::{AppUpdate, Sender}; - -use crate::{ui::components::AppComponents, util::toolbx::ToolbxStatus}; - -use super::{messages::AppMsg, model::AppModel, workers::AsyncHandlerMsg}; - -impl AppUpdate for AppModel { - fn update(&mut self, msg: AppMsg, components: &AppComponents, _sender: Sender) -> bool { - match msg { - AppMsg::ToolbxContainerToggleStartStop(index) => { - if let Some(toolbx_container) = self.toolboxes.get_mut(index.current_index()) { - match toolbx_container.toolbx_container.status { - ToolbxStatus::Exited | ToolbxStatus::Configured | ToolbxStatus::Created => { - toolbx_container.changing_status = true; - components - .async_handler - .sender() - .blocking_send(AsyncHandlerMsg::StartToolbx( - index, - toolbx_container.clone(), - )) - .expect("Receiver dropped"); - } - ToolbxStatus::Running => { - toolbx_container.changing_status = true; - components - .async_handler - .sender() - .blocking_send(AsyncHandlerMsg::StopToolbx( - index, - toolbx_container.clone(), - )) - .expect("Receiver dropped"); - } - } - // TODO: tell button to reactivate somehow - } - } - AppMsg::ToolbxContainerChanged(index, container) => { - if let Some(toolbx_container) = self.toolboxes.get_mut(index.current_index()) { - toolbx_container.update_entry(container); - } - } - AppMsg::ToolbxListUpdate(tbx_vec) => { - println!("Updating Toolbox List"); - self.update_toolbxes(tbx_vec.into_iter()); - } - - AppMsg::OpenToolbxTerminal(index) => { - if let Some(toolbx_container) = self.toolboxes.get_mut(index.current_index()) { - // TODO: support many terminals and check which are installed - let output = Command::new("flatpak-spawn") - .arg("--host") - .arg("gnome-terminal") //Command::new("gnome-terminal") - .arg("--") - .arg("toolbox") - .arg("enter") - .arg(toolbx_container.toolbx_container.name.clone()) - .output(); - - println!("{:?}", output); - - // TODO: update status on worker and add refresh spinner in the meantime - toolbx_container.toolbx_container.update_status(); - } - } - } - true - } -} diff --git a/src/ui/app/widgets.rs b/src/ui/app/widgets.rs deleted file mode 100644 index 6cc42fb..0000000 --- a/src/ui/app/widgets.rs +++ /dev/null @@ -1,42 +0,0 @@ -use relm4::{ - adw::{ - self, - prelude::{BoxExt, GtkWindowExt, OrientableExt, WidgetExt}, - traits::AdwApplicationWindowExt, - }, - gtk::{self, Align, PolicyType, SelectionMode}, - WidgetPlus, Widgets, -}; - -use super::model::AppModel; - -#[relm4::widget(pub)] -impl Widgets for AppWidgets { - view! { - main_window = adw::ApplicationWindow { - set_default_width: 800, - set_default_height: 600, - set_content : main_box = Some(>k::Box) { - set_orientation: gtk::Orientation::Vertical, - append = &adw::HeaderBar { - set_title_widget = Some(>k::Label) { - set_label: "Toolbox Tuner", - } - }, - - append = >k::ScrolledWindow { - set_hexpand: true, - set_vexpand: true, - set_hscrollbar_policy: PolicyType::Never, - set_child = Some(>k::ListBox) { - set_valign: Align::Start, - set_selection_mode: SelectionMode::None, - set_margin_all: 30, - set_css_classes: &["boxed-list"], - factory!(model.toolboxes) - } - } - } - } - } -} diff --git a/src/ui/app/workers.rs b/src/ui/app/workers.rs deleted file mode 100644 index b48e4fd..0000000 --- a/src/ui/app/workers.rs +++ /dev/null @@ -1,83 +0,0 @@ -use std::time::Duration; - -use relm4::factory::DynamicIndex; -use relm4::{send, MessageHandler, Sender}; -use tokio::runtime::{Builder, Runtime}; -use tokio::sync::mpsc::{channel, Sender as TokioSender}; - -use crate::util::toolbx::ToolbxContainer; - -use super::{ - messages::AppMsg, - model::{AppModel, ToolbxEntry}, -}; - -// Code adapted from https://relm4.org/book/stable/message_handler.html -pub struct AsyncHandler { - _rt: Runtime, - sender: TokioSender, -} - -#[derive(Debug)] -pub enum AsyncHandlerMsg { - StopToolbx(DynamicIndex, ToolbxEntry), - StartToolbx(DynamicIndex, ToolbxEntry), - UpdateToolbxes, -} - -impl MessageHandler for AsyncHandler { - type Msg = AsyncHandlerMsg; - type Sender = TokioSender; - - fn init(_parent_model: &AppModel, parent_sender: Sender) -> Self { - let (sender, mut rx) = channel::(10); - - let rt = Builder::new_multi_thread() - .worker_threads(8) - .enable_time() - .build() - .unwrap(); - - rt.spawn(async move { - while let Some(msg) = rx.recv().await { - let parent_sender = parent_sender.clone(); - tokio::spawn(async move { - match msg { - AsyncHandlerMsg::UpdateToolbxes => { - let toolboxes = ToolbxContainer::get_toolboxes(); - send! {parent_sender, AppMsg::ToolbxListUpdate(toolboxes)}; - } - AsyncHandlerMsg::StopToolbx(index, mut tbx) => { - tbx.toolbx_container.stop(); - tbx.changing_status = false; - send! {parent_sender, AppMsg::ToolbxContainerChanged(index, tbx)}; - } - AsyncHandlerMsg::StartToolbx(index, mut tbx) => { - tbx.toolbx_container.start(); - tbx.changing_status = false; - send! {parent_sender, AppMsg::ToolbxContainerChanged(index, tbx)}; - } - } - }); - } - }); - - let _sender = sender.clone(); - rt.spawn(async move { - loop { - _sender.send(AsyncHandlerMsg::UpdateToolbxes).await; - tokio::time::sleep(Duration::from_secs(10)).await; - } - }); - - AsyncHandler { _rt: rt, sender } - } - - fn send(&self, msg: Self::Msg) { - self.sender.blocking_send(msg).unwrap(); - } - - fn sender(&self) -> Self::Sender { - self.sender.clone() - } -} diff --git a/src/ui/components.rs b/src/ui/components.rs deleted file mode 100644 index 579706b..0000000 --- a/src/ui/components.rs +++ /dev/null @@ -1,11 +0,0 @@ -use relm4::RelmComponent; -use relm4::RelmMsgHandler; -use relm4::Sender; - -use super::app::model::AppModel; -use super::app::workers::AsyncHandler; - -#[derive(relm4::Components)] -pub struct AppComponents { - pub async_handler: RelmMsgHandler, -} diff --git a/src/ui/ui_strings.rs b/src/ui/ui_strings.rs deleted file mode 100644 index d98f952..0000000 --- a/src/ui/ui_strings.rs +++ /dev/null @@ -1,20 +0,0 @@ -pub const START_ICON: &str = r#"media-playback-start-symbolic"#; -pub const START_TOOLTIP: &str = r#"Start toolbox"#; - -pub const SHUTDOWN_ICON: &str = r#"system-shutdown-symbolic"#; -pub const SHUTDOWN_TOOLTIP: &str = r#"Stop toolbox"#; - -pub const UPDATE_ICON: &str = r#"software-update-available-symbolic"#; -pub const UPDATE_TOOLTIP: &str = r#"Update all applications inside of the toolbox"#; - -pub const APP_ICON: &str = r#"view-grid-symbolic"#; -pub const APP_TOOLTIP: &str = r#"Select applications to showup in the application menu"#; - -pub const TERMINAL_ICON: &str = r#"utilities-terminal-symbolic"#; -pub const TERMINAL_TOOLTIP: &str = r#"Open terminal inside of toolbox"#; - -pub const SETTINGS_ICON: &str = r#"applications-system-symbolic"#; -pub const SETTINGS_TOOLTIP: &str = r#"Open toolbox settings"#; - -pub const FOLDER_PICKER_ICON: &str = r#"folder-open-symbolic"#; -pub const FOLDER_PICKER_TOOLTIP: &str = r#"Select folder dialogue"#; diff --git a/src/util.rs b/src/util.rs deleted file mode 100644 index 45cefee..0000000 --- a/src/util.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod toolbx; diff --git a/src/util/toolbx.rs b/src/util/toolbx.rs deleted file mode 100644 index bb0a3f3..0000000 --- a/src/util/toolbx.rs +++ /dev/null @@ -1,427 +0,0 @@ -use serde::{Deserialize, Serialize}; -use std::{fmt::Display, iter::zip, process::Command, str::FromStr, string::ParseError, sync::Arc}; - -#[derive(Debug, PartialEq)] -pub enum ToolbxError { - ParseStatusError(String), - JSONSerializationError(String), - CommandExecutionError(String), - CommandUnsuccessfulError(String), -} - -impl std::error::Error for ToolbxError {} - -impl Display for ToolbxError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - ToolbxError::ParseStatusError(parse_error) => write!(f, "{}", parse_error), - ToolbxError::CommandExecutionError(command_exec_error) => { - write!(f, "{}", command_exec_error) - } - ToolbxError::JSONSerializationError(msg) => { - write!(f, "{}", msg) - } - ToolbxError::CommandUnsuccessfulError(command_unsuc_error) => { - write!(f, "{}", command_unsuc_error) - } - } - } -} - -#[derive(Debug, PartialEq, Clone)] -pub enum ToolbxStatus { - Running, - Configured, - Created, - Exited, -} - -impl Default for ToolbxStatus { - fn default() -> Self { - ToolbxStatus::Configured - } -} - -impl FromStr for ToolbxStatus { - type Err = ToolbxError; - - fn from_str(s: &str) -> Result { - match s { - "running" => Ok(ToolbxStatus::Running), - "configured" => Ok(ToolbxStatus::Configured), - "created" => Ok(ToolbxStatus::Created), - "exited" => Ok(ToolbxStatus::Exited), - s => Err(ToolbxError::ParseStatusError(format!( - "'{}' is not a valid toolbx status.", - s - ))), - } - } -} - -#[derive(Debug, PartialEq, Default, Clone)] -pub struct ToolbxContainer { - pub id: String, - pub name: String, - pub created: String, - pub status: ToolbxStatus, - pub image: String, -} - -pub type PodmanInspectArray = Vec; - -#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct PodmanInspectInfo { - #[serde(rename = "Id")] - pub id: String, - #[serde(rename = "Created")] - pub created: String, - #[serde(rename = "State")] - pub state: PodManInspectState, - #[serde(rename = "Image")] - pub image: String, - #[serde(rename = "ImageName")] - pub image_name: String, - #[serde(rename = "Name")] - pub name: String, -} - -#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct PodManInspectState { - #[serde(rename = "Status")] - pub status: String, -} - -pub enum ToolboxCreateParameter { - None, - Distro(String), - Image(String), - Release(String), -} - -impl ToolbxContainer { - pub fn new(name: String) -> ToolbxContainer { - ToolbxContainer { - name: name, - ..Default::default() - } - } - - pub fn create(name: String, parameter: ToolboxCreateParameter) { - todo!("Implement actual functionality to create toolbox via commandline") - } - - pub fn get_toolboxes() -> Vec { - let output = run_cmd_toolbx_list_containers(); - println!("{}", output); - parse_cmd_list_containers(output.as_str()) - } - - fn parse_status(output: &str) -> Result { - let result: Result = serde_json::from_str(output); - match result { - Ok(inspect_vec) => match inspect_vec.first() { - Some(info) => Ok(info.clone()), - None => Err(ToolbxError::JSONSerializationError( - "Inspect command returned empty vector.".to_string(), - )), - }, - Err(e) => Err(ToolbxError::JSONSerializationError(e.to_string())), - } - } - - pub fn update_status(&mut self) -> Result<(), ToolbxError> { - let output = Command::new("flatpak-spawn") - .arg("--host") - .arg("podman") - .arg("container") - .arg("inspect") - .arg(self.name.clone()) - .output() - .expect("Failed to execute command"); - - let output = String::from_utf8_lossy(&output.stdout).to_string(); - let inspect_result = ToolbxContainer::parse_status(output.as_str())?; - self.status = ToolbxStatus::from_str(inspect_result.state.status.as_str())?; - Ok(()) - } - - pub fn stop(&mut self) -> Result<(), ToolbxError> { - let output = Command::new("flatpak-spawn") - .arg("--host") //Command::new("podman") - .arg("podman") - .arg("stop") - .arg(self.name.clone()) - .output(); - - if output.is_err() { - return Err(ToolbxError::CommandExecutionError( - output.unwrap_err().to_string(), - )); - } - let output = output.unwrap(); - - // Success: Output { status: ExitStatus(unix_wait_status(0)), stdout: "tbx_name\n", stderr: "" } - //Fail: - // Output { - // status: ExitStatus(unix_wait_status(32000)), - // stdout: "", - // stderr: "Error: no container with name or ID \"tbx_name\" found: no such container\n" - // } - - if output.status.code() == Some(0) { - self.status = ToolbxStatus::Exited; - Ok(()) - } else { - Err(ToolbxError::CommandUnsuccessfulError( - String::from_utf8_lossy(&output.stderr).into_owned(), - )) - } - } - - pub fn start(&mut self) -> Result<(), ToolbxError> { - let output = Command::new("flatpak-spawn") - .arg("--host") //Command::new("podman") - .arg("podman") - .arg("start") - .arg(self.name.clone()) - .output(); - - if output.is_err() { - return Err(ToolbxError::CommandExecutionError( - output.unwrap_err().to_string(), - )); - } - let output = output.unwrap(); - - // Success: status: Output { ExitStatus(unix_wait_status(0)), stdout: "tbx_name\n", stderr: "" } - // Fail: status: - // Output { - // status: ExitStatus(unix_wait_status(32000)), - // stdout: "", - // stderr: "Error: no container with name or ID \"tbx_name\" found: no such container\n" - // } - - if output.status.code() == Some(0) { - self.status = ToolbxStatus::Running; - Ok(()) - } else { - Err(ToolbxError::CommandUnsuccessfulError( - String::from_utf8_lossy(&output.stderr).into_owned(), - )) - } - } -} - -#[test] -fn test_start_1non_existing_container() { - // TODO: create container that exists based on simple image - // run command - // delete container - //let tbx = ToolbxContainer{created: "".to_string(), id: "".to_string(), name: "latex".to_string(), image: "".to_string(), status: ToolbxStatus::Exited}; - - //tbx.stop(); -} - -#[test] -fn test_inspect_parsing() { - let podman_inspect = concat!( - "[{", - "\"Id\": \"ae05203091ab4cdf047a9aeba6af8a7bed8105f7f59d09a35d2b64c837ecac0d\",", - "\"Created\": \"2021-12-10T20:51:43.140418098+01:00\",", - "\"State\": {", - "\"Status\": \"running\"", - "},", - "\"Image\": \"ab8bc106d4a710a7a27c538762864610467b3559f80b413d30e0a1bfcfe272a5\",", - "\"ImageName\": \"registry.fedoraproject.org/fedora-toolbox:35\",", - "\"Name\": \"rust\"", - "}]" - ); - let inspect_info = ToolbxContainer::parse_status(podman_inspect).unwrap(); - assert_eq!("running", inspect_info.state.status); -} - -#[test] -fn test_start_non_existing_container() { - let name = "zy2lM6BdZoTnKHaVPkUJ".to_string(); - let mut tbx = ToolbxContainer { - created: "".to_string(), - id: "".to_string(), - name: name.clone(), - image: "".to_string(), - status: ToolbxStatus::Exited, - }; - - assert_eq!( - Err(ToolbxError::CommandUnsuccessfulError(format!( - "Error: no container with name or ID \"{}\" found: no such container\n", - name - ))), - tbx.start() - ); -} - -pub fn run_cmd_toolbx_list_containers() -> String { - let output = Command::new("flatpak-spawn") - .arg("--host") - .arg("toolbox") - .arg("list") - .arg("--containers") - .output() - .expect("Failed to execute command"); - - println!("{:?}", String::from_utf8_lossy(&output.stdout).to_string()); - - String::from_utf8_lossy(&output.stdout).to_string() -} - -#[test] -#[ignore] -fn test_cmd_list_containers() { - // This requires toolbx to be installed - let toolbox_cmd_container_header = - "CONTAINER ID CONTAINER NAME CREATED STATUS IMAGE NAME"; - assert!(run_cmd_toolbx_list_containers().starts_with(toolbox_cmd_container_header)); -} - -fn tokenize_line_list_containers(line: &str) -> Vec { - let mut tokens = Vec::::new(); - let mut current_token = Vec::::new(); - - let mut whitespace_section = false; - - let mut iter = line.chars().peekable(); - while let Some(&c) = iter.peek() { - match (whitespace_section, c) { - (false, ' ') => { - iter.next(); - if Some(' ') == iter.peek().map(|x| x.clone()) { - whitespace_section = true; - } else { - current_token.push(c); - } - } - (true, ' ') => { - iter.next(); - } - (true, c) => { - whitespace_section = false; - tokens.push(current_token.into_iter().collect()); - current_token = Vec::new(); - current_token.push(c); - iter.next(); - } - (false, c) => { - current_token.push(c); - iter.next(); - } - } - } - tokens.push(current_token.into_iter().collect()); - - tokens -} - -#[test] -fn test_tokenize_line_list_containers() { - let toolbox_cmd_container_header = "ae05203091ab rust 4 months ago \ - running registry.fedoraproject.org/fedora-toolbox:35"; - - let target = vec![ - "ae05203091ab", - "rust", - "4 months ago", - "running", - "registry.fedoraproject.org/fedora-toolbox:35", - ]; - let result = tokenize_line_list_containers(toolbox_cmd_container_header); - assert_eq!(target, result); -} - -fn parse_line_list_containers(line: &str) -> Result { - let tokens = tokenize_line_list_containers(line); - if tokens.len() != 5 { - panic! {"Expected 5 tokens found {} in {:?}", tokens.len(), tokens}; - } - Ok(ToolbxContainer { - id: tokens[0].clone(), - name: tokens[1].clone(), - created: tokens[2].clone(), - status: ToolbxStatus::from_str(&tokens[3])?, - image: tokens[4].clone(), - }) -} - -#[test] -fn test_parse_line_list_containers() { - let toolbox_cmd_container_header = "ae05203091ab rust 4 months ago \ - running registry.fedoraproject.org/fedora-toolbox:35"; - - let target = ToolbxContainer { - id: "ae05203091ab".to_string(), - name: "rust".to_string(), - created: "4 months ago".to_string(), - status: ToolbxStatus::Running, - image: "registry.fedoraproject.org/fedora-toolbox:35".to_string(), - }; - let result = parse_line_list_containers(toolbox_cmd_container_header); - assert_eq!(target, result.unwrap()); -} - -fn parse_cmd_list_containers(output: &str) -> Vec { - let lines = output.trim().split("\n").skip(1); - println!("{:?}", lines); - lines.map(parse_line_list_containers).flatten().collect() -} - -#[test] -fn test_parse_cmd_list_containers() { - // This requires toolbx to be installed - let toolbox_cmd_container_header = concat!( - "CONTAINER ID CONTAINER NAME CREATED STATUS IMAGE NAME\n", - "cee1002b5f0b fedora-toolbox-35 2 months ago exited registry.fedoraproject.org/fedora-toolbox:35\n", - "9b611313bf65 latex 4 months ago configured registry.fedoraproject.org/fedora-toolbox:35\n", - "1235203091ab website 4 months ago created registry.fedoraproject.org/fedora-toolbox:35\n", - "ae05203091ab rust 4 months ago running registry.fedoraproject.org/fedora-toolbox:35\n" - ); - - let desired_result = vec![ - ToolbxContainer { - id: "cee1002b5f0b".to_string(), - name: "fedora-toolbox-35".to_string(), - created: "2 months ago".to_string(), - status: ToolbxStatus::Exited, - image: "registry.fedoraproject.org/fedora-toolbox:35".to_string(), - }, - ToolbxContainer { - id: "9b611313bf65".to_string(), - name: "latex".to_string(), - created: "4 months ago".to_string(), - status: ToolbxStatus::Configured, - image: "registry.fedoraproject.org/fedora-toolbox:35".to_string(), - }, - ToolbxContainer { - id: "1235203091ab".to_string(), - name: "website".to_string(), - created: "4 months ago".to_string(), - status: ToolbxStatus::Created, - image: "registry.fedoraproject.org/fedora-toolbox:35".to_string(), - }, - ToolbxContainer { - id: "ae05203091ab".to_string(), - name: "rust".to_string(), - created: "4 months ago".to_string(), - status: ToolbxStatus::Running, - image: "registry.fedoraproject.org/fedora-toolbox:35".to_string(), - }, - ]; - - for (result, desired) in zip( - parse_cmd_list_containers(toolbox_cmd_container_header).iter(), - desired_result.iter(), - ) { - assert_eq!(result, desired) - } -}