How to make GtkCellRendererPixbuf work as expander icon?

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:

BTW I just discovered that there’s a command line to transform the SVGs into symbolic PNGs, something that I believe should fix the coloring of the icons in the screenshot (let then tinted in white instead of black)

The name is gtk4-encode-symbolic-svg, for future reference.