summaryrefslogtreecommitdiff
path: root/qml_plugin/src/launcher/mathcalc.rs
blob: 626b9706060da0d2149b49f4084e2e3b6a3bd312 (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
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 crate::RUNTIME;

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>);
    }

    impl cxx_qt::Threading for MathCalc {}
}

#[derive(Default)]
pub struct MathCalcRs {
    result: QVariant,

    ctx: Arc<Mutex<parser::Context>>,
}

impl qobject::MathCalc {
    fn query(self: Pin<&mut Self>, input: QString) {
        let qt_thread = self.qt_thread();
        let ctx = Arc::clone(
            &self
                .rust_mut()
                .ctx,
        );
        // TODO: consider moving to spawn_blocking
        RUNTIME.spawn(
            async move {
                let input = input.to_string();
                let result = parser::eval(
                    &mut *ctx
                        .lock()
                        .await,
                    &input,
                    // TODO: move to const/config
                    53,
                );
                qt_thread.queue(
                    |mut qo| {
                        qo.as_mut()
                            .set_result(
                                result.map_or_default(
                                    |r| {
                                        r.map_or_default(
                                            |r| {
                                                let result: QString = r
                                                    .to_string()
                                                    .into();
                                                if result != input.into() {
                                                    QVariant::from(&result)
                                                } else {
                                                    QVariant::default()
                                                }
                                            },
                                        )
                                    },
                                ),
                            )
                    },
                )
            },
        );
    }

    fn reset(mut self: Pin<&mut Self>) {
        self.as_mut()
            .set_result(QVariant::default());
        self.reset_ctx();
    }

    fn reset_ctx(mut self: Pin<&mut Self>) {
        self.as_mut()
            .rust_mut()
            .ctx =
            Arc::new(Mutex::new(parser::Context::default().set_angle_unit(DEFAULT_ANGLE_UNIT)));
    }
}