GTK library (extension) for directory listing build

Yet another question, related to this subject:

Maybe some high-level library exist to simply build the files tree in the directory with navigation features in parent/child members, sort order, file handler callback function?

I mean specialized library like GtkSourceView for TextBuffer

1 Like

Thanks, but I mean some widget, to simply build the list with the constructor, without create new separated columns, models, sort orderā€¦ Something like the completed directory viewer application but without the window frame

I want create local files navigation page in browser, not file open dialog

Hi,

You can use a Gtk.ListView with a Gtk.DirectoryList as model.

The DirectoryList will take care of building the files tree, automatically in the background.

Youā€™ll just have to implement a factory to create the row widgets, depending on what you wish to display (file name, icon, ā€¦).

2 Likes

Yes, thatā€™s it maybe! Thank you!

@gwillems could you please provide any example of DirectoryList implementation in C or Rust, or Python
because Iā€™m writing this code, and yet not understand what exactly DirectoryList model gives me, comparing to manual list factory:

let directory_list = gtk::DirectoryList::new(None, Some(file));
let selection_model = gtk::SingleSelection::new(Some(directory_list));
let factory = gtk::SignalListItemFactory::new();

factory.connect_setup(|_, list_item| {
    use gtk::prelude::{Cast, ListItemExt};
    let label = gtk::Label::new(Some("Item filename label"));
    list_item
        .downcast_ref::<gtk::ListItem>()
        .expect("Needs to be ListItem")
        .set_child(Some(&label));
});

let list_view = gtk::ListView::new(Some(selection_model), Some(factory));

I expect maybe some filename labels auto parsed there, but no, I want make it manually also. It is my first experience with GTK list building, so I really stuck with that. Found only this article, but it does not explain the DirectoryList implementation:

https://gtk-rs.org/gtk4-rs/stable/latest/book/list_widgets.html

Look at the gtk4-demo > Lists > File browser.

The DirectoryList is declared in a ui file, then initialized here.

The demo also declares a FileBrowserView type as abstraction for the 3 different views, but what really matters is just their factories (see the ui file).

The model is then packed in a GridView, but a ListView would also work.

1 Like

Thank you!

I never like XML templates, just found there only Iā€™m on the right way with current implementation, just wrongly expected File on cast from the ListItem, instead of FileInfo and did that in connect_setup not connect_bind event :slight_smile:

If somebody want short example, here is my working draft in Rust, with one Label test column:


let selection_model = gtk::SingleSelection::builder()
    .model(&gtk::DirectoryList::builder()
    .file(file)
    .attributes("standard::name,standard::display-name,standard::icon,standard::size,standard::content-type")
    .monitored(true)
    .build())
    .build();

let factory = gtk::SignalListItemFactory::new();

factory.connect_setup(|_, object| {
    use gtk::prelude::{Cast, ListItemExt};

    let label = gtk::Label::builder().halign(gtk::Align::Start).build();

    object
        .downcast_ref::<gtk::ListItem>()
        .unwrap()
        .set_child(Some(&label));
});

factory.connect_bind(|_, this| {
    use gtk::prelude::{Cast, ListItemExt};

    // Downcast requirements
    let list_item = this.downcast_ref::<gtk::ListItem>().unwrap();
    let item = list_item.item().unwrap();
    let file_info = item.downcast_ref::<gtk::gio::FileInfo>().unwrap();
    println!("{:?}", file_info.icon());
    println!("{:?}", file_info.name());

    let row = list_item.child().and_downcast_ref::<gtk::Label>().unwrap();
    //..
});

Just one thought: do I really want connect_bind method or maybe I can create column widgets like icons, filename, time, etc in the connect_setup? Thatā€™s strange I should init there empty Label, empty Imageā€¦ when the FileInfo already parsed by DirectoryList

1 Like

Yes, the items may be ā€œrecycledā€ by gtk, i.e. the widgets created in setup will be kept and bind again to another model element.

If you donā€™t use bind, then the row may not show the right values.

Theoretically you could ignore setup and do everything in bind, but as widgets creation is expensive you will get suboptimal performances.

1 Like

Thanks, already dropped setup as itā€™s really not wanted in this case, will use bind one instead!

One feature I canā€™t find yet, is the .. navigation to the parent. Is API option exist somewhere or I should use external widget to handle the parental navigation?

Thatā€™s a special folder, so makes sense itā€™s not listed by default.

Developers have the freedom to choose the back navigation method (Alt+up key, button, ā€¦) that suits their UI the best.

1 Like

Thatā€™s a special folder, so makes sense itā€™s not listed by default.

But cant I simply enable it?

The problem is model generated by DirectoryList backend, now I donā€™t know how to extract this element (if it really exist in the model list) from there, but maybe with push/prepend operation to SingleSelection or somewhere else, yet reading the docsā€¦

Iā€™m just working on local files browser in browser application. That is system feature, I would like to have this .. without any other UI buttons, Firefox already implements it, I want same.

Not sure itā€™s easily feasibleā€¦
Maybe with a separate listmodel with a single Gio.FileInfo for .. that you add in a new section (without header) of the listview/columnview.

1 Like

Well, thanks for info - will try to make it by the ā€˜hard wayā€™ so

Recently found that by enabling single_click_activate option, sometimes I have following warnings in CLI debug:

gtk_widget_compute_point: assertion 'GTK_IS_WIDGET (widget)' failed

And after some time I get core dumped error with application close. So I believe the setup implementation is really wanted, but yet not tried with it as removed. Just for info.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.