#include <gtk/gtk.h>
#define ROWS 100000
static GtkTreeModelFlags list_model_get_flags (GtkTreeModel * model)
{
return GTK_TREE_MODEL_LIST_ONLY;
}
static int list_model_get_n_columns (GtkTreeModel * model)
{
return 3;
}
static GType list_model_get_column_type (GtkTreeModel * model, int column)
{
if (column < 0 || column > 2)
return G_TYPE_INVALID;
if (column == 0)
return G_TYPE_INT;
else
return G_TYPE_STRING;
}
static gboolean list_model_get_iter (GtkTreeModel * model, GtkTreeIter * iter,
GtkTreePath * path)
{
int row = gtk_tree_path_get_indices (path)[0];
if (row < 0 || row >= ROWS)
return FALSE;
iter->user_data = GINT_TO_POINTER (row);
return TRUE;
}
static GtkTreePath * list_model_get_path (GtkTreeModel * model, GtkTreeIter * iter)
{
int row = GPOINTER_TO_INT (iter->user_data);
if (row < 0 || row >= ROWS)
return NULL;
return gtk_tree_path_new_from_indices (row, -1);
}
static void list_model_get_value (GtkTreeModel * model, GtkTreeIter * iter,
int column, GValue * value)
{
int row = GPOINTER_TO_INT (iter->user_data);
if (column < 0 || column > 2 || row < 0 || row >= ROWS)
return;
if (column == 0)
{
g_value_init (value, G_TYPE_INT);
g_value_set_int (value, 1 + row);
}
else
{
g_value_init (value, G_TYPE_STRING);
g_value_set_string (value, (column == 1) ? "Hello, world!" : "Blah blah blah");
}
}
static gboolean list_model_iter_next (GtkTreeModel * model, GtkTreeIter * iter)
{
int row = GPOINTER_TO_INT (iter->user_data);
if (row < 0 || row >= ROWS - 1)
return FALSE;
iter->user_data = GINT_TO_POINTER (row + 1);
return TRUE;
}
static gboolean list_model_iter_children (GtkTreeModel * model,
GtkTreeIter * iter, GtkTreeIter * parent)
{
if (parent)
return FALSE;
iter->user_data = GINT_TO_POINTER (0);
return TRUE;
}
static gboolean list_model_iter_has_child (GtkTreeModel * model, GtkTreeIter * iter)
{
return FALSE;
}
static int list_model_iter_n_children (GtkTreeModel * model, GtkTreeIter * iter)
{
return iter ? 0 : ROWS;
}
static gboolean list_model_iter_nth_child (GtkTreeModel * model,
GtkTreeIter * iter, GtkTreeIter * parent, int n)
{
if (parent || n < 0 || n >= ROWS)
return FALSE;
iter->user_data = GINT_TO_POINTER (n);
return TRUE;
}
static gboolean list_model_iter_parent (GtkTreeModel * model,
GtkTreeIter * iter, GtkTreeIter * child)
{
return FALSE;
}
static void iface_init (void * _iface, void * unused)
{
GtkTreeModelIface * iface = _iface;
iface->get_flags = list_model_get_flags;
iface->get_n_columns = list_model_get_n_columns;
iface->get_column_type = list_model_get_column_type;
iface->get_iter = list_model_get_iter;
iface->get_path = list_model_get_path;
iface->get_value = list_model_get_value;
iface->iter_next = list_model_iter_next;
iface->iter_children = list_model_iter_children;
iface->iter_has_child = list_model_iter_has_child;
iface->iter_n_children = list_model_iter_n_children;
iface->iter_nth_child = list_model_iter_nth_child;
iface->iter_parent = list_model_iter_parent;
}
static const GInterfaceInfo iface_info = {
.interface_init = /* (GInterfaceInitFunc) */ iface_init,
.interface_finalize = NULL,
.interface_data = NULL};
static GType list_model_get_type (void)
{
static GType type = G_TYPE_INVALID;
if (type == G_TYPE_INVALID)
{
type = g_type_register_static_simple (G_TYPE_OBJECT, "MyListModel",
sizeof (GObjectClass), NULL, sizeof (GObject), NULL, 0);
g_type_add_interface_static (type, GTK_TYPE_TREE_MODEL, & iface_info);
}
return type;
}
int main (void)
{
gtk_init (NULL, NULL);
GtkWidget * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size ((GtkWindow *) window, 700, 500);
GtkWidget * scrolled = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy ((GtkScrolledWindow *) scrolled,
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
GObject * model = g_object_new (list_model_get_type (), NULL);
GtkWidget * list = gtk_tree_view_new_with_model ((GtkTreeModel *) model);
for (int col = 0; col < 3; col ++)
{
GtkCellRenderer * renderer = gtk_cell_renderer_text_new ();
GtkTreeViewColumn * column = gtk_tree_view_column_new_with_attributes
(NULL, renderer, "text", col, NULL);
gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
gtk_tree_view_column_set_fixed_width (column, 100);
gtk_tree_view_append_column ((GtkTreeView *) list, column);
}
gtk_container_add ((GtkContainer *) scrolled, list);
gtk_container_add ((GtkContainer *) window, scrolled);
gtk_widget_show_all (window);
g_signal_connect (window, "destroy", (GCallback) gtk_main_quit, NULL);
gtk_main ();
return 0;
}