GTK+ Forums

Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
It is currently Fri Apr 25, 2014 2:30 am

All times are UTC




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: Basic List View using GtkTreeView and GtkTreeStore (C)
PostPosted: Wed Nov 28, 2007 5:14 am 
Offline
Never Seen the Sunlight

Joined: Wed Sep 21, 2005 12:07 am
Posts: 563
Location: Portland, OR USA
Someone asked how to create a simple list view. Here's a demo. It uses the GtkTreeView with a GtkListStore.

I threw this together in a few minutes after a couple beers... so let me know if I did something stupid and I'll fix it later.

You can find out which item is selected using gtk_tree_view_get_selection() function.

Image
Code:
/*
main.c
Eexample of using a GtkTreeView as a simple list view.

Written by Micah Carrick for www.gtkforums.com

Compile:
cc -Wall -g main.c -o example `pkg-config --cflags --libs gtk+-2.0`
*/

#include <gtk/gtk.h>

enum
{
  LIST_ITEM = 0,
  N_COLUMNS
};

static void init_list (GtkWidget *list);
static void add_to_list (GtkWidget *list, const gchar *str);
static void remove_from_list_by_value (GtkWidget *list, const gchar *str);
static void remove_from_list (GtkWidget *list, gint index);

int main (int argc, char *argv[])
{

    GtkWidget           *window, *list, *sw;

    gtk_init (&argc, &argv);

    /* create widgets */
   
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    sw = gtk_scrolled_window_new (NULL, NULL);
    list = gtk_tree_view_new ();
   
    /* customize appearance */
   
    gtk_window_set_title (GTK_WINDOW (window), "List View");
    gtk_container_set_border_width (GTK_CONTAINER (window), 10);
    gtk_widget_set_size_request (window, 250, 150);
   
    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),

            GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
    gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
            GTK_SHADOW_ETCHED_IN);
   
    gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (list), FALSE);
   
    gtk_container_add (GTK_CONTAINER (sw), list);
    gtk_container_add (GTK_CONTAINER (window), sw);

    /* initialize */

    init_list (list);
    add_to_list (list, "Testing #1");
    add_to_list (list, "Testing #2");
    add_to_list (list, "Testing #3");
    add_to_list (list, "Testing #4");
    add_to_list (list, "Testing #5");
   
    remove_from_list_by_value (list, "Testing #2");     /* remove first match */
    remove_from_list (list, 3);                         /* remove the 4th item */
   
    /* #1, #3, and #5 should remain */
   
    /* connect signals */
    g_signal_connect (G_OBJECT (window), "destroy",
            G_CALLBACK (gtk_main_quit), NULL);

    /* show window */

    gtk_widget_show_all (window);

    gtk_main ();

    return 0;
}

static void
init_list (GtkWidget *list)
{

    GtkCellRenderer         *renderer;
    GtkTreeViewColumn       *column;
    GtkListStore            *store;

    /* create and append the single column */
   
    renderer = gtk_cell_renderer_text_new ();
    column = gtk_tree_view_column_new_with_attributes ("List Item",
            renderer, "text", LIST_ITEM, NULL);
    gtk_tree_view_append_column (GTK_TREE_VIEW (list), column);

    /* create the model and add to tree view */
   
    store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING);

    gtk_tree_view_set_model (GTK_TREE_VIEW (list), GTK_TREE_MODEL (store));
   
    /* free reference to the store */
   
    g_object_unref (store);
}

static void
add_to_list (GtkWidget *list, const gchar *str)
{
    GtkListStore            *store;
    GtkTreeIter             iter;
   
    store = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (list)));
   
    gtk_list_store_append (store, &iter);
    gtk_list_store_set (store, &iter, LIST_ITEM, str, -1);
}

static void
remove_from_list_by_value (GtkWidget *list, const gchar *str)
{
    GtkTreeModel            *model;
    GtkTreeIter             iter;
    gboolean                r;
    gchar                   *value;
   
    model = gtk_tree_view_get_model (GTK_TREE_VIEW (list));
   
    /*
    iterate model looking for str and then remove it... only removes the first
    one found. 
    */
   
    if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) return;
    for (r = gtk_tree_model_get_iter_first (model, &iter);
         r == TRUE;
         r = gtk_tree_model_iter_next (model, &iter))
    {               
        gtk_tree_model_get (model, &iter, LIST_ITEM, &value,  -1);
       
        if (g_ascii_strcasecmp(value, str) == 0)
        {
            gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
            break;
        }
       
        /* free the value once the compare is done */
        if (value) g_free (value);       
    }
}

static void
remove_from_list (GtkWidget *list, gint index)
{
    GtkTreeModel            *model;
    GtkTreeIter             iter;
    gint                    i;
   
    model = gtk_tree_view_get_model (GTK_TREE_VIEW (list));
   
    /* iterate model removing by and index (0-based) */
   
    if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) return;
    for (i=0; i < index; i++)
    {
        /* just do nothing if index is out of range */
        if (gtk_tree_model_iter_next (model, &iter) == FALSE) return;
    }
   
    gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
}

_________________
Micah Carrick - Forum Administrator
http://www.micahcarrick.com


Last edited by Micah Carrick on Fri Nov 30, 2007 10:04 pm, edited 4 times in total.

Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 29, 2007 1:26 am 
Offline
Familiar Face

Joined: Mon Aug 13, 2007 5:42 pm
Posts: 5
I think there is a mistake in the code. The comments indicate that the "remove" function should be 0 indexed, however after you call remove_from_list_by_value, then the remove_from_list with 3 as a parameter, it should remove "Testing #5" instead of "Testing #4" (since after the first remove, #5 is the 4th element in the list). I think this is because
Code:
    for (i=1; i < index; i++)

in the remove function should be changed to
Code:
    for (i=0; i < index; i++)

Other than that, I have not found errors in this code. Thank you for this, it has helped relieve a lot of frustration.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 29, 2007 1:31 am 
Offline
Never Seen the Sunlight

Joined: Wed Sep 21, 2005 12:07 am
Posts: 563
Location: Portland, OR USA
Good call. You're right.

_________________
Micah Carrick - Forum Administrator
http://www.micahcarrick.com


Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 29, 2007 4:01 pm 
Offline
Never Seen the Sunlight

Joined: Wed Sep 21, 2005 12:07 am
Posts: 563
Location: Portland, OR USA
I changed the for loop index it in the source listing.

_________________
Micah Carrick - Forum Administrator
http://www.micahcarrick.com


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 08, 2008 2:11 pm 
Offline

Joined: Tue Apr 08, 2008 9:11 am
Posts: 3
is it possible to use data from g_dir_open to be listed in the list?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 08, 2008 2:16 pm 
Offline
Never Seen the Sunlight

Joined: Wed Sep 21, 2005 12:07 am
Posts: 563
Location: Portland, OR USA
Yes, you can use g_dir_open and then loop through the names returned from g_dir_read_name and add each one. An entire file browser is built in Andrew Krause' Foundations of GTK+ Development.

_________________
Micah Carrick - Forum Administrator
http://www.micahcarrick.com


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group