326 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			326 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* Tree View/List Store
 | 
						|
 *
 | 
						|
 * The GtkListStore is used to store data in list form, to be used
 | 
						|
 * later on by a GtkTreeView to display it. This demo builds a
 | 
						|
 * simple GtkListStore and displays it. See the Stock Browser
 | 
						|
 * demo for a more advanced example.
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#include <gtk/gtk.h>
 | 
						|
 | 
						|
static GtkWidget *window = NULL;
 | 
						|
static GtkTreeModel *model = NULL;
 | 
						|
static guint timeout = 0;
 | 
						|
 | 
						|
typedef struct
 | 
						|
{
 | 
						|
  const gboolean  fixed;
 | 
						|
  const guint     number;
 | 
						|
  const gchar    *severity;
 | 
						|
  const gchar    *description;
 | 
						|
}
 | 
						|
Bug;
 | 
						|
 | 
						|
enum
 | 
						|
{
 | 
						|
  COLUMN_FIXED,
 | 
						|
  COLUMN_NUMBER,
 | 
						|
  COLUMN_SEVERITY,
 | 
						|
  COLUMN_DESCRIPTION,
 | 
						|
  COLUMN_PULSE,
 | 
						|
  COLUMN_ICON,
 | 
						|
  COLUMN_ACTIVE,
 | 
						|
  COLUMN_SENSITIVE,
 | 
						|
  NUM_COLUMNS
 | 
						|
};
 | 
						|
 | 
						|
static Bug data[] =
 | 
						|
{
 | 
						|
  { FALSE, 60482, "Normal",     "scrollable notebooks and hidden tabs" },
 | 
						|
  { FALSE, 60620, "Critical",   "gdk_window_clear_area (gdkwindow-win32.c) is not thread-safe" },
 | 
						|
  { FALSE, 50214, "Major",      "Xft support does not clean up correctly" },
 | 
						|
  { TRUE,  52877, "Major",      "GtkFileSelection needs a refresh method. " },
 | 
						|
  { FALSE, 56070, "Normal",     "Can't click button after setting in sensitive" },
 | 
						|
  { TRUE,  56355, "Normal",     "GtkLabel - Not all changes propagate correctly" },
 | 
						|
  { FALSE, 50055, "Normal",     "Rework width/height computations for TreeView" },
 | 
						|
  { FALSE, 58278, "Normal",     "gtk_dialog_set_response_sensitive () doesn't work" },
 | 
						|
  { FALSE, 55767, "Normal",     "Getters for all setters" },
 | 
						|
  { FALSE, 56925, "Normal",     "Gtkcalender size" },
 | 
						|
  { FALSE, 56221, "Normal",     "Selectable label needs right-click copy menu" },
 | 
						|
  { TRUE,  50939, "Normal",     "Add shift clicking to GtkTextView" },
 | 
						|
  { FALSE, 6112,  "Enhancement","netscape-like collapsable toolbars" },
 | 
						|
  { FALSE, 1,     "Normal",     "First bug :=)" },
 | 
						|
};
 | 
						|
 | 
						|
static gboolean
 | 
						|
spinner_timeout (gpointer data)
 | 
						|
{
 | 
						|
  GtkTreeIter iter;
 | 
						|
  guint pulse;
 | 
						|
 | 
						|
  if (model == NULL)
 | 
						|
    return G_SOURCE_REMOVE;
 | 
						|
 | 
						|
  gtk_tree_model_get_iter_first (model, &iter);
 | 
						|
  gtk_tree_model_get (model, &iter,
 | 
						|
                      COLUMN_PULSE, &pulse,
 | 
						|
                      -1);
 | 
						|
  if (pulse == G_MAXUINT)
 | 
						|
    pulse = 0;
 | 
						|
  else
 | 
						|
    pulse++;
 | 
						|
 | 
						|
  gtk_list_store_set (GTK_LIST_STORE (model),
 | 
						|
                      &iter,
 | 
						|
                      COLUMN_PULSE, pulse,
 | 
						|
                      COLUMN_ACTIVE, TRUE,
 | 
						|
                      -1);
 | 
						|
 | 
						|
  return G_SOURCE_CONTINUE;
 | 
						|
}
 | 
						|
 | 
						|
