I’m trying to have a tree view with a folder icon that is rendered open/closed depending if the item is expanded or not, but without success, first using the GTK-Crystal bindings, now using a minimal C example, what am I missing?
- I set the
is-expander
to true on GtkCellRendererPixbuf - I set the
expander-column
in tree view to the column I have the renderer. - I set the
pixbuf-expander-open
/pixbuf-expander-closed
properties to the GtkCellRendererPixbuf
Is something more needed? Is there a easier way to load a symbolic icon into a GdkPixbuf?
Here is the minimal C example I’m using to try to make this work, any help is appreciated:
#include <gtk/gtk.h>
#define MULTI_LINE_STRING(a) #a
const char* template = MULTI_LINE_STRING(
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk" version="4.0"/>
<object class="GtkTreeStore" id="tree_model">
<columns>
<column type="gchararray"/>
</columns>
</object>
<object class="GtkTreeView" id="tree_view">
<property name="vexpand">1</property>
<property name="model">tree_model</property>
<property name="expander-column">treeviewcolumn</property>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn">
<property name="title">Column</property>
<child>
<object class="GtkCellRendererPixbuf" id="pixbuf_renderer">
<property name="is-expander">1</property>
</object>
</child>
<child>
<object class="GtkCellRendererText"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
</object>
</interface>
);
void fill_model(GtkTreeStore* model) {
GtkTreeIter iter;
GtkTreeIter parent_iter;
gtk_tree_store_append(model, &parent_iter, NULL);
gtk_tree_store_set(model, &parent_iter, 0, "Root", -1);
gtk_tree_store_append(model, &iter, &parent_iter);
gtk_tree_store_set(model, &iter, 0, "Child", -1);
}
GdkPixbuf* load_pixbuf(GtkWidget* widget, const char* name) {
GtkIconTheme* theme = gtk_icon_theme_get_for_display(gtk_widget_get_display(widget));
GtkIconPaintable* icon = gtk_icon_theme_lookup_icon(theme, "folder-symbolic", NULL, 16, 1, GTK_TEXT_DIR_NONE, GTK_ICON_LOOKUP_FORCE_SYMBOLIC);
GFile* file = gtk_icon_paintable_get_file(icon);
char* file_path = g_file_get_path(file);
GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file(file_path, NULL);
g_free(file_path);
g_object_unref(file);
return pixbuf;
}
void activate(GtkApplication* app, gpointer data) {
GtkWindow* window = GTK_WINDOW(gtk_application_window_new(app));
g_object_set(G_OBJECT(window), "default-height", 480, "default-width", 640, NULL);
GtkBuilder* builder = gtk_builder_new_from_string(template, -1);
GtkTreeView* tree_view = GTK_TREE_VIEW(gtk_builder_get_object(builder, "tree_view"));
fill_model(GTK_TREE_STORE(gtk_tree_view_get_model(tree_view)));
// Setup tree view
GObject* renderer = gtk_builder_get_object(builder, "pixbuf_renderer");
GdkPixbuf* folder = load_pixbuf(GTK_WIDGET(tree_view), "folder-symbolic");
GdkPixbuf* open_folder = load_pixbuf(GTK_WIDGET(tree_view), "folder-open-symbolic");
g_object_set(renderer, "pixbuf-expander-open", open_folder, NULL);
g_object_set(renderer, "pixbuf-expander-closed", folder, NULL);
// Show everything
gtk_window_set_child(window, GTK_WIDGET(tree_view));
gtk_window_present(window);
g_object_unref(builder);
}
int main(int argc, char** argv) {
GtkApplication* app = gtk_application_new("example.bug", G_APPLICATION_FLAGS_NONE);
g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
return g_application_run(G_APPLICATION(app), argc, argv);
}
Can be compiled with: cc -o test main.c `pkg-config --cflags --libs gtk4`
And here is my total failure: