GTK+ Forums

Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
It is currently Wed Apr 23, 2014 8:58 pm

All times are UTC




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: GTk+ Book - Faulty Example?
PostPosted: Thu Jan 10, 2008 9:04 pm 
Offline
Familiar Face

Joined: Thu Jan 10, 2008 8:54 pm
Posts: 7
Hello,
I am going through the new Gtk Foundations book but have come across a problem with the exercise for chapter 8. In this exercise you are supposed to create a rudimentary file browser. I am using the code provided by the author (and given below) but it is not working properly. The file browser starts at root and you can click on a subdirectory to view its contents. However, once inside a subdirectory you cannot click on another subdirectory. I used some g_prints (not in the code below) to try to determine where the error is and it appears the the current_path list is not working as when you try to get the path from it is all garbled (if you try it you will understand). One idea I have is based on the current language setting but I have no real proof. Any ideas?

Code:
#include <gtk/gtk.h>



enum

{

  ICON = 0,

  FILENAME,

  COLUMNS

};



GList *current_path;



static void setup_tree_view (GtkWidget*);

static void setup_tree_model (GtkWidget*);

static void populate_tree_model (GtkWidget*);

static void row_activated (GtkTreeView*, GtkTreePath*,

                            GtkTreeViewColumn*, gpointer);



int main (int argc,

          char *argv[])

{

  GtkWidget *window, *treeview, *scrolled_win;

 

  gtk_init (&argc, &argv);

 

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

  gtk_window_set_title (GTK_WINDOW (window), "Exercise 8-1");

  gtk_container_set_border_width (GTK_CONTAINER (window), 10);

  gtk_widget_set_size_request (window, 250, 500);



  g_signal_connect (G_OBJECT (window), "destroy",

                    G_CALLBACK (gtk_main_quit), NULL);

 

  treeview = gtk_tree_view_new ();

 

  g_signal_connect (G_OBJECT (treeview), "row-activated",

                    G_CALLBACK (row_activated), NULL);

 

  setup_tree_view (treeview);

  setup_tree_model (treeview);

 

  scrolled_win = gtk_scrolled_window_new (NULL, NULL);

  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),

                                  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);

 

  gtk_container_add (GTK_CONTAINER (scrolled_win), treeview);

  gtk_container_add (GTK_CONTAINER (window), scrolled_win);

  gtk_widget_show_all (window);

 

  gtk_main ();

  return 0;

}



/* Create a tree view with only one column header, but two columns. */

static void

setup_tree_view (GtkWidget *treeview)

{

  GtkCellRenderer *renderer;

  GtkTreeViewColumn *column;

 

  column = gtk_tree_view_column_new ();

  gtk_tree_view_column_set_title (column, "File Browser");

 

  renderer = gtk_cell_renderer_pixbuf_new ();

  gtk_tree_view_column_pack_start (column, renderer, FALSE);

  gtk_tree_view_column_set_attributes (column, renderer, "pixbuf", ICON, NULL);

 

  renderer = gtk_cell_renderer_text_new ();

  gtk_tree_view_column_pack_start (column, renderer, TRUE);

  gtk_tree_view_column_set_attributes (column, renderer, "text", FILENAME, NULL);

 

  gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);

}



/* Setup the content of the tree model. */

static void

populate_tree_model (GtkWidget *treeview)

{

  GtkListStore *store;

  GtkTreeIter iter;

  GdkPixbuf *directory;

  gchar *location, *file;

  GList *temp;

  GDir *dir;

 

  store = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (treeview)));

  gtk_list_store_clear (store);

 

  /* Build the tree path out of current_path. */

  if (current_path == NULL)

    location = g_strdup ("/");

  else

  {

    temp = current_path;

    location = g_strconcat ("/", (gchar*) temp->data, NULL);

    temp = temp->next;



    while (temp != NULL)

    {

      location = g_strconcat (location, "/", (gchar*) temp->data, NULL);

      temp = temp->next;

    }

   

    directory = gdk_pixbuf_new_from_file ("directory.png", NULL);

    gtk_list_store_append (store, &iter);

    gtk_list_store_set (store, &iter, ICON, directory, FILENAME, "..", -1);

  }



  /* Parse through the directory, adding all of its contents to the model. */

  dir = g_dir_open (location, 0, NULL);

  while ((file = (gchar*) g_dir_read_name (dir)))

  {

    GdkPixbuf *pixbuf;

    gchar *temp = g_strconcat (location, "/", file, NULL);

   

    if (g_file_test (temp, G_FILE_TEST_IS_DIR))

      pixbuf = gdk_pixbuf_new_from_file ("directory.png", NULL);

    else

      pixbuf = gdk_pixbuf_new_from_file ("file.png", NULL);

   

    gtk_list_store_append (store, &iter);

    gtk_list_store_set (store, &iter, ICON, pixbuf, FILENAME, file, -1);
   

    g_object_unref (pixbuf);
    g_free (temp);

  }
 
  g_free (location);

}



