summaryrefslogtreecommitdiff
path: root/qml_plugin/src/qml_interface/smartcalc.rs
blob: 9b5f05a0474abb9c66b718b13f24e1c2d4982b5a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
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);
    }
}