Open stolen-programmer opened 1 year ago
You can filter that in native code with the FilterModel. Make a callback when the filter line is edited to update thebfilter. We should probably have an example with that (or a recipe in the docs)
Slint code:
import {VerticalBox, StandardTableView, GroupBox, LineEdit} from "std-widgets.slint";
export global TableViewPageAdapter {
in property <[[StandardListViewItem]]> row_data:
[
];
}
export global LineEditAdapter {
callback editing(string);
in property <string> line_edit_text: "";
}
export component AppWindow inherits Window {
title: "TableView";
width: 1800px;
height: 1000px;
VerticalBox {
horizontal-stretch: 1;
LineEdit {
edited(t) => {
LineEditAdapter.editing(t);
}
placeholder-text: "Filter by name";
}
GroupBox {
title: "Phone list";
horizontal-stretch: 0;
StandardTableView {
columns: [
{ title: "Name" },
{ title: "Phone" },
];
rows: TableViewPageAdapter.row_data;
}
}
}
}
Rust code:
use slint::{Model, ModelExt, StandardListViewItem, VecModel};
use std::rc::Rc;
slint::include_modules!();
struct Phone {
name: String,
phone: String,
}
fn main() -> Result<(), slint::PlatformError> {
let ui = AppWindow::new()?;
let phones_vec: Vec<Phone> = vec![
Phone {
name: String::from("Bob"),
phone: String::from("5555555"),
},
Phone {
name: String::from("John"),
phone: String::from("6666666"),
},
Phone {
name: String::from("Peter"),
phone: String::from("77777777"),
},
Phone {
name: String::from("Mike"),
phone: String::from("8888888888"),
},
];
let row_data: Rc<VecModel<slint::ModelRc<StandardListViewItem>>> = Rc::new(VecModel::default());
for phone in phones_vec.iter() {
let fields = Rc::new(VecModel::default());
fields.push(slint::format!("{}", &phone.name).into());
fields.push(slint::format!("{}", &phone.phone).into());
row_data.push(fields.into());
}
ui.global::<TableViewPageAdapter>()
.set_row_data(row_data.clone().into());
ui.global::<LineEditAdapter>().on_editing({
let ui_weak = ui.as_weak();
move |t| {
let row_data_filtered = Rc::new(row_data.clone().filter(move |row| {
// 0 is the first value of the row (name)
row.row_data(0).unwrap().text.to_lowercase().as_str().contains(t.to_lowercase().as_str())
}));
ui_weak.unwrap().global::<TableViewPageAdapter>().set_row_data(row_data_filtered.into());
}
});
ui.run()
}
This is somewhat different from the filtering I imagined When there are a large number of data entries, performance may be worrying (although this is not common)
I am new to Rust and Slint and I responded because I was looking for a solution for a day (more examples are needed) and in the end I found the solution myself based on the ordering functions in the example. In my application I use an array of about 10,000 x 100 strings to store plant records and the filtering is immediate (I don't know if in really large arrays it can slow down too much). I also thought that the array clonings (necessary because of the particularities of Rust) would be expensive, but if I'm not mistaken only pointers are cloned.
To show how to filter the columns of the
StandardTableView
an examples should be added to theTableViewPage
of the gallery. The page could be extended with aLineEdit
that allows to input text e.g. to filter the table columns byHeader 1
. To filter the columns a FilterModel can be used inmain.rs
andmain.cpp
. There is already aSortModel
used to sort the columns.originally description
I'm sorry, but if I missed anything, please let me know