
#include <stdio.h>
#include <sys/time.h>
#include <gtk/gtk.h>

static GtkListStore *store;
static int n = 512;

static int timediff( struct timeval *large, struct timeval *small )
{
    return (   ( ( large->tv_sec * 1000 * 1000 ) + large->tv_usec )
             - ( ( small->tv_sec * 1000 * 1000 ) + small->tv_usec ) );
}

static void clear_elements (void)
{
    struct timeval before, after;

    gettimeofday (&before, 0);
    gtk_list_store_clear (store);
    gettimeofday (&after, 0);
    fprintf (stderr,
             "Clearing %d elements took %d usec (%.2f seconds).\n",
             n, timediff (&after, &before),
             ((double) timediff (&after, &before)) / (1000.0 * 1000.0));

    n *= 2;
}


static void add_elements (void)
{
    GtkTreeIter iter;
    struct timeval before, after;
    int i;

    gettimeofday (&before, 0);
    for (i = 0; i < n; i++) {
        gtk_list_store_append (store, &iter);
        gtk_list_store_set (store, &iter,
                            0, "this",
                            1, "works",
                            2, "great",
                            3, "and",
                            4, "is",
                            5, "super",
                            6, "fast",
                            -1);
    }
    gettimeofday (&after, 0);
    fprintf (stderr,
             "Adding %d elements took %d usec (%.2f seconds).\n",
             n, timediff (&after, &before),
             ((double) timediff (&after, &before)) / (1000.0 * 1000.0));

    gettimeofday (&before, 0);
    while (gtk_events_pending ()) gtk_main_iteration ();
    gettimeofday (&after, 0);
    fprintf (stderr,
             "Event loop took %d usec (%.2f seconds).\n",
             timediff (&after, &before),
             ((double) timediff (&after, &before)) / (1000.0 * 1000.0));
}

static void button_clicked (GtkWidget *widget, gpointer data)
{
    clear_elements ();
    add_elements ();
}

static void tree_selection_changed_cb (GtkTreeSelection *selection,
                                       gpointer data)
{
    static int count = 0;
    fprintf (stderr, "[%d] Selection changed.\n", count++);
}

int main (int argc, char **argv)
{
    GtkWidget *window;
    GtkCellRenderer *renderer;
    GtkTreeViewColumn *column;
    GtkTreeSelection *select;
    GtkWidget *tree;
    GtkWidget *scrolled;
    GtkWidget *vbox;
    GtkWidget *button;

    gtk_init (&argc, &argv);
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    g_signal_connect (G_OBJECT (window), "destroy",
                      G_CALLBACK (gtk_main_quit), 0);
    g_signal_connect (G_OBJECT (window), "delete_event",
                      G_CALLBACK (gtk_main_quit), 0);

    vbox = gtk_vbox_new (FALSE, 0);
    button = gtk_button_new_with_label ("Refresh list");
    g_signal_connect (G_OBJECT (button), "clicked",
                      G_CALLBACK (button_clicked), 0);
    gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);

    scrolled = gtk_scrolled_window_new (0, 0);
    store = gtk_list_store_new (7,
                                G_TYPE_STRING,
                                G_TYPE_STRING,
                                G_TYPE_STRING,
                                G_TYPE_STRING,
                                G_TYPE_STRING,
                                G_TYPE_STRING,
                                G_TYPE_STRING);
    tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));

    renderer = gtk_cell_renderer_text_new ();
    column = gtk_tree_view_column_new_with_attributes
               ("Column1", renderer, "text", 0, 0);
    gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
    gtk_tree_view_column_set_min_width (column, 40);
    gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
    renderer = gtk_cell_renderer_text_new ();
    column = gtk_tree_view_column_new_with_attributes
               ("Column2", renderer, "text", 1, 0);
    gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
    gtk_tree_view_column_set_min_width (column, 40);
    gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
    renderer = gtk_cell_renderer_text_new ();
    column = gtk_tree_view_column_new_with_attributes
               ("Column3", renderer, "text", 2, 0);
    gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
    gtk_tree_view_column_set_min_width (column, 40);
    gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
    renderer = gtk_cell_renderer_text_new ();
    column = gtk_tree_view_column_new_with_attributes
               ("Column4", renderer, "text", 3, 0);
    gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
    gtk_tree_view_column_set_min_width (column, 40);
    gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
    renderer = gtk_cell_renderer_text_new ();
    column = gtk_tree_view_column_new_with_attributes
               ("Column5", renderer, "text", 4, 0);
    gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
    gtk_tree_view_column_set_min_width (column, 40);
    gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
    renderer = gtk_cell_renderer_text_new ();
    column = gtk_tree_view_column_new_with_attributes
               ("Column6", renderer, "text", 5, 0);
    gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
    gtk_tree_view_column_set_min_width (column, 40);
    gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
    renderer = gtk_cell_renderer_text_new ();
    column = gtk_tree_view_column_new_with_attributes
               ("Column7", renderer, "text", 6, 0);
    gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
    gtk_tree_view_column_set_min_width (column, 40);
    gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);

    gtk_container_add (GTK_CONTAINER (scrolled), tree);
    gtk_container_add (GTK_CONTAINER (vbox), scrolled);
    gtk_container_add (GTK_CONTAINER (window), vbox);

    select = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree));
    gtk_tree_selection_set_mode (select, GTK_SELECTION_MULTIPLE);
    g_signal_connect (G_OBJECT (select), "changed",
                      G_CALLBACK (tree_selection_changed_cb),
                      0);

    add_elements ();

    gtk_widget_set_size_request (window, 400, 400);
    gtk_widget_show_all (window);

    gtk_main ();

    return 0;
}

