Skip to content

Commit

Permalink
Use optimized implementation of filter list using ordered hash set.
Browse files Browse the repository at this point in the history
  • Loading branch information
saivert committed May 9, 2024
1 parent 1958a8d commit 883c5fd
Showing 1 changed file with 30 additions and 34 deletions.
64 changes: 30 additions & 34 deletions src/backend/pwroutefiltermodel.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: GPL-3.0-or-later

use super::{ParamAvailability, PwRouteObject, RouteDirection};
use glib::{closure_local, subclass::prelude::*, Properties};
use gtk::{gio, prelude::*, subclass::prelude::*};
use std::cell::{Cell, RefCell};
use im_rc::Vector;
use super::{ParamAvailability, PwRouteObject, RouteDirection};
use std::collections::BTreeSet;

mod imp {
use super::*;
Expand All @@ -13,7 +13,7 @@ mod imp {
#[properties(wrapper_type = super::PwRouteFilterModel)]
pub struct PwRouteFilterModel {
/// Contains the items that matches the filter predicate.
pub(super) filtered_model: RefCell<Vector<PwRouteObject>>,
pub(super) hashset: RefCell<BTreeSet<u32>>,

#[property(get, set, construct_only, builder(RouteDirection::Unknown))]
pub(super) direction: Cell<RouteDirection>,
Expand All @@ -31,56 +31,56 @@ mod imp {
}

#[glib::derived_properties]
impl ObjectImpl for PwRouteFilterModel {
}
impl ObjectImpl for PwRouteFilterModel {}

impl ListModelImpl for PwRouteFilterModel {
fn item_type(&self) -> glib::Type {
PwRouteObject::static_type()
}
fn n_items(&self) -> u32 {
self.filtered_model.borrow().len() as u32
self.hashset.borrow().len() as u32
}
fn item(&self, position: u32) -> Option<glib::Object> {
self.filtered_model
.borrow()
.get(position as usize)
.map(|o| o.clone().upcast::<glib::Object>())
if let Some(pos) = self.hashset.borrow().iter().nth(position as usize) {
if let Some(model) = self.model.borrow().as_ref() {
return model.item(*pos);
};
};

None
}
}

impl PwRouteFilterModel {
pub fn set_model(&self, new_model: Option<&gio::ListModel>) {
let removed = self.filtered_model.borrow().len() as u32;

if let Some(new_model) = new_model {

assert!(self.item_type().is_a(new_model.item_type()));

let widget = self.obj();
let handler = closure_local!(@watch widget => move |listmodel: &gio::ListModel, _position: u32, _removed: u32, _added: u32| {
let u: Vector<PwRouteObject> = listmodel.iter::<PwRouteObject>()
let handler = closure_local!(@watch widget => move |listmodel: &gio::ListModel, position: u32, _removed: u32, _added: u32| {
let removed = widget.imp().hashset.borrow().len() as u32;

widget.imp().hashset.borrow_mut().clear();

for (a, routeobject) in listmodel.iter::<PwRouteObject>()
.skip(position as usize)
.map_while(Result::ok)
.filter(|routeobject| {
routeobject.direction() == widget.direction() && routeobject.availability() == ParamAvailability::Yes
})
.collect();

let removed = widget.imp().filtered_model.borrow().len() as u32;
let added = {
let mut filtered_model = widget.imp().filtered_model.borrow_mut();
filtered_model.clear();
filtered_model.append(u);
filtered_model.len() as u32
};
.enumerate() {
if routeobject.direction() == widget.direction() && routeobject.availability() == ParamAvailability::Yes {
widget.imp().hashset.borrow_mut().insert(a as u32);
}
}

let added = widget.imp().hashset.borrow().len() as u32;
widget.items_changed(0, removed, added);
});
handler.invoke::<()>(&[&new_model, &0u32, &0u32, &0u32]);
new_model.connect_closure("items-changed", true, handler);

self.model.replace(Some(new_model.clone().upcast()));
} else {
self.filtered_model.borrow_mut().clear();
self.hashset.borrow_mut().clear();
let removed = self.hashset.borrow().len() as u32;
self.obj().items_changed(0, removed, 0);
}
}
Expand All @@ -92,11 +92,7 @@ glib::wrapper! {
}

impl PwRouteFilterModel {
pub(crate) fn new(direction: RouteDirection, model: Option<&impl glib::IsA<gio::ListModel>>) -> Self
{
glib::Object::builder()
.property("model", model)
.property("direction", direction)
.build()
pub(crate) fn new(direction: RouteDirection, model: Option<&impl glib::IsA<gio::ListModel>>) -> Self {
glib::Object::builder().property("model", model).property("direction", direction).build()
}
}

0 comments on commit 883c5fd

Please sign in to comment.