GnuCash c935c2f+
Loading...
Searching...
No Matches
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
35static QofLogModule log_module = GNC_MOD_GUI;
36static GtkTreeModel *account_types_tree_model = NULL;
37
38#define TYPE_MASK "type-mask"
39
40/* Functions for the type system */
41static void
42gnc_tree_model_account_types_finalize (GObject * object);
43
44
45/* Functions implementing GtkTreeModel */
46static void
47gnc_tree_model_account_types_tree_model_init (GtkTreeModelIface * iface);
48
50{
51 GObject gobject;
52 int stamp;
53
54 guint32 selected;
55};
56
57G_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
61static void
62gnc_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
69static void
70gnc_tree_model_account_types_init (GncTreeModelAccountTypes * model)
71{
72 while (model->stamp == 0)
73 {
74 model->stamp = g_random_int ();
75 }
76}
77
78static void
79gnc_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
87GtkTreeModel *
88gnc_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
96static GtkTreeModel *
97gnc_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
105static gboolean
106gnc_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
119GtkTreeModel *
120gnc_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
134void
135gnc_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
144guint32
145gnc_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
152guint32
153gnc_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
196gnc_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
208gnc_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
250void
251gnc_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
283void
284gnc_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
323static GtkTreeModelFlags
324gnc_tree_model_account_types_get_flags (GtkTreeModel * tree_model)
325{
326 return GTK_TREE_MODEL_ITERS_PERSIST | GTK_TREE_MODEL_LIST_ONLY;
327}
328
329static int
330gnc_tree_model_account_types_get_n_columns (GtkTreeModel * tree_model)
331{
332 return GNC_TREE_MODEL_ACCOUNT_TYPES_NUM_COLUMNS;
333}
334
335static GType
336gnc_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
358static gboolean
359gnc_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
381static GtkTreePath *
382gnc_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
399static void
400gnc_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
431static gboolean
432gnc_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
452static gboolean
453gnc_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
469static gboolean
470gnc_tree_model_account_types_iter_has_child (GtkTreeModel * tree_model,
471 GtkTreeIter * iter)
472{
473 return FALSE;
474}
475
476static int
477gnc_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
491static gboolean
492gnc_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
516static gboolean
517gnc_tree_model_account_types_iter_parent (GtkTreeModel * tree_model,
518 GtkTreeIter * iter,
519 GtkTreeIter * child)
520{
521 return FALSE;
522}
523
524static void
525gnc_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
Account handling public routines.
GtkTreeModel implementation to display account types in a GtkTreeView.
GNCAccountType
The account types are used to determine how the transaction data in the account is displayed.
Definition Account.h:103
@ NUM_ACCOUNT_TYPES
stop here; the following types just aren't ready for prime time
Definition Account.h:161
@ ACCT_TYPE_NONE
Not a type.
Definition Account.h:105
const char * xaccAccountGetTypeStr(GNCAccountType type)
The xaccAccountGetTypeStr() routine returns a string suitable for use in the GUI/Interface.
Definition Account.cpp:4357
#define PERR(format, args...)
Log a serious error.
Definition qoflog.h:244