]> Pileus Git - ~andy/gtk/blob - demos/gtk-demo/list_store.c
Use gtk_box_new() instead gtk_[v|h]box_new()
[~andy/gtk] / demos / gtk-demo / list_store.c
1 /* Tree View/List Store
2  *
3  * The GtkListStore is used to store data in list form, to be used
4  * later on by a GtkTreeView to display it. This demo builds a
5  * simple GtkListStore and displays it. See the Stock Browser
6  * demo for a more advanced example.
7  *
8  */
9
10 #include <gtk/gtk.h>
11
12 static GtkWidget *window = NULL;
13 static GtkTreeModel *model = NULL;
14 static guint timeout = 0;
15
16 typedef struct
17 {
18   const gboolean  fixed;
19   const guint     number;
20   const gchar    *severity;
21   const gchar    *description;
22 }
23 Bug;
24
25 enum
26 {
27   COLUMN_FIXED,
28   COLUMN_NUMBER,
29   COLUMN_SEVERITY,
30   COLUMN_DESCRIPTION,
31   COLUMN_PULSE,
32   COLUMN_ICON,
33   COLUMN_ACTIVE,
34   COLUMN_SENSITIVE,
35   NUM_COLUMNS
36 };
37
38 static Bug data[] =
39 {
40   { FALSE, 60482, "Normal",     "scrollable notebooks and hidden tabs" },
41   { FALSE, 60620, "Critical",   "gdk_window_clear_area (gdkwindow-win32.c) is not thread-safe" },
42   { FALSE, 50214, "Major",      "Xft support does not clean up correctly" },
43   { TRUE,  52877, "Major",      "GtkFileSelection needs a refresh method. " },
44   { FALSE, 56070, "Normal",     "Can't click button after setting in sensitive" },
45   { TRUE,  56355, "Normal",     "GtkLabel - Not all changes propagate correctly" },
46   { FALSE, 50055, "Normal",     "Rework width/height computations for TreeView" },
47   { FALSE, 58278, "Normal",     "gtk_dialog_set_response_sensitive () doesn't work" },
48   { FALSE, 55767, "Normal",     "Getters for all setters" },
49   { FALSE, 56925, "Normal",     "Gtkcalender size" },
50   { FALSE, 56221, "Normal",     "Selectable label needs right-click copy menu" },
51   { TRUE,  50939, "Normal",     "Add shift clicking to GtkTextView" },
52   { FALSE, 6112,  "Enhancement","netscape-like collapsable toolbars" },
53   { FALSE, 1,     "Normal",     "First bug :=)" },
54 };
55
56 static gboolean
57 spinner_timeout (gpointer data)
58 {
59   GtkTreeIter iter;
60   guint pulse;
61
62   if (model == NULL)
63     return FALSE;
64
65   gtk_tree_model_get_iter_first (model, &iter);
66   gtk_tree_model_get (model, &iter,
67                       COLUMN_PULSE, &pulse,
68                       -1);
69   if (pulse == G_MAXUINT)
70     pulse = 0;
71   else
72     pulse++;
73
74   gtk_list_store_set (GTK_LIST_STORE (model),
75                       &iter,
76                       COLUMN_PULSE, pulse,
77                       COLUMN_ACTIVE, TRUE,
78                       -1);
79
80   return TRUE;
81 }
82
83 static GtkTreeModel *
84 create_model (void)
85 {
86   gint i = 0;
87   GtkListStore *store;
88   GtkTreeIter iter;
89
90   /* create list store */
91   store = gtk_list_store_new (NUM_COLUMNS,
92                               G_TYPE_BOOLEAN,
93                               G_TYPE_UINT,
94                               G_TYPE_STRING,
95                               G_TYPE_STRING,
96                               G_TYPE_UINT,
97                               G_TYPE_STRING,
98                               G_TYPE_BOOLEAN,
99                               G_TYPE_BOOLEAN);
100
101   /* add data to the list store */
102   for (i = 0; i < G_N_ELEMENTS (data); i++)
103     {
104       gchar *icon_name;
105       gboolean sensitive;
106
107       if (i == 1 || i == 3)
108         icon_name = "battery-critical-charging-symbolic";
109       else
110         icon_name = NULL;
111       if (i == 3)
112         sensitive = FALSE;
113       else
114         sensitive = TRUE;
115       gtk_list_store_append (store, &iter);
116       gtk_list_store_set (store, &iter,
117                           COLUMN_FIXED, data[i].fixed,
118                           COLUMN_NUMBER, data[i].number,
119                           COLUMN_SEVERITY, data[i].severity,
120                           COLUMN_DESCRIPTION, data[i].description,
121                           COLUMN_PULSE, 0,
122                           COLUMN_ICON, icon_name,
123                           COLUMN_ACTIVE, FALSE,
124                           COLUMN_SENSITIVE, sensitive,
125                           -1);
126     }
127
128   return GTK_TREE_MODEL (store);
129 }
130
131 static void
132 fixed_toggled (GtkCellRendererToggle *cell,
133                gchar                 *path_str,
134                gpointer               data)
135 {
136   GtkTreeModel *model = (GtkTreeModel *)data;
137   GtkTreeIter  iter;
138   GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
139   gboolean fixed;
140
141   /* get toggled iter */
142   gtk_tree_model_get_iter (model, &iter, path);
143   gtk_tree_model_get (model, &iter, COLUMN_FIXED, &fixed, -1);
144
145   /* do something with the value */
146   fixed ^= 1;
147
148   /* set new value */
149   gtk_list_store_set (GTK_LIST_STORE (model), &iter, COLUMN_FIXED, fixed, -1);
150
151   /* clean up */
152   gtk_tree_path_free (path);
153 }
154
155 static void
156 add_columns (GtkTreeView *treeview)
157 {
158   GtkCellRenderer *renderer;
159   GtkTreeViewColumn *column;
160   GtkTreeModel *model = gtk_tree_view_get_model (treeview);
161
162   /* column for fixed toggles */
163   renderer = gtk_cell_renderer_toggle_new ();
164   g_signal_connect (renderer, "toggled",
165                     G_CALLBACK (fixed_toggled), model);
166
167   column = gtk_tree_view_column_new_with_attributes ("Fixed?",
168                                                      renderer,
169                                                      "active", COLUMN_FIXED,
170                                                      NULL);
171
172   /* set this column to a fixed sizing (of 50 pixels) */
173   gtk_tree_view_column_set_sizing (GTK_TREE_VIEW_COLUMN (column),
174                                    GTK_TREE_VIEW_COLUMN_FIXED);
175   gtk_tree_view_column_set_fixed_width (GTK_TREE_VIEW_COLUMN (column), 50);
176   gtk_tree_view_append_column (treeview, column);
177
178   /* column for bug numbers */
179   renderer = gtk_cell_renderer_text_new ();
180   column = gtk_tree_view_column_new_with_attributes ("Bug number",
181                                                      renderer,
182                                                      "text",
183                                                      COLUMN_NUMBER,
184                                                      NULL);
185   gtk_tree_view_column_set_sort_column_id (column, COLUMN_NUMBER);
186   gtk_tree_view_append_column (treeview, column);
187
188   /* column for severities */
189   renderer = gtk_cell_renderer_text_new ();
190   column = gtk_tree_view_column_new_with_attributes ("Severity",
191                                                      renderer,
192                                                      "text",
193                                                      COLUMN_SEVERITY,
194                                                      NULL);
195   gtk_tree_view_column_set_sort_column_id (column, COLUMN_SEVERITY);
196   gtk_tree_view_append_column (treeview, column);
197
198   /* column for description */
199   renderer = gtk_cell_renderer_text_new ();
200   column = gtk_tree_view_column_new_with_attributes ("Description",
201                                                      renderer,
202                                                      "text",
203                                                      COLUMN_DESCRIPTION,
204                                                      NULL);
205   gtk_tree_view_column_set_sort_column_id (column, COLUMN_DESCRIPTION);
206   gtk_tree_view_append_column (treeview, column);
207
208   /* column for spinner */
209   renderer = gtk_cell_renderer_spinner_new ();
210   column = gtk_tree_view_column_new_with_attributes ("Spinning",
211                                                      renderer,
212                                                      "pulse",
213                                                      COLUMN_PULSE,
214                                                      "active",
215                                                      COLUMN_ACTIVE,
216                                                      NULL);
217   gtk_tree_view_column_set_sort_column_id (column, COLUMN_PULSE);
218   gtk_tree_view_append_column (treeview, column);
219
220   /* column for symbolic icon */
221   renderer = gtk_cell_renderer_pixbuf_new ();
222   g_object_set (G_OBJECT (renderer), "follow-state", TRUE, NULL);
223   column = gtk_tree_view_column_new_with_attributes ("Symbolic icon",
224                                                      renderer,
225                                                      "icon-name",
226                                                      COLUMN_ICON,
227                                                      "sensitive",
228                                                      COLUMN_SENSITIVE,
229                                                      NULL);
230   gtk_tree_view_column_set_sort_column_id (column, COLUMN_ICON);
231   gtk_tree_view_append_column (treeview, column);
232 }
233
234 static gboolean
235 window_closed (GtkWidget *widget,
236                GdkEvent  *event,
237                gpointer   user_data)
238 {
239   model = NULL;
240   window = NULL;
241   if (timeout != 0)
242     {
243       g_source_remove (timeout);
244       timeout = 0;
245     }
246   return FALSE;
247 }
248
249 GtkWidget *
250 do_list_store (GtkWidget *do_widget)
251 {
252   if (!window)
253     {
254       GtkWidget *vbox;
255       GtkWidget *label;
256       GtkWidget *sw;
257       GtkWidget *treeview;
258
259       /* create window, etc */
260       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
261       gtk_window_set_screen (GTK_WINDOW (window),
262                              gtk_widget_get_screen (do_widget));
263       gtk_window_set_title (GTK_WINDOW (window), "GtkListStore demo");
264
265       g_signal_connect (window, "destroy",
266                         G_CALLBACK (gtk_widget_destroyed), &window);
267       gtk_container_set_border_width (GTK_CONTAINER (window), 8);
268
269       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 8);
270       gtk_container_add (GTK_CONTAINER (window), vbox);
271
272       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).");
273       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
274
275       sw = gtk_scrolled_window_new (NULL, NULL);
276       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
277                                            GTK_SHADOW_ETCHED_IN);
278       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
279                                       GTK_POLICY_NEVER,
280                                       GTK_POLICY_AUTOMATIC);
281       gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
282
283       /* create tree model */
284       model = create_model ();
285
286       /* create tree view */
287       treeview = gtk_tree_view_new_with_model (model);
288       gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (treeview), TRUE);
289       gtk_tree_view_set_search_column (GTK_TREE_VIEW (treeview),
290                                        COLUMN_DESCRIPTION);
291
292       g_object_unref (model);
293
294       gtk_container_add (GTK_CONTAINER (sw), treeview);
295
296       /* add columns to the tree view */
297       add_columns (GTK_TREE_VIEW (treeview));
298
299       /* finish & show */
300       gtk_window_set_default_size (GTK_WINDOW (window), 280, 250);
301       g_signal_connect (window, "delete-event",
302                         G_CALLBACK (window_closed), NULL);
303     }
304
305   if (!gtk_widget_get_visible (window))
306     {
307       gtk_widget_show_all (window);
308       if (timeout == 0) {
309         /* FIXME this should use the animation-duration instead */
310         timeout = g_timeout_add (80, spinner_timeout, NULL);
311       }
312     }
313   else
314     {
315       gtk_widget_destroy (window);
316       window = NULL;
317       if (timeout != 0)
318         {
319           g_source_remove (timeout);
320           timeout = 0;
321         }
322     }
323
324   return window;
325 }