Reputation: 31
I'm making an application on gtk4 and I have a need to display a table with 5 columns. I realized that now the best widget for this would be columnview, I found a small working example but only for outputting directory files and could only figure out half of it. Can anyone show a working example of a widget that accepts strings in C?
In the example, I tried to change the accepted type of the g_list_store_new function from G_TYPE_FILE_INFO to G_TYPE_STRING. But when starting the program, it gave an error.
Compilation : gcc -o a e.c $(pkg-config --cflags --libs gtk4)
File example link: github repository
Upvotes: 3
Views: 1239
Reputation: 1020
Views (such as GTKColumnView) display data from a model. In GTK4, there are generic list model implementations, such as GListStore, that allow you to create lists of arbitrary objects. To add multiple columns to a GListStore, you'll need to create a custom type that contains the data for each column. This type must be derived from GObject and have the appropriate properties for each column. You can then use the g_list_store_new() function to create a new GListStore with this type as a item_type. You'll also need one factory per column. Everything else can be found in the following listing.
/*
* The sole purpose of this program is to test some approaches to using
* columnview with GTK4 and C. It may contain errors and does not
* claim to be considered "best practice".
*/
#include<gtk/gtk.h>
#define CAPITAL_TYPE_ITEM (capital_item_get_type())
G_DECLARE_FINAL_TYPE (CapitalItem, capital_item, CAPITAL, ITEM, GObject)
struct _CapitalItem
{
GObject parent_instance;
const char *name;
const char *country;
const char *founded;
const char *population;
const char *area;
};
struct _CapitalItemClass
{
GObjectClass parent_class;
};
G_DEFINE_TYPE (CapitalItem, capital_item, G_TYPE_OBJECT)
static void capital_item_init(CapitalItem *item)
{
}
static void capital_item_class_init(CapitalItemClass *class)
{
}
static CapitalItem * capital_item_new(const char *name,
const char *country,
const char *founded,
const char *population,
const char *area )
{
CapitalItem *item = g_object_new(CAPITAL_TYPE_ITEM, NULL);
item->name = g_strdup(name);
item->country = g_strdup(country);
item->founded = g_strdup(founded);
item->population = g_strdup(population);
item->area = g_strdup(area);
return item;
}
// a funktion that creates a GListModel with capital_item objects
GListModel * create_capital_model(void)
{
GListStore *store = g_list_store_new(G_TYPE_OBJECT);
g_list_store_append(store, capital_item_new("Washington,D.C.","USA","1790","712,816","177"));
g_list_store_append(store, capital_item_new("London","Britain","43","8,799,800","1,572.03"));
g_list_store_append(store, capital_item_new("Paris","France","3rd c. BC","2,161,000","105"));
g_list_store_append(store, capital_item_new("Berlin","Germany","13th century","3,850,809","891.3"));
g_list_store_append(store, capital_item_new("Rome","Italy","753 BC","2,860,009","1,285"));
return G_LIST_MODEL(store);
}
static const char* capital_item_get_name(CapitalItem *item)
{
return item->name;
}
static const char* capital_item_get_country(CapitalItem *item)
{
return item->country;
}
static const char* capital_item_get_founded(CapitalItem *item)
{
return item->founded;
}
static const char* capital_item_get_population(CapitalItem *item)
{
return item->population;
}
static const char* capital_item_get_area(CapitalItem *item)
{
return item->area;
}
static void setup_cb(GtkSignalListItemFactory *factory,GObject *listitem)
{
GtkWidget *label =gtk_label_new(NULL);
gtk_list_item_set_child(GTK_LIST_ITEM(listitem),label);
}
static void bind_name_cb(GtkSignalListItemFactory *factory, GtkListItem *listitem)
{
GtkWidget *label = gtk_list_item_get_child(listitem);
GObject *item = gtk_list_item_get_item(GTK_LIST_ITEM(listitem));
const char *string = capital_item_get_name(CAPITAL_ITEM(item));
gtk_label_set_text(GTK_LABEL (label), string);
}
static void bind_country_cb(GtkSignalListItemFactory *factory, GtkListItem *listitem)
{
GtkWidget *label = gtk_list_item_get_child(listitem);
GObject *item = gtk_list_item_get_item(GTK_LIST_ITEM(listitem));
const char *string = capital_item_get_country(CAPITAL_ITEM(item));
gtk_label_set_text(GTK_LABEL (label), string);
}
static void bind_founded_cb(GtkSignalListItemFactory *factory, GtkListItem *listitem)
{
GtkWidget *label = gtk_list_item_get_child(listitem);
GObject *item = gtk_list_item_get_item(GTK_LIST_ITEM(listitem));
const char *string = capital_item_get_founded(CAPITAL_ITEM(item));
gtk_label_set_text(GTK_LABEL (label), string);
}
static void bind_population_cb(GtkSignalListItemFactory *factory, GtkListItem *listitem)
{
GtkWidget *label = gtk_list_item_get_child(listitem);
GObject *item = gtk_list_item_get_item(GTK_LIST_ITEM(listitem));
const char *string = capital_item_get_population(CAPITAL_ITEM(item));
gtk_label_set_text(GTK_LABEL (label), string);
}
static void bind_area_cb(GtkSignalListItemFactory *factory, GtkListItem *listitem)
{
GtkWidget *label = gtk_list_item_get_child(listitem);
GObject *item = gtk_list_item_get_item(GTK_LIST_ITEM(listitem));
const char *string = capital_item_get_area(CAPITAL_ITEM(item));
gtk_label_set_text(GTK_LABEL (label), string);
}
static void activate (GtkApplication *app, gpointer user_data)
{
GtkWidget *window;
GtkWidget *scrolled_window;
GtkListItemFactory *factory;
GListModel *model;
GtkSingleSelection *selection;
GtkColumnViewColumn *column;
GtkWidget *cv;
model = create_capital_model();
selection = gtk_single_selection_new(G_LIST_MODEL(model));
gtk_single_selection_set_autoselect(selection,TRUE);
window = gtk_application_window_new(app);
gtk_window_set_title (GTK_WINDOW(window), "ColumnView Example");
gtk_window_set_default_size (GTK_WINDOW(window), 470, 200);
scrolled_window = gtk_scrolled_window_new ();
gtk_window_set_child (GTK_WINDOW(window), scrolled_window);
cv = gtk_column_view_new(GTK_SELECTION_MODEL (selection));
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(scrolled_window),cv);
gtk_column_view_set_show_column_separators (GTK_COLUMN_VIEW (cv),TRUE);
// one factory for each column
factory = gtk_signal_list_item_factory_new();
g_signal_connect(factory, "setup", G_CALLBACK(setup_cb),NULL);
g_signal_connect(factory, "bind", G_CALLBACK(bind_name_cb),NULL);
column = gtk_column_view_column_new("capital city", factory);
gtk_column_view_append_column (GTK_COLUMN_VIEW (cv), column);
g_object_unref (column);
factory = gtk_signal_list_item_factory_new();
g_signal_connect(factory, "setup", G_CALLBACK(setup_cb),NULL);
g_signal_connect(factory, "bind", G_CALLBACK(bind_country_cb),NULL);
column = gtk_column_view_column_new("country", factory);
gtk_column_view_append_column (GTK_COLUMN_VIEW (cv), column);
g_object_unref (column);
factory = gtk_signal_list_item_factory_new();
g_signal_connect(factory, "setup", G_CALLBACK(setup_cb),NULL);
g_signal_connect(factory, "bind", G_CALLBACK(bind_founded_cb),NULL);
column = gtk_column_view_column_new("founded", factory);
gtk_column_view_append_column (GTK_COLUMN_VIEW (cv), column);
g_object_unref (column);
factory = gtk_signal_list_item_factory_new();
g_signal_connect(factory, "setup", G_CALLBACK(setup_cb),NULL);
g_signal_connect(factory, "bind", G_CALLBACK(bind_population_cb),NULL);
column = gtk_column_view_column_new("population", factory);
gtk_column_view_append_column (GTK_COLUMN_VIEW (cv), column);
g_object_unref (column);
factory = gtk_signal_list_item_factory_new();
g_signal_connect(factory, "setup", G_CALLBACK(setup_cb),NULL);
g_signal_connect(factory, "bind", G_CALLBACK(bind_area_cb),NULL);
column = gtk_column_view_column_new("area (km²)", factory);
gtk_column_view_append_column (GTK_COLUMN_VIEW (cv), column);
g_object_unref (column);
gtk_window_present (GTK_WINDOW (window));
}
int main (int argc, char **argv)
{
GtkApplication *app; int status;
app = gtk_application_new("org.gtk.columnview",G_APPLICATION_DEFAULT_FLAGS);
g_signal_connect(app, "activate",G_CALLBACK(activate),NULL);
status = g_application_run (G_APPLICATION(app), argc, argv);
g_object_unref(app);
return status;
}
Upvotes: 6