diff options
| author | littleblack111 <littleblack11111@gmail.com> | 2026-08-01 18:26:09 +0800 |
|---|---|---|
| committer | littleblack111 <littleblack11111@gmail.com> | 2026-08-01 18:26:09 +0800 |
| commit | ba3e36e562f5028f54840258312caed99577acb0 (patch) | |
| tree | 9a982ec1598f5ec0d8c487048230a016c3453e27 | |
| parent | 1d6da847b7075b4babf3409b9445db0b54677893 (diff) | |
launcher(duckduckgo.rs): qml usable interface
| -rw-r--r-- | qml_plugin/src/launcher.rs | 1 | ||||
| -rw-r--r-- | qml_plugin/src/launcher/duckduckgo.rs | 100 | ||||
| -rw-r--r-- | qml_plugin/src/web/duckduckgo.rs | 26 |
3 files changed, 126 insertions, 1 deletions
diff --git a/qml_plugin/src/launcher.rs b/qml_plugin/src/launcher.rs index 4274840..9d823f0 100644 --- a/qml_plugin/src/launcher.rs +++ b/qml_plugin/src/launcher.rs @@ -1,2 +1,3 @@ +pub mod duckduckgo; pub mod mathcalc; pub mod smartcalc; diff --git a/qml_plugin/src/launcher/duckduckgo.rs b/qml_plugin/src/launcher/duckduckgo.rs new file mode 100644 index 0000000..1106212 --- /dev/null +++ b/qml_plugin/src/launcher/duckduckgo.rs @@ -0,0 +1,100 @@ +use cxx_qt::Threading; +use cxx_qt_lib::QString; +use std::{pin::Pin, ptr}; + +use crate::{ + RUNTIME, + web::duckduckgo::{self, DuckDuckGoContent}, +}; + +#[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, valid + )] + #[qproperty( + QString, title + )] + #[qproperty( + QString, + description_html + )] + #[qproperty( + QString, + preview_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 preview_image: QString, +} + +#[derive(Default)] +pub struct DuckDuckGoRs { + valid: bool, + title: QString, + description_html: QString, + preview_image: QString, +} + +impl qobject::DuckDuckGo { + fn query(self: Pin<&mut Self>, input: QString) { + let qt_thread = self.qt_thread(); + RUNTIME.spawn( + async move { + let input = input.to_string(); + let result: Result<QmlDuckDuckGo, _> = duckduckgo::query(&input) + .await + .map(|r| r.into()); + qt_thread.queue( + |mut qo| match result { + Ok(r) => { + qo.as_mut() + .set_valid(true); + qo.as_mut() + .set_title(r.title); + qo.as_mut() + .set_description_html(r.description_html); + qo.as_mut() + .set_preview_image(r.preview_image); + } + Err(_) => qo.set_valid(false), + }, + ) + }, + ); + } + + fn reset(mut self: Pin<&mut Self>) { + self.as_mut() + .set_valid(false); + self.as_mut() + .set_title("".into()); + self.as_mut() + .set_description_html("".into()); + self.as_mut() + .set_preview_image("".into()); + } +} diff --git a/qml_plugin/src/web/duckduckgo.rs b/qml_plugin/src/web/duckduckgo.rs index f80e4c8..3793485 100644 --- a/qml_plugin/src/web/duckduckgo.rs +++ b/qml_plugin/src/web/duckduckgo.rs @@ -1,5 +1,6 @@ use std::ops::{Deref, DerefMut}; +use crate::launcher::duckduckgo::QmlDuckDuckGo; use duckduckgo::{ browser::Browser, params::{SafeSearch, SearchParams, Toggle}, @@ -9,12 +10,35 @@ use serde::Deserialize; const DUCKDUCKGO: &str = "https://duckduckgo.com"; +#[derive(Default, PartialEq)] pub struct DuckDuckGoContent { title: String, description_html: String, preview_image: Option<Url>, } +impl From<DuckDuckGoContent> for QmlDuckDuckGo { + fn from(value: DuckDuckGoContent) -> Self { + Self { + title: value + .title + .into(), + description_html: value + .description_html + .into(), + preview_image: value + .preview_image + .map( + |u| { + u.to_string() + .into() + }, + ) + .unwrap_or_default(), + } + } +} + #[derive(Debug, Deserialize)] pub struct Infobox { pub content: Vec<InfoboxContent>, @@ -121,7 +145,7 @@ pub async fn query(input: &str) -> anyhow::Result<DuckDuckGoContent> { // TODO: try also Results[*].Icon.URL and RelatedTopics[*].Icon.URL preview_image: resp .image - .and_then(|i| Url::parse(&(DUCKDUCKGO.to_owned() + &i)).ok()), + .and_then(|i| Url::parse(&format!("{DUCKDUCKGO}{i}",)).ok()), }, ) } |
