I’ve been attempting to create an image grid using a grid view and a signal list factory. However, when I create the buttons that will hold the images, whenever the widget is rebound another signal handler is attached to it. I would use the unbind signal but for some reason every button already has 3 button clicked handlers even though they have been added to the list store only once. The only way I got around that is not creating the buttons in the setup and doing it instead in the bind. However, this causes the button widget to be deleted when it goes out of scope. I also tried doing all my setup in the setup signal but I need access to the items in the item store but when ever I try and access the item inside the ListItem in the connect setup signal the item is set to None. What can be done do that the signal handlers do no keep being added or the newly created widgets stay alive during the lifetime of the item inside the list store?
I’m using gtk4-rs with the 4_12 features.
image_signal_list_item_factory.connect_bind(clone!(
#[weak]
monitors_dropdown,
#[weak]
wallpaper_changers_dropdown,
#[weak]
settings,
move |_factory, item| {
let item = item.downcast_ref::<ListItem>().unwrap();
let button = item.child().and_downcast::<Button>().unwrap();
let entry = item.item().and_downcast::<BoxedAnyObject>().unwrap();
let image: Ref<GtkPictureFile> = entry.borrow();
let path = image.clone().chache_image_file.path;
button.set_size_request(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT);
let previous_wallpapers_text_buffer = previous_wallpapers_text_buffer.clone();
button.connect_clicked(clone!(
#[strong]
path,
move |_| {
let path = path.clone();
let selected_monitor = monitors_dropdown
.selected_item()
.unwrap()
.downcast::<StringObject>()
.unwrap()
.string()
.to_string();
let selected_changer =
get_selected_changer(&wallpaper_changers_dropdown, &settings);
let mut previous_wallpapers = serde_json::from_str::<Vec<Wallpaper>>(
&gschema_string_to_string(settings.string("saved-wallpapers").as_ref()),
)
.unwrap();
let mut new_monitor_wallpapers: Vec<Wallpaper> = vec![];
if !previous_wallpapers
.iter()
.any(|w| w.monitor == selected_monitor.clone())
{
new_monitor_wallpapers.push(Wallpaper {
monitor: selected_monitor.clone(),
path: path.clone(),
changer: selected_changer.clone(),
})
}
for wallpaper in &mut previous_wallpapers {
if wallpaper.monitor == selected_monitor {
wallpaper.path = path.clone();
wallpaper.changer = selected_changer.clone();
}
}
previous_wallpapers.append(&mut new_monitor_wallpapers);
let previous_wallpapers = previous_wallpapers
.clone()
.into_iter()
.map(|w| Wallpaper {
monitor: w.monitor,
path: w.path,
changer: selected_changer.clone(),
})
.collect::<Vec<_>>();
debug!(
"{}: {:#?}",
gettext("Saved wallpapers"),
previous_wallpapers
);
let saved_wallpapers = string_to_gschema_string(
&serde_json::to_string::<Vec<Wallpaper>>(&previous_wallpapers).unwrap(),
);
previous_wallpapers_text_buffer.set_text(&saved_wallpapers);
debug!("{}: {}", gettext("Stored Text"), saved_wallpapers);
selected_changer
.clone()
.change(PathBuf::from(&path.clone()), selected_monitor.clone())
}
));
button.set_tooltip_text(Some(&image.chache_image_file.name));
button.set_child(Some(&image.picture));
}
));