From 629e4236fd9f987093f86dfed33c250d8305e8ee Mon Sep 17 00:00:00 2001 From: jimbrankelly Date: Mon, 21 Oct 2024 20:45:19 -0500 Subject: [PATCH 1/8] Create ListBox-Sorted-StringList-model Modified version of the ListBox-Model example using a StringList that is sorted. The StringSorter object uses a PropertyExpression to specify the sorted parameter. Delete button is functional but l suspect wrong entry is deleted. It is not needed for my use case, but it would be good to have it function correctly. Add button is not functional but might be a nice addition to the example. --- examples/ListBox-Sorted-StringList-model | 126 +++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 examples/ListBox-Sorted-StringList-model diff --git a/examples/ListBox-Sorted-StringList-model b/examples/ListBox-Sorted-StringList-model new file mode 100644 index 000000000000..a749fac41a93 --- /dev/null +++ b/examples/ListBox-Sorted-StringList-model @@ -0,0 +1,126 @@ +// Variation on ListBox model example to show use of StringList and StringSorter. +// Issues: list disply doesn't update correctly on delete. + +// TODO: add a dialog window to allow adding rows. +// use plain gtk::Window for this per current practice. + +use gtk::{ + glib::{self, clone}, + prelude::*, +}; + +fn main() -> glib::ExitCode { + let application = gtk::Application::builder() + .application_id("com.github.gtk-rs.examples.listbox-sorted-StringList") + .build(); + + application.connect_activate(build_ui); + + application.run() +} + +fn build_ui(application: >k::Application) { + let window = gtk::ApplicationWindow::builder() + .default_width(320) + .default_height(480) + .application(application) + .title("Sorted StringList") + .build(); + + let vbox = gtk::Box::new(gtk::Orientation::Vertical, 5); + + // Create a StringSorter with a property expression to sort + // StringObjects in a StringList. StringObject has a "string" property. + let expression = gtk::PropertyExpression::new( + gtk::StringObject::static_type(), + None::, + "string"); + let sorter = gtk::StringSorter::new(Some(expression)); + sorter.set_ignore_case(true); + + // Create our list store as a StringList and populate with some strings. + let model = gtk::StringList::new(&["zoo", "abba", "donkey", "sunrise", "river", "phoenix"]); + + // Create a sort model and bind it to the ListStore and the sorter. + let sort_model = gtk::SortListModel::new( + Some(model.clone()), + Some(sorter.clone())); + + // And then create the UI part, the listbox and bind the sort + // model to it. Whenever the UI needs to show a new row, e.g. because + // it was notified that the model changed, it will call the callback + // with the corresponding item from the model and will ask for a new + // gtk::ListBoxRow that should be displayed. + // + // The gtk::ListBoxRow can contain any possible widgets. + // Here we use an Inscription. + + let listbox = gtk::ListBox::new(); + listbox.bind_model( + Some(&sort_model), + clone!( + #[weak(rename_to = _panel)] + window, + #[upgrade_or_panic] + move |obj| { + let list_object = obj + .downcast_ref::() + .expect("The object should be of type `StringObject`."); + let row = gtk::Inscription::new(Some(&list_object.string())); + row.set_xalign(0.0); + row.upcast() + } + ), + ); + + let scrolled_window = gtk::ScrolledWindow::builder() + .hscrollbar_policy(gtk::PolicyType::Never) // Disable horizontal scrolling + .min_content_height(480) + .min_content_width(360) + .build(); + + scrolled_window.set_child(Some(&listbox)); + + let hbox = gtk::Box::new(gtk::Orientation::Horizontal, 5); + + // The add button opens a new dialog which is basically the same as the edit + // dialog, except that we don't have a corresponding item yet at that point + // and only create it once the Ok button in the dialog is clicked, and only + // then add it to the model. Once added to the model, it will immediately + // appear in the listbox UI + let add_button = gtk::Button::with_label("Add"); + add_button.set_sensitive(false); + + hbox.append(&add_button); + + // Via the delete button we delete the item from the model that + // is at the index of the selected row. Also deleting from the + // model is immediately reflected in the listbox. + let delete_button = gtk::Button::with_label("Delete"); + delete_button.connect_clicked(clone!( + #[weak] + model, + #[weak] + listbox, + move |_| { + let selected = listbox.selected_row(); + + if let Some(selected) = selected { + let idx = selected.index(); + model.remove(idx as u32); + } + } + )); + hbox.append(&delete_button); + + vbox.append(&hbox); + vbox.append(&scrolled_window); + + window.set_child(Some(&vbox)); + + for i in 0..10 { + model.append(&format!("Name {i}")); + } + + window.present(); +} From c3a57df0dbf474173accb077cb897f8b924bef85 Mon Sep 17 00:00:00 2001 From: jimbrankelly Date: Tue, 22 Oct 2024 02:12:59 -0500 Subject: [PATCH 2/8] Update ListBox-Sorted-StringList-model Revised so that correct model entry is deleted when delete button is pressed. --- examples/ListBox-Sorted-StringList-model | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/examples/ListBox-Sorted-StringList-model b/examples/ListBox-Sorted-StringList-model index a749fac41a93..316582a5ab72 100644 --- a/examples/ListBox-Sorted-StringList-model +++ b/examples/ListBox-Sorted-StringList-model @@ -1,5 +1,5 @@ // Variation on ListBox model example to show use of StringList and StringSorter. -// Issues: list disply doesn't update correctly on delete. +// Issues: list display doesn't update correctly on delete. // TODO: add a dialog window to allow adding rows. // use plain gtk::Window for this per current practice. @@ -106,8 +106,26 @@ fn build_ui(application: >k::Application) { let selected = listbox.selected_row(); if let Some(selected) = selected { - let idx = selected.index(); - model.remove(idx as u32); + let selected = selected.child() + .expect("Listrow child should be a widget"); + let selected = selected.downcast_ref::() + .expect("The object should be of type `Inscription`."); + if let Some(selected) = selected.text() { + let mut selected_index = None; + for ind in 0..model.n_items() { + if let Some(item) = model.item(ind) { + let item = item.downcast_ref::() + .expect("Object should be a stringobject"); + if item.string() == selected { + selected_index = Some(ind); + break; + } + } + } + if let Some(index) = selected_index { + model.remove(index); + } + } } } )); From 34386f3d27dd0c5395bc10fbff75e002c5296330 Mon Sep 17 00:00:00 2001 From: jimbrankelly Date: Tue, 22 Oct 2024 17:12:50 +0000 Subject: [PATCH 3/8] Adding README and main.rs --- examples/listbox_sort_stringlist/README.md | 15 +++ examples/listbox_sort_stringlist/main.rs | 147 +++++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 examples/listbox_sort_stringlist/README.md create mode 100644 examples/listbox_sort_stringlist/main.rs diff --git a/examples/listbox_sort_stringlist/README.md b/examples/listbox_sort_stringlist/README.md new file mode 100644 index 000000000000..9b8f880087c7 --- /dev/null +++ b/examples/listbox_sort_stringlist/README.md @@ -0,0 +1,15 @@ +# ListBox and StringListModel with Sorter example + +This example demonstrates how to use `gtk::ListBox` in combination with +a StringList model and StringSorter with a PropertyExpression. + +It sets up a `gtk::ListBox` containing an Inscription on each row. +The rows are sorted alphabetically. + +In addition, it is possible to delete rows. + +Run it by executing: + +```bash +cargo run --bin list_box_sort_stringlist +`` diff --git a/examples/listbox_sort_stringlist/main.rs b/examples/listbox_sort_stringlist/main.rs new file mode 100644 index 000000000000..f521c8fcf155 --- /dev/null +++ b/examples/listbox_sort_stringlist/main.rs @@ -0,0 +1,147 @@ +// Variation on ListBox model example to show use of StringList and StringSorter. + +// TODO: add a dialog window to allow adding rows. +// use plain gtk::Window for this per current practice. + +use gtk::{ + glib::{self, clone}, + prelude::*, +}; + +fn main() -> glib::ExitCode { + let application = gtk::Application::builder() + .application_id("com.github.gtk-rs.examples.listbox-sorted-StringList") + .build(); + + application.connect_activate(build_ui); + + application.run() +} + +fn build_ui(application: >k::Application) { + let window = gtk::ApplicationWindow::builder() + .default_width(320) + .default_height(480) + .application(application) + .title("Sorted StringList") + .build(); + + let vbox = gtk::Box::new(gtk::Orientation::Vertical, 5); + + // Create a StringSorter with a property expression to sort + // StringObjects in a StringList. StringObject has a "string" property. + let expression = gtk::PropertyExpression::new( + gtk::StringObject::static_type(), + None::, + "string"); + let sorter = gtk::StringSorter::new(Some(expression)); + sorter.set_ignore_case(true); + + // Create our list store as a StringList and populate with some strings. + let model = gtk::StringList::new(&["zoo", "abba", "donkey", "sunrise", "river", "phoenix"]); + + // Create a sort model and bind it to the ListStore and the sorter. + let sort_model = gtk::SortListModel::new( + Some(model.clone()), + Some(sorter.clone())); + + // And then create the UI part, the listbox and bind the sort + // model to it. Whenever the UI needs to show a new row, e.g. because + // it was notified that the model changed, it will call the callback + // with the corresponding item from the model and will ask for a new + // gtk::ListBoxRow that should be displayed. + // + // The gtk::ListBoxRow can contain any possible widgets. + // Here we use an Inscription. + + let listbox = gtk::ListBox::new(); + listbox.bind_model( + Some(&sort_model), + clone!( + #[weak(rename_to = _panel)] + window, + #[upgrade_or_panic] + move |obj| { + let list_object = obj + .downcast_ref::() + .expect("The object should be of type `StringObject`."); + let row = gtk::Inscription::new(Some(&list_object.string())); + row.set_xalign(0.0); + row.upcast() + } + ), + ); + + let scrolled_window = gtk::ScrolledWindow::builder() + .hscrollbar_policy(gtk::PolicyType::Never) // Disable horizontal scrolling + .min_content_height(480) + .min_content_width(360) + .build(); + + scrolled_window.set_child(Some(&listbox)); + + let hbox = gtk::Box::new(gtk::Orientation::Horizontal, 5); + + // The add button opens a new dialog which is basically the same as the edit + // dialog, except that we don't have a corresponding item yet at that point + // and only create it once the Ok button in the dialog is clicked, and only + // then add it to the model. Once added to the model, it will immediately + // appear in the listbox UI + let add_button = gtk::Button::with_label("Add"); + add_button.set_sensitive(false); + + hbox.append(&add_button); + + // Via the delete button we delete the item from the model that + // is at the index of the selected row. Also deleting from the + // model is immediately reflected in the listbox. + let delete_button = gtk::Button::with_label("Delete"); + delete_button.connect_clicked(clone!( + #[weak] + model, + #[weak] + listbox, + move |_| { + let selected = listbox.selected_row(); + //let sorted_model = listbox.model(); + + if let Some(selected) = selected { + // Find the selected text. + let selected = selected.child() + .expect("Listrow child should be a widget"); + let selected = selected.downcast_ref::() + .expect("The object should be of type `Inscription`."); + if let Some(selected) = selected.text() { + let mut selected_index = None; + // Find the position in the StringList model of the selected string + for ind in 0..model.n_items() { + if let Some(item) = model.item(ind) { + let item = item.downcast_ref::() + .expect("Object should be a stringobject"); + if item.string() == selected { + selected_index = Some(ind); + break; + } + } + } + // If the selected string is found in the stringlist model, delete it + if let Some(index) = selected_index { + model.remove(index); + } + } + } + } + )); + hbox.append(&delete_button); + + vbox.append(&hbox); + vbox.append(&scrolled_window); + + window.set_child(Some(&vbox)); + + for i in 0..10 { + model.append(&format!("Name {i}")); + } + + window.present(); +} From cecb8322ea264b286e93224dc49dee25e4ae5426 Mon Sep 17 00:00:00 2001 From: jimbrankelly Date: Tue, 22 Oct 2024 17:28:46 +0000 Subject: [PATCH 4/8] Updated cargo.toml and examples README --- examples/Cargo.toml | 5 + examples/ListBox-Sorted-StringList-model | 144 ----------------------- examples/README.md | 1 + 3 files changed, 6 insertions(+), 144 deletions(-) delete mode 100644 examples/ListBox-Sorted-StringList-model diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 38a8211b87e5..03efa065bf75 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -160,6 +160,11 @@ name = "gtk_builder" path = "gtk_builder/main.rs" required-features = ["v4_10"] +[[bin]] +name = "listbox_sort_stringlist" +path = "listbox_sort_stringlist/main.rs" +required-features = ["v4_14"] + [[bin]] name = "list_box_model" path = "list_box_model/main.rs" diff --git a/examples/ListBox-Sorted-StringList-model b/examples/ListBox-Sorted-StringList-model deleted file mode 100644 index 316582a5ab72..000000000000 --- a/examples/ListBox-Sorted-StringList-model +++ /dev/null @@ -1,144 +0,0 @@ -// Variation on ListBox model example to show use of StringList and StringSorter. -// Issues: list display doesn't update correctly on delete. - -// TODO: add a dialog window to allow adding rows. -// use plain gtk::Window for this per current practice. - -use gtk::{ - glib::{self, clone}, - prelude::*, -}; - -fn main() -> glib::ExitCode { - let application = gtk::Application::builder() - .application_id("com.github.gtk-rs.examples.listbox-sorted-StringList") - .build(); - - application.connect_activate(build_ui); - - application.run() -} - -fn build_ui(application: >k::Application) { - let window = gtk::ApplicationWindow::builder() - .default_width(320) - .default_height(480) - .application(application) - .title("Sorted StringList") - .build(); - - let vbox = gtk::Box::new(gtk::Orientation::Vertical, 5); - - // Create a StringSorter with a property expression to sort - // StringObjects in a StringList. StringObject has a "string" property. - let expression = gtk::PropertyExpression::new( - gtk::StringObject::static_type(), - None::, - "string"); - let sorter = gtk::StringSorter::new(Some(expression)); - sorter.set_ignore_case(true); - - // Create our list store as a StringList and populate with some strings. - let model = gtk::StringList::new(&["zoo", "abba", "donkey", "sunrise", "river", "phoenix"]); - - // Create a sort model and bind it to the ListStore and the sorter. - let sort_model = gtk::SortListModel::new( - Some(model.clone()), - Some(sorter.clone())); - - // And then create the UI part, the listbox and bind the sort - // model to it. Whenever the UI needs to show a new row, e.g. because - // it was notified that the model changed, it will call the callback - // with the corresponding item from the model and will ask for a new - // gtk::ListBoxRow that should be displayed. - // - // The gtk::ListBoxRow can contain any possible widgets. - // Here we use an Inscription. - - let listbox = gtk::ListBox::new(); - listbox.bind_model( - Some(&sort_model), - clone!( - #[weak(rename_to = _panel)] - window, - #[upgrade_or_panic] - move |obj| { - let list_object = obj - .downcast_ref::() - .expect("The object should be of type `StringObject`."); - let row = gtk::Inscription::new(Some(&list_object.string())); - row.set_xalign(0.0); - row.upcast() - } - ), - ); - - let scrolled_window = gtk::ScrolledWindow::builder() - .hscrollbar_policy(gtk::PolicyType::Never) // Disable horizontal scrolling - .min_content_height(480) - .min_content_width(360) - .build(); - - scrolled_window.set_child(Some(&listbox)); - - let hbox = gtk::Box::new(gtk::Orientation::Horizontal, 5); - - // The add button opens a new dialog which is basically the same as the edit - // dialog, except that we don't have a corresponding item yet at that point - // and only create it once the Ok button in the dialog is clicked, and only - // then add it to the model. Once added to the model, it will immediately - // appear in the listbox UI - let add_button = gtk::Button::with_label("Add"); - add_button.set_sensitive(false); - - hbox.append(&add_button); - - // Via the delete button we delete the item from the model that - // is at the index of the selected row. Also deleting from the - // model is immediately reflected in the listbox. - let delete_button = gtk::Button::with_label("Delete"); - delete_button.connect_clicked(clone!( - #[weak] - model, - #[weak] - listbox, - move |_| { - let selected = listbox.selected_row(); - - if let Some(selected) = selected { - let selected = selected.child() - .expect("Listrow child should be a widget"); - let selected = selected.downcast_ref::() - .expect("The object should be of type `Inscription`."); - if let Some(selected) = selected.text() { - let mut selected_index = None; - for ind in 0..model.n_items() { - if let Some(item) = model.item(ind) { - let item = item.downcast_ref::() - .expect("Object should be a stringobject"); - if item.string() == selected { - selected_index = Some(ind); - break; - } - } - } - if let Some(index) = selected_index { - model.remove(index); - } - } - } - } - )); - hbox.append(&delete_button); - - vbox.append(&hbox); - vbox.append(&scrolled_window); - - window.set_child(Some(&vbox)); - - for i in 0..10 { - model.append(&format!("Name {i}")); - } - - window.present(); -} diff --git a/examples/README.md b/examples/README.md index f57a0befa2b2..840bc3d263dd 100644 --- a/examples/README.md +++ b/examples/README.md @@ -39,6 +39,7 @@ cargo run --bin basics - [Glium GL-Area](./glium_gl_area/) - [Grid Packing](./grid_packing) - [GtkBuilder example](./gtk_builder/) +- [ListModel: StringList with Sorter](./listbox_sort_stringlist/) - [ListView: Applications Launcher](./list_view_apps_launcher/) - [Rotation Bin](./rotation_bin/) - [Scale](./scale/) From b1d3b85d72591357762fc8cee8e64f17712c2b3e Mon Sep 17 00:00:00 2001 From: Jim Kelly Date: Sun, 27 Oct 2024 09:29:00 -0500 Subject: [PATCH 5/8] ran rustfmt --- examples/listbox_sort_stringlist/main.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/listbox_sort_stringlist/main.rs b/examples/listbox_sort_stringlist/main.rs index f521c8fcf155..6a9f01e69f29 100644 --- a/examples/listbox_sort_stringlist/main.rs +++ b/examples/listbox_sort_stringlist/main.rs @@ -28,12 +28,13 @@ fn build_ui(application: >k::Application) { let vbox = gtk::Box::new(gtk::Orientation::Vertical, 5); - // Create a StringSorter with a property expression to sort + // Create a StringSorter with a property expression to sort // StringObjects in a StringList. StringObject has a "string" property. let expression = gtk::PropertyExpression::new( gtk::StringObject::static_type(), None::, - "string"); + "string", + ); let sorter = gtk::StringSorter::new(Some(expression)); sorter.set_ignore_case(true); @@ -41,9 +42,7 @@ fn build_ui(application: >k::Application) { let model = gtk::StringList::new(&["zoo", "abba", "donkey", "sunrise", "river", "phoenix"]); // Create a sort model and bind it to the ListStore and the sorter. - let sort_model = gtk::SortListModel::new( - Some(model.clone()), - Some(sorter.clone())); + let sort_model = gtk::SortListModel::new(Some(model.clone()), Some(sorter.clone())); // And then create the UI part, the listbox and bind the sort // model to it. Whenever the UI needs to show a new row, e.g. because @@ -107,17 +106,18 @@ fn build_ui(application: >k::Application) { if let Some(selected) = selected { // Find the selected text. - let selected = selected.child() - .expect("Listrow child should be a widget"); - let selected = selected.downcast_ref::() - .expect("The object should be of type `Inscription`."); + let selected = selected.child().expect("Listrow child should be a widget"); + let selected = selected + .downcast_ref::() + .expect("The object should be of type `Inscription`."); if let Some(selected) = selected.text() { let mut selected_index = None; // Find the position in the StringList model of the selected string for ind in 0..model.n_items() { if let Some(item) = model.item(ind) { - let item = item.downcast_ref::() - .expect("Object should be a stringobject"); + let item = item + .downcast_ref::() + .expect("Object should be a stringobject"); if item.string() == selected { selected_index = Some(ind); break; @@ -130,7 +130,7 @@ fn build_ui(application: >k::Application) { } } } - } + } )); hbox.append(&delete_button); From cc9858f002a5f665bc547795f2c963fe90b2bb76 Mon Sep 17 00:00:00 2001 From: jimbrankelly Date: Tue, 29 Oct 2024 05:23:04 -0500 Subject: [PATCH 6/8] Update examples/listbox_sort_stringlist/main.rs Co-authored-by: Bilal Elmoussaoui --- examples/listbox_sort_stringlist/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/listbox_sort_stringlist/main.rs b/examples/listbox_sort_stringlist/main.rs index 6a9f01e69f29..c0f77b34bbf5 100644 --- a/examples/listbox_sort_stringlist/main.rs +++ b/examples/listbox_sort_stringlist/main.rs @@ -10,7 +10,7 @@ use gtk::{ fn main() -> glib::ExitCode { let application = gtk::Application::builder() - .application_id("com.github.gtk-rs.examples.listbox-sorted-StringList") + .application_id("com.github.gtk-rs.examples.SortedStringList") .build(); application.connect_activate(build_ui); From e0b01a53a978c4f14f1136f6749dec9c8939d4a9 Mon Sep 17 00:00:00 2001 From: jimbrankelly Date: Tue, 29 Oct 2024 05:25:15 -0500 Subject: [PATCH 7/8] Update examples/listbox_sort_stringlist/main.rs Co-authored-by: Bilal Elmoussaoui --- examples/listbox_sort_stringlist/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/listbox_sort_stringlist/main.rs b/examples/listbox_sort_stringlist/main.rs index c0f77b34bbf5..785b793e2b99 100644 --- a/examples/listbox_sort_stringlist/main.rs +++ b/examples/listbox_sort_stringlist/main.rs @@ -42,7 +42,7 @@ fn build_ui(application: >k::Application) { let model = gtk::StringList::new(&["zoo", "abba", "donkey", "sunrise", "river", "phoenix"]); // Create a sort model and bind it to the ListStore and the sorter. - let sort_model = gtk::SortListModel::new(Some(model.clone()), Some(sorter.clone())); + let sort_model = gtk::SortListModel::new(Some(model.clone()), Some(sorter)); // And then create the UI part, the listbox and bind the sort // model to it. Whenever the UI needs to show a new row, e.g. because From 88602b573d5d31b62409fe4a1d056192a3189d63 Mon Sep 17 00:00:00 2001 From: Jim Kelly Date: Tue, 29 Oct 2024 10:53:53 -0500 Subject: [PATCH 8/8] Deleted add and delete buttons --- examples/listbox_sort_stringlist/main.rs | 59 ------------------------ 1 file changed, 59 deletions(-) diff --git a/examples/listbox_sort_stringlist/main.rs b/examples/listbox_sort_stringlist/main.rs index 785b793e2b99..ba9ef27bb483 100644 --- a/examples/listbox_sort_stringlist/main.rs +++ b/examples/listbox_sort_stringlist/main.rs @@ -1,8 +1,5 @@ // Variation on ListBox model example to show use of StringList and StringSorter. -// TODO: add a dialog window to allow adding rows. -// use plain gtk::Window for this per current practice. - use gtk::{ glib::{self, clone}, prelude::*, @@ -79,62 +76,6 @@ fn build_ui(application: >k::Application) { scrolled_window.set_child(Some(&listbox)); - let hbox = gtk::Box::new(gtk::Orientation::Horizontal, 5); - - // The add button opens a new dialog which is basically the same as the edit - // dialog, except that we don't have a corresponding item yet at that point - // and only create it once the Ok button in the dialog is clicked, and only - // then add it to the model. Once added to the model, it will immediately - // appear in the listbox UI - let add_button = gtk::Button::with_label("Add"); - add_button.set_sensitive(false); - - hbox.append(&add_button); - - // Via the delete button we delete the item from the model that - // is at the index of the selected row. Also deleting from the - // model is immediately reflected in the listbox. - let delete_button = gtk::Button::with_label("Delete"); - delete_button.connect_clicked(clone!( - #[weak] - model, - #[weak] - listbox, - move |_| { - let selected = listbox.selected_row(); - //let sorted_model = listbox.model(); - - if let Some(selected) = selected { - // Find the selected text. - let selected = selected.child().expect("Listrow child should be a widget"); - let selected = selected - .downcast_ref::() - .expect("The object should be of type `Inscription`."); - if let Some(selected) = selected.text() { - let mut selected_index = None; - // Find the position in the StringList model of the selected string - for ind in 0..model.n_items() { - if let Some(item) = model.item(ind) { - let item = item - .downcast_ref::() - .expect("Object should be a stringobject"); - if item.string() == selected { - selected_index = Some(ind); - break; - } - } - } - // If the selected string is found in the stringlist model, delete it - if let Some(index) = selected_index { - model.remove(index); - } - } - } - } - )); - hbox.append(&delete_button); - - vbox.append(&hbox); vbox.append(&scrolled_window); window.set_child(Some(&vbox));