summaryrefslogtreecommitdiff
path: root/qml_plugin/src/qml_interface
diff options
context:
space:
mode:
authorlittleblack111 <littleblack11111@gmail.com>2026-09-18 15:13:01 +0800
committerlittleblack111 <littleblack11111@gmail.com>2026-10-01 15:10:27 +0800
commit3cea94b72dbfdd2077a59fc52a7460e200b6061e (patch)
tree294a8cb1ef3aadc189073492bb041f6af2b17f70 /qml_plugin/src/qml_interface
parent8a71bd72f53e3629fb1d23d7c1b153207ba44789 (diff)
refactor: qml_pluginmain
Diffstat (limited to 'qml_plugin/src/qml_interface')
-rw-r--r--qml_plugin/src/qml_interface/duckduckgo.rs88
-rw-r--r--qml_plugin/src/qml_interface/mathcalc.rs106
-rw-r--r--qml_plugin/src/qml_interface/network.rs55
-rw-r--r--qml_plugin/src/qml_interface/smartcalc.rs123
4 files changed, 372 insertions, 0 deletions
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<QmlDuckDuckGo, _> =
+ 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<Mutex<parser::Context>>,
+
+ 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);
+ }
+}