From 3cea94b72dbfdd2077a59fc52a7460e200b6061e Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Fri, 18 Sep 2026 15:13:01 +0800 Subject: refactor: qml_plugin --- qml_plugin/Cargo.lock | 555 ++++++++++++++++++++++++++++- qml_plugin/Cargo.toml | 2 + qml_plugin/build.rs | 14 +- qml_plugin/rustfmt.toml | 8 +- qml_plugin/src/launcher.rs | 5 - qml_plugin/src/launcher/duckduckgo.rs | 88 ----- qml_plugin/src/launcher/mathcalc.rs | 106 ------ qml_plugin/src/launcher/smartcalc.rs | 123 ------- qml_plugin/src/lib.rs | 3 +- qml_plugin/src/qml_interface.rs | 8 + qml_plugin/src/qml_interface/duckduckgo.rs | 88 +++++ qml_plugin/src/qml_interface/mathcalc.rs | 106 ++++++ qml_plugin/src/qml_interface/network.rs | 55 +++ qml_plugin/src/qml_interface/smartcalc.rs | 123 +++++++ qml_plugin/src/services.rs | 1 + qml_plugin/src/services/network.rs | 66 ++++ qml_plugin/src/web/duckduckgo.rs | 78 ++-- 17 files changed, 1055 insertions(+), 374 deletions(-) delete mode 100644 qml_plugin/src/launcher.rs delete mode 100644 qml_plugin/src/launcher/duckduckgo.rs delete mode 100644 qml_plugin/src/launcher/mathcalc.rs delete mode 100644 qml_plugin/src/launcher/smartcalc.rs create mode 100644 qml_plugin/src/qml_interface.rs create mode 100644 qml_plugin/src/qml_interface/duckduckgo.rs create mode 100644 qml_plugin/src/qml_interface/mathcalc.rs create mode 100644 qml_plugin/src/qml_interface/network.rs create mode 100644 qml_plugin/src/qml_interface/smartcalc.rs create mode 100644 qml_plugin/src/services.rs create mode 100644 qml_plugin/src/services/network.rs (limited to 'qml_plugin') diff --git a/qml_plugin/Cargo.lock b/qml_plugin/Cargo.lock index 240f109..bba7909 100644 --- a/qml_plugin/Cargo.lock +++ b/qml_plugin/Cargo.lock @@ -32,6 +32,126 @@ version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "pin-project-lite", + "slab", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-lock" +version = "3.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-process" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "async-signal" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52b5aaafa020cf5053a01f2a60e8ff5dccf550f0f77ec54a4e47285ac2bab485" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix", + "signal-hook-registry", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + [[package]] name = "async-trait" version = "0.1.91" @@ -96,6 +216,19 @@ version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" +[[package]] +name = "blocking" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a70e4329df6cb94385eed412ec92375c3cdd8a6e502493d1229b6414e4036dfa" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + [[package]] name = "bumpalo" version = "3.20.3" @@ -251,6 +384,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "convert_case" version = "0.6.0" @@ -333,6 +475,12 @@ dependencies = [ "libc", ] +[[package]] +name = "crossbeam-utils" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6" + [[package]] name = "cssparser" version = "0.37.0" @@ -607,12 +755,69 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "endi" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" + +[[package]] +name = "enumflags2" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "event-listener" +version = "5.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2" +dependencies = [ + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + [[package]] name = "fastrand" version = "2.5.0" @@ -679,6 +884,25 @@ version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7" +[[package]] +name = "futures-io" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed" + +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + [[package]] name = "futures-sink" version = "0.3.33" @@ -774,6 +998,18 @@ version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +[[package]] +name = "hermit-abi" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17592d60ebacc7d5e169f4663c5f84f9161cc90328abcfe8456f41e4dfcb284" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "html5ever" version = "0.39.0" @@ -1397,7 +1633,7 @@ dependencies = [ "jni-sys", "log", "simd_cesu8", - "thiserror 2.0.19", + "thiserror 2.0.20", "walkdir", "windows-link", ] @@ -1494,6 +1730,12 @@ dependencies = [ "cc", ] +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + [[package]] name = "litemap" version = "0.8.2" @@ -1544,6 +1786,15 @@ version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + [[package]] name = "mime" version = "0.3.17" @@ -1624,6 +1875,16 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + [[package]] name = "papaya" version = "0.2.4" @@ -1634,6 +1895,12 @@ dependencies = [ "seize", ] +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + [[package]] name = "parking_lot" version = "0.12.5" @@ -1740,12 +2007,37 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" +[[package]] +name = "piper" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + [[package]] name = "pkg-config" version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix", + "windows-sys 0.61.2", +] + [[package]] name = "potential_utf" version = "0.1.5" @@ -1769,6 +2061,15 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit", +] + [[package]] name = "proc-macro2" version = "1.0.107" @@ -1809,8 +2110,10 @@ dependencies = [ "serde", "serde_json", "smart-calculator", + "thiserror 2.0.20", "tokio", "unwrap-print", + "zbus", ] [[package]] @@ -1841,7 +2144,7 @@ dependencies = [ "rustc-hash", "rustls", "socket2", - "thiserror 2.0.19", + "thiserror 2.0.20", "tokio", "tracing", "web-time", @@ -1864,7 +2167,7 @@ dependencies = [ "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.19", + "thiserror 2.0.20", "tinyvec", "tracing", "web-time", @@ -2047,6 +2350,19 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + [[package]] name = "rustls" version = "0.23.42" @@ -2280,6 +2596,17 @@ dependencies = [ "zmij", ] +[[package]] +name = "serde_repr" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d3b1629de253c70a0508c3899572da79ca359fdab27c7920ff00406df418906" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -2307,6 +2634,16 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + [[package]] name = "simd_cesu8" version = "1.2.0" @@ -2359,7 +2696,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "thiserror 2.0.19", + "thiserror 2.0.20", ] [[package]] @@ -2483,6 +2820,19 @@ dependencies = [ "libc", ] +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.4.3", + "once_cell", + "rustix", + "windows-sys 0.61.2", +] + [[package]] name = "tendril" version = "0.5.1" @@ -2512,11 +2862,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.19" +version = "2.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" dependencies = [ - "thiserror-impl 2.0.19", + "thiserror-impl 2.0.20", ] [[package]] @@ -2532,9 +2882,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.19" +version = "2.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" dependencies = [ "proc-macro2", "quote", @@ -2607,8 +2957,10 @@ dependencies = [ "libc", "mio", "pin-project-lite", + "signal-hook-registry", "socket2", "tokio-macros", + "tracing", "windows-sys 0.61.2", ] @@ -2647,6 +2999,36 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.25.15+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1340ea94a5856333492c9064b02c778b191dd2c853778d9609debdcdfea3a614" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.1.3+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" +dependencies = [ + "winnow", +] + [[package]] name = "tower" version = "0.5.3" @@ -2699,9 +3081,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "tracing-core" version = "0.1.36" @@ -2717,6 +3111,17 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "uds_windows" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" +dependencies = [ + "memoffset", + "tempfile", + "windows-sys 0.61.2", +] + [[package]] name = "unicode-ident" version = "1.0.24" @@ -2783,6 +3188,17 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +[[package]] +name = "uuid" +version = "1.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ef6dac1e96601b4fb3acccccff2139741fcb757cb9a36089bf5be91cfb285ce" +dependencies = [ + "js-sys", + "serde_core", + "wasm-bindgen", +] + [[package]] name = "version_check" version = "0.9.5" @@ -3080,6 +3496,15 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "winnow" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" +dependencies = [ + "memchr", +] + [[package]] name = "write16" version = "1.0.0" @@ -3118,6 +3543,77 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zbus" +version = "5.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5db4be7c075cb421e4b7ee645541604239bd243ba7c357511f4ff3a74b555907" +dependencies = [ + "async-broadcast", + "async-executor", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "enumflags2", + "event-listener", + "futures-core", + "futures-lite", + "hex", + "libc", + "ordered-stream", + "rustix", + "serde", + "serde_repr", + "tokio", + "tracing", + "uds_windows", + "uuid", + "windows-sys 0.61.2", + "winnow", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "5.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2990635d09ade6df1868f72f8cac69a876a90981e8bd3c40b1be413f8dc88f40" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 3.0.3", + "zbus_names", + "zvariant", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "4.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8bf88b4a3ff53e883001e0e0115b297a9d53c31b9c1edd2bfdd853e3428624e" +dependencies = [ + "serde", + "winnow", + "zvariant", +] + +[[package]] +name = "zcheapstr" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1afec51604565183aeb5c54c20aeab286120d4e4460f7f76e3e8bb8c0d99473" +dependencies = [ + "serde", +] + [[package]] name = "zerofrom" version = "0.1.8" @@ -3185,3 +3681,44 @@ name = "zmij" version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" + +[[package]] +name = "zvariant" +version = "5.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1d34c27cc6cdd1f458427519dd6b8612f7b7e3f7b9a0b2355d041dda9869147" +dependencies = [ + "endi", + "enumflags2", + "serde", + "winnow", + "zcheapstr", + "zvariant_derive", + "zvariant_utils", +] + +[[package]] +name = "zvariant_derive" +version = "5.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "864155e69b4352db0c7f374917bf45d1e0c8d17659c8b3dbf9795f3673f8c497" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 3.0.3", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad0294361a320b694a328460dc73add56c306150f5cb6bfafc44446120008a3" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "syn 3.0.3", + "winnow", +] diff --git a/qml_plugin/Cargo.toml b/qml_plugin/Cargo.toml index f690c26..792f71d 100644 --- a/qml_plugin/Cargo.toml +++ b/qml_plugin/Cargo.toml @@ -17,8 +17,10 @@ reqwest = "0.13.4" serde = { version = "1.0.229", features = ["derive"] } serde_json = "1.0.151" smart-calculator = "1.0.3" +thiserror = "2.0.20" tokio = { version = "1.53.1", features = ["rt-multi-thread", "macros"] } unwrap-print = "0.2.0" +zbus = { version = "5.19.0", features = ["tokio"] } [build-dependencies] cxx-qt-build = "0.9.1" diff --git a/qml_plugin/build.rs b/qml_plugin/build.rs index 25e03ae..18e6fc4 100644 --- a/qml_plugin/build.rs +++ b/qml_plugin/build.rs @@ -1,19 +1,21 @@ +use std::fs; + use cxx_qt_build::{CxxQtBuilder, PluginType, QmlModule}; const NAME: &str = "core"; +const INTERFACE_DIR: &str = "src/qml_interface"; fn main() { let version_script = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("qml_plugin.version"); - println!("cargo:rustc-cdylib-link-arg=-Wl,--version-script={}", version_script.display()); + println!( + "cargo:rustc-cdylib-link-arg=-Wl,--version-script={}", + version_script.display() + ); CxxQtBuilder::new_qml_module(QmlModule::new(NAME).plugin_type(PluginType::Dynamic)) .qt_module("Qml") - .files([ - "src/launcher/smartcalc.rs", - "src/launcher/mathcalc.rs", - "src/launcher/duckduckgo.rs", - ]) + .files(fs::read_dir(INTERFACE_DIR).unwrap().map(|d| d.unwrap().path())) .build(); } diff --git a/qml_plugin/rustfmt.toml b/qml_plugin/rustfmt.toml index fd3f9c9..00e252f 100644 --- a/qml_plugin/rustfmt.toml +++ b/qml_plugin/rustfmt.toml @@ -1,12 +1,12 @@ # max_width = 104400000000 -use_small_heuristics = "Max" +use_small_heuristics = "Off" # chain_width = 0 -# fn_call_width = 0 -# attr_fn_like_width = 0 +fn_call_width = 0 +attr_fn_like_width = 0 # array_width = 0 struct_lit_width = 0 -# struct_variant_width = 0 +struct_variant_width = 0 # single_line_if_else_max_width = 0 wrap_comments = true diff --git a/qml_plugin/src/launcher.rs b/qml_plugin/src/launcher.rs deleted file mode 100644 index 180a756..0000000 --- a/qml_plugin/src/launcher.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod duckduckgo; -pub mod mathcalc; -pub mod smartcalc; - -// TODO: use background worker + mpsc diff --git a/qml_plugin/src/launcher/duckduckgo.rs b/qml_plugin/src/launcher/duckduckgo.rs deleted file mode 100644 index 0375cdf..0000000 --- a/qml_plugin/src/launcher/duckduckgo.rs +++ /dev/null @@ -1,88 +0,0 @@ -use cxx_qt::{CxxQtType, Threading}; -use cxx_qt_lib::QString; -use std::pin::Pin; -use unwrap_print::PrintableResult; - -use crate::{ExclusiveExecutor, web::duckduckgo}; - -#[cxx_qt::bridge] -mod qobject { - extern "C++" { - include!("cxx-qt-lib/qstring.h"); - type QString = cxx_qt_lib::QString; - } - - extern "RustQt" { - #[qobject] - #[qml_element] - #[qml_singleton] - #[qproperty(bool, ok)] - #[qproperty(QString, title)] - #[qproperty(QString, description_html)] - #[qproperty(QString, image)] - type DuckDuckGo = super::DuckDuckGoRs; - - #[qinvokable] - fn query(self: Pin<&mut DuckDuckGo>, input: QString); - - #[qinvokable] - fn reset(self: Pin<&mut DuckDuckGo>); - } - - impl cxx_qt::Threading for DuckDuckGo {} -} - -#[derive(Default)] -pub struct QmlDuckDuckGo { - pub title: QString, - pub description_html: QString, - pub image: QString, -} - -#[derive(Default)] -pub struct DuckDuckGoRs { - ok: bool, - title: QString, - description_html: QString, - image: QString, - - executor: ExclusiveExecutor, -} - -impl qobject::DuckDuckGo { - fn query(self: Pin<&mut Self>, input: QString) { - let qt_thread = self.qt_thread(); - self.rust_mut().executor.spawn(async move { - let qinput = input.to_string(); - let result: Result = - duckduckgo::query(&qinput).await.map(|r| r.into()); - // consider just unwrapping since this is in a separate thread and - // is already end of life anw - _ = qt_thread - .queue(move |mut qo| match result { - Ok(r) => { - if (r.title.to_lower() == input.to_lower() || r.title.is_empty()) - && r.description_html.is_empty() - && r.image.is_empty() - { - qo.as_mut().set_ok(false); - } else { - qo.as_mut().set_ok(true); - qo.as_mut().set_title(r.title); - qo.as_mut().set_description_html(r.description_html); - qo.as_mut().set_image(r.image); - } - } - Err(_) => qo.set_ok(false), - }) - .unwrap_print(); - }); - } - - fn reset(mut self: Pin<&mut Self>) { - self.as_mut().set_ok(false); - self.as_mut().set_title("".into()); - self.as_mut().set_description_html("".into()); - self.as_mut().set_image("".into()); - } -} diff --git a/qml_plugin/src/launcher/mathcalc.rs b/qml_plugin/src/launcher/mathcalc.rs deleted file mode 100644 index 601dc3b..0000000 --- a/qml_plugin/src/launcher/mathcalc.rs +++ /dev/null @@ -1,106 +0,0 @@ -use cxx_qt::{CxxQtType, Threading}; -use cxx_qt_lib::{QString, QVariant}; -use kalk::parser; -use std::{pin::Pin, sync::Arc}; -use tokio::sync::Mutex; -use unwrap_print::PrintableResult; - -use crate::ExclusiveExecutor; - -const DEFAULT_ANGLE_UNIT: &str = "deg"; - -#[cxx_qt::bridge] -mod qobject { - extern "C++" { - include!("cxx-qt-lib/qstring.h"); - include!("cxx-qt-lib/qvariant.h"); - type QString = cxx_qt_lib::QString; - type QVariant = cxx_qt_lib::QVariant; - } - - extern "RustQt" { - #[qobject] - #[qml_element] - #[qml_singleton] - #[qproperty(QVariant, result)] - type MathCalc = super::MathCalcRs; - - #[qinvokable] - fn query(self: Pin<&mut MathCalc>, input: QString); - - #[qinvokable] - fn reset(self: Pin<&mut MathCalc>); - - #[qinvokable] - fn reset_ctx(self: Pin<&mut MathCalc>); - - #[qinvokable] - fn reset_result(self: Pin<&mut MathCalc>); - } - - impl cxx_qt::Threading for MathCalc {} -} - -pub struct MathCalcRs { - result: QVariant, - ctx: Arc>, - - executor: ExclusiveExecutor, -} - -impl Default for MathCalcRs { - fn default() -> Self { - Self { - result: QVariant::default(), - ctx: Arc::new(Mutex::new(qobject::MathCalc::new_ctx())), - executor: ExclusiveExecutor::default(), - } - } -} - -impl qobject::MathCalc { - fn query(mut self: Pin<&mut Self>, input: QString) { - let qt_thread = self.qt_thread(); - let ctx = Arc::clone(&self.as_mut().rust_mut().ctx); - // TODO: consider moving to spawn_blocking - self.rust_mut().executor.spawn(async move { - let input = input.to_string(); - let result = parser::eval( - &mut *ctx.lock().await, - &input, - // TODO: move to const/config - 53, - ) - .map_or_default(|r| { - r.map_or_default(|r| { - let r: QString = r - // to display scientific notation properly - // other ones show both version without e or shows *10^_ - // and have a = prefix - // to_string_big will result in 1/2=5.0000000000000000e − 1 - .to_string() - .into(); - if r != input.into() { QVariant::from(&r) } else { QVariant::default() } - }) - }); - _ = qt_thread.queue(|mut qo| qo.as_mut().set_result(result)).unwrap_print(); - }); - } - - fn reset(mut self: Pin<&mut Self>) { - self.as_mut().reset_result(); - self.reset_ctx(); - } - - fn new_ctx() -> parser::Context { - parser::Context::default().set_angle_unit(DEFAULT_ANGLE_UNIT) - } - - fn reset_ctx(mut self: Pin<&mut Self>) { - self.as_mut().rust_mut().ctx = Arc::new(Mutex::new(Self::new_ctx())) - } - - fn reset_result(mut self: Pin<&mut Self>) { - self.as_mut().set_result(QVariant::default()) - } -} diff --git a/qml_plugin/src/launcher/smartcalc.rs b/qml_plugin/src/launcher/smartcalc.rs deleted file mode 100644 index 9b5f05a..0000000 --- a/qml_plugin/src/launcher/smartcalc.rs +++ /dev/null @@ -1,123 +0,0 @@ -use cxx_qt::{CxxQtType, Threading}; -use cxx_qt_lib::{QString, QVariant}; -use std::pin::Pin; -use unwrap_print::PrintableResult; - -use crate::ExclusiveExecutor; - -#[cxx_qt::bridge] -mod qobject { - extern "C++" { - include!("cxx-qt-lib/qstring.h"); - include!("cxx-qt-lib/qvariant.h"); - type QString = cxx_qt_lib::QString; - type QVariant = cxx_qt_lib::QVariant; - } - - extern "RustQt" { - #[qobject] - #[qml_element] - #[qml_singleton] - #[qproperty(QVariant, result)] - #[qproperty(ResultType, result_type)] - #[qproperty(QVariant, cached_query)] - type SmartCalc = super::SmartCalcRs; - - #[qinvokable] - fn query(self: Pin<&mut SmartCalc>, input: QString); - - #[qinvokable] - fn reset(self: Pin<&mut SmartCalc>); - - #[qinvokable] - fn reset_result(self: Pin<&mut SmartCalc>); - } - - impl cxx_qt::Threading for SmartCalc {} - - #[qenum(SmartCalc)] - pub enum ResultType { - Math, - Unit, - Currency, - Crypto, - Time, - Date, - Unset, - } -} - -impl Default for qobject::ResultType { - fn default() -> Self { - qobject::ResultType::Unset - } -} - -impl From<&smart_calculator::types::ResultType> for qobject::ResultType { - fn from(value: &smart_calculator::types::ResultType) -> Self { - match value { - smart_calculator::types::ResultType::Math => qobject::ResultType::Math, - smart_calculator::types::ResultType::Unit => qobject::ResultType::Unit, - smart_calculator::types::ResultType::Currency => qobject::ResultType::Currency, - smart_calculator::types::ResultType::Crypto => qobject::ResultType::Crypto, - smart_calculator::types::ResultType::Time => qobject::ResultType::Time, - smart_calculator::types::ResultType::Date => qobject::ResultType::Date, - } - } -} - -#[derive(Default)] -pub struct SmartCalcRs { - result: QVariant, - result_type: qobject::ResultType, - - cached_query: QVariant, - - executor: ExclusiveExecutor, -} - -impl qobject::SmartCalc { - fn query(mut self: Pin<&mut Self>, input: QString) { - if self.cached_query == (&input).into() { - return; - } - self.as_mut().set_cached_query((&input.clone()).into()); - let qt_thread = self.qt_thread(); - self.as_mut().rust_mut().executor.spawn(async move { - let result = smart_calculator::calculate(&input.to_string(), None).await; - _ = qt_thread - .queue(|mut qo| { - qo.as_mut().set_result_type(match &result { - Ok(value) => (&value.res_type).into(), - Err(_) => qobject::ResultType::Unset, - }); - qo.as_mut().set_result( - // TODO: do the calc outside of ts main qt ui render - // thread.(all *.rs) - match result { - Ok(value) => { - if value.formatted == value.input { - QVariant::default() - } else { - let result: QString = value.formatted.into(); - QVariant::from(&result) - } - } - Err(_) => QVariant::default(), - }, - ) - }) - .unwrap_print(); - }); - } - - fn reset(mut self: Pin<&mut Self>) { - self.as_mut().set_cached_query(QVariant::default()); - self.reset_result(); - } - - fn reset_result(mut self: Pin<&mut Self>) { - self.as_mut().set_result(QVariant::default()); - self.as_mut().set_result_type(qobject::ResultType::Unset); - } -} diff --git a/qml_plugin/src/lib.rs b/qml_plugin/src/lib.rs index 0f1411c..b00b8be 100644 --- a/qml_plugin/src/lib.rs +++ b/qml_plugin/src/lib.rs @@ -34,5 +34,6 @@ impl ExclusiveExecutor { } } -mod launcher; +mod qml_interface; +mod services; mod web; diff --git a/qml_plugin/src/qml_interface.rs b/qml_plugin/src/qml_interface.rs new file mode 100644 index 0000000..f93fa23 --- /dev/null +++ b/qml_plugin/src/qml_interface.rs @@ -0,0 +1,8 @@ +// TODO: use background worker + mpsc +/// Launchers +pub mod duckduckgo; +pub mod mathcalc; +pub mod smartcalc; + +/// Services +pub mod network; diff --git a/qml_plugin/src/qml_interface/duckduckgo.rs b/qml_plugin/src/qml_interface/duckduckgo.rs new file mode 100644 index 0000000..0375cdf --- /dev/null +++ b/qml_plugin/src/qml_interface/duckduckgo.rs @@ -0,0 +1,88 @@ +use cxx_qt::{CxxQtType, Threading}; +use cxx_qt_lib::QString; +use std::pin::Pin; +use unwrap_print::PrintableResult; + +use crate::{ExclusiveExecutor, web::duckduckgo}; + +#[cxx_qt::bridge] +mod qobject { + extern "C++" { + include!("cxx-qt-lib/qstring.h"); + type QString = cxx_qt_lib::QString; + } + + extern "RustQt" { + #[qobject] + #[qml_element] + #[qml_singleton] + #[qproperty(bool, ok)] + #[qproperty(QString, title)] + #[qproperty(QString, description_html)] + #[qproperty(QString, image)] + type DuckDuckGo = super::DuckDuckGoRs; + + #[qinvokable] + fn query(self: Pin<&mut DuckDuckGo>, input: QString); + + #[qinvokable] + fn reset(self: Pin<&mut DuckDuckGo>); + } + + impl cxx_qt::Threading for DuckDuckGo {} +} + +#[derive(Default)] +pub struct QmlDuckDuckGo { + pub title: QString, + pub description_html: QString, + pub image: QString, +} + +#[derive(Default)] +pub struct DuckDuckGoRs { + ok: bool, + title: QString, + description_html: QString, + image: QString, + + executor: ExclusiveExecutor, +} + +impl qobject::DuckDuckGo { + fn query(self: Pin<&mut Self>, input: QString) { + let qt_thread = self.qt_thread(); + self.rust_mut().executor.spawn(async move { + let qinput = input.to_string(); + let result: Result = + duckduckgo::query(&qinput).await.map(|r| r.into()); + // consider just unwrapping since this is in a separate thread and + // is already end of life anw + _ = qt_thread + .queue(move |mut qo| match result { + Ok(r) => { + if (r.title.to_lower() == input.to_lower() || r.title.is_empty()) + && r.description_html.is_empty() + && r.image.is_empty() + { + qo.as_mut().set_ok(false); + } else { + qo.as_mut().set_ok(true); + qo.as_mut().set_title(r.title); + qo.as_mut().set_description_html(r.description_html); + qo.as_mut().set_image(r.image); + } + } + Err(_) => qo.set_ok(false), + }) + .unwrap_print(); + }); + } + + fn reset(mut self: Pin<&mut Self>) { + self.as_mut().set_ok(false); + self.as_mut().set_title("".into()); + self.as_mut().set_description_html("".into()); + self.as_mut().set_image("".into()); + } +} diff --git a/qml_plugin/src/qml_interface/mathcalc.rs b/qml_plugin/src/qml_interface/mathcalc.rs new file mode 100644 index 0000000..601dc3b --- /dev/null +++ b/qml_plugin/src/qml_interface/mathcalc.rs @@ -0,0 +1,106 @@ +use cxx_qt::{CxxQtType, Threading}; +use cxx_qt_lib::{QString, QVariant}; +use kalk::parser; +use std::{pin::Pin, sync::Arc}; +use tokio::sync::Mutex; +use unwrap_print::PrintableResult; + +use crate::ExclusiveExecutor; + +const DEFAULT_ANGLE_UNIT: &str = "deg"; + +#[cxx_qt::bridge] +mod qobject { + extern "C++" { + include!("cxx-qt-lib/qstring.h"); + include!("cxx-qt-lib/qvariant.h"); + type QString = cxx_qt_lib::QString; + type QVariant = cxx_qt_lib::QVariant; + } + + extern "RustQt" { + #[qobject] + #[qml_element] + #[qml_singleton] + #[qproperty(QVariant, result)] + type MathCalc = super::MathCalcRs; + + #[qinvokable] + fn query(self: Pin<&mut MathCalc>, input: QString); + + #[qinvokable] + fn reset(self: Pin<&mut MathCalc>); + + #[qinvokable] + fn reset_ctx(self: Pin<&mut MathCalc>); + + #[qinvokable] + fn reset_result(self: Pin<&mut MathCalc>); + } + + impl cxx_qt::Threading for MathCalc {} +} + +pub struct MathCalcRs { + result: QVariant, + ctx: Arc>, + + executor: ExclusiveExecutor, +} + +impl Default for MathCalcRs { + fn default() -> Self { + Self { + result: QVariant::default(), + ctx: Arc::new(Mutex::new(qobject::MathCalc::new_ctx())), + executor: ExclusiveExecutor::default(), + } + } +} + +impl qobject::MathCalc { + fn query(mut self: Pin<&mut Self>, input: QString) { + let qt_thread = self.qt_thread(); + let ctx = Arc::clone(&self.as_mut().rust_mut().ctx); + // TODO: consider moving to spawn_blocking + self.rust_mut().executor.spawn(async move { + let input = input.to_string(); + let result = parser::eval( + &mut *ctx.lock().await, + &input, + // TODO: move to const/config + 53, + ) + .map_or_default(|r| { + r.map_or_default(|r| { + let r: QString = r + // to display scientific notation properly + // other ones show both version without e or shows *10^_ + // and have a = prefix + // to_string_big will result in 1/2=5.0000000000000000e − 1 + .to_string() + .into(); + if r != input.into() { QVariant::from(&r) } else { QVariant::default() } + }) + }); + _ = qt_thread.queue(|mut qo| qo.as_mut().set_result(result)).unwrap_print(); + }); + } + + fn reset(mut self: Pin<&mut Self>) { + self.as_mut().reset_result(); + self.reset_ctx(); + } + + fn new_ctx() -> parser::Context { + parser::Context::default().set_angle_unit(DEFAULT_ANGLE_UNIT) + } + + fn reset_ctx(mut self: Pin<&mut Self>) { + self.as_mut().rust_mut().ctx = Arc::new(Mutex::new(Self::new_ctx())) + } + + fn reset_result(mut self: Pin<&mut Self>) { + self.as_mut().set_result(QVariant::default()) + } +} diff --git a/qml_plugin/src/qml_interface/network.rs b/qml_plugin/src/qml_interface/network.rs new file mode 100644 index 0000000..7ece121 --- /dev/null +++ b/qml_plugin/src/qml_interface/network.rs @@ -0,0 +1,55 @@ +use cxx_qt::{CxxQtType, Threading}; +use cxx_qt_lib::{QString, QVariant}; +use std::pin::Pin; +use unwrap_print::PrintableResult; +use zbus::zvariant::NoneValue; + +use crate::{ExclusiveExecutor, services::network}; + +#[cxx_qt::bridge] +mod qobject { + extern "C++" { + include!("cxx-qt-lib/qvariant.h"); + type QVariant = cxx_qt_lib::QVariant; + } + + extern "RustQt" { + #[qobject] + #[qml_element] + #[qml_singleton] + #[qproperty( + QVariant, result + )] + type Network = super::NetworkRs; + + #[qinvokable] + fn query_primary_device(self: Pin<&mut Network>); + } + + impl cxx_qt::Threading for Network {} +} + +#[derive(Default)] +pub struct NetworkRs { + result: QVariant, + + executor: ExclusiveExecutor, +} + +impl qobject::Network { + fn query_primary_device(self: Pin<&mut Self>) { + let qt_thread = self.qt_thread(); + self.rust_mut().executor.spawn( + async move { + let result = match network::get().await { + Ok(o) => { + let r: QString = o.into(); + QVariant::from(&r) + } + Err(_) => QVariant::null_value(), + }; + _ = qt_thread.queue(|mut qo| qo.as_mut().set_result(result)).unwrap_print(); + }, + ); + } +} diff --git a/qml_plugin/src/qml_interface/smartcalc.rs b/qml_plugin/src/qml_interface/smartcalc.rs new file mode 100644 index 0000000..9b5f05a --- /dev/null +++ b/qml_plugin/src/qml_interface/smartcalc.rs @@ -0,0 +1,123 @@ +use cxx_qt::{CxxQtType, Threading}; +use cxx_qt_lib::{QString, QVariant}; +use std::pin::Pin; +use unwrap_print::PrintableResult; + +use crate::ExclusiveExecutor; + +#[cxx_qt::bridge] +mod qobject { + extern "C++" { + include!("cxx-qt-lib/qstring.h"); + include!("cxx-qt-lib/qvariant.h"); + type QString = cxx_qt_lib::QString; + type QVariant = cxx_qt_lib::QVariant; + } + + extern "RustQt" { + #[qobject] + #[qml_element] + #[qml_singleton] + #[qproperty(QVariant, result)] + #[qproperty(ResultType, result_type)] + #[qproperty(QVariant, cached_query)] + type SmartCalc = super::SmartCalcRs; + + #[qinvokable] + fn query(self: Pin<&mut SmartCalc>, input: QString); + + #[qinvokable] + fn reset(self: Pin<&mut SmartCalc>); + + #[qinvokable] + fn reset_result(self: Pin<&mut SmartCalc>); + } + + impl cxx_qt::Threading for SmartCalc {} + + #[qenum(SmartCalc)] + pub enum ResultType { + Math, + Unit, + Currency, + Crypto, + Time, + Date, + Unset, + } +} + +impl Default for qobject::ResultType { + fn default() -> Self { + qobject::ResultType::Unset + } +} + +impl From<&smart_calculator::types::ResultType> for qobject::ResultType { + fn from(value: &smart_calculator::types::ResultType) -> Self { + match value { + smart_calculator::types::ResultType::Math => qobject::ResultType::Math, + smart_calculator::types::ResultType::Unit => qobject::ResultType::Unit, + smart_calculator::types::ResultType::Currency => qobject::ResultType::Currency, + smart_calculator::types::ResultType::Crypto => qobject::ResultType::Crypto, + smart_calculator::types::ResultType::Time => qobject::ResultType::Time, + smart_calculator::types::ResultType::Date => qobject::ResultType::Date, + } + } +} + +#[derive(Default)] +pub struct SmartCalcRs { + result: QVariant, + result_type: qobject::ResultType, + + cached_query: QVariant, + + executor: ExclusiveExecutor, +} + +impl qobject::SmartCalc { + fn query(mut self: Pin<&mut Self>, input: QString) { + if self.cached_query == (&input).into() { + return; + } + self.as_mut().set_cached_query((&input.clone()).into()); + let qt_thread = self.qt_thread(); + self.as_mut().rust_mut().executor.spawn(async move { + let result = smart_calculator::calculate(&input.to_string(), None).await; + _ = qt_thread + .queue(|mut qo| { + qo.as_mut().set_result_type(match &result { + Ok(value) => (&value.res_type).into(), + Err(_) => qobject::ResultType::Unset, + }); + qo.as_mut().set_result( + // TODO: do the calc outside of ts main qt ui render + // thread.(all *.rs) + match result { + Ok(value) => { + if value.formatted == value.input { + QVariant::default() + } else { + let result: QString = value.formatted.into(); + QVariant::from(&result) + } + } + Err(_) => QVariant::default(), + }, + ) + }) + .unwrap_print(); + }); + } + + fn reset(mut self: Pin<&mut Self>) { + self.as_mut().set_cached_query(QVariant::default()); + self.reset_result(); + } + + fn reset_result(mut self: Pin<&mut Self>) { + self.as_mut().set_result(QVariant::default()); + self.as_mut().set_result_type(qobject::ResultType::Unset); + } +} diff --git a/qml_plugin/src/services.rs b/qml_plugin/src/services.rs new file mode 100644 index 0000000..a61610b --- /dev/null +++ b/qml_plugin/src/services.rs @@ -0,0 +1 @@ +pub mod network; diff --git a/qml_plugin/src/services/network.rs b/qml_plugin/src/services/network.rs new file mode 100644 index 0000000..4883dba --- /dev/null +++ b/qml_plugin/src/services/network.rs @@ -0,0 +1,66 @@ +use zbus::{Connection, proxy, zvariant::OwnedObjectPath}; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("The connection is not active.")] + InactiveConnection, + #[error("Device doesn't exist")] + DeviceNotFound, + #[error("Failed to communicate with NetworkManager: {0}")] + Zbus(#[from] zbus::Error), +} + +#[proxy( + interface = "org.freedesktop.NetworkManager", + default_service = "org.freedesktop.NetworkManager", + default_path = "/org/freedesktop/NetworkManager" +)] +trait NetworkManager { + #[zbus(property)] + fn primary_connection(&self) -> zbus::Result; +} + +#[proxy( + interface = "org.freedesktop.NetworkManager.Connection.Active", + default_service = "org.freedesktop.NetworkManager" +)] +trait ActiveConnection { + #[zbus(property)] + fn id(&self) -> zbus::Result; + + #[zbus( + property, + name = "Type" + )] + fn type_(&self) -> zbus::Result; + + #[zbus(property)] + fn devices(&self) -> zbus::Result>; +} + +#[proxy( + interface = "org.freedesktop.NetworkManager.Device", + default_service = "org.freedesktop.NetworkManager" +)] +trait Device { + #[zbus(property)] + fn interface(&self) -> zbus::Result; +} + +pub async fn get() -> Result { + let conn = Connection::system().await?; + + let nm_conn = NetworkManagerProxy::new(&conn).await?.primary_connection().await?; + + if nm_conn.as_str() == "/" { + return Err(Error::InactiveConnection); + } + + if let Some(device_path) = + ActiveConnectionProxy::builder(&conn).path(nm_conn)?.build().await?.devices().await?.first() + { + Ok(DeviceProxy::builder(&conn).path(device_path)?.build().await?.interface().await?) + } else { + Err(Error::DeviceNotFound) + } +} diff --git a/qml_plugin/src/web/duckduckgo.rs b/qml_plugin/src/web/duckduckgo.rs index 6b4edae..e5f1b64 100644 --- a/qml_plugin/src/web/duckduckgo.rs +++ b/qml_plugin/src/web/duckduckgo.rs @@ -1,6 +1,5 @@ use std::ops::{Deref, DerefMut}; -use crate::launcher::duckduckgo::QmlDuckDuckGo; use duckduckgo::{ browser::Browser, params::{SafeSearch, SearchParams, Toggle}, @@ -8,6 +7,8 @@ use duckduckgo::{ use reqwest::Url; use serde::Deserialize; +use crate::qml_interface::duckduckgo::QmlDuckDuckGo; + const DUCKDUCKGO: &str = "https://duckduckgo.com"; #[derive(Default, PartialEq)] @@ -83,36 +84,49 @@ pub async fn query(input: &str) -> anyhow::Result { _ => None, }; - let alt_desc = resp.entity.unwrap_or(match infobox { - Some(i) => i - .iter() - .find(|i| i.data_type == "wd_description" || i.data_type == "official_website") - .map_or(String::new(), |i| { - if i.data_type == "official_website" { - i.label.clone() - } else { - match i.value { - InfoboxValue::Entity(_) => unreachable!(), - InfoboxValue::String(ref s) => s.to_string(), + let alt_desc = resp.entity.unwrap_or( + match infobox { + Some(i) => i + .iter() + .find(|i| i.data_type == "wd_description" || i.data_type == "official_website") + .map_or( + String::new(), + |i| { + if i.data_type == "official_website" { + i.label.clone() + } else { + match i.value { + InfoboxValue::Entity(_) => unreachable!(), + InfoboxValue::String(ref s) => s.to_string(), + } + } + }, + ), + // TODO: find better way to get title from infobox + None => String::new(), + }, + ); + + Ok( + DuckDuckGoContent { + title: resp + .heading + .filter(|h| !h.is_empty()) + .unwrap_or(resp.definition.filter(|d| !d.is_empty()).unwrap_or(alt_desc.clone())), + description_html: resp + .answer + .filter(|a| !a.is_empty()) + .unwrap_or(resp.r#abstract.filter(|a| !a.is_empty()).unwrap_or(alt_desc)), + // TODO: try also Results[*].Icon.URL and RelatedTopics[*].Icon.URL + image: resp.image.filter(|i| !i.is_empty()).and_then( + |i| { + if !i.is_empty() { + Url::parse(&format!("{DUCKDUCKGO}{i}",)).ok() + } else { + None } - } - }), - // TODO: find better way to get title from infobox - None => String::new(), - }); - - Ok(DuckDuckGoContent { - title: resp - .heading - .filter(|h| !h.is_empty()) - .unwrap_or(resp.definition.filter(|d| !d.is_empty()).unwrap_or(alt_desc.clone())), - description_html: resp - .answer - .filter(|a| !a.is_empty()) - .unwrap_or(resp.r#abstract.filter(|a| !a.is_empty()).unwrap_or(alt_desc)), - // TODO: try also Results[*].Icon.URL and RelatedTopics[*].Icon.URL - image: resp.image.filter(|i| !i.is_empty()).and_then(|i| { - if !i.is_empty() { Url::parse(&format!("{DUCKDUCKGO}{i}",)).ok() } else { None } - }), - }) + }, + ), + }, + ) } -- cgit v1.2.3