GnuCash  5.6-150-g038405b370+
gnc-tree-view-account.c
1 /**********************************************************************\
2  * gnc-tree-view-account.c -- GtkTreeView implementation to display *
3  * accounts in a GtkTreeView. *
4  * Copyright (C) 2003,2005,2006 David Hampton <hampton@employees.org> *
5  * *
6  * This program is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU General Public License as *
8  * published by the Free Software Foundation; either version 2 of *
9  * the License, or (at your option) any later version. *
10  * *
11  * This program is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14  * GNU General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU General Public License *
17  * along with this program; if not, contact: *
18  * *
19  * Free Software Foundation Voice: +1-617-542-5942 *
20  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
21  * Boston, MA 02110-1301, USA gnu@gnu.org *
22  * *
23 \**********************************************************************/
24 
25 #include <config.h>
26 
27 #include <stdbool.h>
28 #include <gtk/gtk.h>
29 #include <glib/gi18n.h>
30 #include <string.h>
31 
32 #include "gnc-tree-view.h"
33 #include "gnc-tree-model-account.h"
35 #include "gnc-tree-view-account.h"
36 
37 #include "Account.h"
38 #include "gnc-accounting-period.h"
39 #include "gnc-commodity.h"
40 #include "gnc-component-manager.h"
41 #include "gnc-engine.h"
42 #include "gnc-glib-utils.h"
43 #include "gnc-gobject-utils.h"
44 #include "gnc-prefs.h"
45 #include "gnc-hooks.h"
46 #include "gnc-session.h"
47 #include "gnc-icons.h"
48 #include "gnc-ui-balances.h"
49 #include "dialog-utils.h"
50 #include "window-main-summarybar.h"
51 
52 #define SAMPLE_ACCOUNT_VALUE "$1,000,000.00"
53 #define GNC_PREF_ACCOUNT_COLOR "show-account-color"
54 
57 /* This static indicates the debugging module that this .o belongs to. */
58 static QofLogModule log_module = GNC_MOD_GUI;
59 
61 static void gnc_tree_view_account_finalize (GObject *object);
62 static gboolean gnc_tree_view_search_compare (GtkTreeModel *model, gint column,
63  const gchar *key, GtkTreeIter *iter, gpointer search_data);
64 
65 static void gtva_update_column_names (GncTreeViewAccount *view);
66 static void gtva_currency_changed_cb (void);
67 
68 static gboolean gnc_tree_view_account_filter_helper (GtkTreeModel *model,
69  GtkTreeIter *iter,
70  gpointer data);
71 
72 static void gtva_setup_column_renderer_edited_cb(GncTreeViewAccount *account_view,
73  GtkTreeViewColumn *column,
74  GtkCellRenderer *renderer,
75  GncTreeViewAccountColumnTextEdited col_edited_cb);
76 
77 static void tax_info_data_func (GtkTreeViewColumn *col,
78  GtkCellRenderer *renderer,
79  GtkTreeModel *model,
80  GtkTreeIter *iter,
81  gpointer view);
82 
83 static void acc_color_data_func (GtkTreeViewColumn *col,
84  GtkCellRenderer *renderer,
85  GtkTreeModel *model,
86  GtkTreeIter *iter,
87  gpointer view);
88 
89 static void gnc_tree_view_account_color_update (gpointer gsettings,
90  gchar *key, gpointer user_data);
91 
92 static gboolean
93 gnc_tree_view_tooltip_cb (GtkWidget *widget, gint x, gint y, gboolean keyboard_tip,
94  GtkTooltip *tooltip, gpointer user_data);
95 
97 {
98  GncTreeView gnc_tree_view;
99  int stamp;
100 
101  AccountViewInfo avi;
102 
104  gpointer filter_data;
105  GSourceFunc filter_destroy;
106 
107  GtkTreeViewColumn *name_column;
108  GtkTreeViewColumn *code_column;
109  GtkTreeViewColumn *desc_column;
110  GtkTreeViewColumn *present_report_column;
111  GtkTreeViewColumn *balance_report_column;
112  GtkTreeViewColumn *cleared_report_column;
113  GtkTreeViewColumn *reconciled_report_column;
114  GtkTreeViewColumn *future_min_report_column;
115  GtkTreeViewColumn *total_report_column;
116  GtkTreeViewColumn *notes_column;
117 
118  gboolean show_account_color;
119 
120 } GncTreeViewAccountPrivate;
121 
122 
123 /************************************************************/
124 /* g_object required functions */
125 /************************************************************/
126 
127 G_DEFINE_TYPE(GncTreeViewAccount, gnc_tree_view_account, GNC_TYPE_TREE_VIEW)
128 
129 static void
130 gnc_tree_view_account_class_init (GncTreeViewAccountClass *klass)
131 {
132  GObjectClass *o_class;
133 
134  /* GObject signals */
135  o_class = G_OBJECT_CLASS (klass);
136  o_class->finalize = gnc_tree_view_account_finalize;
137 
138  gnc_hook_add_dangler(HOOK_CURRENCY_CHANGED,
139  (GFunc)gtva_currency_changed_cb, NULL, NULL);
140 }
141 
142 /********************************************************************\
143  * gnc_init_account_view_info *
144  * initialize an account view info structure with default values *
145  * *
146  * Args: avi - structure to initialize *
147  * Returns: nothing *
148 \********************************************************************/
149 static void
150 gnc_init_account_view_info(AccountViewInfo *avi)
151 {
152  int i;
153 
154  for (i = 0; i < NUM_ACCOUNT_TYPES; i++)
155  avi->include_type[i] = TRUE;
156  avi->show_hidden = FALSE;
157 }
158 
159 static void
160 gnc_tree_view_account_init (GncTreeViewAccount *view)
161 {
162  gnc_prefs_register_cb (GNC_PREFS_GROUP_GENERAL,
163  GNC_PREF_ACCOUNT_COLOR,
164  gnc_tree_view_account_color_update,
165  view);
166 
167  gnc_init_account_view_info(&view->avi);
168 }
169 
170 static void
171 gnc_tree_view_account_finalize (GObject *object)
172 {
173  ENTER("view %p", object);
174  g_return_if_fail (object != NULL);
175  g_return_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (object));
176 
177  GncTreeViewAccount *view = GNC_TREE_VIEW_ACCOUNT (object);
178 
179  gnc_prefs_remove_cb_by_func (GNC_PREFS_GROUP_GENERAL,
180  GNC_PREF_ACCOUNT_COLOR,
181  gnc_tree_view_account_color_update,
182  view);
183  if (view->filter_destroy)
184  {
185  view->filter_destroy(view->filter_data);
186  view->filter_destroy = NULL;
187  }
188  view->filter_fn = NULL;
189 
190  G_OBJECT_CLASS (gnc_tree_view_account_parent_class)->finalize (object);
191  LEAVE(" ");
192 }
193 
194 
195 /************************************************************
196  * Callbacks *
197  ************************************************************/
198 static void
199 gnc_tree_view_account_hidden_toggled (GtkCellRendererToggle *cell,
200  const gchar *s_path_str,
201  gpointer user_data)
202 {
203  GncTreeViewAccount *tree_view;
204  GtkTreePath *s_path;
205  Account *account;
206  gboolean hidden;
207 
208  /* Change the requested account */
209  tree_view = user_data;
210  s_path = gtk_tree_path_new_from_string (s_path_str);
211  account = gnc_tree_view_account_get_account_from_path (tree_view, s_path);
212  if (account)
213  {
214  hidden = !gtk_cell_renderer_toggle_get_active (cell); // hasn't changed yet.
215  xaccAccountSetHidden (account, hidden);
216  }
217 
218  /* Clean up */
219  gtk_tree_path_free (s_path);
220 }
221 
222 
223 static void
224 gnc_tree_view_account_placeholder_toggled (GtkCellRendererToggle *cell,
225  const gchar *s_path_str,
226  gpointer user_data)
227 {
228  GncTreeViewAccount *tree_view;
229  GtkTreePath *s_path;
230  Account *account;
231  gboolean placeholder;
232 
233  /* Change the requested account */
234  tree_view = user_data;
235  s_path = gtk_tree_path_new_from_string (s_path_str);
236  account = gnc_tree_view_account_get_account_from_path (tree_view, s_path);
237  if (account)
238  {
239  placeholder = !gtk_cell_renderer_toggle_get_active (cell); // hasn't changed yet.
240  xaccAccountSetPlaceholder (account, placeholder);
241  }
242 
243  /* Clean up */
244  gtk_tree_path_free (s_path);
245 }
246 
247 
248 /************************************************************/
249 /* sort functions */
250 /************************************************************/
251 
252 static GtkTreeModel *
253 sort_cb_setup_w_iters (GtkTreeModel *f_model,
254  GtkTreeIter *f_iter_a,
255  GtkTreeIter *f_iter_b,
256  GtkTreeIter *iter_a,
257  GtkTreeIter *iter_b,
258  const Account **account_a,
259  const Account **account_b)
260 {
261  GtkTreeModel *model;
262 
263  model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
264  gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER(f_model),
265  iter_a,
266  f_iter_a);
267  gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER(f_model),
268  iter_b,
269  f_iter_b);
270  *account_a = gnc_tree_model_account_get_account (GNC_TREE_MODEL_ACCOUNT(model), iter_a);
271  *account_b = gnc_tree_model_account_get_account (GNC_TREE_MODEL_ACCOUNT(model), iter_b);
272  return model;
273 }
274 
275 static void
276 sort_cb_setup (GtkTreeModel *f_model,
277  GtkTreeIter *f_iter_a,
278  GtkTreeIter *f_iter_b,
279  const Account **account_a,
280  const Account **account_b)
281 {
282  GtkTreeIter iter_a, iter_b;
283 
284  sort_cb_setup_w_iters (f_model, f_iter_a, f_iter_b,
285  &iter_a, &iter_b, account_a, account_b);
286 }
287 
288 
289 static gint
290 sort_by_earliest_date (GtkTreeModel *f_model, GtkTreeIter *f_iter1, GtkTreeIter *f_iter2,
291  gpointer user_data)
292 {
293  const Account *account1, *account2;
294  sort_cb_setup (f_model, f_iter1, f_iter2, &account1, &account2);
295 
296  time64 date1 = gnc_account_get_earliest_date (account1);
297  time64 date2 = gnc_account_get_earliest_date (account2);
298  return date1 == date2 ? xaccAccountOrder (account1, account2) :
299  date1 == INT64_MAX || date1 < date2 ? -1 : 1;
300 }
301 
302 static gint
303 sort_by_last_reconcile_date (GtkTreeModel *f_model,
304  GtkTreeIter *f_iter1,
305  GtkTreeIter *f_iter2,
306  gpointer user_data)
307 {
308  const Account *account1, *account2;
309  time64 account1_date = 0, account2_date = 0;
310 
311  sort_cb_setup (f_model, f_iter1, f_iter2, &account1, &account2);
312 
313  gboolean rec1 = xaccAccountGetReconcileLastDate (account1, &account1_date);
314  gboolean rec2 = xaccAccountGetReconcileLastDate (account2, &account2_date);
315 
316  if (!rec1)
317  return rec2 ? -1 : xaccAccountOrder (account1, account2);
318  if (!rec2)
319  return 1;
320  if (account1_date < account2_date)
321  return -1;
322  else if (account1_date > account2_date)
323  return 1;
324  else
325  return xaccAccountOrder (account1, account2);
326 }
327 
328 static gint
329 sort_by_string (GtkTreeModel *f_model,
330  GtkTreeIter *f_iter1,
331  GtkTreeIter *f_iter2,
332  gpointer user_data)
333 {
334  GtkTreeModel *model;
335  GtkTreeIter iter1, iter2;
336  const Account *account1, *account2;
337  gchar *str1, *str2;
338  gint column = GPOINTER_TO_INT(user_data);
339  gint result;
340 
341  model = sort_cb_setup_w_iters(f_model, f_iter1, f_iter2, &iter1, &iter2, &account1, &account2);
342 
343  /* Get the strings. */
344  gtk_tree_model_get(GTK_TREE_MODEL(model), &iter1, column, &str1, -1);
345  gtk_tree_model_get(GTK_TREE_MODEL(model), &iter2, column, &str2, -1);
346 
347  result = safe_utf8_collate(str1, str2);
348  g_free(str1);
349  g_free(str2);
350  if (result != 0)
351  return result;
352  return xaccAccountOrder(account1, account2);
353 }
354 
355 static gint
356 sort_by_code (GtkTreeModel *f_model,
357  GtkTreeIter *f_iter_a,
358  GtkTreeIter *f_iter_b,
359  gpointer user_data)
360 {
361  const Account *account_a, *account_b;
362 
363  sort_cb_setup (f_model, f_iter_a, f_iter_b, &account_a, &account_b);
364 
365  /* Default ordering uses this column first. */
366  return xaccAccountOrder(account_a, account_b);
367 }
368 
369 static gint
370 sort_by_xxx_value (xaccGetBalanceInCurrencyFn fn,
371  gboolean recurse,
372  GtkTreeModel *f_model,
373  GtkTreeIter *f_iter_a,
374  GtkTreeIter *f_iter_b,
375  gpointer user_data)
376 {
377  const Account *account_a, *account_b;
378  const gnc_commodity *cur = gnc_default_currency();
379  gnc_numeric balance_a, balance_b;
380  gint result;
381 
382  /* Find the accounts */
383  sort_cb_setup (f_model, f_iter_a, f_iter_b, &account_a, &account_b);
384 
385  /* Get balances */
386  balance_a = gnc_ui_account_get_balance_full(fn, account_a, recurse, NULL, cur);
387  balance_b = gnc_ui_account_get_balance_full(fn, account_b, recurse, NULL, cur);
388 
389  result = gnc_numeric_compare(balance_a, balance_b);
390  if (result != 0)
391  return result;
392  return xaccAccountOrder(account_a, account_b);
393 }
394 
395 static gint
396 sort_by_present_value (GtkTreeModel *f_model,
397  GtkTreeIter *f_iter_a,
398  GtkTreeIter *f_iter_b,
399  gpointer user_data)
400 {
401  return sort_by_xxx_value (xaccAccountGetPresentBalanceInCurrency, TRUE,
402  f_model, f_iter_a, f_iter_b, user_data);
403 }
404 
405 static gint
406 sort_by_balance_value (GtkTreeModel *f_model,
407  GtkTreeIter *f_iter_a,
408  GtkTreeIter *f_iter_b,
409  gpointer user_data)
410 {
411  return sort_by_xxx_value (xaccAccountGetBalanceInCurrency, TRUE,
412  f_model, f_iter_a, f_iter_b, user_data);
413 }
414 
415 static gint
416 sort_by_cleared_value (GtkTreeModel *f_model,
417  GtkTreeIter *f_iter_a,
418  GtkTreeIter *f_iter_b,
419  gpointer user_data)
420 {
421  return sort_by_xxx_value (xaccAccountGetClearedBalanceInCurrency, TRUE,
422  f_model, f_iter_a, f_iter_b, user_data);
423 }
424 
425 static gint
426 sort_by_reconciled_value (GtkTreeModel *f_model,
427  GtkTreeIter *f_iter_a,
428  GtkTreeIter *f_iter_b,
429  gpointer user_data)
430 {
431  return sort_by_xxx_value (xaccAccountGetReconciledBalanceInCurrency, TRUE,
432  f_model, f_iter_a, f_iter_b, user_data);
433 }
434 
435 static gint
436 sort_by_future_min_value (GtkTreeModel *f_model,
437  GtkTreeIter *f_iter_a,
438  GtkTreeIter *f_iter_b,
439  gpointer user_data)
440 {
441  return sort_by_xxx_value (xaccAccountGetProjectedMinimumBalanceInCurrency, TRUE,
442  f_model, f_iter_a, f_iter_b, user_data);
443 }
444 
445 static gint
446 sort_by_total_value (GtkTreeModel *f_model,
447  GtkTreeIter *f_iter_a,
448  GtkTreeIter *f_iter_b,
449  gpointer user_data)
450 {
451  return sort_by_xxx_value (xaccAccountGetBalanceInCurrency, TRUE,
452  f_model, f_iter_a, f_iter_b, user_data);
453 }
454 
455 static gint
456 sort_by_hidden (GtkTreeModel *f_model,
457  GtkTreeIter *f_iter_a,
458  GtkTreeIter *f_iter_b,
459  gpointer user_data)
460 {
461  const Account *account_a, *account_b;
462  gboolean flag_a, flag_b;
463 
464  /* Find the accounts */
465  sort_cb_setup (f_model, f_iter_a, f_iter_b, &account_a, &account_b);
466 
467  /* Get the placeholder flags. */
468  flag_a = xaccAccountGetHidden (account_a);
469  flag_b = xaccAccountGetHidden (account_b);
470 
471  if (flag_a > flag_b)
472  return -1;
473  else if (flag_a < flag_b)
474  return 1;
475  return xaccAccountOrder (account_a, account_b);
476 }
477 
478 static gint
479 sort_by_placeholder (GtkTreeModel *f_model,
480  GtkTreeIter *f_iter_a,
481  GtkTreeIter *f_iter_b,
482  gpointer user_data)
483 {
484  const Account *account_a, *account_b;
485  gboolean flag_a, flag_b;
486 
487  /* Find the accounts */
488  sort_cb_setup (f_model, f_iter_a, f_iter_b, &account_a, &account_b);
489 
490  /* Get the placeholder flags. */
491  flag_a = xaccAccountGetPlaceholder(account_a);
492  flag_b = xaccAccountGetPlaceholder(account_b);
493 
494  if (flag_a > flag_b)
495  return -1;
496  else if (flag_a < flag_b)
497  return 1;
498  return xaccAccountOrder(account_a, account_b);
499 }
500 
501 static gint
502 sort_by_opening_balance (GtkTreeModel *f_model,
503  GtkTreeIter *f_iter_a,
504  GtkTreeIter *f_iter_b,
505  gpointer user_data)
506 {
507  const Account *account_a, *account_b;
508  gboolean flag_a, flag_b;
509 
510  /* Find the accounts */
511  sort_cb_setup (f_model, f_iter_a, f_iter_b, &account_a, &account_b);
512 
513  /* Get the opening balance flags. */
514  flag_a = xaccAccountGetIsOpeningBalance (account_a);
515  flag_b = xaccAccountGetIsOpeningBalance (account_b);
516 
517  if (flag_a > flag_b)
518  return -1;
519  else if (flag_a < flag_b)
520  return 1;
521  return xaccAccountOrder(account_a, account_b);
522 }
523 
524 static gint
525 sort_by_xxx_period_value (GtkTreeModel *f_model,
526  GtkTreeIter *f_iter_a,
527  GtkTreeIter *f_iter_b,
528  gboolean recurse)
529 {
530  Account *acct1, *acct2;
531  time64 t1, t2;
532  gnc_numeric b1, b2;
533  gint result;
534 
535  sort_cb_setup (f_model, f_iter_a, f_iter_b,
536  (const Account **)&acct1, (const Account **)&acct2);
537 
538  t1 = gnc_accounting_period_fiscal_start();
539  t2 = gnc_accounting_period_fiscal_end();
540 
541  b1 = xaccAccountGetBalanceChangeForPeriod(acct1, t1, t2, recurse);
542  b2 = xaccAccountGetBalanceChangeForPeriod(acct2, t1, t2, recurse);
543 
544  result = gnc_numeric_compare(b1, b2);
545  if (result != 0)
546  return result;
547  return xaccAccountOrder(acct1, acct2);
548 }
549 
550 static gint
551 sort_by_balance_period_value (GtkTreeModel *f_model,
552  GtkTreeIter *f_iter_a,
553  GtkTreeIter *f_iter_b,
554  gpointer user_data)
555 {
556  return sort_by_xxx_period_value (f_model, f_iter_a, f_iter_b, FALSE);
557 }
558 
559 static gint
560 sort_by_total_period_value (GtkTreeModel *f_model,
561  GtkTreeIter *f_iter_a,
562  GtkTreeIter *f_iter_b,
563  gpointer user_data)
564 {
565  return sort_by_xxx_period_value (f_model, f_iter_a, f_iter_b, TRUE);
566 }
567 
568 /************************************************************/
569 /* Tax_Info data function */
570 /************************************************************/
571 
572 /*
573  * The tax-info column in the account tree view is based on the
574  * combination of two columns in the account tree model. The data
575  * function displays only the the data in the
576  * GNC_TREE_MODEL_ACCOUNT_COL_TAX_INFO model column if the row is
577  * expanded; otherwise it combines it with the data
578  * in the GNC_TREE_MODEL_ACCOUNT_COL_TAX_INFO_SUB_ACCT model column.
579  */
580 static void
581 tax_info_data_func (GtkTreeViewColumn *col,
582  GtkCellRenderer *renderer,
583  GtkTreeModel *model,
584  GtkTreeIter *iter,
585  gpointer view)
586 {
587  gchar *tax_info = NULL;
588  GtkTreePath *path;
589 
590  gtk_tree_model_get(model,
591  iter,
592  GNC_TREE_MODEL_ACCOUNT_COL_TAX_INFO,
593  &tax_info,
594  -1);
595 
596  path = gtk_tree_model_get_path(model, iter);
597  if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(view), path))
598  g_object_set(renderer, "text",
599  (tax_info == NULL ? "" : tax_info), NULL);
600  else
601  {
602  gchar *tax_info_sub_acct = NULL;
603 
604  gtk_tree_model_get(model,
605  iter,
606  GNC_TREE_MODEL_ACCOUNT_COL_TAX_INFO_SUB_ACCT,
607  &tax_info_sub_acct,
608  -1);
609  if ((g_strcmp0 (tax_info_sub_acct, "") == 0) ||
610  (tax_info_sub_acct == NULL))
611  g_object_set(renderer, "text",
612  (tax_info == NULL ? "" : tax_info), NULL);
613  else
614  {
615  if ((g_strcmp0 (tax_info, "") == 0) ||
616  (tax_info == NULL))
617  g_object_set(renderer, "text",
618  (tax_info_sub_acct == NULL ? "" : tax_info_sub_acct),
619  NULL);
620  else
621  {
622  gchar *combined_tax_info;
623  combined_tax_info = g_strdup_printf ("%s; %s",
624  (tax_info == NULL ? "" : tax_info),
625  (tax_info_sub_acct == NULL ? "" :
626  tax_info_sub_acct));
627  g_object_set(renderer, "text", combined_tax_info, NULL);
628  g_free(combined_tax_info);
629  }
630  }
631  g_free(tax_info_sub_acct);
632  }
633  g_free(tax_info);
634  gtk_tree_path_free(path);
635 }
636 
637 /************************************************************/
638 /* acc_color data function */
639 /************************************************************/
640 /*
641  * The account-color column in the account tree view is obtained
642  * from the GNC_TREE_MODEL_ACCOUNT_COL_COLOR_ACCOUNT which is
643  * checked for a valid color string to set the background color
644  * of the cell.
645  */
646 static void
647 update_cell_renderers (GList *renderers, gchar *account_color)
648 {
649  GtkCellRenderer *cell;
650  GList *node;
651 
652  /* Update the cell background in the list of renderers */
653  for (node = renderers; node; node = node->next)
654  {
655  cell = node->data;
656  g_object_set (cell, "cell-background", account_color, NULL);
657  }
658 }
659 
660 /* Colorizes a cell in the account tree view if
661  * - a color is assigned to the given account
662  * - the user enabled account colorization in the preferences
663  * Only the account color column is special: it will always
664  * be colored if a valid color was set, regardless of the
665  * preference setting.
666  */
667 static void
668 acc_color_data_func (GtkTreeViewColumn *col,
669  GtkCellRenderer *renderer,
670  GtkTreeModel *model,
671  GtkTreeIter *iter,
672  gpointer data)
673 {
674  gchar *acc_color = NULL, *acc_cond_color = NULL;
675  gchar *item;
676  GdkRGBA color;
677  gchar *column_name;
678  GList *renderers;
679 
680  gtk_tree_model_get(model,
681  iter,
682  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_ACCOUNT,
683  &item,
684  -1);
685 
686  /* Check if color was set for the account */
687  if ((item) && (*item != '\0'))
688  acc_color = g_strstrip(g_strdup(item));
689  g_free (item);
690 
691  /* Test if the color string represents a valid color */
692  if (acc_color && (!gdk_rgba_parse(&color, acc_color)))
693  {
694  g_free (acc_color);
695  acc_color = NULL;
696  }
697 
698  /* Determine whether columns other than the
699  * Account Color column should be colored. */
700  GncTreeViewAccount *view = data;
701  if (view->show_account_color)
702  acc_cond_color = acc_color;
703 
704  column_name = g_object_get_data(G_OBJECT(col), PREF_NAME);
705  renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (col));
706 
707  /* Account Color column is always colored, other columns only conditionally. */
708  if (g_strcmp0(column_name, "account-color") == 0)
709  update_cell_renderers (renderers, acc_color);
710  else
711  update_cell_renderers (renderers, acc_cond_color);
712 
713  g_list_free (renderers);
714  g_free (acc_color);
715 }
716 
722 static void
723 gnc_tree_view_account_color_update (gpointer gsettings, gchar *key, gpointer user_data)
724 {
725  GncTreeViewAccount *view;
726 
727  g_return_if_fail(GNC_IS_TREE_VIEW_ACCOUNT(user_data));
728  view = user_data;
729  if (g_strcmp0 (key, GNC_PREF_ACCOUNT_COLOR) == 0)
730  view->show_account_color = gnc_prefs_get_bool(GNC_PREFS_GROUP_GENERAL, key);
731 
732  // do a refilter so the tree view background color gets updated
734 }
735 
739 void
740 gnc_tree_view_account_column_add_color (GncTreeViewAccount *view, GtkTreeViewColumn *col)
741 {
742  GtkCellRenderer *renderer = gnc_tree_view_column_get_renderer(col);
743 
744  gtk_tree_view_column_set_cell_data_func (col, renderer, acc_color_data_func,
745  GTK_TREE_VIEW(view), NULL);
746 }
747 
748 /************************************************************/
749 /* New View Creation */
750 /************************************************************/
751 
752 /*
753  * Create a new account tree view with (optional) top level root node.
754  * This view will be based on a model that is common to all view of
755  * the same set of books, but will have its own private filter on that
756  * model.
757  */
758 GtkTreeView *
759 gnc_tree_view_account_new_with_root (Account *root, gboolean show_root)
760 {
761  GtkTreeModel *model, *f_model, *s_model;
762  GtkTreePath *virtual_root_path = NULL;
763  const gchar *sample_type, *sample_commodity;
764  GtkTreeViewColumn *tax_info_column, *acc_color_column, *acc_balance_limit_column;
765  GtkCellRenderer *renderer;
766  GList *col_list = NULL, *node = NULL;
767 
768  ENTER(" ");
769  /* Create our view */
770  GncTreeViewAccount *view = g_object_new (GNC_TYPE_TREE_VIEW_ACCOUNT,
771  "has-tooltip", true,
772  "name", "gnc-id-account-tree", NULL);
773 
774  /* Get the show_account_color value from gsettings */
775  view->show_account_color = gnc_prefs_get_bool(GNC_PREFS_GROUP_GENERAL, GNC_PREF_ACCOUNT_COLOR);
776 
777  /* Create/get a pointer to the existing model for this set of books. */
778  model = gnc_tree_model_account_new (root);
779 
780  /* Set up the view private filter layer on the common model. */
781  if (!show_root)
782  virtual_root_path = gtk_tree_path_new_first ();
783  f_model = gtk_tree_model_filter_new (model, virtual_root_path);
784  /* A GncTreeModelAccount is based on a GncTreeModel, which is a
785  * GObject that provides a GtkTreeModel interface. */
786  g_object_unref(G_OBJECT(model));
787  if (virtual_root_path)
788  gtk_tree_path_free(virtual_root_path);
789 
790  /* Set up the view private sort layer on the common model. */
791  s_model = gtk_tree_model_sort_new_with_model(f_model);
792  g_object_unref(G_OBJECT(f_model));
793  gtk_tree_view_set_model (GTK_TREE_VIEW (view), s_model);
794  g_object_unref(G_OBJECT(s_model));
795 
796  /* Set default visibilities */
797  gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(view), FALSE);
798 
800  sample_commodity = gnc_commodity_get_fullname(gnc_default_currency());
801 
802  view->name_column
803  = gnc_tree_view_add_text_column(GNC_TREE_VIEW(view), _("Account Name"), "name",
804  GNC_ICON_ACCOUNT, "Expenses:Entertainment",
805  GNC_TREE_MODEL_ACCOUNT_COL_NAME,
806  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
807  sort_by_string);
808 
809  gnc_tree_view_add_text_column(GNC_TREE_VIEW(view), _("Type"), "type", NULL, sample_type,
810  GNC_TREE_MODEL_ACCOUNT_COL_TYPE,
811  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
812  sort_by_string);
813 
814  gnc_tree_view_add_text_column(GNC_TREE_VIEW(view), _("Commodity"), "commodity", NULL,
815  sample_commodity,
816  GNC_TREE_MODEL_ACCOUNT_COL_COMMODITY,
817  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
818  sort_by_string);
819  view->code_column
820  = gnc_tree_view_add_text_column(GNC_TREE_VIEW(view), _("Account Code"), "account-code", NULL,
821  "1-123-1234",
822  GNC_TREE_MODEL_ACCOUNT_COL_CODE,
823  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
824  sort_by_code);
825  view->desc_column
826  = gnc_tree_view_add_text_column(GNC_TREE_VIEW(view), _("Description"), "description", NULL,
827  "Sample account description.",
828  GNC_TREE_MODEL_ACCOUNT_COL_DESCRIPTION,
829  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
830  sort_by_string);
831 
832  gnc_tree_view_add_numeric_column(GNC_TREE_VIEW(view), _("Last Num"), "lastnum", "12345",
833  GNC_TREE_MODEL_ACCOUNT_COL_LASTNUM,
834  GNC_TREE_VIEW_COLUMN_COLOR_NONE,
835  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
836  sort_by_string);
837 
838  gnc_tree_view_add_numeric_column(GNC_TREE_VIEW(view), _("Present"), "present",
839  SAMPLE_ACCOUNT_VALUE,
840  GNC_TREE_MODEL_ACCOUNT_COL_PRESENT,
841  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_PRESENT,
842  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
843  sort_by_present_value);
844  view->present_report_column
845  = gnc_tree_view_add_numeric_column(GNC_TREE_VIEW(view), _("Present (Report)"), "present_report",
846  SAMPLE_ACCOUNT_VALUE,
847  GNC_TREE_MODEL_ACCOUNT_COL_PRESENT_REPORT,
848  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_PRESENT,
849  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
850  sort_by_present_value);
851 
852  gnc_tree_view_add_numeric_column(GNC_TREE_VIEW(view), _("Balance"), "balance",
853  SAMPLE_ACCOUNT_VALUE,
854  GNC_TREE_MODEL_ACCOUNT_COL_BALANCE,
855  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_BALANCE,
856  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
857  sort_by_balance_value);
858  view->balance_report_column
859  = gnc_tree_view_add_numeric_column(GNC_TREE_VIEW(view), _("Balance (Report)"), "balance_report",
860  SAMPLE_ACCOUNT_VALUE,
861  GNC_TREE_MODEL_ACCOUNT_COL_BALANCE_REPORT,
862  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_BALANCE,
863  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
864  sort_by_balance_value);
865 
866  gnc_tree_view_add_numeric_column(GNC_TREE_VIEW(view), _("Balance (Period)"), "balance-period",
867  SAMPLE_ACCOUNT_VALUE,
868  GNC_TREE_MODEL_ACCOUNT_COL_BALANCE_PERIOD,
869  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_BALANCE_PERIOD,
870  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
871  sort_by_balance_period_value);
872 
873  gnc_tree_view_add_numeric_column(GNC_TREE_VIEW(view), _("Cleared"), "cleared",
874  SAMPLE_ACCOUNT_VALUE,
875  GNC_TREE_MODEL_ACCOUNT_COL_CLEARED,
876  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_CLEARED,
877  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
878  sort_by_cleared_value);
879  view->cleared_report_column
880  = gnc_tree_view_add_numeric_column(GNC_TREE_VIEW(view), _("Cleared (Report)"), "cleared_report",
881  SAMPLE_ACCOUNT_VALUE,
882  GNC_TREE_MODEL_ACCOUNT_COL_CLEARED_REPORT,
883  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_CLEARED,
884  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
885  sort_by_cleared_value);
886 
887  gnc_tree_view_add_numeric_column(GNC_TREE_VIEW(view), _("Reconciled"), "reconciled",
888  SAMPLE_ACCOUNT_VALUE,
889  GNC_TREE_MODEL_ACCOUNT_COL_RECONCILED,
890  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_RECONCILED,
891  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
892  sort_by_reconciled_value);
893  view->reconciled_report_column
894  = gnc_tree_view_add_numeric_column(GNC_TREE_VIEW(view), _("Reconciled (Report)"), "reconciled_report",
895  SAMPLE_ACCOUNT_VALUE,
896  GNC_TREE_MODEL_ACCOUNT_COL_RECONCILED_REPORT,
897  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_RECONCILED,
898  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
899  sort_by_reconciled_value);
900 
901  gnc_tree_view_add_text_column(GNC_TREE_VIEW(view), _("Earliest Date"), "earliest-date", NULL,
902  "31 December 2000",
903  GNC_TREE_MODEL_ACCOUNT_COL_EARLIEST_DATE,
904  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
905  sort_by_earliest_date);
906 
907  gnc_tree_view_add_text_column(GNC_TREE_VIEW(view), _("Last Reconcile Date"), "last-recon-date", NULL,
908  "Last Reconcile Date",
909  GNC_TREE_MODEL_ACCOUNT_COL_RECONCILED_DATE,
910  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
911  sort_by_last_reconcile_date);
912 
913  gnc_tree_view_add_numeric_column(GNC_TREE_VIEW(view), _("Future Minimum"), "future_min",
914  SAMPLE_ACCOUNT_VALUE,
915  GNC_TREE_MODEL_ACCOUNT_COL_FUTURE_MIN,
916  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_FUTURE_MIN,
917  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
918  sort_by_future_min_value);
919  view->future_min_report_column
920  = gnc_tree_view_add_numeric_column(GNC_TREE_VIEW(view), _("Future Minimum (Report)"), "future_min_report",
921  SAMPLE_ACCOUNT_VALUE,
922  GNC_TREE_MODEL_ACCOUNT_COL_FUTURE_MIN_REPORT,
923  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_FUTURE_MIN,
924  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
925  sort_by_future_min_value);
926 
927  gnc_tree_view_add_numeric_column(GNC_TREE_VIEW(view), _("Total"), "total",
928  SAMPLE_ACCOUNT_VALUE,
929  GNC_TREE_MODEL_ACCOUNT_COL_TOTAL,
930  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_TOTAL,
931  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
932  sort_by_total_value);
933  view->total_report_column
934  = gnc_tree_view_add_numeric_column(GNC_TREE_VIEW(view), _("Total (Report)"), "total_report",
935  SAMPLE_ACCOUNT_VALUE,
936  GNC_TREE_MODEL_ACCOUNT_COL_TOTAL_REPORT,
937  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_TOTAL,
938  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
939  sort_by_total_value);
940 
941  gnc_tree_view_add_numeric_column(GNC_TREE_VIEW(view), _("Total (Period)"), "total-period",
942  SAMPLE_ACCOUNT_VALUE,
943  GNC_TREE_MODEL_ACCOUNT_COL_TOTAL_PERIOD,
944  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_TOTAL_PERIOD,
945  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
946  sort_by_total_period_value);
947 
948  /* Translators: The C is the column title and stands for Color, this should be one character */
949  acc_color_column
950  = gnc_tree_view_add_text_column(GNC_TREE_VIEW(view), C_("Column header for 'Color'", "C"), "account-color", NULL,
951  "xx",
952  GNC_TREE_VIEW_COLUMN_DATA_NONE,
953  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
954  NULL);
955 
956  /* Add the full title to the object for menu creation */
957  g_object_set_data_full(G_OBJECT(acc_color_column), REAL_TITLE,
958  g_strdup(_("Account Color")), g_free);
959 
960  /* Also add the full title to the column header as a tooltip */
961  gtk_widget_set_tooltip_text (gtk_tree_view_column_get_button (acc_color_column), _("Account Color"));
962 
963  acc_balance_limit_column
964  = gnc_tree_view_add_pix_column (GNC_TREE_VIEW(view),
965  C_("Column header for 'Balance Limit'", "L"),
966  "account-balance-limit",
967  "xx",
968  GNC_TREE_MODEL_ACCOUNT_COL_BALANCE_LIMIT,
969  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
970  NULL);
971 
972  /* Add the full title to the object for menu creation */
973  g_object_set_data_full(G_OBJECT(acc_balance_limit_column), REAL_TITLE,
974  g_strdup(_("Balance Limit")), g_free);
975 
976  /* Also add the full title to the column header as a tooltip */
977  gtk_widget_set_tooltip_text (gtk_tree_view_column_get_button (acc_balance_limit_column), _("Balance Limit"));
978 
979  view->notes_column
980  = gnc_tree_view_add_text_view_column(GNC_TREE_VIEW(view), _("Notes"), "notes", NULL,
981  "Sample account notes.",
982  GNC_TREE_MODEL_ACCOUNT_COL_NOTES,
983  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
984  sort_by_string);
985 
986  tax_info_column
987  = gnc_tree_view_add_text_column(GNC_TREE_VIEW(view), _("Tax Info"), "tax-info", NULL,
988  "Sample tax info.",
989  GNC_TREE_MODEL_ACCOUNT_COL_TAX_INFO,
990  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
991  sort_by_string);
992 
993  renderer = gnc_tree_view_column_get_renderer(tax_info_column);
994  gtk_tree_view_column_set_cell_data_func(tax_info_column,
995  renderer,
996  tax_info_data_func,
997  GTK_TREE_VIEW(view),
998  NULL);
999 
1000  gnc_tree_view_add_toggle_column (GNC_TREE_VIEW(view), _("Hidden"),
1001  C_("Column header for 'Hidden'", "H"),
1002  "hidden",
1003  GNC_TREE_MODEL_ACCOUNT_COL_HIDDEN,
1004  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
1005  sort_by_hidden,
1006  gnc_tree_view_account_hidden_toggled);
1007 
1008  gnc_tree_view_add_toggle_column(GNC_TREE_VIEW(view), _("Placeholder"),
1009  C_("Column header for 'Placeholder'", "P"),
1010  "placeholder",
1011  GNC_TREE_MODEL_ACCOUNT_COL_PLACEHOLDER,
1012  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
1013  sort_by_placeholder,
1014  gnc_tree_view_account_placeholder_toggled);
1015 
1016  gnc_tree_view_add_toggle_column(GNC_TREE_VIEW(view), _("Opening Balance"),
1017  C_("Column header for 'Opening Balance'", "O"),
1018  "opening-balance",
1019  GNC_TREE_MODEL_ACCOUNT_COL_OPENING_BALANCE,
1020  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
1021  sort_by_opening_balance,
1022  NULL);
1023 
1024  /* Add function to each column that optionally sets a background color for accounts */
1025  col_list = gtk_tree_view_get_columns(GTK_TREE_VIEW(view));
1026  for (node = col_list; node; node = node->next)
1027  {
1028  renderer = gnc_tree_view_column_get_renderer(node->data);
1029  gtk_tree_view_column_set_cell_data_func(node->data,
1030  renderer,
1031  acc_color_data_func,
1032  GTK_TREE_VIEW(view),
1033  NULL);
1034  }
1035  g_list_free (col_list);
1036 
1037  /* Update column titles to use the currency name. */
1038  gtva_update_column_names(view);
1039 
1040  /* By default only the first column is visible. */
1041  gnc_tree_view_configure_columns(GNC_TREE_VIEW(view));
1042  gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (f_model),
1043  gnc_tree_view_account_filter_helper,
1044  view,
1045  NULL);
1046 
1047  /* Default the sorting to account name */
1048  gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(s_model),
1049  GNC_TREE_MODEL_ACCOUNT_COL_NAME,
1050  GTK_SORT_ASCENDING);
1051 
1052  /* Set account find-as-you-type search function */
1053  gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW(view), gnc_tree_view_search_compare, NULL, NULL);
1054 
1055  g_signal_connect (G_OBJECT(view), "query-tooltip",
1056  G_CALLBACK(gnc_tree_view_tooltip_cb), NULL);
1057 
1058  gtk_widget_show(GTK_WIDGET(view));
1059  LEAVE("%p", view);
1060  return GTK_TREE_VIEW(view);
1061 }
1062 
1063 /*
1064  * Create a new account tree view with (optional) top level root node.
1065  * This view will be based on a model that is common to all view of
1066  * the same set of books, but will have its own private filter on that
1067  * model.
1068  */
1069 GtkTreeView *
1070 gnc_tree_view_account_new (gboolean show_root)
1071 {
1072  Account *root;
1073 
1074  root = gnc_book_get_root_account (gnc_get_current_book ());
1075  return gnc_tree_view_account_new_with_root (root, show_root);
1076 }
1077 
1078 /************************************************************/
1079 /* Auxiliary Functions */
1080 /************************************************************/
1081 
1082 #define debug_path(fn, path) { \
1083  gchar *path_string = gtk_tree_path_to_string(path); \
1084  fn("tree path %s", path_string); \
1085  g_free(path_string); \
1086  }
1087 
1088 static GtkTreePath *
1089 gnc_tree_view_account_get_path_from_account (GncTreeViewAccount *view,
1090  Account *account)
1091 {
1092  GtkTreeModel *model, *f_model, *s_model;
1093  GtkTreePath *path, *f_path, *s_path;
1094 
1095  ENTER("view %p, account %p (%s)", view, account, xaccAccountGetName(account));
1096 
1097  if (account == NULL)
1098  {
1099  LEAVE("no account");
1100  return NULL;
1101  }
1102 
1103  /* Reach down to the real model and get a path for this account */
1104  s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
1105  f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
1106  model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
1107  path = gnc_tree_model_account_get_path_from_account (GNC_TREE_MODEL_ACCOUNT(model), account);
1108  if (path == NULL)
1109  {
1110  LEAVE("no path");
1111  return NULL;
1112  }
1113 
1114  /* convert back to a filtered path */
1115  f_path = gtk_tree_model_filter_convert_child_path_to_path (GTK_TREE_MODEL_FILTER (f_model), path);
1116  gtk_tree_path_free(path);
1117  if (!f_path)
1118  {
1119  LEAVE("no filter path");
1120  return NULL;
1121  }
1122 
1123  /* convert back to a sorted path */
1124  s_path = gtk_tree_model_sort_convert_child_path_to_path (GTK_TREE_MODEL_SORT (s_model), f_path);
1125  gtk_tree_path_free(f_path);
1126  debug_path(LEAVE, s_path);
1127  return s_path;
1128 }
1129 
1130 static gboolean
1131 gnc_tree_view_account_get_iter_from_account (GncTreeViewAccount *view,
1132  Account *account,
1133  GtkTreeIter *s_iter)
1134 {
1135  GtkTreeModel *model, *f_model, *s_model;
1136  GtkTreeIter iter, f_iter;
1137 
1138  g_return_val_if_fail(GNC_IS_TREE_VIEW_ACCOUNT(view), FALSE);
1139  g_return_val_if_fail(account != NULL, FALSE);
1140  g_return_val_if_fail(s_iter != NULL, FALSE);
1141 
1142  ENTER("view %p, account %p (%s)", view, account, xaccAccountGetName(account));
1143 
1144  /* Reach down to the real model and get an iter for this account */
1145  s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
1146  f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
1147  model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
1149  GNC_TREE_MODEL_ACCOUNT(model), account, &iter))
1150  {
1151  LEAVE("model_get_iter_from_account failed");
1152  return FALSE;
1153  }
1154 
1155  /* convert back to a sort iter */
1156  gtk_tree_model_filter_convert_child_iter_to_iter (
1157  GTK_TREE_MODEL_FILTER(f_model), &f_iter, &iter);
1158  gtk_tree_model_sort_convert_child_iter_to_iter (GTK_TREE_MODEL_SORT(s_model),
1159  s_iter, &f_iter);
1160  LEAVE(" ");
1161  return TRUE;
1162 }
1163 
1164 gint
1165 gnc_tree_view_account_count_children (GncTreeViewAccount *view,
1166  Account *account)
1167 {
1168  GtkTreeModel *s_model;
1169  GtkTreeIter s_iter;
1170  gint num_children;
1171 
1172  ENTER("view %p, account %p (%s)", view, account, xaccAccountGetName(account));
1173 
1174  if (account == NULL)
1175  {
1176  LEAVE("no account");
1177  return 0;
1178  }
1179 
1180  if (!gnc_tree_view_account_get_iter_from_account (view, account, &s_iter))
1181  {
1182  LEAVE("view_get_iter_from_account failed");
1183  return 0;
1184  }
1185 
1186  /* Any children? */
1187  s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
1188  num_children = gtk_tree_model_iter_n_children(s_model, &s_iter);
1189  LEAVE("%d children", num_children);
1190  return num_children;
1191 }
1192 
1193 void
1195 {
1196  GtkTreeModel *model, *f_model, *s_model;
1197 
1198  s_model = gtk_tree_view_get_model (GTK_TREE_VIEW(view));
1199  f_model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT(s_model));
1200  model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER(f_model));
1201 
1202  gnc_tree_model_account_clear_cache (GNC_TREE_MODEL_ACCOUNT(model));
1203 }
1204 
1205 /************************************************************/
1206 /* Account Tree View Filter Functions */
1207 /************************************************************/
1208 
1209 /*
1210  * Get a copy of the account view info structure in use by the
1211  * specified tree.
1212  */
1213 void
1214 gnc_tree_view_account_get_view_info (GncTreeViewAccount *view,
1215  AccountViewInfo *avi)
1216 {
1217  g_return_if_fail(GNC_IS_TREE_VIEW_ACCOUNT(view));
1218  g_return_if_fail(avi != NULL);
1219 
1220  *avi = view->avi;
1221 }
1222 
1223 /*
1224  * Set the account view info data in use by the specified tree to
1225  * match the callers request.
1226  */
1227 void
1228 gnc_tree_view_account_set_view_info (GncTreeViewAccount *view,
1229  AccountViewInfo *avi)
1230 {
1231  ENTER("%p", view);
1232  g_return_if_fail(GNC_IS_TREE_VIEW_ACCOUNT(view));
1233  g_return_if_fail(avi != NULL);
1234 
1235  view->avi = *avi;
1236 
1238  view, gnc_tree_view_account_filter_by_view_info,
1239  &view->avi, NULL);
1240 
1241  LEAVE(" ");
1242 }
1243 
1244 static gboolean
1245 gnc_tree_view_account_filter_helper (GtkTreeModel *model,
1246  GtkTreeIter *iter,
1247  gpointer data)
1248 {
1249  Account *account;
1250  GncTreeViewAccount *view = data;
1251 
1252  g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (model), FALSE);
1253  g_return_val_if_fail (iter != NULL, FALSE);
1254 
1256  GNC_TREE_MODEL_ACCOUNT(model), iter);
1257 
1258  if (view->filter_fn)
1259  return view->filter_fn(account, view->filter_data);
1260  else return TRUE;
1261 }
1262 
1263 /*
1264  * Set an GtkTreeModel visible filter on this account. This filter will be
1265  * called for each account that the tree is about to show, and the
1266  * account will be passed to the callback function.
1267  *
1268  * Use NULL as func to remove filter.
1269  */
1270 void
1271 gnc_tree_view_account_set_filter (GncTreeViewAccount *view,
1273  gpointer data,
1274  GSourceFunc destroy)
1275 {
1276  ENTER("view %p, filter func %p, data %p, destroy %p",
1277  view, func, data, destroy);
1278 
1279  g_return_if_fail(GNC_IS_TREE_VIEW_ACCOUNT(view));
1280 
1281  if (view->filter_destroy)
1282  {
1283  view->filter_destroy(view->filter_data);
1284  }
1285  view->filter_destroy = destroy;
1286  view->filter_data = data;
1287  view->filter_fn = func;
1288 
1290  LEAVE(" ");
1291 }
1292 
1293 /*
1294  * Forces the entire account tree to be re-evaluated for visibility.
1295  */
1296 void
1297 gnc_tree_view_account_refilter (GncTreeViewAccount *view)
1298 {
1299  GtkTreeModel *f_model, *s_model;
1300 
1301  g_return_if_fail(GNC_IS_TREE_VIEW_ACCOUNT(view));
1302 
1303  s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
1304  f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
1305  gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (f_model));
1306 }
1307 
1308 gboolean
1309 gnc_tree_view_account_filter_by_view_info(Account* acct, gpointer data)
1310 {
1311  GNCAccountType acct_type;
1312  AccountViewInfo* avi = (AccountViewInfo*)data;
1313 
1314  g_return_val_if_fail(GNC_IS_ACCOUNT(acct), FALSE);
1315  acct_type = xaccAccountGetType(acct);
1316 
1317  if (!avi->include_type[acct_type]) return FALSE;
1318  if (!avi->show_hidden && xaccAccountIsHidden(acct)) return FALSE;
1319  return TRUE;
1320 }
1321 
1322 /************************************************************/
1323 /* Account Tree View Get/Set Functions */
1324 /************************************************************/
1325 
1326 /*
1327  * Retrieve the selected account from an account tree view. The
1328  * account tree must be in single selection mode.
1329  */
1330 Account *
1332  GtkTreePath *s_path)
1333 {
1334  GtkTreeModel *model, *f_model, *s_model;
1335  GtkTreePath *path, *f_path;
1336  GtkTreeIter iter;
1337  Account *account;
1338 
1339  ENTER("view %p", view);
1340  g_return_val_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (view), NULL);
1341  g_return_val_if_fail (s_path != NULL, NULL);
1342 
1343  s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
1344  f_path = gtk_tree_model_sort_convert_path_to_child_path (
1345  GTK_TREE_MODEL_SORT (s_model), s_path);
1346  if (!f_path)
1347  {
1348  LEAVE("no filter path");
1349  return NULL;
1350  }
1351 
1352  f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
1353  path = gtk_tree_model_filter_convert_path_to_child_path (
1354  GTK_TREE_MODEL_FILTER (f_model), f_path);
1355  gtk_tree_path_free(f_path);
1356  if (!path)
1357  {
1358  LEAVE("no path");
1359  return NULL;
1360  }
1361 
1362  model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
1363  if (!gtk_tree_model_get_iter (model, &iter, path))
1364  {
1365  LEAVE("no iter");
1366  return NULL;
1367  }
1368 
1369  account = iter.user_data;
1370  gtk_tree_path_free(path);
1371  LEAVE("account %p (%s)", account, xaccAccountGetName (account));
1372  return account;
1373 }
1374 
1375 
1376 Account *
1378  GtkTreeIter *s_iter)
1379 {
1380  GtkTreeModel *model, *f_model;
1381  GtkTreeIter iter, f_iter;
1382  Account *account;
1383 
1384  g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT(s_model), NULL);
1385  g_return_val_if_fail (s_iter != NULL, NULL);
1386 
1387  ENTER("model %p, iter %p", s_model, s_iter);
1388 
1389  gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT(s_model),
1390  &f_iter,
1391  s_iter);
1392  f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
1393  gtk_tree_model_filter_convert_iter_to_child_iter (
1394  GTK_TREE_MODEL_FILTER(f_model), &iter, &f_iter);
1395  model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
1397  GNC_TREE_MODEL_ACCOUNT(model), &iter);
1398  LEAVE("account %p (%s)", account, xaccAccountGetName (account));
1399  return account;
1400 }
1401 
1402 
1403 /*
1404  * Retrieve the selected account from an account tree view. The
1405  * account tree must be in single selection mode.
1406  */
1407 Account *
1409 {
1410  GtkTreeSelection *selection;
1411  GtkTreeModel *f_model, *s_model;
1412  GtkTreeIter iter, f_iter, s_iter;
1413  Account *account;
1414  GtkSelectionMode mode;
1415 
1416  ENTER("view %p", view);
1417  g_return_val_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (view), NULL);
1418 
1419  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(view));
1420  mode = gtk_tree_selection_get_mode(selection);
1421  if ((mode != GTK_SELECTION_SINGLE) && (mode != GTK_SELECTION_BROWSE))
1422  {
1423  return NULL;
1424  }
1425  if (!gtk_tree_selection_get_selected (selection, &s_model, &s_iter))
1426  {
1427  LEAVE("no account, get_selected failed");
1428  return FALSE;
1429  }
1430 
1431  gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (s_model),
1432  &f_iter, &s_iter);
1433 
1434  f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
1435  gtk_tree_model_filter_convert_iter_to_child_iter (
1436  GTK_TREE_MODEL_FILTER (f_model), &iter, &f_iter);
1437 
1438  account = iter.user_data;
1439  LEAVE("account %p (%s)", account, xaccAccountGetName (account));
1440  return account;
1441 }
1442 
1443 /*
1444  * Selects a single account in the account tree view. The account
1445  * tree must be in single selection mode.
1446  */
1447 void
1449  Account *account)
1450 {
1451  GtkTreeModel *model, *f_model, *s_model;
1452  GtkTreePath *path, *f_path, *s_path, *parent_path;
1453  GtkTreeSelection *selection;
1454 
1455  ENTER("view %p, account %p (%s)", view,
1456  account, xaccAccountGetName (account));
1457  g_return_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (view));
1458 
1459  /* Clear any existing selection. */
1460  selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
1461  gtk_tree_selection_unselect_all (selection);
1462 
1463  if (account == NULL)
1464  return;
1465 
1466  s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
1467  f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
1468  model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
1469 
1471  GNC_TREE_MODEL_ACCOUNT(model), account);
1472  if (path == NULL)
1473  {
1474  LEAVE("no path");
1475  return;
1476  }
1477  debug_path(DEBUG, path);
1478 
1479  f_path = gtk_tree_model_filter_convert_child_path_to_path (
1480  GTK_TREE_MODEL_FILTER (f_model), path);
1481  gtk_tree_path_free(path);
1482  if (f_path == NULL)
1483  {
1484  LEAVE("no filter path");
1485  return;
1486  }
1487  debug_path(DEBUG, f_path);
1488 
1489  s_path = gtk_tree_model_sort_convert_child_path_to_path (GTK_TREE_MODEL_SORT (s_model),
1490  f_path);
1491  gtk_tree_path_free(f_path);
1492  if (s_path == NULL)
1493  {
1494  LEAVE("no sort path");
1495  return;
1496  }
1497 
1498  /* gtk_tree_view requires that a row be visible before it can be selected */
1499  parent_path = gtk_tree_path_copy (s_path);
1500  if (gtk_tree_path_up (parent_path))
1501  {
1502  /* This function is misnamed. It expands the actual item
1503  * specified, not the path to the item specified. I.E. It expands
1504  * one level too many, thus the get of the parent. */
1505  gtk_tree_view_expand_to_path(GTK_TREE_VIEW(view), parent_path);
1506  }
1507  gtk_tree_path_free(parent_path);
1508 
1509  gtk_tree_view_set_cursor (GTK_TREE_VIEW (view), s_path, 0, FALSE);
1510 
1511  /* give gtk+ a chance to resize the tree view first by handling pending
1512  * configure events */
1513  while (gtk_events_pending ())
1514  gtk_main_iteration ();
1515  gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW(view), s_path, NULL, FALSE, 0.0, 0.0);
1516  debug_path(LEAVE, s_path);
1517  gtk_tree_path_free(s_path);
1518 }
1519 
1520 /* Information re selection process */
1521 typedef struct
1522 {
1523  GList* return_list;
1524  GncTreeViewAccount* view;
1526 
1527 /*
1528  * This helper function is called once for each row in the tree view
1529  * that is currently selected. Its task is to append the corresponding
1530  * account to the end of a glist.
1531  */
1532 static void
1533 get_selected_accounts_helper (GtkTreeModel *s_model,
1534  GtkTreePath *s_path,
1535  GtkTreeIter *s_iter,
1536  gpointer data)
1537 {
1538  GncTreeViewSelectionInfo *gtvsi = data;
1539  GtkTreeModel *f_model;
1540  GtkTreeIter iter, f_iter;
1541  Account *account;
1542 
1543  gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (s_model),
1544  &f_iter, s_iter);
1545 
1546  f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
1547  gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (f_model),
1548  &iter, &f_iter);
1549  account = iter.user_data;
1550 
1551  /* Only selected if it passes the filter */
1552  if (gtvsi->view->filter_fn == NULL || gtvsi->view->filter_fn(account, gtvsi->view->filter_data))
1553  {
1554  gtvsi->return_list = g_list_prepend (gtvsi->return_list, account);
1555  }
1556 }
1557 
1558 /*
1559  * Given an account tree view, return a list of the selected accounts. The
1560  * account tree must be in multiple selection mode.
1561  *
1562  * Note: It is the responsibility of the caller to free the returned
1563  * list.
1564  */
1565 GList *
1567 {
1568  GtkTreeSelection *selection;
1570 
1571  g_return_val_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (view), NULL);
1572 
1573  info.return_list = NULL;
1574  info.view = view;
1575  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(view));
1576  gtk_tree_selection_selected_foreach(selection, get_selected_accounts_helper, &info);
1577  info.return_list = g_list_reverse (info.return_list);
1578  return info.return_list;
1579 }
1580 
1581 /*
1582  * Given an account tree view and a list of accounts, select those
1583  * accounts in the tree view.
1584  */
1585 void
1587  GList *account_list,
1588  gboolean show_last)
1589 {
1590  GtkTreeModel *model, *f_model, *s_model;
1591  GtkTreePath *path, *f_path, *s_path, *parent_path;
1592  GtkTreeSelection *selection;
1593  GList *element;
1594  Account *account;
1595 
1596  g_return_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (view));
1597 
1598  s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
1599  f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
1600  model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
1601 
1602  /* Clear any existing selection. */
1603  selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
1604  gtk_tree_selection_unselect_all (selection);
1605  gtk_tree_view_collapse_all (GTK_TREE_VIEW(view));
1606 
1607  /* Now go select what the user requested. */
1608  for (element = account_list; element; )
1609  {
1610  account = element->data;
1611  element = g_list_next(element);
1612 
1613  if (account == NULL)
1614  {
1615  /*
1616  * Oops. Someone must have deleted this account and not cleaned
1617  * up all references to it.
1618  */
1619  continue;
1620  }
1621 
1622  path = gnc_tree_model_account_get_path_from_account (GNC_TREE_MODEL_ACCOUNT(model), account);
1623  if (path == NULL)
1624  {
1625  /*
1626  * Oops. Someone must have deleted this account and not cleaned
1627  * up all references to it.
1628  */
1629  continue;
1630  }
1631 
1632  f_path = gtk_tree_model_filter_convert_child_path_to_path (GTK_TREE_MODEL_FILTER (f_model),
1633  path);
1634  gtk_tree_path_free(path);
1635  if (f_path == NULL)
1636  continue;
1637 
1638  s_path = gtk_tree_model_sort_convert_child_path_to_path (GTK_TREE_MODEL_SORT (s_model),
1639  f_path);
1640  gtk_tree_path_free(f_path);
1641  if (s_path == NULL)
1642  continue;
1643 
1644  /* gtk_tree_view requires that a row be visible before it can be selected */
1645  parent_path = gtk_tree_path_copy (s_path);
1646  if (gtk_tree_path_up (parent_path))
1647  {
1648  /* This function is misnamed. It expands the actual item
1649  * specified, not the path to the item specified. I.E. It
1650  * expands one level too many, thus the get of the parent. */
1651  gtk_tree_view_expand_to_path(GTK_TREE_VIEW(view), parent_path);
1652  }
1653  gtk_tree_path_free(parent_path);
1654 
1655  gtk_tree_selection_select_path (selection, s_path);
1656  if (show_last && (element == NULL))
1657  gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW(view), s_path, NULL, FALSE, 0.0, 0.0);
1658  gtk_tree_path_free(s_path);
1659  }
1660 }
1661 
1662 /*
1663  * Selects all sub-accounts of an account.
1664  */
1665 void
1667  Account *account)
1668 {
1669  GtkTreeModel *s_model;
1670  GtkTreeSelection *selection;
1671  GtkTreePath *sp_account, *sp_start, *sp_end;
1672  GtkTreeIter si_account, si_start, si_end;
1673  gboolean have_start, have_end = FALSE;
1674  gint num_children;
1675 
1676  ENTER("view %p, account %p (%s)", view, account, xaccAccountGetName(account));
1677 
1678  g_return_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (view));
1679 
1680  if (account == NULL)
1681  {
1682  LEAVE("no account");
1683  return;
1684  }
1685 
1686  if (!gnc_tree_view_account_get_iter_from_account (view, account, &si_account))
1687  {
1688  LEAVE("view_get_iter_from_account failed");
1689  return;
1690  }
1691 
1692  /* Any children? */
1693  s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
1694  num_children = gtk_tree_model_iter_n_children(s_model, &si_account);
1695  if (num_children == 0)
1696  {
1697  LEAVE("no children");
1698  return;
1699  }
1700 
1701  /* Expand the tree. Required for selection to work */
1702  sp_account = gtk_tree_model_get_path (s_model, &si_account);
1703  gtk_tree_view_expand_row (GTK_TREE_VIEW(view), sp_account, TRUE);
1704 
1705  /* compute start/end paths */
1706  have_start = gtk_tree_model_iter_nth_child(s_model, &si_start, &si_account, 0);
1707  si_end = si_account;
1708  while (num_children)
1709  {
1710  GtkTreeIter tmp_iter = si_end;
1711  have_end = gtk_tree_model_iter_nth_child(s_model, &si_end, &tmp_iter,
1712  num_children - 1);
1713  if (have_end)
1714  num_children = gtk_tree_model_iter_n_children(s_model, &si_end);
1715  else
1716  num_children = 0;
1717  }
1718 
1719  if (have_start && have_end)
1720  {
1721  sp_start = gtk_tree_model_get_path (s_model, &si_start);
1722  sp_end = gtk_tree_model_get_path (s_model, &si_end);
1723 
1724  /* select everything between */
1725  selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
1726  gtk_tree_selection_select_range (selection, sp_start, sp_end);
1727 
1728  /* clean up */
1729  gtk_tree_path_free(sp_start);
1730  gtk_tree_path_free(sp_end);
1731  }
1732  gtk_tree_path_free(sp_account);
1733  LEAVE(" ");
1734  return;
1735 }
1736 
1737 void
1739  Account *account)
1740 {
1741  GtkTreePath *path;
1742 
1743  g_return_if_fail(view != NULL);
1744  g_return_if_fail(GNC_IS_TREE_VIEW_ACCOUNT(view));
1745  ENTER("view %p, account %p", view, account);
1746 
1747  path = gnc_tree_view_account_get_path_from_account(view, account);
1748  if (path)
1749  {
1750  gtk_tree_view_expand_to_path(GTK_TREE_VIEW(view), path);
1751  gtk_tree_path_free(path);
1752  }
1753  LEAVE(" ");
1754 }
1755 
1756 
1757 /*
1758  * Retrieve the account currently under the cursor.
1759  */
1760 Account *
1762 {
1763  GtkTreePath *s_path;
1764  Account *account;
1765 
1766  ENTER("view %p", view);
1767  g_return_val_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (view), NULL);
1768 
1769  gtk_tree_view_get_cursor (GTK_TREE_VIEW(view), &s_path, NULL);
1770  if (!s_path)
1771  {
1772  LEAVE("no account");
1773  return NULL;
1774  }
1775 
1776  account = gnc_tree_view_account_get_account_from_path (view, s_path);
1777  gtk_tree_path_free(s_path);
1778  LEAVE("account %p (%s)", account, xaccAccountGetName (account));
1779  return account;
1780 }
1781 
1782 
1783 /************************************************************/
1784 /* Account Tree View Add Column Functions */
1785 /************************************************************/
1786 
1787 static void
1788 gtva_update_column_name (GtkTreeViewColumn *column,
1789  const gchar *fmt,
1790  const gchar *mnemonic)
1791 {
1792  gchar *name;
1793 
1794  g_return_if_fail(column);
1795 
1796  name = g_strdup_printf(fmt, mnemonic);
1797  gtk_tree_view_column_set_title(column, name);
1798  g_free(name);
1799 }
1800 
1801 
1802 static void
1803 gtva_update_column_names (GncTreeViewAccount *view)
1804 {
1805  const gchar *mnemonic = gnc_commodity_get_mnemonic(gnc_default_report_currency());
1806 
1807  gtva_update_column_name(view->present_report_column,
1808  /* Translators: %s is a currency mnemonic.*/
1809  _("Present (%s)"), mnemonic);
1810  gtva_update_column_name(view->balance_report_column,
1811  /* Translators: %s is a currency mnemonic.*/
1812  _("Balance (%s)"), mnemonic);
1813  gtva_update_column_name(view->cleared_report_column,
1814  /* Translators: %s is a currency mnemonic.*/
1815  _("Cleared (%s)"), mnemonic);
1816  gtva_update_column_name(view->reconciled_report_column,
1817  /* Translators: %s is a currency mnemonic.*/
1818  _("Reconciled (%s)"), mnemonic);
1819  gtva_update_column_name(view->future_min_report_column,
1820  /* Translators: %s is a currency mnemonic.*/
1821  _("Future Minimum (%s)"), mnemonic);
1822  gtva_update_column_name(view->total_report_column,
1823  /* Translators: %s is a currency mnemonic.*/
1824  _("Total (%s)"), mnemonic);
1825  gnc_tree_view_set_show_column_menu(GNC_TREE_VIEW(view), FALSE);
1826  gnc_tree_view_set_show_column_menu(GNC_TREE_VIEW(view), TRUE);
1827 }
1828 
1829 
1830 static void
1831 gtva_currency_changed_cb (void)
1832 {
1833  const GList *views, *ptr;
1834 
1835  views = gnc_gobject_tracking_get_list (GNC_TREE_VIEW_ACCOUNT_NAME);
1836  for (ptr = views; ptr; ptr = g_list_next(ptr))
1837  {
1838  gtva_update_column_names (ptr->data);
1839  }
1840 }
1841 /* Retrieve a specified account string property and put the result
1842  * into the tree column's text property.
1843  */
1844 static void
1845 account_cell_property_data_func (GtkTreeViewColumn *tree_column,
1846  GtkCellRenderer *cell,
1847  GtkTreeModel *s_model,
1848  GtkTreeIter *s_iter,
1849  gpointer key)
1850 {
1851  GncTreeViewAccount *view;
1852  Account *account;
1853  gchar *string = NULL;
1854 
1855  g_return_if_fail (GTK_IS_TREE_MODEL_SORT (s_model));
1856  account = gnc_tree_view_account_get_account_from_iter(s_model, s_iter);
1857  qof_instance_get (QOF_INSTANCE (account), key, &string, NULL);
1858  if (string == NULL)
1859  string = g_strdup ("");
1860 
1861  g_object_set (G_OBJECT (cell), "text", string, "xalign", 0.0, NULL);
1862  g_free (string);
1863 
1864  view = g_object_get_data(G_OBJECT(tree_column), "tree-view");
1865 
1866  if (GNC_IS_TREE_VIEW_ACCOUNT (view))
1867  acc_color_data_func (tree_column, cell, s_model, s_iter, view);
1868 }
1869 
1870 
1871 GtkTreeViewColumn *
1873  const gchar *column_title,
1874  const gchar *propname)
1875 {
1876  GtkCellRenderer *renderer;
1877  GtkTreeViewColumn *column;
1878 
1879  g_return_val_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (view), NULL);
1880  g_return_val_if_fail (propname != NULL, NULL);
1881 
1882  column = gnc_tree_view_add_text_column(GNC_TREE_VIEW(view), column_title,
1883  propname, NULL, "Sample text",
1884  -1, -1, NULL);
1885 
1886  /* This new kvp column has only had one renderer added to it so
1887  * far. Find that renderer. */
1888  renderer = gnc_tree_view_column_get_renderer(column);
1889  g_object_set (G_OBJECT (renderer), "xalign", 1.0, NULL);
1890 
1891  // add a pointer to the view to make it easier to access in data_func
1892  g_object_set_data(G_OBJECT(column), "tree-view", (gpointer)view);
1893 
1894  gtk_tree_view_column_set_cell_data_func (column, renderer,
1895  account_cell_property_data_func,
1896  g_strdup(propname), g_free);
1897  return column;
1898 }
1899 
1900 static void col_edited_helper(GtkCellRendererText *cell, gchar *path_string,
1901  gchar *new_text, gpointer _s_model)
1902 {
1903  Account *account;
1904  GtkTreeModel *s_model;
1905  GtkTreeIter s_iter;
1906  GncTreeViewAccountColumnTextEdited col_edited_cb;
1907  GtkTreeViewColumn *col;
1908 
1909  col_edited_cb = g_object_get_data(G_OBJECT(cell),
1910  "column_edited_callback");
1911  col = GTK_TREE_VIEW_COLUMN(g_object_get_data(G_OBJECT(cell),
1912  "column_view"));
1913  s_model = GTK_TREE_MODEL(_s_model);
1914 
1915  if (!gtk_tree_model_get_iter_from_string(s_model, &s_iter, path_string))
1916  return;
1917 
1918  account = gnc_tree_view_account_get_account_from_iter(s_model, &s_iter);
1919  col_edited_cb(account, col, new_text);
1920 }
1921 
1922 static void col_source_helper(GtkTreeViewColumn *col, GtkCellRenderer *cell,
1923  GtkTreeModel *s_model, GtkTreeIter *s_iter,
1924  gpointer _col_source_cb)
1925 {
1926  Account *account;
1927  gchar *text;
1928  GncTreeViewAccountColumnSource col_source_cb;
1929 
1930  g_return_if_fail (GTK_IS_TREE_MODEL_SORT (s_model));
1931  col_source_cb = (GncTreeViewAccountColumnSource) _col_source_cb;
1932  account = gnc_tree_view_account_get_account_from_iter(s_model, s_iter);
1933  text = col_source_cb(account, col, cell);
1934  g_object_set (G_OBJECT (cell), "text", text, "xalign", 1.0, NULL);
1935  g_free(text);
1936 }
1937 
1942 void
1943 gtva_setup_column_renderer_edited_cb(GncTreeViewAccount *account_view,
1944  GtkTreeViewColumn *column,
1945  GtkCellRenderer *renderer,
1946  GncTreeViewAccountColumnTextEdited col_edited_cb)
1947 {
1948  GtkTreeModel *s_model;
1949 
1950  if (col_edited_cb == NULL)
1951  {
1952  g_object_set(G_OBJECT(renderer), "editable", FALSE, NULL);
1953  g_object_set_data(G_OBJECT(renderer), "column_edited_callback", col_edited_cb);
1954  s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(account_view));
1955  g_signal_handlers_disconnect_by_func(G_OBJECT(renderer), col_edited_cb, s_model);
1956  g_object_set_data(G_OBJECT(renderer), "column_view", column);
1957  }
1958  else
1959  {
1960  g_object_set(G_OBJECT(renderer), "editable", TRUE, NULL);
1961  g_object_set_data(G_OBJECT(renderer), "column_edited_callback",
1962  col_edited_cb);
1963  s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(account_view));
1964  g_signal_connect(G_OBJECT(renderer), "edited",
1965  (GCallback) col_edited_helper, s_model);
1966  g_object_set_data(G_OBJECT(renderer), "column_view", column);
1967  }
1968 }
1969 
1970 GtkTreeViewColumn *
1971 gnc_tree_view_account_add_custom_column(GncTreeViewAccount *account_view,
1972  const gchar *column_title,
1973  GncTreeViewAccountColumnSource
1974  col_source_cb,
1975  GncTreeViewAccountColumnTextEdited
1976  col_edited_cb)
1977 {
1978  GtkCellRenderer *renderer;
1979 
1980  g_return_val_if_fail(GNC_IS_TREE_VIEW_ACCOUNT(account_view), NULL);
1981 
1982  renderer = gtk_cell_renderer_text_new();
1983 
1984  return gnc_tree_view_account_add_custom_column_renderer(
1985  account_view, column_title, col_source_cb, col_edited_cb, renderer);
1986 }
1987 
1988 GtkTreeViewColumn *
1989 gnc_tree_view_account_add_custom_column_renderer(GncTreeViewAccount *account_view,
1990  const gchar *column_title,
1991  GncTreeViewAccountColumnSource
1992  col_source_cb,
1993  GncTreeViewAccountColumnTextEdited
1994  col_edited_cb,
1995  GtkCellRenderer *renderer)
1996 {
1997  GtkTreeViewColumn *column;
1998 
1999  g_return_val_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (account_view), NULL);
2000 
2001  g_object_set (G_OBJECT (renderer), "xalign", 1.0, NULL);
2002 
2003  column = gtk_tree_view_column_new_with_attributes (column_title,
2004  renderer, NULL);
2005  if (col_edited_cb)
2006  {
2007  gtva_setup_column_renderer_edited_cb(account_view, column,
2008  renderer, col_edited_cb);
2009  }
2010  gtk_tree_view_column_set_cell_data_func (column, renderer,
2011  col_source_helper,
2012  col_source_cb, NULL);
2013  gnc_tree_view_append_column (GNC_TREE_VIEW(account_view), column);
2014  return column;
2015 }
2016 
2017 
2018 /* BEGIN FILTER FUNCTIONS */
2019 #define FILTER_TREE_VIEW "types_tree_view"
2020 
2032 gboolean
2034  gpointer user_data)
2035 {
2036  AccountFilterDialog *fd = user_data;
2037  GNCAccountType acct_type;
2038  gnc_numeric total;
2039  gboolean result;
2040 
2041  ENTER("account %p:%s", account, xaccAccountGetName(account));
2042 
2043  if (g_hash_table_size (fd->filter_override) > 0)
2044  {
2045  Account *test_acc = NULL;
2046  test_acc = g_hash_table_lookup (fd->filter_override, account);
2047  if (test_acc != NULL)
2048  {
2049  LEAVE(" filter: override");
2050  return TRUE;
2051  }
2052  }
2053 
2054  if (!fd->show_hidden && xaccAccountIsHidden (account))
2055  {
2056  LEAVE(" hide: hidden");
2057  return FALSE;
2058  }
2059 
2060  if (!fd->show_zero_total)
2061  {
2062  total = xaccAccountGetBalanceInCurrency (account, NULL, TRUE);
2063  if (gnc_numeric_zero_p(total))
2064  {
2065  LEAVE(" hide: zero balance");
2066  return FALSE;
2067  }
2068  }
2069 
2070  if (!fd->show_unused)
2071  {
2072  if (gnc_account_and_descendants_empty(account))
2073  {
2074  LEAVE(" hide: unused");
2075  return FALSE;
2076  }
2077  }
2078 
2079  acct_type = xaccAccountGetType(account);
2080  result = (fd->visible_types & (1 << acct_type)) ? TRUE : FALSE;
2081  LEAVE(" %s", result ? "show" : "hide");
2082  return result;
2083 }
2084 
2092 void
2093 gppat_filter_show_hidden_toggled_cb (GtkToggleButton *button,
2094  AccountFilterDialog *fd)
2095 {
2096  g_return_if_fail(GTK_IS_TOGGLE_BUTTON(button));
2097 
2098  ENTER("button %p", button);
2099  fd->show_hidden = gtk_toggle_button_get_active(button);
2100  gnc_tree_view_account_refilter(fd->tree_view);
2101  LEAVE("show_hidden %d", fd->show_hidden);
2102 }
2103 
2111 void
2112 gppat_filter_show_zero_toggled_cb (GtkToggleButton *button,
2113  AccountFilterDialog *fd)
2114 {
2115  g_return_if_fail(GTK_IS_TOGGLE_BUTTON(button));
2116 
2117  ENTER("button %p", button);
2118  fd->show_zero_total = gtk_toggle_button_get_active(button);
2119  gnc_tree_view_account_refilter(fd->tree_view);
2120  LEAVE("show_zero %d", fd->show_zero_total);
2121 }
2122 
2130 void
2131 gppat_filter_show_unused_toggled_cb (GtkToggleButton *button,
2132  AccountFilterDialog *fd)
2133 {
2134  g_return_if_fail(GTK_IS_TOGGLE_BUTTON(button));
2135 
2136  ENTER("button %p", button);
2137  fd->show_unused = gtk_toggle_button_get_active(button);
2138  gnc_tree_view_account_refilter(fd->tree_view);
2139  LEAVE("show_unused %d", fd->show_unused);
2140 }
2141 
2150 void
2151 gppat_filter_clear_all_cb (GtkWidget *button,
2152  AccountFilterDialog *fd)
2153 {
2154  g_return_if_fail(GTK_IS_BUTTON(button));
2155 
2156  ENTER("button %p", button);
2157  fd->visible_types = 0;
2158  gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(fd->model));
2159  gnc_tree_view_account_refilter(fd->tree_view);
2160  LEAVE("types 0x%x", fd->visible_types);
2161 }
2162 
2169 void
2170 gppat_filter_select_all_cb (GtkWidget *button,
2171  AccountFilterDialog *fd)
2172 {
2173  g_return_if_fail(GTK_IS_BUTTON(button));
2174 
2175  ENTER("button %p", button);
2176  fd->visible_types = -1;
2177  gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(fd->model));
2178  gnc_tree_view_account_refilter(fd->tree_view);
2179  LEAVE("types 0x%x", fd->visible_types);
2180 }
2181 
2189 void
2191  AccountFilterDialog *fd)
2192 {
2193  ENTER("button %p", button);
2194  gppat_filter_select_all_cb(button, fd);
2195  LEAVE(" ");
2196 }
2197 
2209 static void
2210 gppat_filter_visible_set_func (GtkTreeViewColumn *column,
2211  GtkCellRenderer *renderer,
2212  GtkTreeModel *model,
2213  GtkTreeIter *iter,
2214  gpointer data)
2215 {
2216  AccountFilterDialog *fd = data;
2217  GNCAccountType type;
2218  gboolean active;
2219 
2220  gtk_tree_model_get(model, iter, GNC_TREE_MODEL_ACCOUNT_TYPES_COL_TYPE, &type, -1);
2221 
2222  active = (fd->visible_types & (1 << type)) ? TRUE : FALSE;
2223  g_object_set (G_OBJECT (renderer), "active", active, NULL);
2224 }
2225 
2231 static void
2232 gppat_filter_visible_toggled_cb (GtkCellRendererToggle *renderer,
2233  gchar *path_str,
2234  AccountFilterDialog *fd)
2235 {
2236  GtkTreeModel *model = fd->model;
2237  GtkTreeIter iter;
2238  GtkTreePath *path;
2239  GNCAccountType type;
2240 
2241  ENTER("toggled %p", path_str);
2242  path = gtk_tree_path_new_from_string(path_str);
2243 
2244  if (gtk_tree_model_get_iter(model, &iter, path))
2245  {
2246  gtk_tree_model_get(model, &iter, GNC_TREE_MODEL_ACCOUNT_TYPES_COL_TYPE, &type, -1);
2247  fd->visible_types ^= (1 << type);
2248  gnc_tree_view_account_refilter(fd->tree_view);
2249  }
2250  gtk_tree_path_free(path);
2251  LEAVE("types 0x%x", fd->visible_types);
2252 }
2253 
2264 void
2265 gppat_filter_response_cb (GtkWidget *dialog,
2266  gint response,
2267  AccountFilterDialog *fd)
2268 {
2269  gpointer gptemp;
2270 
2271  g_return_if_fail(GTK_IS_DIALOG(dialog));
2272 
2273  ENTER("dialog %p, response %d", dialog, response);
2274 
2275  if (response != GTK_RESPONSE_OK)
2276  {
2277  fd->visible_types = fd->original_visible_types;
2278  fd->show_hidden = fd->original_show_hidden;
2279  fd->show_zero_total = fd->original_show_zero_total;
2280  fd->show_unused = fd->original_show_unused;
2281  gnc_tree_view_account_refilter(fd->tree_view);
2282  }
2283 
2284  /* Clean up and delete dialog */
2285  gptemp = (gpointer)fd->dialog;
2286  g_atomic_pointer_compare_and_exchange(&gptemp,
2287  (gpointer)dialog, NULL);
2288  fd->dialog = gptemp;
2289  gtk_widget_destroy(dialog);
2290  LEAVE("types 0x%x", fd->visible_types);
2291 }
2292 
2293 void
2294 account_filter_dialog_create(AccountFilterDialog *fd, GncPluginPage *page)
2295 {
2296  GtkWidget *dialog, *button;
2297  GtkTreeView *view;
2298  GtkCellRenderer *renderer;
2299  GtkBuilder *builder;
2300  gchar *title;
2301 
2302  ENTER("(fd %p, page %p)", fd, page);
2303 
2304  if (fd->dialog)
2305  {
2306  gtk_window_present(GTK_WINDOW(fd->dialog));
2307  LEAVE("existing dialog");
2308  return;
2309  }
2310 
2311  /* Create the dialog */
2312  builder = gtk_builder_new();
2313  gnc_builder_add_from_file (builder, "dialog-account.glade", "account_filter_by_dialog");
2314  dialog = GTK_WIDGET(gtk_builder_get_object (builder, "account_filter_by_dialog"));
2315  fd->dialog = dialog;
2316  gtk_window_set_transient_for(GTK_WINDOW(dialog),
2317  GTK_WINDOW(GNC_PLUGIN_PAGE(page)->window));
2318  /* Translators: The %s is the name of the plugin page */
2319  title = g_strdup_printf(_("Filter %s by..."),
2320  _(gnc_plugin_page_get_page_name(GNC_PLUGIN_PAGE(page))));
2321  gtk_window_set_title(GTK_WINDOW(dialog), title);
2322  g_free(title);
2323 
2324  /* Remember current state */
2325  fd->original_visible_types = fd->visible_types;
2326  fd->original_show_hidden = fd->show_hidden;
2327  fd->original_show_zero_total = fd->show_zero_total;
2328  fd->original_show_unused = fd->show_unused;
2329 
2330  /* Update the dialog widgets for the current state */
2331  button = GTK_WIDGET(gtk_builder_get_object (builder, "show_hidden"));
2332  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
2333  fd->show_hidden);
2334  button = GTK_WIDGET(gtk_builder_get_object (builder, "show_zero"));
2335  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
2336  fd->show_zero_total);
2337  button = GTK_WIDGET(gtk_builder_get_object (builder, "show_unused"));
2338  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
2339  fd->show_unused);
2340 
2341  /* Set up the tree view and model */
2342  view = GTK_TREE_VIEW(gtk_builder_get_object (builder, FILTER_TREE_VIEW));
2343 
2344  fd->model = gnc_tree_model_account_types_filter_using_mask
2345  (~(1 << ACCT_TYPE_ROOT));
2346  gtk_tree_view_set_model(view, fd->model);
2347  g_object_unref (fd->model);
2348 
2349  renderer = gtk_cell_renderer_toggle_new();
2350 
2351  g_signal_connect(renderer, "toggled",
2352  G_CALLBACK(gppat_filter_visible_toggled_cb), fd);
2353 
2354  gtk_tree_view_insert_column_with_data_func (view, -1, NULL, renderer,
2355  gppat_filter_visible_set_func, fd, NULL);
2356 
2357  gtk_tree_view_insert_column_with_attributes (view,
2358  -1, _("Account Types"), gtk_cell_renderer_text_new(),
2359  "text", GNC_TREE_MODEL_ACCOUNT_TYPES_COL_NAME, NULL);
2360 
2361  /* Wire up the rest of the callbacks */
2362  gtk_builder_connect_signals(builder, fd);
2363  g_object_unref(G_OBJECT(builder));
2364 
2365  /* Show it */
2366  gtk_widget_show_all(dialog);
2367  LEAVE(" ");
2368 }
2369 
2370 // page state section
2371 #define ACCT_COUNT "NumberOfOpenAccounts"
2372 #define ACCT_OPEN "OpenAccount%d"
2373 #define ACCT_SELECTED "SelectedAccount"
2374 #define SHOW_HIDDEN "ShowHidden"
2375 #define SHOW_ZERO "ShowZeroTotal"
2376 #define SHOW_UNUSED "ShowUnused"
2377 #define ACCT_TYPES "AccountTypes"
2378 
2379 // account/budget state section
2380 // versions less than 3.2 would crash if key did not have an "_"
2381 #define SHOW_HIDDEN_ACCOUNTS "Show_Hidden"
2382 #define SHOW_ZERO_TOTALS "Show_ZeroTotal"
2383 #define SHOW_UNUSED_ACCOUNTS "Show_Unused"
2384 #define ACCOUNT_TYPES "Account_Types"
2385 
2386 
2387 typedef struct foo
2388 {
2389  GKeyFile *key_file;
2390  const gchar *group_name;
2391  int count;
2392 } bar_t;
2393 
2405 static void
2406 tree_save_expanded_row (GncTreeViewAccount *view,
2407  GtkTreePath *path,
2408  gpointer user_data)
2409 {
2410  Account *account;
2411  bar_t *bar = user_data;
2412  gchar *key;
2413  gchar *account_name;
2414 
2415  account = gnc_tree_view_account_get_account_from_path (view, path);
2416  if (account == NULL)
2417  return;
2418 
2419  account_name = gnc_account_get_full_name(account);
2420  if (account_name == NULL)
2421  return;
2422 
2423  key = g_strdup_printf(ACCT_OPEN, ++bar->count);
2424  g_key_file_set_string(bar->key_file, bar->group_name, key, account_name);
2425  g_free(key);
2426  g_free(account_name);
2427 }
2428 
2429 
2440 static void
2441 tree_save_selected_row (GncTreeViewAccount *view,
2442  gpointer user_data)
2443 {
2444  Account *account;
2445  bar_t *bar = user_data;
2446  gchar *account_name;
2447 
2449  if (account == NULL)
2450  return;
2451 
2452  account_name = gnc_account_get_full_name (account);
2453  if (account_name == NULL)
2454  return;
2455 
2456  g_key_file_set_string(bar->key_file, bar->group_name, ACCT_SELECTED,
2457  account_name);
2458  g_free(account_name);
2459 }
2460 
2461 void
2462 gnc_tree_view_account_save(GncTreeViewAccount *view,
2463  AccountFilterDialog *fd,
2464  GKeyFile *key_file, const gchar *group_name)
2465 {
2466  bar_t bar;
2467 
2468  g_return_if_fail (key_file != NULL);
2469  g_return_if_fail (group_name != NULL);
2470 
2471  ENTER("view %p, key_file %p, group_name %s", view, key_file,
2472  group_name);
2473 
2474  g_key_file_set_integer(key_file, group_name, ACCT_TYPES,
2475  fd->visible_types);
2476  g_key_file_set_boolean(key_file, group_name, SHOW_HIDDEN,
2477  fd->show_hidden);
2478  g_key_file_set_boolean(key_file, group_name, SHOW_ZERO,
2479  fd->show_zero_total);
2480  g_key_file_set_boolean(key_file, group_name, SHOW_UNUSED,
2481  fd->show_unused);
2482 
2483  bar.key_file = key_file;
2484  bar.group_name = group_name;
2485  bar.count = 0;
2486  tree_save_selected_row(view, &bar);
2487  gtk_tree_view_map_expanded_rows(
2488  GTK_TREE_VIEW(view), (GtkTreeViewMappingFunc) tree_save_expanded_row,
2489  &bar);
2490  g_key_file_set_integer(key_file, group_name, ACCT_COUNT, bar.count);
2491  LEAVE(" ");
2492 
2493 }
2494 
2495 void
2496 gnc_tree_view_account_save_filter (GncTreeViewAccount *view,
2497  AccountFilterDialog *fd,
2498  GKeyFile *key_file,
2499  const gchar *group_name)
2500 {
2501  g_return_if_fail (key_file != NULL);
2502  g_return_if_fail (group_name != NULL);
2503 
2504  ENTER("view %p, key_file %p, group_name %s", view, key_file,
2505  group_name);
2506 
2507  g_key_file_set_integer (key_file, group_name, ACCOUNT_TYPES,
2508  fd->visible_types);
2509  g_key_file_set_boolean (key_file, group_name, SHOW_HIDDEN_ACCOUNTS,
2510  fd->show_hidden);
2511  g_key_file_set_boolean (key_file, group_name, SHOW_ZERO_TOTALS,
2512  fd->show_zero_total);
2513  g_key_file_set_boolean (key_file, group_name, SHOW_UNUSED_ACCOUNTS,
2514  fd->show_unused);
2515  LEAVE("");
2516 }
2517 
2525 static void
2526 tree_restore_expanded_row (GncTreeViewAccount *view,
2527  const gchar *account_name)
2528 {
2529  Account *account;
2530  QofBook *book;
2531 
2532  book = qof_session_get_book(gnc_get_current_session());
2533  g_return_if_fail(book);
2534  account = gnc_account_lookup_by_full_name(gnc_book_get_root_account(book),
2535  account_name);
2536  if (account)
2538 }
2539 
2540 
2548 static void
2549 tree_restore_selected_row (GncTreeViewAccount *view,
2550  const gchar *account_name)
2551 {
2552  Account *account;
2553  QofBook *book;
2554 
2555  book = qof_session_get_book(gnc_get_current_session());
2556  g_return_if_fail(book);
2557  account = gnc_account_lookup_by_full_name(gnc_book_get_root_account(book),
2558  account_name);
2559  if (account)
2561 }
2562 
2563 void
2564 gnc_tree_view_account_restore(GncTreeViewAccount *view,
2565  AccountFilterDialog *fd,
2566  GKeyFile *key_file, const gchar *group_name)
2567 {
2568  GError *error = NULL;
2569  gchar *key, *value;
2570  gint i, count;
2571  gboolean show;
2572 
2573  /* Filter information. Ignore missing keys. */
2574  show = g_key_file_get_boolean(key_file, group_name, SHOW_HIDDEN, &error);
2575  if (error)
2576  {
2577  g_warning("error reading group %s key %s: %s",
2578  group_name, SHOW_HIDDEN, error->message);
2579  g_error_free(error);
2580  error = NULL;
2581  show = TRUE;
2582  }
2583  fd->show_hidden = show;
2584 
2585  show = g_key_file_get_boolean(key_file, group_name, SHOW_ZERO, &error);
2586  if (error)
2587  {
2588  g_warning("error reading group %s key %s: %s",
2589  group_name, SHOW_ZERO, error->message);
2590  g_error_free(error);
2591  error = NULL;
2592  show = TRUE;
2593  }
2594  fd->show_zero_total = show;
2595 
2596  show = g_key_file_get_boolean(key_file, group_name, SHOW_UNUSED, &error);
2597  if (error)
2598  {
2599  g_warning("error reading group %s key %s: %s",
2600  group_name, SHOW_UNUSED, error->message);
2601  g_error_free(error);
2602  error = NULL;
2603  show = TRUE;
2604  }
2605  fd->show_unused = show;
2606 
2607  i = g_key_file_get_integer(key_file, group_name, ACCT_TYPES, &error);
2608  if (error)
2609  {
2610  g_warning("error reading group %s key %s: %s",
2611  group_name, ACCT_TYPES, error->message);
2612  g_error_free(error);
2613  error = NULL;
2614  i = -1;
2615  }
2616  fd->visible_types = i;
2617 
2618  /* Expanded accounts. Skip if count key missing. */
2619  count = g_key_file_get_integer(key_file, group_name, ACCT_COUNT, &error);
2620  if (error == NULL)
2621  {
2622  for (i = 1; i <= count; i++)
2623  {
2624  key = g_strdup_printf(ACCT_OPEN, i);
2625  value = g_key_file_get_string(key_file, group_name, key, &error);
2626  if (error)
2627  {
2628  g_warning("error reading group %s key %s: %s",
2629  group_name, key, error->message);
2630  g_error_free(error);
2631  error = NULL;
2632  }
2633  else
2634  {
2635  tree_restore_expanded_row(view, value);
2636  g_free(value);
2637  }
2638  g_free(key);
2639  }
2640  }
2641  else
2642  {
2643  g_warning("error reading group %s key %s: %s",
2644  group_name, ACCT_COUNT, error->message);
2645  g_error_free(error);
2646  }
2647 
2648  /* Selected account (if any) */
2649  value = g_key_file_get_string(key_file, group_name, ACCT_SELECTED, NULL);
2650  if (value)
2651  {
2652  tree_restore_selected_row(view, value);
2653  g_free(value);
2654  }
2655 
2656  /* Update tree view for any changes */
2658 }
2659 
2660 void
2661 gnc_tree_view_account_restore_filter (GncTreeViewAccount *view,
2662  AccountFilterDialog *fd,
2663  GKeyFile *key_file,
2664  const gchar *group_name)
2665 {
2666  GError *error = NULL;
2667  gint i;
2668  gboolean show;
2669 
2670  g_return_if_fail (key_file != NULL);
2671  g_return_if_fail (group_name != NULL);
2672 
2673  /* if entry not found, filter will use the default setting */
2674 
2675  /* Filter information. Ignore missing keys. */
2676  show = g_key_file_get_boolean (key_file, group_name, SHOW_HIDDEN_ACCOUNTS, &error);
2677  if (error)
2678  {
2679  g_error_free (error);
2680  error = NULL;
2681  }
2682  else
2683  fd->show_hidden = show;
2684 
2685  show = g_key_file_get_boolean(key_file, group_name, SHOW_ZERO_TOTALS, &error);
2686  if (error)
2687  {
2688  g_error_free (error);
2689  error = NULL;
2690  }
2691  else
2692  fd->show_zero_total = show;
2693 
2694  show = g_key_file_get_boolean(key_file, group_name, SHOW_UNUSED_ACCOUNTS, &error);
2695  if (error)
2696  {
2697  g_error_free (error);
2698  error = NULL;
2699  }
2700  else
2701  fd->show_unused = show;
2702 
2703  i = g_key_file_get_integer(key_file, group_name, ACCOUNT_TYPES, &error);
2704  if (error)
2705  {
2706  g_error_free (error);
2707  error = NULL;
2708  }
2709  else
2710  fd->visible_types = i;
2711 }
2712 
2713 // @@fixme -- factor this app-not-gui-specific-logic out.
2714 void
2715 gnc_tree_view_account_name_edited_cb(Account *account, GtkTreeViewColumn *col, const gchar *new_name)
2716 {
2717  // check for accounts with the same name among our parent's children.
2718  // should probably factor this consistency check out to the account
2719  // itself....
2720  {
2721  Account *parent = gnc_account_get_parent(account);
2722  Account *existing = gnc_account_lookup_by_name(parent, new_name);
2723  if (existing != NULL && existing != account)
2724  {
2725  PERR("account with the same name [%s] already exists.", new_name);
2726  return;
2727  }
2728  }
2729  xaccAccountSetName(account, new_name);
2730 }
2731 
2732 void
2733 gnc_tree_view_account_code_edited_cb(Account *account, GtkTreeViewColumn *col, const gchar *new_code)
2734 {
2735  if (g_strcmp0(xaccAccountGetCode(account), new_code) == 0)
2736  return;
2737  xaccAccountSetCode(account, new_code);
2738 }
2739 
2740 void
2741 gnc_tree_view_account_description_edited_cb(Account *account, GtkTreeViewColumn *col, const gchar *new_desc)
2742 {
2743  if (g_strcmp0(xaccAccountGetDescription(account), new_desc) == 0)
2744  return;
2745  xaccAccountSetDescription(account, new_desc);
2746 }
2747 
2748 void
2749 gnc_tree_view_account_notes_edited_cb(Account *account, GtkTreeViewColumn *col, const gchar *new_notes)
2750 {
2751  if (g_strcmp0(xaccAccountGetNotes(account), new_notes) == 0)
2752  return;
2753  xaccAccountSetNotes(account, new_notes);
2754 }
2755 
2756 static void
2757 gtva_set_column_editor(GncTreeViewAccount *view,
2758  GtkTreeViewColumn *column,
2759  GncTreeViewAccountColumnTextEdited edited_cb)
2760 {
2761  GList *renderers_orig, *renderers;
2762  GtkCellRenderer *renderer = NULL;
2763 
2764  // look for the first text-renderer; on the 0th column of the account tree,
2765  // there are two renderers: pixbuf and text. So find the text one.
2766  for (renderers_orig = renderers = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
2767  renderers && !GTK_IS_CELL_RENDERER_TEXT(renderers->data);
2768  renderers = renderers->next);
2769  if (renderers)
2770  renderer = GTK_CELL_RENDERER(renderers->data);
2771  g_list_free(renderers_orig);
2772  g_return_if_fail(renderer != NULL);
2773  gtva_setup_column_renderer_edited_cb(GNC_TREE_VIEW_ACCOUNT(view), column, renderer, edited_cb);
2774 }
2775 
2776 void
2777 gnc_tree_view_account_set_name_edited(GncTreeViewAccount *view,
2778  GncTreeViewAccountColumnTextEdited edited_cb)
2779 {
2780  gtva_set_column_editor(view, view->name_column, edited_cb);
2781 }
2782 
2783 void
2784 gnc_tree_view_account_set_code_edited(GncTreeViewAccount *view,
2785  GncTreeViewAccountColumnTextEdited edited_cb)
2786 {
2787  gtva_set_column_editor(view, view->code_column, edited_cb);
2788 }
2789 
2790 void
2791 gnc_tree_view_account_set_description_edited(GncTreeViewAccount *view,
2792  GncTreeViewAccountColumnTextEdited edited_cb)
2793 {
2794  gtva_set_column_editor(view, view->desc_column, edited_cb);
2795 }
2796 
2797 void
2798 gnc_tree_view_account_set_notes_edited(GncTreeViewAccount *view,
2799  GncTreeViewAccountColumnTextEdited edited_cb)
2800 {
2801  gtva_set_column_editor(view, view->notes_column, edited_cb);
2802 }
2803 
2804 static
2805 gboolean gnc_tree_view_search_compare (GtkTreeModel *model, gint column,
2806  const gchar *key, GtkTreeIter *iter, gpointer search_data)
2807 {
2808  gchar *normalized_key;
2809  gchar *case_normalized_key = NULL;
2810  gboolean match = FALSE;
2811 
2812  normalized_key = g_utf8_normalize (key, -1, G_NORMALIZE_NFC);
2813  if (normalized_key)
2814  case_normalized_key = g_utf8_casefold (normalized_key, -1);
2815  if (case_normalized_key)
2816  {
2817  int i;
2818 
2819  for (i=0;i<3;i++)
2820  {
2821  gchar *normalized_string;
2822  gchar *case_normalized_string = NULL;
2823  gchar *str = NULL;
2824 
2825  switch (i)
2826  {
2827  case 0:
2828  gtk_tree_model_get(model,iter,GNC_TREE_MODEL_ACCOUNT_COL_NAME,&str,-1);
2829  break;
2830  case 1:
2831  gtk_tree_model_get(model,iter,GNC_TREE_MODEL_ACCOUNT_COL_CODE,&str,-1);
2832  break;
2833  case 2:
2834  gtk_tree_model_get(model,iter,GNC_TREE_MODEL_ACCOUNT_COL_DESCRIPTION,&str,-1);
2835  break;
2836  }
2837 
2838  if (!str)
2839  continue;
2840 
2841  normalized_string = g_utf8_normalize (str, -1, G_NORMALIZE_NFC);
2842  if (normalized_string)
2843  case_normalized_string = g_utf8_casefold (normalized_string, -1);
2844  if (case_normalized_string&&NULL!=strstr(case_normalized_string,case_normalized_key))
2845  match=TRUE;
2846 
2847  g_free (str);
2848  g_free (normalized_string);
2849  g_free (case_normalized_string);
2850 
2851  if (match)
2852  break;
2853  }
2854  }
2855 
2856  g_free (normalized_key);
2857  g_free (case_normalized_key);
2858 
2859  // inverted return (FALSE means a match)
2860  return !match;
2861 }
2862 
2863 void gnc_tree_view_account_set_editing_started_cb(GncTreeViewAccount *view,
2864  GFunc editing_started_cb, gpointer editing_cb_data)
2865 {
2866  gnc_tree_view_set_editing_started_cb (GNC_TREE_VIEW(view),
2867  editing_started_cb, editing_cb_data);
2868 }
2869 
2871  GFunc editing_finished_cb, gpointer editing_cb_data)
2872 {
2873  gnc_tree_view_set_editing_finished_cb (GNC_TREE_VIEW(view),
2874  editing_finished_cb, editing_cb_data);
2875 }
2876 
2877 
2878 static gboolean
2879 gnc_tree_view_tooltip_cb (GtkWidget *widget, gint x, gint y, gboolean keyboard_tip,
2880  GtkTooltip *tooltip, gpointer user_data)
2881 {
2882  GtkTreeView *tree_view = GTK_TREE_VIEW(widget);
2883  GtkTreePath *path = NULL;
2884  GtkTreeViewColumn *column = NULL;
2885  gtk_tree_view_convert_widget_to_bin_window_coords (tree_view, x, y, &x, &y);
2886  if (keyboard_tip || !gtk_tree_view_get_path_at_pos (tree_view, x, y, &path,
2887  &column, NULL, NULL))
2888  {
2889  gtk_tree_path_free (path);
2890  return false;
2891  }
2892 
2893  // Get the iter pointing to our current column
2894  gboolean show_tooltip = false;
2895  GtkTreeModel *model = gtk_tree_view_get_model (tree_view);
2896  GtkTreeIter iter;
2897  if (gtk_tree_model_get_iter (model, &iter, path) && column)
2898  {
2899  gchar *ttip = NULL;
2900 
2901  // Select text based on column
2902  switch (gtk_tree_view_column_get_sort_column_id (column))
2903  {
2904  case GNC_TREE_MODEL_ACCOUNT_COL_BALANCE_LIMIT:
2905  gtk_tree_model_get (model, &iter,
2906  GNC_TREE_MODEL_ACCOUNT_COL_BALANCE_LIMIT_EXPLANATION, &ttip,
2907  -1);
2908  break;
2909  default:
2910  break;
2911  }
2912 
2913  // Did we select any text? If yes, display the tooltip
2914  if (ttip && *ttip)
2915  {
2916  show_tooltip = true;
2917  gtk_tooltip_set_text (tooltip, ttip);
2918  gtk_tree_view_set_tooltip_cell (tree_view, tooltip, path, column, NULL);
2919  }
2920  g_free (ttip);
2921  }
2922 
2923  // Clean up the object
2924  gtk_tree_path_free (path);
2925  return show_tooltip;
2926 }
Account * gnc_account_get_parent(const Account *acc)
This routine returns a pointer to the parent of the specified account.
Definition: Account.cpp:2902
void gnc_tree_view_account_get_view_info(GncTreeViewAccount *view, AccountViewInfo *avi)
Given pointers to an account tree and old style filter block, this function will copy the current con...
GtkTreeViewColumn * gnc_tree_view_account_add_property_column(GncTreeViewAccount *view, const gchar *column_title, const gchar *propname)
Add a new column to the set of columns in an account tree view.
void qof_instance_get(const QofInstance *inst, const gchar *first_prop,...)
Wrapper for g_object_get.
The instance data structure for a content plugin.
const GList * gnc_gobject_tracking_get_list(const gchar *name)
Get a list of all known objects of a specified type.
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
Retrieve the mnemonic for the specified commodity.
gulong gnc_prefs_register_cb(const char *group, const gchar *pref_name, gpointer func, gpointer user_data)
Register a callback that gets triggered when the given preference changes.
Definition: gnc-prefs.cpp:127
GList * gnc_tree_view_account_get_selected_accounts(GncTreeViewAccount *view)
This function returns a list of the accounts associated with the selected items in the account tree v...
Account * gnc_tree_view_account_get_cursor_account(GncTreeViewAccount *view)
This function returns the account in the account tree view at the current location of the cursor...
void xaccAccountSetNotes(Account *acc, const char *str)
Set the account&#39;s notes.
Definition: Account.cpp:2629
void gnc_tree_view_account_set_editing_finished_cb(GncTreeViewAccount *view, GFunc editing_finished_cb, gpointer editing_cb_data)
Setup the callback for when the user finishes editing the account tree so actions can be enabled like...
int safe_utf8_collate(const char *da, const char *db)
Collate two UTF-8 strings.
GNCAccountType xaccAccountGetType(const Account *acc)
Returns the account&#39;s account type.
Definition: Account.cpp:3234
void gnc_tree_view_set_editing_started_cb(GncTreeView *view, GFunc editing_started_cb, gpointer editing_cb_data)
Setup a callback for when the user starts editing so appropriate actions can be taken like disable th...
void gppat_filter_response_cb(GtkWidget *dialog, gint response, AccountFilterDialog *fd)
The Filter dialog was closed.
const char * xaccAccountGetCode(const Account *acc)
Get the account&#39;s accounting code.
Definition: Account.cpp:3303
STRUCTS.
common utilities for manipulating a GtkTreeView within gnucash
#define DEBUG(format, args...)
Print a debugging message.
Definition: qoflog.h:264
const gchar * gnc_plugin_page_get_page_name(GncPluginPage *page)
Retrieve the name of this page.
Account * gnc_tree_model_account_get_account(GncTreeModelAccount *model, GtkTreeIter *iter)
Convert a model/iter pair to a gnucash account.
void xaccAccountSetCode(Account *acc, const char *str)
Set the account&#39;s accounting code.
Definition: Account.cpp:2459
void gppat_filter_select_all_cb(GtkWidget *button, AccountFilterDialog *fd)
The "select all account types" button in the Filter dialog was clicked.
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
stop here; the following types just aren&#39;t ready for prime time
Definition: Account.h:161
void gnc_tree_view_account_expand_to_account(GncTreeViewAccount *view, Account *account)
This function forces the account tree expand whatever levels are necessary to make the specified acco...
void gnc_tree_view_account_column_add_color(GncTreeViewAccount *view, GtkTreeViewColumn *col)
Add the account color background data function to the GncTreeViewAccount column to show or not the co...
void gnc_tree_view_account_set_view_info(GncTreeViewAccount *view, AccountViewInfo *avi)
Given pointers to an account tree and old style filter block, this function will applies the settings...
void gnc_tree_view_set_show_column_menu(GncTreeView *view, gboolean visible)
This function is called to set the "show-column-menu" property on this view.
gint gnc_numeric_compare(gnc_numeric a, gnc_numeric b)
Returns 1 if a>b, -1 if b>a, 0 if a == b.
void gppat_filter_clear_all_cb(GtkWidget *button, AccountFilterDialog *fd)
The "clear all account types" button in the Filter dialog was clicked.
void gnc_tree_view_account_set_editing_started_cb(GncTreeViewAccount *view, GFunc editing_started_cb, gpointer editing_cb_data)
Setup the callback for when the user starts editing the account tree so actions can be disabled like ...
#define PERR(format, args...)
Log a serious error.
Definition: qoflog.h:244
GtkTreeViewColumn * gnc_tree_view_add_numeric_column(GncTreeView *view, const gchar *column_title, const gchar *pref_name, const gchar *sizing_text, gint model_data_column, gint model_color_column, gint model_visibility_column, GtkTreeIterCompareFunc column_sort_fn)
This function adds a new numeric column to a GncTreeView base view.
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
gboolean gnc_tree_model_account_get_iter_from_account(GncTreeModelAccount *model, Account *account, GtkTreeIter *iter)
Convert a model/account pair into a gtk_tree_model_iter.
gnc_commodity * gnc_default_report_currency(void)
Return the default currency for use in reports, as set by the user.
void gnc_tree_view_account_set_selected_accounts(GncTreeViewAccount *view, GList *account_list, gboolean show_last)
This function selects a set of accounts in the account tree view.
gnc_commodity * gnc_default_currency(void)
Return the default currency set by the user.
void gppat_filter_show_hidden_toggled_cb(GtkToggleButton *button, AccountFilterDialog *fd)
The "show hidden" button in the Filter dialog changed state.
gboolean xaccAccountIsHidden(const Account *acc)
Should this account be "hidden".
Definition: Account.cpp:4154
Account * gnc_account_lookup_by_name(const Account *parent, const char *name)
The gnc_account_lookup_by_name() subroutine fetches the account by name from the descendants of the s...
Definition: Account.cpp:3060
int xaccAccountOrder(const Account *aa, const Account *ab)
The xaccAccountOrder() subroutine defines a sorting order on accounts.
Definition: Account.cpp:2356
gint gnc_tree_view_append_column(GncTreeView *view, GtkTreeViewColumn *column)
Add a column to a view based upon a GncTreeView.
GtkTreeModel implementation for gnucash account tree.
GtkTreeViewColumn * gnc_tree_view_add_pix_column(GncTreeView *view, const gchar *column_title, const gchar *pref_name, const gchar *sizing_text, gint model_data_column, gint model_visibility_column, GtkTreeIterCompareFunc column_sort_fn)
This function adds a new pixbuf view column to a GncTreeView base view.
GtkTreeViewColumn * gnc_tree_view_add_toggle_column(GncTreeView *view, const gchar *column_title, const gchar *column_short_title, const gchar *pref_name, gint model_data_column, gint model_visibility_column, GtkTreeIterCompareFunc column_sort_fn, renderer_toggled toggle_edited_cb)
This function adds a new toggle column to a GncTreeView base view.
void gnc_tree_view_set_editing_finished_cb(GncTreeView *view, GFunc editing_finished_cb, gpointer editing_cb_data)
Setup a callback for when the user finishes editing so appropriate actions can be taken like enable t...
void gnc_tree_view_account_set_filter(GncTreeViewAccount *view, gnc_tree_view_account_filter_func func, gpointer data, GSourceFunc destroy)
This function attaches a filter function to the given account tree.
GtkCellRenderer * gnc_tree_view_column_get_renderer(GtkTreeViewColumn *column)
Return the "main" cell renderer from a GtkTreeViewColumn added to a GncTreeView my one of the conveni...
QofBook * qof_session_get_book(const QofSession *session)
Returns the QofBook of this session.
Definition: qofsession.cpp:575
gchar * gnc_account_get_full_name(const Account *account)
The gnc_account_get_full_name routine returns the fully qualified name of the account using the given...
Definition: Account.cpp:3272
GtkTreeViewColumn * gnc_tree_view_add_text_view_column(GncTreeView *view, const gchar *column_title, const gchar *pref_name, const gchar *icon_name, const gchar *sizing_text, gint model_data_column, gint model_visibility_column, GtkTreeIterCompareFunc column_sort_fn)
This function adds a new text view column to a GncTreeView base view.
void gnc_tree_model_account_clear_cache(GncTreeModelAccount *model)
Clear the tree model account cached values.
Account handling public routines.
void gnc_tree_view_account_select_subaccounts(GncTreeViewAccount *view, Account *account)
This function selects all sub-accounts of an account in the account tree view.
void xaccAccountSetPlaceholder(Account *acc, gboolean val)
Set the "placeholder" flag for an account.
Definition: Account.cpp:4077
void gnc_tree_view_account_refilter(GncTreeViewAccount *view)
This function forces the account tree filter to be evaluated.
Gobject helper routines.
GtkTreeView implementation for gnucash account tree.
GtkTreeModel * gnc_tree_model_account_new(Account *root)
Create a new GtkTreeModel for manipulating gnucash accounts.
GtkTreeViewColumn * gnc_tree_view_account_add_custom_column(GncTreeViewAccount *account_view, const gchar *column_title, GncTreeViewAccountColumnSource col_source_cb, GncTreeViewAccountColumnTextEdited col_edited_cb)
Add a new custom column to the set of columns in an account tree view.
GtkTreeView * gnc_tree_view_account_new_with_root(Account *root, gboolean show_root)
Create a new account tree view.
const char * xaccAccountGetDescription(const Account *acc)
Get the account&#39;s description.
Definition: Account.cpp:3310
time64 gnc_account_get_earliest_date(const Account *account)
Returns the date of the earliest split in the account, or INT64_MAX.
Definition: Account.cpp:5082
GtkTreeView * gnc_tree_view_account_new(gboolean show_root)
Create a new account tree view.
void gnc_tree_view_configure_columns(GncTreeView *view)
Make all the correct columns visible, respecting their default visibility setting, their "always" visibility setting, and the last saved state if available.
General utilities for dealing with accounting periods.
gboolean gnc_plugin_page_account_tree_filter_accounts(Account *account, gpointer user_data)
This function tells the account tree view whether or not to filter out a particular account...
void gnc_tree_view_account_clear_model_cache(GncTreeViewAccount *view)
This function clears the tree model account cache so the values will be updated/refreshed.
Account * gnc_tree_view_account_get_account_from_iter(GtkTreeModel *s_model, GtkTreeIter *s_iter)
This function returns the account associated with the specified iter.
const char * gnc_commodity_get_fullname(const gnc_commodity *cm)
Retrieve the full name for the specified commodity.
Account * gnc_account_lookup_by_full_name(const Account *any_acc, const gchar *name)
The gnc_account_lookup_full_name() subroutine works like gnc_account_lookup_by_name, but uses fully-qualified names using the given separator.
Definition: Account.cpp:3130
Account * gnc_tree_view_account_get_account_from_path(GncTreeViewAccount *view, GtkTreePath *s_path)
This function returns the account associated with the specified path.
All type declarations for the whole Gnucash engine.
gboolean xaccAccountGetReconcileLastDate(const Account *acc, time64 *last_date)
DOCUMENT ME!
Definition: Account.cpp:4518
GNCAccountType
The account types are used to determine how the transaction data in the account is displayed...
Definition: Account.h:101
gboolean xaccAccountGetHidden(const Account *acc)
Get the "hidden" flag for an account.
Definition: Account.cpp:4142
GtkTreeModel implementation to display account types in a GtkTreeView.
GLib helper routines.
Generic api to store and retrieve preferences.
gboolean xaccAccountGetIsOpeningBalance(const Account *acc)
Get the "opening-balance" flag for an account.
Definition: Account.cpp:4095
void gnc_tree_view_account_set_selected_account(GncTreeViewAccount *view, Account *account)
This function selects an account in the account tree view.
void gppat_filter_show_unused_toggled_cb(GtkToggleButton *button, AccountFilterDialog *fd)
The "show unused" button in the Filter dialog changed state.
void xaccAccountSetHidden(Account *acc, gboolean val)
Set the "hidden" flag for an account.
Definition: Account.cpp:4148
gint gnc_tree_view_account_count_children(GncTreeViewAccount *view, Account *account)
This function determines if an account in the account tree view has any visible children.
GtkTreePath * gnc_tree_model_account_get_path_from_account(GncTreeModelAccount *model, Account *account)
Convert a model/account pair into a gtk_tree_model_path.
GtkTreeViewColumn * gnc_tree_view_add_text_column(GncTreeView *view, const gchar *column_title, const gchar *pref_name, const gchar *icon_name, const gchar *sizing_text, gint model_data_column, gint model_visibility_column, GtkTreeIterCompareFunc column_sort_fn)
This function adds a new text column to a GncTreeView base view.
gboolean xaccAccountGetPlaceholder(const Account *acc)
Get the "placeholder" flag for an account.
Definition: Account.cpp:4071
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Get a boolean value from the preferences backend.
Account * gnc_tree_view_account_get_selected_account(GncTreeViewAccount *view)
This function returns the account associated with the selected item in the account tree view...
gboolean(* gnc_tree_view_account_filter_func)(Account *account, gpointer data)
This is the description of a filter function used by the account tree.
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Definition: gnc-date.h:87
void xaccAccountSetDescription(Account *acc, const char *str)
Set the account&#39;s description.
Definition: Account.cpp:2478
const char * xaccAccountGetName(const Account *acc)
Get the account&#39;s name.
Definition: Account.cpp:3256
const char * xaccAccountGetTypeStr(GNCAccountType type)
The xaccAccountGetTypeStr() routine returns a string suitable for use in the GUI/Interface.
Definition: Account.cpp:4309
void xaccAccountSetName(Account *acc, const char *str)
Set the account&#39;s name.
Definition: Account.cpp:2439
The hidden root account of an account tree.
Definition: Account.h:153
Commodity handling public routines.
The Credit card account is used to denote credit (e.g.
Definition: Account.h:113
void gppat_filter_select_default_cb(GtkWidget *button, AccountFilterDialog *fd)
The "select default account types" button in the Filter dialog was clicked.
void gnc_prefs_remove_cb_by_func(const gchar *group, const gchar *pref_name, gpointer func, gpointer user_data)
Remove a function that was registered for a callback when the given preference changed.
Definition: gnc-prefs.cpp:142
const char * xaccAccountGetNotes(const Account *acc)
Get the account&#39;s notes.
Definition: Account.cpp:3341
void gppat_filter_show_zero_toggled_cb(GtkToggleButton *button, AccountFilterDialog *fd)
The "show zero totals" button in the Filter dialog changed state.