1 | // Copyright © SixtyFPS GmbH <info@slint.dev> |
2 | // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.1 OR LicenseRef-Slint-commercial |
3 | |
4 | use pyo3::prelude::*; |
5 | use pyo3::types::{IntoPyDict, PyDict}; |
6 | |
7 | pub struct PyValue(pub slint_interpreter::Value); |
8 | struct PyValueRef<'a>(&'a slint_interpreter::Value); |
9 | |
10 | impl IntoPy<PyObject> for PyValue { |
11 | fn into_py(self, py: Python<'_>) -> PyObject { |
12 | // Share the conversion code below that operates on the reference |
13 | self.to_object(py).into_py(py) |
14 | } |
15 | } |
16 | |
17 | impl ToPyObject for PyValue { |
18 | fn to_object(&self, py: Python<'_>) -> PyObject { |
19 | PyValueRef(&self.0).to_object(py) |
20 | } |
21 | } |
22 | |
23 | impl<'a> IntoPy<PyObject> for PyValueRef<'a> { |
24 | fn into_py(self, py: Python<'_>) -> PyObject { |
25 | // Share the conversion code below that operates on the reference |
26 | self.to_object(py).into_py(py) |
27 | } |
28 | } |
29 | |
30 | impl<'a> ToPyObject for PyValueRef<'a> { |
31 | fn to_object(&self, py: Python<'_>) -> PyObject { |
32 | match &self.0 { |
33 | slint_interpreter::Value::Void => ().into_py(py), |
34 | slint_interpreter::Value::Number(num) => num.into_py(py), |
35 | slint_interpreter::Value::String(str) => str.into_py(py), |
36 | slint_interpreter::Value::Bool(b) => b.into_py(py), |
37 | slint_interpreter::Value::Image(image) => { |
38 | crate::image::PyImage::from(image).into_py(py) |
39 | } |
40 | slint_interpreter::Value::Model(model) => { |
41 | crate::models::PyModelShared::rust_into_js_model(model) |
42 | .unwrap_or_else(|| crate::models::ReadOnlyRustModel::from(model).into_py(py)) |
43 | } |
44 | slint_interpreter::Value::Struct(structval) => structval |
45 | .iter() |
46 | .map(|(name, val)| (name.to_string().into_py(py), PyValueRef(val).into_py(py))) |
47 | .into_py_dict(py) |
48 | .into_py(py), |
49 | slint_interpreter::Value::Brush(brush) => { |
50 | crate::brush::PyBrush::from(brush.clone()).into_py(py) |
51 | } |
52 | v @ _ => { |
53 | eprintln!("Python: conversion from slint to python needed for {:#?} and not implemented yet" , v); |
54 | ().into_py(py) |
55 | } |
56 | } |
57 | } |
58 | } |
59 | |
60 | impl FromPyObject<'_> for PyValue { |
61 | fn extract(ob: &PyAny) -> PyResult<Self> { |
62 | if ob.is_none() { |
63 | return Ok(slint_interpreter::Value::Void.into()); |
64 | } |
65 | |
66 | let interpreter_val = ob |
67 | .extract::<bool>() |
68 | .map(|b| slint_interpreter::Value::Bool(b)) |
69 | .or_else(|_| { |
70 | ob.extract::<&'_ str>().map(|s| slint_interpreter::Value::String(s.into())) |
71 | }) |
72 | .or_else(|_| ob.extract::<f64>().map(|num| slint_interpreter::Value::Number(num))) |
73 | .or_else(|_| { |
74 | ob.extract::<PyRef<'_, crate::image::PyImage>>() |
75 | .map(|pyimg| slint_interpreter::Value::Image(pyimg.image.clone())) |
76 | }) |
77 | .or_else(|_| { |
78 | ob.extract::<PyRef<'_, crate::brush::PyBrush>>() |
79 | .map(|pybrush| slint_interpreter::Value::Brush(pybrush.brush.clone())) |
80 | }) |
81 | .or_else(|_| { |
82 | ob.extract::<PyRef<'_, crate::brush::PyColor>>() |
83 | .map(|pycolor| slint_interpreter::Value::Brush(pycolor.color.clone().into())) |
84 | }) |
85 | .or_else(|_| { |
86 | ob.extract::<PyRef<'_, crate::models::PyModelBase>>() |
87 | .map(|pymodel| slint_interpreter::Value::Model(pymodel.as_model())) |
88 | }) |
89 | .or_else(|_| { |
90 | ob.extract::<PyRef<'_, crate::models::ReadOnlyRustModel>>() |
91 | .map(|rustmodel| slint_interpreter::Value::Model(rustmodel.0.clone())) |
92 | }) |
93 | .or_else(|_| { |
94 | ob.extract::<&PyDict>().and_then(|dict| { |
95 | let dict_items: Result<Vec<(String, slint_interpreter::Value)>, PyErr> = dict |
96 | .iter() |
97 | .map(|(name, pyval)| { |
98 | let name = name.extract::<&str>()?.to_string(); |
99 | let slintval: PyValue = pyval.extract()?; |
100 | Ok((name, slintval.0)) |
101 | }) |
102 | .collect::<Result<Vec<(_, _)>, PyErr>>(); |
103 | Ok(slint_interpreter::Value::Struct(slint_interpreter::Struct::from_iter( |
104 | dict_items?.into_iter(), |
105 | ))) |
106 | }) |
107 | })?; |
108 | |
109 | Ok(PyValue(interpreter_val)) |
110 | } |
111 | } |
112 | impl From<slint_interpreter::Value> for PyValue { |
113 | fn from(value: slint_interpreter::Value) -> Self { |
114 | Self(value) |
115 | } |
116 | } |
117 | |