GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gnc-tree-model-account-types.c
1 /*
2  * gnc-tree-model-account-types.c -- GtkTreeModel implementation
3  * to display account types in a GtkTreeView.
4  *
5  * Copyright (C) 2003 Jan Arne Petersen <[email protected]>
6  * Copyright (C) 2005, 2006 Chris Shoemaker <[email protected]>
7  * Copyright (C) 2006 Eskil Bylund <[email protected]>
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of
12  * the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, contact:
21  *
22  * Free Software Foundation Voice: +1-617-542-5942
23  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
24  * Boston, MA 02110-1301, USA [email protected]
25  */
26 
27 #include "config.h"
28 
29 #include <gtk/gtk.h>
30 
31 #include "qof.h"
33 #include "Account.h"
34 
35 static QofLogModule log_module = GNC_MOD_GUI;
36 static GtkTreeModel *account_types_tree_model = NULL;
37 
38 #define TYPE_MASK "type-mask"
39 
40 /* Functions for the type system */
41 static void
42 gnc_tree_model_account_types_class_init (GncTreeModelAccountTypesClass *klass);
43 static void
44 gnc_tree_model_account_types_init (GncTreeModelAccountTypes * model);
45 static void
46 gnc_tree_model_account_types_finalize (GObject * object);
47 
48 
49 /* Functions implementing GtkTreeModel */
50 static void
51 gnc_tree_model_account_types_tree_model_init (GtkTreeModelIface * iface);
52 
54 {
55  guint32 selected;
57 
58 #define GNC_TREE_MODEL_ACCOUNT_TYPES_GET_PRIVATE(o) \
59  (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_TREE_MODEL_ACCOUNT_TYPES, \
60  GncTreeModelAccountTypesPrivate))
61 
62 static GObjectClass *parent_class = NULL;
63 
64 GType
65 gnc_tree_model_account_types_get_type (void)
66 {
67  static GType gnc_tree_model_account_types_type = 0;
68 
69  if (gnc_tree_model_account_types_type == 0)
70  {
71  static const GTypeInfo our_info =
72  {
74  NULL,
75  NULL,
76  (GClassInitFunc) gnc_tree_model_account_types_class_init,
77  NULL,
78  NULL,
79  sizeof (GncTreeModelAccountTypes),
80  0,
81  (GInstanceInitFunc) gnc_tree_model_account_types_init
82  };
83 
84  static const GInterfaceInfo tree_model_info =
85  {
86  (GInterfaceInitFunc) gnc_tree_model_account_types_tree_model_init,
87  NULL,
88  NULL
89  };
90 
91  gnc_tree_model_account_types_type =
92  g_type_register_static (G_TYPE_OBJECT,
93  "GncTreeModelAccountTypes",
94  &our_info, 0);
95 
96  g_type_add_interface_static (gnc_tree_model_account_types_type,
97  GTK_TYPE_TREE_MODEL, &tree_model_info);
98  }
99 
100  return gnc_tree_model_account_types_type;
101 }
102 
103 static void
104 gnc_tree_model_account_types_class_init (GncTreeModelAccountTypesClass * klass)
105 {
106  GObjectClass *object_class = G_OBJECT_CLASS (klass);
107 
108  parent_class = g_type_class_peek_parent (klass);
109 
110  object_class->finalize = gnc_tree_model_account_types_finalize;
111 
112  g_type_class_add_private(klass, sizeof(GncTreeModelAccountTypesPrivate));
113 }
114 
115 static void
116 gnc_tree_model_account_types_init (GncTreeModelAccountTypes * model)
117 {
118  while (model->stamp == 0)
119  {
120  model->stamp = g_random_int ();
121  }
122 }
123 
124 static void
125 gnc_tree_model_account_types_finalize (GObject * object)
126 {
127  g_return_if_fail (object != NULL);
128  g_return_if_fail (GNC_IS_TREE_MODEL_ACCOUNT_TYPES (object));
129 
130  G_OBJECT_CLASS (parent_class)->finalize (object);
131 }
132 
133 GtkTreeModel *
134 gnc_tree_model_account_types_new (guint32 selected)
135 {
138 
139  model = g_object_new (GNC_TYPE_TREE_MODEL_ACCOUNT_TYPES, NULL);
140  priv = GNC_TREE_MODEL_ACCOUNT_TYPES_GET_PRIVATE(model);
141  priv->selected = selected;
142 
143  return GTK_TREE_MODEL (model);
144 }
145 
146 static GtkTreeModel *
147 gnc_tree_model_account_types_master(void)
148 {
149  if (!account_types_tree_model)
150  account_types_tree_model = gnc_tree_model_account_types_new(0);
151  return account_types_tree_model;
152 }
153 
154 
155 static gboolean
156 gnc_tree_model_account_types_is_valid (GtkTreeModel *model,
157  GtkTreeIter *iter, gpointer data)
158 {
159  GNCAccountType type;
160  GObject *f_model = G_OBJECT (data);
161  guint32 valid_types = GPOINTER_TO_UINT (g_object_get_data (
162  f_model, TYPE_MASK));
163 
164  gtk_tree_model_get (model, iter,
165  GNC_TREE_MODEL_ACCOUNT_TYPES_COL_TYPE, &type, -1);
166  return (valid_types & (1 << type)) ? TRUE : FALSE;
167 }
168 
169 GtkTreeModel *
170 gnc_tree_model_account_types_filter_using_mask (guint32 types)
171 {
172  GtkTreeModel *f_model;
173 
174  f_model = gtk_tree_model_filter_new (gnc_tree_model_account_types_master (),
175  NULL);
176  g_object_set_data (G_OBJECT (f_model), TYPE_MASK, GUINT_TO_POINTER (types));
177  gtk_tree_model_filter_set_visible_func (
178  GTK_TREE_MODEL_FILTER (f_model), gnc_tree_model_account_types_is_valid,
179  f_model, NULL);
180 
181  return f_model;
182 }
183 
184 void
185 gnc_tree_model_account_types_set_mask (GtkTreeModel *f_model,
186  guint32 types)
187 {
188  g_return_if_fail (f_model);
189 
190  g_object_set_data (G_OBJECT (f_model), TYPE_MASK, GUINT_TO_POINTER (types));
191  gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (f_model));
192 }
193 
194 guint32
195 gnc_tree_model_account_types_get_mask (GtkTreeModel *f_model)
196 {
197  g_return_val_if_fail (f_model, 0);
198 
199  return GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (f_model), TYPE_MASK));
200 }
201 
202 guint32
203 gnc_tree_model_account_types_get_selection (GtkTreeSelection *sel)
204 {
205  GtkTreeModel *f_model, *model;
206  GtkTreePath *path;
207  GtkTreeView *view;
208  GList *list, *node;
209  guint32 bits = 0;
210 
211  g_return_val_if_fail(GTK_IS_TREE_SELECTION(sel), 0);
212  view = gtk_tree_selection_get_tree_view(sel);
213  g_return_val_if_fail (view, 0);
214 
215  /* circumvent a bug in gtk+ not always filling f_model */
216  f_model = NULL;
217  list = gtk_tree_selection_get_selected_rows(sel, &f_model);
218  if (!f_model)
219  f_model = gtk_tree_view_get_model(view);
220 
221  model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
222  if (model != account_types_tree_model)
223  PERR("TreeSelection's TreeModel is not the account-types Model");
224  else
225  {
226  for (node = list; node; node = node->next)
227  {
228  path = gtk_tree_model_filter_convert_path_to_child_path(
229  GTK_TREE_MODEL_FILTER(f_model), (GtkTreePath*)node->data);
230  if (!path || gtk_tree_path_get_depth(path) != 1)
231  {
232  PERR("Invalid Account-types TreePath.");
233  continue;
234  }
235  bits |= (1 << gtk_tree_path_get_indices(path)[0]);
236  }
237  }
238 
239  g_list_foreach (list, (GFunc)gtk_tree_path_free, NULL);
240  g_list_free (list);
241 
242  return bits;
243 }
244 
246 gnc_tree_model_account_types_get_selection_single(GtkTreeSelection *sel)
247 {
248  gint i;
249  guint32 selected = gnc_tree_model_account_types_get_selection(sel);
250 
251  for (i = 0; i < NUM_ACCOUNT_TYPES; i++)
252  if (selected & (1 << i))
253  return i;
254  return ACCT_TYPE_NONE;
255 }
256 
257 void
258 gnc_tree_model_account_types_set_selection (GtkTreeSelection *sel,
259  guint32 selected)
260 {
261  GtkTreePath *path, *f_path;
262  GtkTreeModelFilter *f_model;
263  gint i;
264  GtkTreeView *view;
265 
266  g_return_if_fail(GTK_IS_TREE_SELECTION(sel));
267  view = gtk_tree_selection_get_tree_view(sel);
268  g_return_if_fail (view);
269  f_model = GTK_TREE_MODEL_FILTER(gtk_tree_view_get_model(view));
270  g_return_if_fail(gtk_tree_model_filter_get_model(f_model) ==
271  account_types_tree_model);
272  gtk_tree_selection_unselect_all(sel);
273  path = gtk_tree_path_new_first();
274 
275  for (i = 0; i < NUM_ACCOUNT_TYPES; i++)
276  {
277  if (selected & (1 << i))
278  {
279  f_path = gtk_tree_model_filter_convert_child_path_to_path(
280  f_model, path);
281  gtk_tree_selection_select_path(sel, f_path);
282  gtk_tree_view_scroll_to_cell(view, f_path, NULL, FALSE, 0.0, 0.0);
283  }
284  gtk_tree_path_next(path);
285  }
286  gtk_tree_path_free(path);
287 }
288 
289 
290 /* Static functions implementing GtkTreeModel */
291 
292 static GtkTreeModelFlags
293 gnc_tree_model_account_types_get_flags (GtkTreeModel * tree_model)
294 {
295  return GTK_TREE_MODEL_ITERS_PERSIST | GTK_TREE_MODEL_LIST_ONLY;
296 }
297 
298 static int
299 gnc_tree_model_account_types_get_n_columns (GtkTreeModel * tree_model)
300 {
301  return GNC_TREE_MODEL_ACCOUNT_TYPES_NUM_COLUMNS;
302 }
303 
304 static GType
305 gnc_tree_model_account_types_get_column_type (GtkTreeModel * tree_model,
306  int index)
307 {
308  g_return_val_if_fail(GNC_IS_TREE_MODEL_ACCOUNT_TYPES (tree_model),
309  G_TYPE_INVALID);
310  g_return_val_if_fail((index < GNC_TREE_MODEL_ACCOUNT_TYPES_NUM_COLUMNS)
311  && (index >= 0), G_TYPE_INVALID);
312 
313  switch (index)
314  {
315  case GNC_TREE_MODEL_ACCOUNT_TYPES_COL_TYPE:
316  return G_TYPE_INT;
317  case GNC_TREE_MODEL_ACCOUNT_TYPES_COL_NAME:
318  return G_TYPE_STRING;
319  case GNC_TREE_MODEL_ACCOUNT_TYPES_COL_SELECTED:
320  return G_TYPE_BOOLEAN;
321  default:
322  g_assert_not_reached ();
323  return G_TYPE_INVALID;
324  }
325 }
326 
327 static gboolean
328 gnc_tree_model_account_types_get_iter (GtkTreeModel * tree_model,
329  GtkTreeIter * iter, GtkTreePath * path)
330 {
331  GncTreeModelAccountTypes *model = GNC_TREE_MODEL_ACCOUNT_TYPES(tree_model);
332  gint i;
333 
334  g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT_TYPES (model), FALSE);
335  g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
336 
337  i = gtk_tree_path_get_indices (path)[0];
338 
339  if (i > ACCT_TYPE_NONE && i < NUM_ACCOUNT_TYPES)
340  {
341  iter->stamp = model->stamp;
342  iter->user_data = GINT_TO_POINTER (i);
343  return TRUE;
344  }
345 
346  iter->stamp = 0;
347  return FALSE;
348 }
349 
350 static GtkTreePath *
351 gnc_tree_model_account_types_get_path (GtkTreeModel * tree_model,
352  GtkTreeIter * iter)
353 {
354  GncTreeModelAccountTypes *model = GNC_TREE_MODEL_ACCOUNT_TYPES(tree_model);
355  GtkTreePath *path;
356 
357  g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT_TYPES (model), NULL);
358  g_return_val_if_fail (iter != NULL, NULL);
359  g_return_val_if_fail (iter->stamp == model->stamp, NULL);
360 
361  path = gtk_tree_path_new ();
362 
363  gtk_tree_path_append_index (path, GPOINTER_TO_INT (iter->user_data));
364 
365  return path;
366 }
367 
368 static void
369 gnc_tree_model_account_types_get_value (GtkTreeModel * tree_model,
370  GtkTreeIter * iter, int column,
371  GValue * value)
372 {
373  GncTreeModelAccountTypes *model = GNC_TREE_MODEL_ACCOUNT_TYPES(tree_model);
375 
376  g_return_if_fail (GNC_IS_TREE_MODEL_ACCOUNT_TYPES (model));
377  g_return_if_fail (iter != NULL);
378  g_return_if_fail (iter->stamp == model->stamp);
379 
380  priv = GNC_TREE_MODEL_ACCOUNT_TYPES_GET_PRIVATE(model);
381  switch (column)
382  {
383  case GNC_TREE_MODEL_ACCOUNT_TYPES_COL_TYPE:
384  g_value_init (value, G_TYPE_INT);
385  g_value_set_int (value, GPOINTER_TO_INT (iter->user_data));
386  break;
387  case GNC_TREE_MODEL_ACCOUNT_TYPES_COL_NAME:
388  g_value_init (value, G_TYPE_STRING);
389  g_value_set_string (value, xaccAccountGetTypeStr (
390  GPOINTER_TO_INT (iter->user_data)));
391  break;
392  case GNC_TREE_MODEL_ACCOUNT_TYPES_COL_SELECTED:
393  g_value_init (value, G_TYPE_BOOLEAN);
394  g_value_set_boolean (value, priv->selected &
395  (1 << GPOINTER_TO_INT (iter->user_data)));
396  break;
397  default:
398  g_assert_not_reached ();
399  }
400 }
401 
402 static gboolean
403 gnc_tree_model_account_types_iter_next (GtkTreeModel * tree_model,
404  GtkTreeIter * iter)
405 {
406  GncTreeModelAccountTypes *model = GNC_TREE_MODEL_ACCOUNT_TYPES(tree_model);
407 
408  g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT_TYPES (model), FALSE);
409  g_return_val_if_fail (iter != NULL, FALSE);
410  g_return_val_if_fail (iter->stamp == model->stamp, FALSE);
411 
412  if (GPOINTER_TO_INT (iter->user_data) < NUM_ACCOUNT_TYPES - 1)
413  {
414  iter->user_data = GINT_TO_POINTER(
415  GPOINTER_TO_INT(iter->user_data) + 1);
416  return TRUE;
417  }
418 
419  iter->stamp = 0;
420  return FALSE;
421 }
422 
423 static gboolean
424 gnc_tree_model_account_types_iter_children (GtkTreeModel * tree_model,
425  GtkTreeIter * iter,
426  GtkTreeIter * parent)
427 {
428 
429  g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT_TYPES(tree_model), FALSE);
430 
431  if (parent != NULL)
432  return FALSE;
433 
434  iter->stamp = GNC_TREE_MODEL_ACCOUNT_TYPES (tree_model)->stamp;
435  iter->user_data = GINT_TO_POINTER (0);
436 
437  return TRUE;
438 }
439 
440 static gboolean
441 gnc_tree_model_account_types_iter_has_child (GtkTreeModel * tree_model,
442  GtkTreeIter * iter)
443 {
444  return FALSE;
445 }
446 
447 static int
448 gnc_tree_model_account_types_iter_n_children (GtkTreeModel * tree_model,
449  GtkTreeIter * iter)
450 {
451  g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT_TYPES (tree_model), -1);
452 
453  if (iter == NULL)
454  return NUM_ACCOUNT_TYPES;
455 
456  g_return_val_if_fail (
457  GNC_TREE_MODEL_ACCOUNT_TYPES (tree_model)->stamp == iter->stamp, -1);
458 
459  return 0;
460 }
461 
462 static gboolean
463 gnc_tree_model_account_types_iter_nth_child (GtkTreeModel * tree_model,
464  GtkTreeIter * iter,
465  GtkTreeIter * parent, int n)
466 {
468 
469  g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT_TYPES (tree_model), FALSE);
470 
471  if (parent != NULL)
472  return FALSE;
473 
474  model = GNC_TREE_MODEL_ACCOUNT_TYPES (tree_model);
475 
476  if (n > ACCT_TYPE_NONE && n < NUM_ACCOUNT_TYPES)
477  {
478  iter->stamp = model->stamp;
479  iter->user_data = GINT_TO_POINTER (n);
480  return TRUE;
481  }
482 
483  iter->stamp = 0;
484  return FALSE;
485 }
486 
487 static gboolean
488 gnc_tree_model_account_types_iter_parent (GtkTreeModel * tree_model,
489  GtkTreeIter * iter,
490  GtkTreeIter * child)
491 {
492  return FALSE;
493 }
494 
495 static void
496 gnc_tree_model_account_types_tree_model_init (GtkTreeModelIface * iface)
497 {
498  iface->get_flags = gnc_tree_model_account_types_get_flags;
499  iface->get_n_columns = gnc_tree_model_account_types_get_n_columns;
500  iface->get_column_type = gnc_tree_model_account_types_get_column_type;
501  iface->get_iter = gnc_tree_model_account_types_get_iter;
502  iface->get_path = gnc_tree_model_account_types_get_path;
503  iface->get_value = gnc_tree_model_account_types_get_value;
504  iface->iter_next = gnc_tree_model_account_types_iter_next;
505  iface->iter_children = gnc_tree_model_account_types_iter_children;
506  iface->iter_has_child = gnc_tree_model_account_types_iter_has_child;
507  iface->iter_n_children = gnc_tree_model_account_types_iter_n_children;
508  iface->iter_nth_child = gnc_tree_model_account_types_iter_nth_child;
509  iface->iter_parent = gnc_tree_model_account_types_iter_parent;
510 }
511 
#define PERR(format, args...)
Definition: qoflog.h:237
Account handling public routines.
GNCAccountType
Definition: Account.h:96
GtkTreeModel implementation to display account types in a GtkTreeView.
const char * xaccAccountGetTypeStr(GNCAccountType type)
Definition: Account.c:4137
const gchar * QofLogModule
Definition: qofid.h:89