gtk-rs-core
gtk-rs-core copied to clipboard
Add an Iterator for ListModel
This PR implements an Iterator for the ListModel
interface.
The Iterator can be created by the interface’s iter
method. Example usage:
for member in members.iter::<User>() {
…
}
As you can see, the iter
method takes a type parameter T
that is the type of the yielded items. At creation time of the Iterator a type check is performed to make sure it is a subtype of the model’s item type. Having a type-wise more convenient Iterator is also the reason I decided against implementing IntoIterator
as it forces you to yield Object
-type items. (This restriction could be lifted, if ListModel
itself had the correct type parameter.)
The Iterator gives always sensible results, even if the model underneath it changes. That means no duplicates or unnecessary omissions. It accomplishes that cheaply by listening to the items-changed
signal of the underlying model and adjusting its internal index accordingly.
Implementing DoubleEndedIterator
and ExactSizeIterator
should be possible, too, I might do that after a round of feedback.
What happens when an item gets removed while you're iterating through the list model?
What happens when an item gets removed while you're iterating through the list model?
Funny, I asked the same question. I also asked for an alternative: what happens if you remove the current item and all the following ones?
First of all, the iterator never panics.
What happens when an item gets removed while you're iterating through the list model?
The iterator does the natural thing and continues relative to the items it was working on before the change of model. More specifically, I differentiate three cases: before, after and inside the change. The before and after cases continue relative to where they were before. For the inside case, I used the hopefully least unexpected thing and skip to after the change. The exact function of adjusting the underlying index can be seen at adjust_index
.
what happens if you remove the current item and all the following ones?
The next
method of the iterator returns None
, so the iteration ends when it is called the next time.
I think a test case that ensures that it works as expected is needed here
This definitely needs many tests and documentation for the behaviour, and some justification why this is the right behaviour. @bilelmoussaoui as someone actually doing things with list models, would this behaviour be the one you would expect?
@GuillaumeGomez @bilelmoussaoui What do you think, which behaviour would make most sense here? Personally I think the Result
/transactional way would make sense.
I'm new to this thread, so sorry if I've missed something.
Since a list model contains a list of GObjects, it's just a list of pointers. They're cheap to clone.
Can't we just get the entire list of GObjects in a sweep, put them in a Vec<glib::Object>
and then return Vec::into_iter
?
It's not the best solution, but hey, it works, it's transactional, and it's better than nothing. It can be improved later
That would be possible, yes.
That… yes. :sweat_smile:
That one is merged now but I'd still like to get something around this here in