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