tests: Add pspp-convert.at to Git.
[pspp] / src / ui / gui / psppire-empty-list-store.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2011, 2012 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18
19 #include "psppire-empty-list-store.h"
20
21 static void psppire_empty_list_store_class_init (PsppireEmptyListStoreClass *);
22 static void psppire_empty_list_store_init (PsppireEmptyListStore *);
23
24 /* GtkTreeModel interface. */
25 static void gtk_tree_model_interface_init (GtkTreeModelIface *iface);
26 static GtkTreeModelFlags empty_list_store_get_flags (GtkTreeModel *tree_model);
27 static gint empty_list_store_get_n_columns (GtkTreeModel *tree_model);
28 static GType empty_list_store_get_column_type (GtkTreeModel *tree_model,
29                                                gint          index_);
30 static gboolean empty_list_store_get_iter (GtkTreeModel *tree_model,
31                                            GtkTreeIter  *iter,
32                                            GtkTreePath  *path);
33 static GtkTreePath * empty_list_store_get_path (GtkTreeModel *tree_model,
34                                                 GtkTreeIter  *iter);
35 static void empty_list_store_get_value (GtkTreeModel *tree_model,
36                                         GtkTreeIter  *iter,
37                                         gint          column,
38                                         GValue       *value);
39 static gboolean empty_list_store_iter_next (GtkTreeModel *tree_model,
40                                             GtkTreeIter  *iter);
41 static gboolean empty_list_store_iter_children (GtkTreeModel *tree_model,
42                                                 GtkTreeIter  *iter,
43                                                 GtkTreeIter  *parent);
44 static gboolean empty_list_store_iter_has_child (GtkTreeModel *tree_model,
45                                                  GtkTreeIter  *iter);
46 static gint empty_list_store_iter_n_children (GtkTreeModel *tree_model,
47                                               GtkTreeIter  *iter);
48 static gboolean empty_list_store_iter_nth_child (GtkTreeModel *tree_model,
49                                                  GtkTreeIter  *iter,
50                                                  GtkTreeIter  *parent,
51                                                  gint          n);
52 static gboolean empty_list_store_iter_parent (GtkTreeModel *tree_model,
53                                               GtkTreeIter  *iter,
54                                               GtkTreeIter  *child);
55
56 GType
57 psppire_empty_list_store_get_type (void)
58 {
59   static GType type = 0;
60   if (!type)
61     {
62       static const GTypeInfo psppire_empty_list_store_info =
63         {
64           sizeof(PsppireEmptyListStoreClass),
65           NULL,    /* base init */
66           NULL,    /* base finalize */
67           (GClassInitFunc) psppire_empty_list_store_class_init,
68           NULL,    /* class finalize */
69           NULL,    /* class data */
70           sizeof(PsppireEmptyListStore),
71           0,    /* n_preallocs, ignored since 2.10 */
72           (GInstanceInitFunc) psppire_empty_list_store_init,
73           NULL
74         };
75       static const GInterfaceInfo gtk_tree_model_info =
76         {
77           (GInterfaceInitFunc) gtk_tree_model_interface_init,
78           (GInterfaceFinalizeFunc) NULL,
79           NULL
80         };
81       type = g_type_register_static (G_TYPE_OBJECT,
82                                  "PsppireEmptyListStore",
83                                  &psppire_empty_list_store_info, 0);
84       g_type_add_interface_static (type, GTK_TYPE_TREE_MODEL,
85                                    &gtk_tree_model_info);
86     }
87   return type;
88 }
89
90 enum
91   {
92     PROP_0,
93     PROP_N_ROWS
94   };
95
96 static void
97 psppire_empty_list_store_set_property (GObject      *object,
98                                        guint         prop_id,
99                                        const GValue *value,
100                                        GParamSpec   *pspec)
101 {
102   PsppireEmptyListStore *obj = PSPPIRE_EMPTY_LIST_STORE (object);
103
104   switch (prop_id)
105     {
106     case PROP_N_ROWS:
107       obj->n_rows = g_value_get_int (value);
108       break;
109
110     default:
111       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
112       break;
113     }
114 }
115
116 static void
117 psppire_empty_list_store_get_property (GObject      *object,
118                                        guint         prop_id,
119                                        GValue       *value,
120                                        GParamSpec   *pspec)
121 {
122   PsppireEmptyListStore *obj = PSPPIRE_EMPTY_LIST_STORE (object);
123
124   switch (prop_id)
125     {
126     case PROP_N_ROWS:
127       g_value_set_int (value, obj->n_rows);
128       break;
129
130     default:
131       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
132       break;
133     }
134 }
135
136 static void
137 psppire_empty_list_store_class_init (PsppireEmptyListStoreClass *class)
138 {
139   GObjectClass *gobject_class;
140   gobject_class = G_OBJECT_CLASS (class);
141
142   gobject_class->set_property = psppire_empty_list_store_set_property;
143   gobject_class->get_property = psppire_empty_list_store_get_property;
144
145   g_object_class_install_property (gobject_class,
146                                    PROP_N_ROWS,
147                                    g_param_spec_int ("n-rows",
148                                                      ("Number of rows"),
149                                                      ("Number of rows in GtkTreeModel"),
150                                                      0,
151                                                      G_MAXINT,
152                                                      0,
153                                                      G_PARAM_READWRITE));
154 }
155
156 static void
157 psppire_empty_list_store_init (PsppireEmptyListStore *obj)
158 {
159   obj->n_rows = 0;
160 }
161
162 PsppireEmptyListStore *
163 psppire_empty_list_store_new (gint n_rows)
164 {
165   return PSPPIRE_EMPTY_LIST_STORE (g_object_new (PSPPIRE_TYPE_EMPTY_LIST_STORE,
166                                                  "n-rows", n_rows,
167                                                  NULL));
168 }
169
170 gint
171 psppire_empty_list_store_get_n_rows (const PsppireEmptyListStore *obj)
172 {
173   return obj->n_rows;
174 }
175
176 void
177 psppire_empty_list_store_set_n_rows (PsppireEmptyListStore *obj,
178                                      gint n_rows)
179 {
180   obj->n_rows = n_rows;
181 }
182
183 void
184 psppire_empty_list_store_row_changed (PsppireEmptyListStore *obj,
185                                       gint row)
186 {
187   GtkTreeModel *tree_model = GTK_TREE_MODEL (obj);
188   GtkTreeIter iter;
189   GtkTreePath *path;
190
191   path = gtk_tree_path_new_from_indices (row, -1);
192   gtk_tree_model_get_iter (tree_model, &iter, path);
193   gtk_tree_model_row_changed (tree_model, path, &iter);
194   gtk_tree_path_free (path);
195 }
196
197 void
198 psppire_empty_list_store_row_inserted (PsppireEmptyListStore *obj,
199                                        gint row)
200 {
201   GtkTreeModel *tree_model = GTK_TREE_MODEL (obj);
202   GtkTreeIter iter;
203   GtkTreePath *path;
204
205   path = gtk_tree_path_new_from_indices (row, -1);
206   gtk_tree_model_get_iter (tree_model, &iter, path);
207   gtk_tree_model_row_inserted (tree_model, path, &iter);
208   gtk_tree_path_free (path);
209 }
210
211 void
212 psppire_empty_list_store_row_deleted (PsppireEmptyListStore *obj,
213                                       gint row)
214 {
215   GtkTreeModel *tree_model = GTK_TREE_MODEL (obj);
216   GtkTreePath *path;
217
218   path = gtk_tree_path_new_from_indices (row, -1);
219   gtk_tree_model_row_deleted (tree_model, path);
220   gtk_tree_path_free (path);
221 }
222 \f
223 /* GtkTreeModel interface. */
224
225 /* Random number used in 'stamp' member of GtkTreeIter. */
226 #define TREE_MODEL_STAMP 0x10c44c13
227
228 static gboolean
229 empty_list_store_init_iter (GtkTreeModel *model, gint idx, GtkTreeIter *iter)
230 {
231   const PsppireEmptyListStore *store = PSPPIRE_EMPTY_LIST_STORE (model);
232
233   if (idx < 0 || idx >= store->n_rows)
234     {
235       iter->stamp = 0;
236       iter->user_data = GINT_TO_POINTER (-1);
237       return FALSE;
238     }
239   else
240     {
241       iter->stamp = TREE_MODEL_STAMP;
242       iter->user_data = GINT_TO_POINTER (idx);
243       return TRUE;
244     }
245 }
246
247 static void
248 gtk_tree_model_interface_init (GtkTreeModelIface *iface)
249 {
250   g_return_if_fail (iface != NULL);
251
252   iface->get_flags = empty_list_store_get_flags;
253   iface->get_n_columns = empty_list_store_get_n_columns;
254   iface->get_column_type = empty_list_store_get_column_type;
255   iface->get_iter = empty_list_store_get_iter;
256   iface->get_path = empty_list_store_get_path;
257   iface->get_value = empty_list_store_get_value;
258   iface->iter_next = empty_list_store_iter_next;
259   iface->iter_children = empty_list_store_iter_children;
260   iface->iter_has_child = empty_list_store_iter_has_child;
261   iface->iter_n_children = empty_list_store_iter_n_children;
262   iface->iter_nth_child = empty_list_store_iter_nth_child;
263   iface->iter_parent = empty_list_store_iter_parent;
264 }
265
266 static GtkTreeModelFlags
267 empty_list_store_get_flags (GtkTreeModel *tree_model G_GNUC_UNUSED)
268 {
269   return GTK_TREE_MODEL_LIST_ONLY;
270 }
271
272 static gint
273 empty_list_store_get_n_columns (GtkTreeModel *tree_model G_GNUC_UNUSED)
274 {
275   return 0;
276 }
277
278 static GType
279 empty_list_store_get_column_type (GtkTreeModel *tree_model,
280                                   gint          index_)
281 {
282   g_return_val_if_reached (G_TYPE_NONE);
283 }
284
285 static gboolean
286 empty_list_store_get_iter (GtkTreeModel *tree_model,
287                            GtkTreeIter  *iter,
288                            GtkTreePath  *path)
289 {
290   gint *indices, depth;
291
292   g_return_val_if_fail (path, FALSE);
293
294   indices = gtk_tree_path_get_indices (path);
295   depth = gtk_tree_path_get_depth (path);
296
297   g_return_val_if_fail (depth == 1, FALSE);
298
299   return empty_list_store_init_iter (tree_model, indices[0], iter);
300 }
301
302 static GtkTreePath *
303 empty_list_store_get_path (GtkTreeModel *tree_model,
304                            GtkTreeIter  *iter)
305 {
306   GtkTreePath *path;
307
308   g_return_val_if_fail (iter->stamp == TREE_MODEL_STAMP, FALSE);
309
310   path = gtk_tree_path_new ();
311   gtk_tree_path_append_index (path, GPOINTER_TO_INT (iter->user_data));
312
313   return path;
314 }
315
316 static void
317 empty_list_store_get_value (GtkTreeModel *tree_model,
318                             GtkTreeIter  *iter,
319                             gint          column,
320                             GValue       *value)
321 {
322   g_return_if_reached ();
323 }
324
325 static gboolean
326 empty_list_store_iter_next (GtkTreeModel *tree_model,
327                             GtkTreeIter  *iter)
328 {
329   gint idx;
330
331   g_return_val_if_fail (iter->stamp == TREE_MODEL_STAMP, FALSE);
332
333   idx = GPOINTER_TO_INT (iter->user_data);
334   return empty_list_store_init_iter (tree_model, idx + (idx >= 0), iter);
335 }
336
337 static gboolean
338 empty_list_store_iter_children (GtkTreeModel *tree_model,
339                                 GtkTreeIter  *iter,
340                                 GtkTreeIter  *parent)
341 {
342   return FALSE;
343 }
344
345 static gboolean
346 empty_list_store_iter_has_child (GtkTreeModel *tree_model,
347                                  GtkTreeIter  *iter)
348 {
349   return FALSE;
350 }
351
352 static gint
353 empty_list_store_iter_n_children (GtkTreeModel *tree_model,
354                                   GtkTreeIter  *iter)
355 {
356   return iter == NULL ? PSPPIRE_EMPTY_LIST_STORE (tree_model)->n_rows : 0;
357 }
358
359 static gboolean
360 empty_list_store_iter_nth_child (GtkTreeModel *tree_model,
361                                  GtkTreeIter  *iter,
362                                  GtkTreeIter  *parent,
363                                  gint          n)
364 {
365   g_return_val_if_fail (parent == NULL, FALSE);
366
367   return empty_list_store_init_iter (tree_model, n, iter);
368 }
369
370 static gboolean
371 empty_list_store_iter_parent (GtkTreeModel *tree_model,
372                               GtkTreeIter  *iter,
373                               GtkTreeIter  *child)
374 {
375   return FALSE;
376 }
377
378 gint
379 empty_list_store_iter_to_row (const GtkTreeIter *iter)
380 {
381   g_return_val_if_fail (iter->stamp == TREE_MODEL_STAMP, 0);
382   return GPOINTER_TO_INT (iter->user_data);
383 }