From 1f9873b40fee2d33c5b7103a25077ec61a387063 Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Mon, 27 Jul 2026 13:14:10 +0800 Subject: refactor: ISmartCalc new(SmartCalc): Unit --- config/Launcher.qml | 4 +- popups/launcher/components/Date.qml | 86 +------------------ popups/launcher/components/ISmartCalc.qml | 88 +++++++++++++++++++ popups/launcher/components/Unit.qml | 7 ++ qml_plugin/build.rs | 2 +- qml_plugin/src/launcher.rs | 2 +- qml_plugin/src/launcher/calc.rs | 135 ------------------------------ qml_plugin/src/launcher/smartcalc.rs | 135 ++++++++++++++++++++++++++++++ 8 files changed, 239 insertions(+), 220 deletions(-) create mode 100644 popups/launcher/components/ISmartCalc.qml create mode 100644 popups/launcher/components/Unit.qml delete mode 100644 qml_plugin/src/launcher/calc.rs create mode 100644 qml_plugin/src/launcher/smartcalc.rs diff --git a/config/Launcher.qml b/config/Launcher.qml index cb29c05..a1cb193 100644 --- a/config/Launcher.qml +++ b/config/Launcher.qml @@ -49,6 +49,8 @@ Singleton { Component { Date {} }, - + Component { + Unit {} + }, ] } diff --git a/popups/launcher/components/Date.qml b/popups/launcher/components/Date.qml index a23c0b0..0929b75 100644 --- a/popups/launcher/components/Date.qml +++ b/popups/launcher/components/Date.qml @@ -1,85 +1,7 @@ -import Quickshell -import QtQuick -import QtQuick.Layouts - -import qs.components -import qs.services -import qs.config - import core -IComponent { - property int cursorPosition: SelectionState.cursorPosition - property string answer: active && valid ? SmartCalc.result : "" - - name: "Date" - preview: Component { - Icon { - text: "๐Ÿ“…" - } - } - - process: function () { - SmartCalc.query(input); - const isValid = active && SmartCalc.result && SmartCalc.result.length > 0 && (SmartCalc.result_type == SmartCalc.Time || SmartCalc.result_type == SmartCalc.Date); - const answer = isValid ? SmartCalc.result : ""; - return { - valid: isValid, - priority: isValid, - answer: answer, - predictiveCompletion: isValid ? ' is ' + answer : '' - }; - } - exec: function () { - Clip.copy(answer); - } - - IInnerComponent { - RowLayout { - spacing: 0 - Layout.fillWidth: true - Layout.fillHeight: true - Layout.preferredHeight: parent.height - - Item { - Layout.fillWidth: true - IText { - anchors.centerIn: parent - elide: cursorPosition > input.length / 2 ? Text.ElideLeft : Text.ElideRight - width: Math.min(implicitWidth, parent.width - Launcher.innerMargin * 2) - clip: true - renderType: Text.CurveRendering - visible: valid - text: input.replace(/ /g, "").replace(/\+/g, " + ").replace(/-/g, " - ").replace(/\*/g, " ร— ").replace(/\//g, " รท ").replace(/%/g, " % ").replace(/\(/g, " ( ").replace(/\)/g, " ) ") - font { - pixelSize: Launcher.widgetFontSize - bold: true - } - } - } - - IText { - visible: valid - text: "โ†’" - font.pixelSize: Launcher.widgetFontSize - font.bold: true - } - - Item { - Layout.fillWidth: true - IText { - animate: true - anchors.centerIn: parent - width: Math.min(implicitWidth, parent.width - Launcher.innerMargin * 2) - renderType: Text.CurveRendering - visible: valid - text: valid ? answer : '' - font { - pixelSize: Launcher.widgetFontSize - bold: true - } - } - } - } - } +ISmartCalc { + symbol: "๐Ÿ“…" + category: SmartCalc.result_type == SmartCalc.Time || SmartCalc.result_type == SmartCalc.Date + predictiveText: 'is' } diff --git a/popups/launcher/components/ISmartCalc.qml b/popups/launcher/components/ISmartCalc.qml new file mode 100644 index 0000000..6e6381c --- /dev/null +++ b/popups/launcher/components/ISmartCalc.qml @@ -0,0 +1,88 @@ +import Quickshell +import QtQuick +import QtQuick.Layouts + +import qs.components +import qs.services +import qs.config + +import core + +IComponent { + property string symbol + required property bool category + required property string predictiveText + + property int cursorPosition: SelectionState.cursorPosition + property string answer: active && valid ? SmartCalc.result : "" + + preview: Component { + Icon { + text: symbol + } + } + + process: function () { + SmartCalc.query(input); + const isValid = active && SmartCalc.result && SmartCalc.result.length > 0 && category; + const answer = isValid ? SmartCalc.result : ""; + return { + valid: isValid, + priority: isValid, + answer: answer, + predictiveCompletion: isValid ? ` ${predictiveText} ` + answer : '' + }; + } + exec: function () { + Clip.copy(answer); + } + + IInnerComponent { + RowLayout { + spacing: 0 + Layout.fillWidth: true + Layout.fillHeight: true + Layout.preferredHeight: parent.height + + Item { + Layout.fillWidth: true + IText { + anchors.centerIn: parent + elide: cursorPosition > input.length / 2 ? Text.ElideLeft : Text.ElideRight + width: Math.min(implicitWidth, parent.width - Launcher.innerMargin * 2) + clip: true + renderType: Text.CurveRendering + visible: valid + text: input.replace(/ /g, "").replace(/\+/g, " + ").replace(/-/g, " - ").replace(/\*/g, " ร— ").replace(/\//g, " รท ").replace(/%/g, " % ").replace(/\(/g, " ( ").replace(/\)/g, " ) ") + font { + pixelSize: Launcher.widgetFontSize + bold: true + } + } + } + + IText { + visible: valid + text: "โ†’" + font.pixelSize: Launcher.widgetFontSize + font.bold: true + } + + Item { + Layout.fillWidth: true + IText { + animate: true + anchors.centerIn: parent + width: Math.min(implicitWidth, parent.width - Launcher.innerMargin * 2) + renderType: Text.CurveRendering + visible: valid + text: valid ? answer : '' + font { + pixelSize: Launcher.widgetFontSize + bold: true + } + } + } + } + } +} diff --git a/popups/launcher/components/Unit.qml b/popups/launcher/components/Unit.qml new file mode 100644 index 0000000..f03f69c --- /dev/null +++ b/popups/launcher/components/Unit.qml @@ -0,0 +1,7 @@ +import core + +ISmartCalc { + symbol: "โ‡„" + category: SmartCalc.result_type == SmartCalc.Unit + predictiveText: 'โ†’' +} diff --git a/qml_plugin/build.rs b/qml_plugin/build.rs index 2adb19c..8a02b92 100644 --- a/qml_plugin/build.rs +++ b/qml_plugin/build.rs @@ -13,6 +13,6 @@ fn main() { CxxQtBuilder::new_qml_module(QmlModule::new(NAME).plugin_type(PluginType::Dynamic)) .qt_module("Qml") - .files(["src/launcher/calc.rs"]) + .files(["src/launcher/smartcalc.rs"]) .build(); } diff --git a/qml_plugin/src/launcher.rs b/qml_plugin/src/launcher.rs index 5632eea..8cb8676 100644 --- a/qml_plugin/src/launcher.rs +++ b/qml_plugin/src/launcher.rs @@ -1 +1 @@ -pub mod calc; +pub mod smartcalc; diff --git a/qml_plugin/src/launcher/calc.rs b/qml_plugin/src/launcher/calc.rs deleted file mode 100644 index 7b1b066..0000000 --- a/qml_plugin/src/launcher/calc.rs +++ /dev/null @@ -1,135 +0,0 @@ -use cxx_qt::Threading; -use cxx_qt_lib::{QString, QVariant}; -use std::pin::Pin; - -use crate::RUNTIME; - -#[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>); - } - - 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, -} - -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(); - RUNTIME.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( - match result { - Ok(value) => { - if value.formatted == value.input { - QVariant::default() - } else { - let result: QString = value - .formatted - .into(); - QVariant::from(&result) - } - } - Err(_) => QVariant::default(), - }, - ) - }, - ) - }, - ); - } - - fn reset(mut self: Pin<&mut Self>) { - self.as_mut() - .set_result(QVariant::default()); - self.as_mut() - .set_result_type(qobject::ResultType::Unset); - self.as_mut() - .set_cached_query(QVariant::default()); - } -} diff --git a/qml_plugin/src/launcher/smartcalc.rs b/qml_plugin/src/launcher/smartcalc.rs new file mode 100644 index 0000000..7b1b066 --- /dev/null +++ b/qml_plugin/src/launcher/smartcalc.rs @@ -0,0 +1,135 @@ +use cxx_qt::Threading; +use cxx_qt_lib::{QString, QVariant}; +use std::pin::Pin; + +use crate::RUNTIME; + +#[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>); + } + + 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, +} + +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(); + RUNTIME.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( + match result { + Ok(value) => { + if value.formatted == value.input { + QVariant::default() + } else { + let result: QString = value + .formatted + .into(); + QVariant::from(&result) + } + } + Err(_) => QVariant::default(), + }, + ) + }, + ) + }, + ); + } + + fn reset(mut self: Pin<&mut Self>) { + self.as_mut() + .set_result(QVariant::default()); + self.as_mut() + .set_result_type(qobject::ResultType::Unset); + self.as_mut() + .set_cached_query(QVariant::default()); + } +} -- cgit v1.2.3