/* Add the tree store, but the actual content is setup in populate_tree_model(). */

static void

setup_tree_model (GtkWidget *treeview)

{

  GtkListStore *store;

 

  store = gtk_list_store_new (COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING);

  gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL (store));

  g_object_unref (store);

 

  populate_tree_model (treeview);

}



static void

row_activated (GtkTreeView *treeview,

               GtkTreePath *path,

               GtkTreeViewColumn *column,

               gpointer data)

{

  GtkTreeModel *model;

  GtkTreeIter iter;

  gchar *file;



  model = gtk_tree_view_get_model (treeview);

  if (gtk_tree_model_get_iter (model, &iter, path))

  {

    gtk_tree_model_get (model, &iter, FILENAME, &file, -1);

   

    if (g_ascii_strcasecmp ("..", file) == 0)

    {

      GList *last = g_list_last (current_path);

      current_path = g_list_remove_link (current_path, last);

      g_list_free_1 (last);

      populate_tree_model (GTK_WIDGET (treeview));

    }

    else

    {

      gchar *location;

      GList *temp;



      if (current_path == NULL)

        location = "/";

      else

      {

        temp = current_path;

        location = g_strconcat ("/", (gchar*) temp->data, NULL);

        temp = temp->next;

     

        while (temp != NULL)

        {

          location = g_strconcat (location, "/", (gchar*) temp->data, NULL);

          temp = temp->next;

        }

       

        location = g_strconcat (location, "/", NULL);

      }



      location = g_strconcat (location, file, NULL);

      if (g_file_test (location, G_FILE_TEST_IS_DIR))

      {

        current_path = g_list_append (current_path, (gpointer) file);

        populate_tree_model (GTK_WIDGET (treeview));

      }   
     
      g_free (location);   

    }
   
    g_free (file);

  }

}



Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 10, 2008 10:41 pm 
Offline
Never Seen the Sunlight

Joined: Wed Sep 21, 2005 12:07 am
Posts: 563
Location: Portland, OR USA
I did the technical review on that book... this is not good. Not sure how I missed it.

In any case, I will work on it a bit when I have time and let Andrew know.

What your'e seeing which you thought was language problems (garbage) is an uninitialized string... there's a problem with that GList somewhere.

I'll update this post when I know more.

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


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 10, 2008 11:04 pm 
Offline
Never Seen the Sunlight

Joined: Wed Sep 21, 2005 12:07 am
Posts: 563
Location: Portland, OR USA
PS. There's a full file browser in the end. Chapter 13 has it's code.

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


Top
 Profile  
 
 Post subject: Got it!?
PostPosted: Fri Jan 11, 2008 12:24 am 
Offline
Familiar Face

Joined: Thu Jan 10, 2008 8:54 pm
Posts: 7
I removed the g_free(file) at the end of the row_activated function and then it worked!

Thanks
Nicholas


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 11, 2008 12:34 am 
Offline
Never Seen the Sunlight

Joined: Wed Sep 21, 2005 12:07 am
Posts: 563
Location: Portland, OR USA
That makes perfect sense. When the data is freed, the pointer still points to that bit of memory but the data is gone. So you get the garbage output.

Although I haven't looked, we still want to be careful. If the g_free call was part of a conditional where it IS supposed to be in some circumstances, then we could end up with a memory leak.

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


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

All times are UTC


Who is online

Users browsing this forum: No registered users and 3 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