summaryrefslogtreecommitdiff
path: root/qml_plugin/src
diff options
context:
space:
mode:
authorlittleblack111 <littleblack11111@gmail.com>2026-08-01 18:26:09 +0800
committerlittleblack111 <littleblack11111@gmail.com>2026-08-01 18:26:09 +0800
commitba3e36e562f5028f54840258312caed99577acb0 (patch)
tree9a982ec1598f5ec0d8c487048230a016c3453e27 /qml_plugin/src
parent1d6da847b7075b4babf3409b9445db0b54677893 (diff)
launcher(duckduckgo.rs): qml usable interface
Diffstat (limited to 'qml_plugin/src')
-rw-r--r--qml_plugin/src/launcher.rs1
-rw-r--r--qml_plugin/src/launcher/duckduckgo.rs100
-rw-r--r--qml_plugin/src/web/duckduckgo.rs26
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()),
},
)
}