Python: Initial support for implementing models in Python

This provides a Model base class in Python and sub-classes of that
can be set as data models in slint.

The ListModel is provided as basic sub-class operating on a list() and
allowing mutation and notifying the view on the Slint side.

Similarly, an array declared in Slint is exposed as an object to Python
that looks like a Model.

Both support the sequence protocol.

Fixes #4135
This commit is contained in:
Simon Hausmann 2024-03-04 16:05:20 +01:00 committed by Simon Hausmann
parent 82d784a4d4
commit 2f313f84ec
6 changed files with 393 additions and 1 deletions

View file

@ -37,7 +37,10 @@ impl<'a> ToPyObject for PyValueRef<'a> {
slint_interpreter::Value::Image(image) => {
crate::image::PyImage::from(image).into_py(py)
}
slint_interpreter::Value::Model(_) => todo!(),
slint_interpreter::Value::Model(model) => {
crate::models::PyModelShared::rust_into_js_model(model)
.unwrap_or_else(|| crate::models::ReadOnlyRustModel::from(model).into_py(py))
}
slint_interpreter::Value::Struct(structval) => structval
.iter()
.map(|(name, val)| (name.to_string().into_py(py), PyValueRef(val).into_py(py)))
@ -72,6 +75,14 @@ impl FromPyObject<'_> for PyValue {
ob.extract::<PyRef<'_, crate::brush::PyBrush>>()
.map(|pybrush| slint_interpreter::Value::Brush(pybrush.brush.clone()))
})
.or_else(|_| {
ob.extract::<PyRef<'_, crate::models::PyModelBase>>()
.map(|pymodel| slint_interpreter::Value::Model(pymodel.as_model()))
})
.or_else(|_| {
ob.extract::<PyRef<'_, crate::models::ReadOnlyRustModel>>()
.map(|rustmodel| slint_interpreter::Value::Model(rustmodel.0.clone()))
})
.or_else(|_| {
ob.extract::<&PyDict>().and_then(|dict| {
let dict_items: Result<Vec<(String, slint_interpreter::Value)>, PyErr> = dict