static GtkTreeModel *
 | 
						|
create_model (void)
 | 
						|
{
 | 
						|
  gint i = 0;
 | 
						|
  GtkListStore *store;
 | 
						|
  GtkTreeIter iter;
 | 
						|
 | 
						|
  /* create list store */
 | 
						|
  store = gtk_list_store_new (NUM_COLUMNS,
 | 
						|
                              G_TYPE_BOOLEAN,
 | 
						|
                              G_TYPE_UINT,
 | 
						|
                              G_TYPE_STRING,
 | 
						|
                              G_TYPE_STRING,
 | 
						|
                              G_TYPE_UINT,
 | 
						|
                              G_TYPE_STRING,
 | 
						|
                              G_TYPE_BOOLEAN,
 | 
						|
                              G_TYPE_BOOLEAN);
 | 
						|
 | 
						|
  /* add data to the list store */
 | 
						|
  for (i = 0; i < G_N_ELEMENTS (data); i++)
 | 
						|
    {
 | 
						|
      gchar *icon_name;
 | 
						|
      gboolean sensitive;
 | 
						|
 | 
						|
      if (i == 1 || i == 3)
 | 
						|
        icon_name = "battery-caution-charging-symbolic";
 | 
						|
      else
 | 
						|
        icon_name = NULL;
 | 
						|
      if (i == 3)
 | 
						|
        sensitive = FALSE;
 | 
						|
      else
 | 
						|
        sensitive = TRUE;
 | 
						|
      gtk_list_store_append (store, &iter);
 | 
						|
      gtk_list_store_set (store, &iter,
 | 
						|
                          COLUMN_FIXED, data[i].fixed,
 | 
						|
                          COLUMN_NUMBER, data[i].number,
 | 
						|
                          COLUMN_SEVERITY, data[i].severity,
 | 
						|
                          COLUMN_DESCRIPTION, data[i].description,
 | 
						|
                          COLUMN_PULSE, 0,
 | 
						|
                          COLUMN_ICON, icon_name,
 | 
						|
                          COLUMN_ACTIVE, FALSE,
 | 
						|
                          COLUMN_SENSITIVE, sensitive,
 | 
						|
                          -1);
 | 
						|
    }
 | 
						|
 | 
						|
  return GTK_TREE_MODEL (store);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
fixed_toggled (GtkCellRendererToggle *cell,
 | 
						|
               gchar                 *path_str,
 | 
						|
               gpointer               data)
 | 
						|
{
 | 
						|
  GtkTreeModel *model = (GtkTreeModel *)data;
 | 
						|
  GtkTreeIter  iter;
 | 
						|
  GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
 | 
						|
  gboolean fixed;
 | 
						|
 | 
						|
  /* get toggled iter */
 | 
						|
  gtk_tree_model_get_iter (model, &iter, path);
 | 
						|
  gtk_tree_model_get (model, &iter, COLUMN_FIXED, &fixed, -1);
 | 
						|
 | 
						|
  /* do something with the value */
 | 
						|
  fixed ^= 1;
 | 
						|
 | 
						|
  /* set new value */
 | 
						|
  gtk_list_store_set (GTK_LIST_STORE (model), &iter, COLUMN_FIXED, fixed, -1);
 | 
						|
 | 
						|
  /* clean up */
 | 
						|
  gtk_tree_path_free (path);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
add_columns (GtkTreeView *treeview)
 | 
						|
{
 | 
						|
  GtkCellRenderer *renderer;
 | 
						|
  GtkTreeViewColumn *column;
 | 
						|
  GtkTreeModel *model = gtk_tree_view_get_model (treeview);
 | 
						|
 | 
						|
  /* column for fixed toggles */
 | 
						|
  renderer = gtk_cell_renderer_toggle_new ();
 | 
						|
  g_signal_connect (renderer, "toggled",
 | 
						|
                    G_CALLBACK (fixed_toggled), model);
 | 
						|
 | 
						|
  column = gtk_tree_view_column_new_with_attributes ("Fixed?",
 | 
						|
                                                     renderer,
 | 
						|
                                                     "active", COLUMN_FIXED,
 | 
						|
                                                     NULL);
 | 
						|
 | 
						|
  /* set this column to a fixed sizing (of 50 pixels) */
 | 
						|
  gtk_tree_view_column_set_sizing (GTK_TREE_VIEW_COLUMN (column),
 | 
						|
                                   GTK_TREE_VIEW_COLUMN_FIXED);
 | 
						|
  gtk_tree_view_column_set_fixed_width (GTK_TREE_VIEW_COLUMN (column), 50);
 | 
						|
  gtk_tree_view_append_column (treeview, column);
 | 
						|
 | 
						|
  /* column for bug numbers */
 | 
						|
  renderer = gtk_cell_renderer_text_new ();
 | 
						|
  column = gtk_tree_view_column_new_with_attributes ("Bug number",
 | 
						|
                                                     renderer,
 | 
						|
                                                     "text",
 | 
						|
                                                     COLUMN_NUMBER,
 | 
						|
                                                     NULL);
 | 
						|
  gtk_tree_view_column_set_sort_column_id (column, COLUMN_NUMBER);
 | 
						|
  gtk_tree_view_append_column (treeview, column);
 | 
						|
 | 
						|
  /* column for severities */
 | 
						|
  renderer = gtk_cell_renderer_text_new ();
 | 
						|
  column = gtk_tree_view_column_new_with_attributes ("Severity",
 | 
						|
                                                     renderer,
 | 
						|
                                                     "text",
 | 
						|
                                                     COLUMN_SEVERITY,
 | 
						|
                                                     NULL);
 | 
						|
  gtk_tree_view_column_set_sort_column_id (column, COLUMN_SEVERITY);
 | 
						|
  gtk_tree_view_append_column (treeview, column);
 | 
						|
 | 
						|
  /* column for description */
 | 
						|
  renderer = gtk_cell_renderer_text_new ();
 | 
						|
  column = gtk_tree_view_column_new_with_attributes ("Description",
 | 
						|
                                                     renderer,
 | 
						|
                                                     "text",
 | 
						|
                                                     COLUMN_DESCRIPTION,
 | 
						|
                                                     NULL);
 | 
						|
  gtk_tree_view_column_set_sort_column_id (column, COLUMN_DESCRIPTION);
 | 
						|
  gtk_tree_view_append_column (treeview, column);
 | 
						|
 | 
						|
  /* column for spinner */
 | 
						|
  renderer = gtk_cell_renderer_spinner_new ();
 | 
						|
  column = gtk_tree_view_column_new_with_attributes ("Spinning",
 | 
						|
                                                     renderer,
 | 
						|
                                                     "pulse",
 | 
						|
                                                     COLUMN_PULSE,
 | 
						|
                                                     "active",
 | 
						|
                                                     COLUMN_ACTIVE,
 | 
						|
                                                     NULL);
 | 
						|
  gtk_tree_view_column_set_sort_column_id (column, COLUMN_PULSE);
 | 
						|
  gtk_tree_view_append_column (treeview, column);
 | 
						|
 | 
						|
  /* column for symbolic icon */
 | 
						|
  renderer = gtk_cell_renderer_pixbuf_new ();
 | 
						|
  g_object_set (G_OBJECT (renderer), "follow-state", TRUE, NULL);
 | 
						|
  column = gtk_tree_view_column_new_with_attributes ("Symbolic icon",
 | 
						|
                                                     renderer,
 | 
						|
                                                     "icon-name",
 | 
						|
                                                     COLUMN_ICON,
 | 
						|
                                                     "sensitive",
 | 
						|
                                                     COLUMN_SENSITIVE,
 | 
						|
                                                     NULL);
 | 
						|
  gtk_tree_view_column_set_sort_column_id (column, COLUMN_ICON);
 | 
						|
  gtk_tree_view_append_column (treeview, column);
 | 
						|
}
 | 
						|
 | 
						|
static gboolean
 | 
						|
window_closed (GtkWidget *widget,
 | 
						|
               GdkEvent  *event,
 | 
						|
               gpointer   user_data)
 | 
						|
{
 | 
						|
  model = NULL;
 | 
						|
  window = NULL;
 | 
						|
  if (timeout != 0)
 | 
						|
    {
 | 
						|
      g_source_remove (timeout);
 | 
						|
      timeout = 0;
 | 
						|
    }
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
GtkWidget *
 | 
						|
do_list_store (GtkWidget *do_widget)
 | 
						|
{
 | 
						|
  if (!window)
 | 
						|
    {
 | 
						|
      GtkWidget *vbox;
 | 
						|
      GtkWidget *label;
 | 
						|
      GtkWidget *sw;
 | 
						|
      GtkWidget *treeview;
 | 
						|
 | 
						|
      /* create window, etc */
 | 
						|
      window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 | 
						|
      gtk_window_set_screen (GTK_WINDOW (window),
 | 
						|
                             gtk_widget_get_screen (do_widget));
 | 
						|
      gtk_window_set_title (GTK_WINDOW (window), "GtkListStore demo");
 | 
						|
 | 
						|
      g_signal_connect (window, "destroy",
 | 
						|
                        G_CALLBACK (gtk_widget_destroyed), &window);
 | 
						|
      gtk_container_set_border_width (GTK_CONTAINER (window), 8);
 | 
						|
 | 
						|
      vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8);
 | 
						|
      gtk_container_add (GTK_CONTAINER (window), vbox);
 | 
						|
 | 
						|
      label = gtk_label_new ("This is the bug list (note: not based on real data, it would be nice to have a nice ODBC interface to bugzilla or so, though).");
 | 
						|
      gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
 | 
						|
 | 
						|
      sw = gtk_scrolled_window_new (NULL, NULL);
 | 
						|
      gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
 | 
						|
                                           GTK_SHADOW_ETCHED_IN);
 | 
						|
      gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
 | 
						|
                                      GTK_POLICY_NEVER,
 | 
						|
                                      GTK_POLICY_AUTOMATIC);
 | 
						|
      gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
 | 
						|
 | 
						|
      /* create tree model */
 | 
						|
      model = create_model ();
 | 
						|
 | 
						|
      /* create tree view */
 | 
						|
      treeview = gtk_tree_view_new_with_model (model);
 | 
						|
      gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (treeview), TRUE);
 | 
						|
      gtk_tree_view_set_search_column (GTK_TREE_VIEW (treeview),
 | 
						|
                                       COLUMN_DESCRIPTION);
 | 
						|
 | 
						|
      g_object_unref (model);
 | 
						|
 | 
						|
      gtk_container_add (GTK_CONTAINER (sw), treeview);
 | 
						|
 | 
						|
      /* add columns to the tree view */
 | 
						|
      add_columns (GTK_TREE_VIEW (treeview));
 | 
						|
 | 
						|
      /* finish & show */
 | 
						|
      gtk_window_set_default_size (GTK_WINDOW (window), 280, 250);
 | 
						|
      g_signal_connect (window, "delete-event",
 | 
						|
                        G_CALLBACK (window_closed), NULL);
 | 
						|
    }
 | 
						|
 | 
						|
  if (!gtk_widget_get_visible (window))
 | 
						|
    {
 | 
						|
      gtk_widget_show_all (window);
 | 
						|
      if (timeout == 0) {
 | 
						|
        /* FIXME this should use the animation-duration instead */
 | 
						|
        timeout = g_timeout_add (80, spinner_timeout, NULL);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      gtk_widget_destroy (window);
 | 
						|
      window = NULL;
 | 
						|
      if (timeout != 0)
 | 
						|
        {
 | 
						|
          g_source_remove (timeout);
 | 
						|
          timeout = 0;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
  return window;
 | 
						|
}
 |