slint
slint copied to clipboard
Add support for filtering and mapping models in `.slint` directly
I have a property<[FooMsg]> msgs
that stores list messages I want to display in different tabs. I am not maintaining different properties for each tab. I can do that if the answer here is a No. Each message FooMsg
has a field called tag
that determines the Tab
of the message.
Inside a Tab
, Here is a psedo code that I use to filter the messages and display them.
for msg[i] in root.msgs {
if msg.tag == root.tag {
Text {
text : msg.text;
row: i;
}
}
}
I was hoping for something like (pseudo code):
for msg in root.msg.filter( |x| x.tag == root.tag) {
Text { text: msg.text, row : i };
}
Note that the value of i
will be different in the second case. The second case is suitable for generating a grid-layout because i
will take values that increase by 1 at each step and there won't be gaps.
In short, I am looking for a filter
like function for the array before I can iterate over it. Suggestions?
While this isn’t possible in pure Slint yet, you can do this if you provide your Mode from Rust and place it behind a FilterModel. Would that help?
FWIW it would be nice to be able to write a filter like in your example in pure Slint as well.
We just would need to find a good syntax for it.
// Like in rust
for xx in model.filter(|x| x.tag == root.tag) : Rectangle {
// like in JS
for xx in model.filter(x => x.tag == root.tag) : Rectangle {
// specialized syntax
for xx in model | #.tag == root.tag : Rectangle {
We also would probably need a map
adapror syntax as well.
Maybe a sorting one too?
Right, and we'd need the map/filter/sort in C++ as well. This sounds very well doable. My order of preference in syntax is JS > Rust > Special ;-)
While this isn’t possible in pure Slint yet, you can do this if you provide your Mode from Rust and place it behind a FilterModel. Would that help?
Thanks! This might just work 🥳 .
I also think the JS syntax is easier on the eyes than Rust syntax (especially when you are also supporting JS and C++).
While this isn’t possible in pure Slint yet, you can do this if you provide your Mode from Rust and place it behind a FilterModel. Would that help?
Thanks again for the suggestion @tronical. It worked! Not sure if I am using it the most efficiently but for now it solves my problem.
// Connect msglist to slint Window.
let msglist_app = ModelRc::new(FilterModel::new(self.msglist.clone(), |s| s.code == "App"));
self.window.unwrap().set_msglist(msglist_app);
👍 We could leave this ticket open to track the ability to specify filters in .slint itself. If you're okay with that then I'll edit the title slightly to reflect the intent.
@tronical Sounds good.
Any other workarounds suggested for this? It seems like it makes maintaining the "one source of truth" that Slint seems to otherwise do pretty well break quickly without losing modularity.