GnuCash  5.6-150-g038405b370+
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules 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 <jpetersen@uni-bonn.de>
6  * Copyright (C) 2005, 2006 Chris Shoemaker <c.shoemaker@cox.net>
7  * Copyright (C) 2006 Eskil Bylund <eskil.bylund@gmail.com>
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 gnu@gnu.org
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_finalize (GObject * object);
43 
44 
45 /* Functions implementing GtkTreeModel */
46 static void
47 gnc_tree_model_account_types_tree_model_init (GtkTreeModelIface * iface);
48 
50 {
51  GObject gobject;
52  int stamp;
53 
54  guint32 selected;
55 };
56 
57 G_DEFINE_TYPE_WITH_CODE(GncTreeModelAccountTypes, gnc_tree_model_account_types, G_TYPE_OBJECT,
58  G_IMPLEMENT_INTERFACE(GTK_TYPE_TREE_MODEL,
59  gnc_tree_model_account_types_tree_model_init))
60 
61 static void
62 gnc_tree_model_account_types_class_init (GncTreeModelAccountTypesClass * klass)
63 {
64  GObjectClass *object_class = G_OBJECT_CLASS (klass);
65 
66  object_class->finalize = gnc_tree_model_account_types_finalize;
67 }
68 
69 static void
70 gnc_tree_model_account_types_init (GncTreeModelAccountTypes * model)
71 {
72  while (model->stamp == 0)
73  {
74  model->stamp = g_random_int ();
75  }
76 }
77 
78 static void
79 gnc_tree_model_account_types_finalize (GObject * object)
80 {
81  g_return_if_fail (object != NULL);
82  g_return_if_fail (GNC_IS_TREE_MODEL_ACCOUNT_TYPES (object));
83 
84  G_OBJECT_CLASS (gnc_tree_model_account_types_parent_class)->finalize (object);
85 }
86 
87 GtkTreeModel *
88 gnc_tree_model_account_types_new (guint32 selected)
89 {
90  GncTreeModelAccountTypes *model = g_object_new (GNC_TYPE_TREE_MODEL_ACCOUNT_TYPES, NULL);
91  model->selected = selected;
92 
93  return GTK_TREE_MODEL (model);
94 }
95 
96 static GtkTreeModel *
97 gnc_tree_model_account_types_master(void)
98 {
99  if (!account_types_tree_model)
100  account_types_tree_model = gnc_tree_model_account_types_new(0);
101  return account_types_tree_model;
102 }
103 
104 
105 static gboolean
106 gnc_tree_model_account_types_is_valid (GtkTreeModel *model,
107  GtkTreeIter *iter, gpointer data)
108 {
109  GNCAccountType type;
110  GObject *f_model = G_OBJECT (data);
111  guint32 valid_types = GPOINTER_TO_UINT (g_object_get_data (
112  f_model, TYPE_MASK));
113 
114  gtk_tree_model_get (model, iter,
115  GNC_TREE_MODEL_ACCOUNT_TYPES_COL_TYPE, &type, -1);
116  return (valid_types & (1 << type)) ? TRUE : FALSE;
117 }
118 
119 GtkTreeModel *
120 gnc_tree_model_account_types_filter_using_mask (guint32 types)
121 {
122  GtkTreeModel *f_model;
123 
124  f_model = gtk_tree_model_filter_new (gnc_tree_model_account_types_master (),
125  NULL);
126  g_object_set_data (G_OBJECT (f_model), TYPE_MASK, GUINT_TO_POINTER (types));
127  gtk_tree_model_filter_set_visible_func (
128  GTK_TREE_MODEL_FILTER (f_model), gnc_tree_model_account_types_is_valid,
129  f_model, NULL);
130 
131  return f_model;
132 }
133 
134 void
135 gnc_tree_model_account_types_set_mask (GtkTreeModel *f_model,
136  guint32 types)
137 {
138  g_return_if_fail (f_model);
139 
140  g_object_set_data (G_OBJECT (f_model), TYPE_MASK, GUINT_TO_POINTER (types));
141  gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (f_model));
142 }
143 
144 guint32
145 gnc_tree_model_account_types_get_mask (GtkTreeModel *f_model)
146 {
147  g_return_val_if_fail (f_model, 0);
148 
149  return GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (f_model), TYPE_MASK));
150 }
151 
152 guint32
153 gnc_tree_model_account_types_get_selection (GtkTreeSelection *sel)
154 {
155  GtkTreeModel *f_model, *model;
156  GtkTreePath *path;
157  GtkTreeView *view;
158  GList *list, *node;
159  guint32 bits = 0;
160 
161  g_return_val_if_fail(GTK_IS_TREE_SELECTION(sel), 0);
162  view = gtk_tree_selection_get_tree_view(sel);
163  g_return_val_if_fail (view, 0);
164 
165  /* circumvent a bug in gtk+ not always filling f_model */
166  f_model = NULL;
167  list = gtk_tree_selection_get_selected_rows(sel, &f_model);
168  if (!f_model)
169  f_model = gtk_tree_view_get_model(view);
170 
171  model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
172  if (model != account_types_tree_model)
173  PERR("TreeSelection's TreeModel is not the account-types Model");
174  else
175  {
176  for (node = list; node; node = node->next)
177  {
178  path = gtk_tree_model_filter_convert_path_to_child_path(
179  GTK_TREE_MODEL_FILTER(f_model), (GtkTreePath*)node->data);
180  if (!path || gtk_tree_path_get_depth(path) != 1)
181  {
182  PERR("Invalid Account-types TreePath.");
183  continue;
184  }
185  bits |= (1 << gtk_tree_path_get_indices(path)[0]);
186  }
187  }
188 
189  g_list_foreach (list, (GFunc)gtk_tree_path_free, NULL);
190  g_list_free (list);
191 
192  return bits;
193 }
194 
196 gnc_tree_model_account_types_get_selection_single(GtkTreeSelection *sel)
197 {
198  gint i;
199  guint32 selected = gnc_tree_model_account_types_get_selection(sel);
200 
201  for (i = 0; i < NUM_ACCOUNT_TYPES; i++)
202  if (selected & (1 << i))
203  return i;
204  return ACCT_TYPE_NONE;
205 }
206 
208 gnc_tree_model_account_types_get_active_combo (GtkComboBox *combo)
209 {
210  GtkTreeModelSort *s_model;
211  GtkTreeModelFilter *f_model;
212  GtkTreeIter iter;
213  guint32 bits = 0;
214  gint i;
215 
216  g_return_val_if_fail (GTK_IS_COMBO_BOX(combo), 0);
217 
218  if (gtk_combo_box_get_active_iter (combo, &iter))
219  {
220  s_model = GTK_TREE_MODEL_SORT(gtk_combo_box_get_model (combo));
221  f_model = GTK_TREE_MODEL_FILTER(gtk_tree_model_sort_get_model (s_model));
222 
223  if (gtk_tree_model_filter_get_model (f_model) != account_types_tree_model)
224  PERR("TreeSelection's TreeModel is not the account-types Model");
225  else
226  {
227  GtkTreePath *s_path = gtk_tree_model_get_path (GTK_TREE_MODEL(s_model), &iter);
228  GtkTreePath *f_path = gtk_tree_model_sort_convert_path_to_child_path (s_model, s_path);
229  GtkTreePath *path = gtk_tree_model_filter_convert_path_to_child_path (f_model, f_path);
230 
231  gtk_tree_path_free (f_path);
232  gtk_tree_path_free (s_path);
233 
234  if (!path || gtk_tree_path_get_depth (path) != 1)
235  {
236  PERR("Invalid Account-types TreePath.");
237  gtk_tree_path_free (path);
238  return ACCT_TYPE_NONE;
239  }
240  bits |= (1 << gtk_tree_path_get_indices (path)[0]);
241  gtk_tree_path_free (path);
242  }
243  }
244  for (i = 0; i < NUM_ACCOUNT_TYPES; i++)
245  if (bits & (1 << i))
246  return i;
247  return ACCT_TYPE_NONE;
248 }
249 
250 void
251 gnc_tree_model_account_types_set_selection (GtkTreeSelection *sel,
252  guint32 selected)
253 {
254  GtkTreePath *path;
255  GtkTreeModelFilter *f_model;
256  gint i;
257  GtkTreeView *view;
258 
259  g_return_if_fail(GTK_IS_TREE_SELECTION(sel));
260  view = gtk_tree_selection_get_tree_view(sel);
261  g_return_if_fail (view);
262  f_model = GTK_TREE_MODEL_FILTER(gtk_tree_view_get_model(view));
263  g_return_if_fail(gtk_tree_model_filter_get_model(f_model) ==
264  account_types_tree_model);
265  gtk_tree_selection_unselect_all(sel);
266  path = gtk_tree_path_new_first();
267 
268  for (i = 0; i < NUM_ACCOUNT_TYPES; i++)
269  {
270  if (selected & (1 << i))
271  {
272  GtkTreePath *f_path = gtk_tree_model_filter_convert_child_path_to_path(
273  f_model, path);
274  gtk_tree_selection_select_path(sel, f_path);
275  gtk_tree_view_scroll_to_cell(view, f_path, NULL, FALSE, 0.0, 0.0);
276  gtk_tree_path_free(f_path);
277  }
278  gtk_tree_path_next(path);
279  }
280  gtk_tree_path_free(path);
281 }
282 
283 void
284 gnc_tree_model_account_types_set_active_combo (GtkComboBox *combo,
285  guint32 selected)
286 {
287  GtkTreePath *path;
288  GtkTreeModelFilter *f_model;
289  GtkTreeModelSort *s_model;
290  gint i;
291 
292  g_return_if_fail (GTK_IS_COMBO_BOX(combo));
293 
294  s_model = GTK_TREE_MODEL_SORT(gtk_combo_box_get_model (combo));
295  f_model = GTK_TREE_MODEL_FILTER(gtk_tree_model_sort_get_model (s_model));
296  g_return_if_fail (gtk_tree_model_filter_get_model (f_model) ==
297  account_types_tree_model);
298 
299  gtk_combo_box_set_active (combo, -1);
300 
301  path = gtk_tree_path_new_first ();
302 
303  for (i = 0; i < NUM_ACCOUNT_TYPES; i++)
304  {
305  if (selected & (1 << i))
306  {
307  GtkTreeIter iter;
308  GtkTreePath *f_path = gtk_tree_model_filter_convert_child_path_to_path (f_model, path);
309  GtkTreePath *s_path = gtk_tree_model_sort_convert_child_path_to_path (s_model, f_path);
310 
311  gtk_tree_model_get_iter (GTK_TREE_MODEL(s_model), &iter, s_path);
312  gtk_combo_box_set_active_iter (combo, &iter);
313  gtk_tree_path_free (f_path);
314  gtk_tree_path_free (s_path);
315  }
316  gtk_tree_path_next (path);
317  }
318  gtk_tree_path_free (path);
319 }
320 
321 /* Static functions implementing GtkTreeModel */
322 
323 static GtkTreeModelFlags
324 gnc_tree_model_account_types_get_flags (GtkTreeModel * tree_model)
325 {
326  return GTK_TREE_MODEL_ITERS_PERSIST | GTK_TREE_MODEL_LIST_ONLY;
327 }
328 
329 static int
330 gnc_tree_model_account_types_get_n_columns (GtkTreeModel * tree_model)
331 {
332  return GNC_TREE_MODEL_ACCOUNT_TYPES_NUM_COLUMNS;
333 }
334 
335 static GType
336 gnc_tree_model_account_types_get_column_type (GtkTreeModel * tree_model,
337  int index)
338 {
339  g_return_val_if_fail(GNC_IS_TREE_MODEL_ACCOUNT_TYPES (tree_model),
340  G_TYPE_INVALID);
341  g_return_val_if_fail((index < GNC_TREE_MODEL_ACCOUNT_TYPES_NUM_COLUMNS)
342  && (index >= 0), G_TYPE_INVALID);
343 
344  switch (index)
345  {
346  case GNC_TREE_MODEL_ACCOUNT_TYPES_COL_TYPE:
347  return G_TYPE_INT;
348  case GNC_TREE_MODEL_ACCOUNT_TYPES_COL_NAME:
349  return G_TYPE_STRING;
350  case GNC_TREE_MODEL_ACCOUNT_TYPES_COL_SELECTED:
351  return G_TYPE_BOOLEAN;
352  default:
353  g_assert_not_reached ();
354  return G_TYPE_INVALID;
355  }
356 }
357 
358 static gboolean
359 gnc_tree_model_account_types_get_iter (GtkTreeModel * tree_model,
360  GtkTreeIter * iter, GtkTreePath * path)
361 {
362  GncTreeModelAccountTypes *model = GNC_TREE_MODEL_ACCOUNT_TYPES(tree_model);
363  gint i;
364 
365  g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT_TYPES (model), FALSE);
366  g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
367 
368  i = gtk_tree_path_get_indices (path)[0];
369 
370  if (i > ACCT_TYPE_NONE && i < NUM_ACCOUNT_TYPES)
371  {
372  iter->stamp = model->stamp;
373  iter->user_data = GINT_TO_POINTER (i);
374  return TRUE;
375  }
376 
377  iter->stamp = 0;
378  return FALSE;
379 }
380 
381 static GtkTreePath *
382 gnc_tree_model_account_types_get_path (GtkTreeModel * tree_model,
383  GtkTreeIter * iter)
384 {
385  GncTreeModelAccountTypes *model = GNC_TREE_MODEL_ACCOUNT_TYPES(tree_model);
386  GtkTreePath *path;
387 
388  g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT_TYPES (model), NULL);
389  g_return_val_if_fail (iter != NULL, NULL);
390  g_return_val_if_fail (iter->stamp == model->stamp, NULL);
391 
392  path = gtk_tree_path_new ();
393 
394  gtk_tree_path_append_index (path, GPOINTER_TO_INT (iter->user_data));
395 
396  return path;
397 }
398 
399 static void
400 gnc_tree_model_account_types_get_value (GtkTreeModel * tree_model,
401  GtkTreeIter * iter, int column,
402  GValue * value)
403 {
404  GncTreeModelAccountTypes *model = GNC_TREE_MODEL_ACCOUNT_TYPES(tree_model);
405 
406  g_return_if_fail (GNC_IS_TREE_MODEL_ACCOUNT_TYPES (model));
407  g_return_if_fail (iter != NULL);
408  g_return_if_fail (iter->stamp == model->stamp);
409 
410  switch (column)
411  {
412  case GNC_TREE_MODEL_ACCOUNT_TYPES_COL_TYPE:
413  g_value_init (value, G_TYPE_INT);
414  g_value_set_int (value, GPOINTER_TO_INT (iter->user_data));
415  break;
416  case GNC_TREE_MODEL_ACCOUNT_TYPES_COL_NAME:
417  g_value_init (value, G_TYPE_STRING);
418  g_value_set_string (value, xaccAccountGetTypeStr (
419  GPOINTER_TO_INT (iter->user_data)));
420  break;
421  case GNC_TREE_MODEL_ACCOUNT_TYPES_COL_SELECTED:
422  g_value_init (value, G_TYPE_BOOLEAN);
423  g_value_set_boolean (value, model->selected &
424  (1 << GPOINTER_TO_INT (iter->user_data)));
425  break;
426  default:
427  g_assert_not_reached ();
428  }
429 }
430 
431 static gboolean
432 gnc_tree_model_account_types_iter_next (GtkTreeModel * tree_model,
433  GtkTreeIter * iter)
434 {
435  GncTreeModelAccountTypes *model = GNC_TREE_MODEL_ACCOUNT_TYPES(tree_model);
436 
437  g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT_TYPES (model), FALSE);
438  g_return_val_if_fail (iter != NULL, FALSE);
439  g_return_val_if_fail (iter->stamp == model->stamp, FALSE);
440 
441  if (GPOINTER_TO_INT (iter->user_data) < NUM_ACCOUNT_TYPES - 1)
442  {
443  iter->user_data = GINT_TO_POINTER(
444  GPOINTER_TO_INT(iter->user_data) + 1);
445  return TRUE;
446  }
447 
448  iter->stamp = 0;
449  return FALSE;
450 }
451 
452 static gboolean
453 gnc_tree_model_account_types_iter_children (GtkTreeModel * tree_model,
454  GtkTreeIter * iter,
455  GtkTreeIter * parent)
456 {
457 
458  g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT_TYPES(tree_model), FALSE);
459 
460  if (parent != NULL)
461  return FALSE;
462 
463  iter->stamp = GNC_TREE_MODEL_ACCOUNT_TYPES (tree_model)->stamp;
464  iter->user_data = GINT_TO_POINTER (0);
465 
466  return TRUE;
467 }
468 
469 static gboolean
470 gnc_tree_model_account_types_iter_has_child (GtkTreeModel * tree_model,
471  GtkTreeIter * iter)
472 {
473  return FALSE;
474 }
475 
476 static int
477 gnc_tree_model_account_types_iter_n_children (GtkTreeModel * tree_model,
478  GtkTreeIter * iter)
479 {
480  g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT_TYPES (tree_model), -1);
481 
482  if (iter == NULL)
483  return NUM_ACCOUNT_TYPES;
484 
485  g_return_val_if_fail (
486  GNC_TREE_MODEL_ACCOUNT_TYPES (tree_model)->stamp == iter->stamp, -1);
487 
488  return 0;
489 }
490 
491 static gboolean
492 gnc_tree_model_account_types_iter_nth_child (GtkTreeModel * tree_model,
493  GtkTreeIter * iter,
494  GtkTreeIter * parent, int n)
495 {
496  GncTreeModelAccountTypes *model;
497 
498  g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT_TYPES (tree_model), FALSE);
499 
500  if (parent != NULL)
501  return FALSE;
502 
503  model = GNC_TREE_MODEL_ACCOUNT_TYPES (tree_model);
504 
505  if (n > ACCT_TYPE_NONE && n < NUM_ACCOUNT_TYPES)
506  {
507  iter->stamp = model->stamp;
508  iter->user_data = GINT_TO_POINTER (n);
509  return TRUE;
510  }
511 
512  iter->stamp = 0;
513  return FALSE;
514 }
515 
516 static gboolean
517 gnc_tree_model_account_types_iter_parent (GtkTreeModel * tree_model,
518  GtkTreeIter * iter,
519  GtkTreeIter * child)
520 {
521  return FALSE;
522 }
523 
524 static void
525 gnc_tree_model_account_types_tree_model_init (GtkTreeModelIface * iface)
526 {
527  iface->get_flags = gnc_tree_model_account_types_get_flags;
528  iface->get_n_columns = gnc_tree_model_account_types_get_n_columns;
529  iface->get_column_type = gnc_tree_model_account_types_get_column_type;
530  iface->get_iter = gnc_tree_model_account_types_get_iter;
531  iface->get_path = gnc_tree_model_account_types_get_path;
532  iface->get_value = gnc_tree_model_account_types_get_value;
533  iface->iter_next = gnc_tree_model_account_types_iter_next;
534  iface->iter_children = gnc_tree_model_account_types_iter_children;
535  iface->iter_has_child = gnc_tree_model_account_types_iter_has_child;
536  iface->iter_n_children = gnc_tree_model_account_types_iter_n_children;
537  iface->iter_nth_child = gnc_tree_model_account_types_iter_nth_child;
538  iface->iter_parent = gnc_tree_model_account_types_iter_parent;
539 }
540 
stop here; the following types just aren&#39;t ready for prime time
Definition: Account.h:161
#define PERR(format, args...)
Log a serious error.
Definition: qoflog.h:244
G_DEFINE_TYPE_WITH_CODE(GncMainWindow, gnc_main_window, GTK_TYPE_APPLICATION_WINDOW, G_IMPLEMENT_INTERFACE(GNC_TYPE_WINDOW, gnc_window_main_window_init)) static guint main_window_signals[LAST_SIGNAL]
A holding place for all the signals generated by the main window code.
Account handling public routines.
GNCAccountType
The account types are used to determine how the transaction data in the account is displayed...
Definition: Account.h:101
GtkTreeModel implementation to display account types in a GtkTreeView.
const char * xaccAccountGetTypeStr(GNCAccountType type)
The xaccAccountGetTypeStr() routine returns a string suitable for use in the GUI/Interface.
Definition: Account.cpp:4312
Not a type.
Definition: Account.h:105