[Gtk-rs] Widgets returning None even when they hold data

Question originally asked here. I have a filechoosernative and a comboboxtext in my UI. Now I am trying to extract data from those two inside callbacks but they are returning me None even though they clearly have data set by the user. Why is this happening?

Excerpt from https://gitlab.com/9898287/nixwriter/-/blob/rir/src/frontend/mod.rs#L41

    fn get_selected_file(&self) -> Option<std::path::PathBuf> {
        let selected_file = self.fcn.get_filename();
        dbg!(&selected_file);
        selected_file
    }

Excerpt from https://gitlab.com/9898287/nixwriter/-/blob/rir/src/frontend/mod.rs#L35

    fn get_selected_device(&self) -> Option<udisks::DiskDevice> {
        // Combo box text only stores a Gstring (Device ID)
        // Search through the list of devices from udisks2 again
        // and find the device with matching device ID

        let selected_device = match self.lsblk_cbt.get_active_text() {
            Some(txt) => {
                dbg!(&txt);
                for disk in crate::aux::backend::get_disks() {
                    if disk.drive.id == txt {
                        return Some(disk);
                    }
                }
                dbg!("No matching device found. Must reload.");
                None
            }
            None => {
                dbg!("lsblk_cbt is returning nothing");
                None
            }
        };
        dbg!(&selected_device);
        selected_device
    }

Both return None in https://gitlab.com/9898287/nixwriter/-/blob/rir/src/frontend/mod.rs#L110

    fn set_lsblk_cbt(&mut self) {
        let cbt = self.lsblk_cbt.clone();
        for ddev in crate::aux::backend::get_disks() {
            cbt.append_text(&ddev.drive.id);
        }
        let (device_chosen, file_chosen) = (
            self.get_selected_device().is_some(),
            self.get_selected_file().is_some(),
        );
        let start = self.start.clone();
        cbt.connect_changed(move |_| {
            start.set_sensitive(device_chosen && file_chosen);
            dbg!("From set_lsblk_cbt", device_chosen, file_chosen);
        });
    }

even after the user has set a file and selected an item from ComboboxText.

I'm taking a guess here, but you call set_lsblk_cbt during app initialization, and that calls get_selected_device and get_selected_file. It looks to me like you should be calling those methods inside of the closure passed to connect_changed so they will run each time, rather than outside of it where they will only run during app initialization.

I think you're right. But if I want to pass self into the closure, I have to create a clone to self to prevent the lifetime issue. Now I have to figure out what smart pointer Gtk-rs widgets are so my UI is clonable in the same fashion.


Update: It's Rc<RefCell<T>>. Works as expected.

It's actually really cheap to just clone a widget in Gtk and pass it in via a move closure. It just costs a pointer copy. There's a good page that describes Gtk-rs callbacks and closures here.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.