i_slint_core::model

Trait Model

Source
pub trait Model {
    type Data;

    // Required methods
    fn row_count(&self) -> usize;
    fn row_data(&self, row: usize) -> Option<Self::Data>;
    fn model_tracker(&self) -> &dyn ModelTracker;

    // Provided methods
    fn set_row_data(&self, _row: usize, _data: Self::Data) { ... }
    fn iter(&self) -> ModelIterator<'_, Self::Data> 
       where Self: Sized { ... }
    fn as_any(&self) -> &dyn Any { ... }
}
Expand description

A Model is providing Data for the repeated elements with for in the .slint language

If the model can be changed, the type implementing the Model trait should holds a ModelNotify, and is responsible to call functions on it to let the UI know that something has changed.

Properties of type array will be mapped to a ModelRc<T>, which wraps a Rc<Model<Data = T>>. The ModelRc documentation has examples on how to set models to array properties.

It is more efficient to operate on the model and send changes through the ModelNotify rather than resetting the property with a different model.

§Example

As an example, let’s see the implementation of VecModel.

pub struct VecModel<T> {
    // the backing data, stored in a `RefCell` as this model can be modified
    array: std::cell::RefCell<Vec<T>>,
    // the ModelNotify will allow to notify the UI that the model changes
    notify: ModelNotify,
}

impl<T: Clone + 'static> Model for VecModel<T> {
    type Data = T;

    fn row_count(&self) -> usize {
        self.array.borrow().len()
    }

    fn row_data(&self, row: usize) -> Option<Self::Data> {
        self.array.borrow().get(row).cloned()
    }

    fn set_row_data(&self, row: usize, data: Self::Data) {
        self.array.borrow_mut()[row] = data;
        // don't forget to call row_changed
        self.notify.row_changed(row);
    }

    fn model_tracker(&self) -> &dyn ModelTracker {
        &self.notify
    }

    fn as_any(&self) -> &dyn core::any::Any {
        // a typical implementation just return `self`
        self
    }
}

// when modifying the model, we call the corresponding function in
// the ModelNotify
impl<T> VecModel<T> {
    /// Add a row at the end of the model
    pub fn push(&self, value: T) {
        self.array.borrow_mut().push(value);
        self.notify.row_added(self.array.borrow().len() - 1, 1)
    }

    /// Remove the row at the given index from the model
    pub fn remove(&self, index: usize) {
        self.array.borrow_mut().remove(index);
        self.notify.row_removed(index, 1)
    }
}

Required Associated Types§

Source

type Data

The model data: A model is a set of rows and each row has this data

Required Methods§

Source

fn row_count(&self) -> usize

The number of rows in the model

Source

fn row_data(&self, row: usize) -> Option<Self::Data>

Returns the data for a particular row.

This function should normally be called with row < row_count() and should return None otherwise.

This function does not register dependencies on the current binding. For an equivalent function that tracks dependencies, see ModelExt::row_data_tracked

Source

fn model_tracker(&self) -> &dyn ModelTracker

The implementation should return a reference to its ModelNotify field.

You can return &() if you your Model is constant and does not have a ModelNotify field.

Provided Methods§

Source

fn set_row_data(&self, _row: usize, _data: Self::Data)

Sets the data for a particular row.

This function should be called with row < row_count(), otherwise the implementation can panic.

If the model cannot support data changes, then it is ok to do nothing. The default implementation will print a warning to stderr.

If the model can update the data, it should also call ModelNotify::row_changed on its internal ModelNotify.

Source

fn iter(&self) -> ModelIterator<'_, Self::Data>
where Self: Sized,

Returns an iterator visiting all elements of the model.

Source

fn as_any(&self) -> &dyn Any

Return something that can be downcast’ed (typically self)

This is useful to get back to the actual model from a ModelRc stored in a ItemTree.

let handle = ModelRc::new(VecModel::from(vec![1i32, 2, 3]));
// later:
handle.as_any().downcast_ref::<VecModel<i32>>().unwrap().push(4);
assert_eq!(handle.row_data(3).unwrap(), 4);

Note: the default implementation returns nothing interesting. this method should be implemented by model implementation to return something useful. For example:

    fn as_any(&self) -> &dyn core::any::Any { self }

Implementations on Foreign Types§

Source§

impl Model for bool

Source§

type Data = ()

Source§

fn row_count(&self) -> usize

Source§

fn row_data(&self, row: usize) -> Option<Self::Data>

Source§

fn as_any(&self) -> &dyn Any

Source§

fn model_tracker(&self) -> &dyn ModelTracker

Source§

impl Model for usize

Source§

type Data = i32

Source§

fn row_count(&self) -> usize

Source§

fn row_data(&self, row: usize) -> Option<Self::Data>

Source§

fn as_any(&self) -> &dyn Any

Source§

fn model_tracker(&self) -> &dyn ModelTracker

Source§

impl<M: Model> Model for Rc<M>

Source§

type Data = <M as Model>::Data

Source§

fn row_count(&self) -> usize

Source§

fn row_data(&self, row: usize) -> Option<Self::Data>

Source§

fn model_tracker(&self) -> &dyn ModelTracker

Source§

fn as_any(&self) -> &dyn Any

Source§

fn set_row_data(&self, row: usize, data: Self::Data)

Implementors§

Source§

impl<M> Model for ReverseModel<M>
where M: Model + 'static,

Source§

type Data = <M as Model>::Data

Source§

impl<M, F> Model for FilterModel<M, F>
where M: Model + 'static, F: Fn(&M::Data) -> bool + 'static,

Source§

type Data = <M as Model>::Data

Source§

impl<M, F, T, U> Model for MapModel<M, F>
where M: 'static + Model<Data = T>, F: 'static + Fn(T) -> U,

Source§

type Data = U

Source§

impl<M, S> Model for SortModel<M, S>
where M: Model + 'static, S: SortHelper<M::Data>,

Source§

type Data = <M as Model>::Data

Source§

impl<T> Model for ModelRc<T>

Source§

type Data = T

Source§

impl<T: Clone + 'static> Model for SharedVectorModel<T>

Source§

type Data = T

Source§

impl<T: Clone + 'static> Model for VecModel<T>

Source§

type Data = T