GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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 <[email protected]> *
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 [email protected] *
22  * *
23 \**********************************************************************/
24 
25 #include "config.h"
26 
27 #include <gtk/gtk.h>
28 #include <glib/gi18n.h>
29 #include <string.h>
30 
31 #include "gnc-tree-view.h"
32 #include "gnc-tree-model-account.h"
34 #include "gnc-tree-view-account.h"
35 
36 #include "Account.h"
37 #include "gnc-accounting-period.h"
38 #include "gnc-commodity.h"
39 #include "gnc-component-manager.h"
40 #include "gnc-engine.h"
41 #include "gnc-glib-utils.h"
42 #include "gnc-gobject-utils.h"
43 #include "gnc-prefs.h"
44 #include "gnc-hooks.h"
45 #include "gnc-session.h"
46 #include "gnc-icons.h"
47 #include "gnc-ui-balances.h"
48 #include "dialog-utils.h"
49 #include "window-main-summarybar.h"
50 
51 #define SAMPLE_ACCOUNT_VALUE "$1,000,000.00"
52 #define GNC_PREF_ACCOUNT_COLOR "show-account-color"
53 
56 /* This static indicates the debugging module that this .o belongs to. */
57 static QofLogModule log_module = GNC_MOD_GUI;
58 
60 static void gnc_tree_view_account_class_init (GncTreeViewAccountClass *klass);
61 static void gnc_tree_view_account_init (GncTreeViewAccount *view);
62 static void gnc_tree_view_account_finalize (GObject *object);
63 static gboolean gnc_tree_view_search_compare (GtkTreeModel *model, gint column, const gchar *key, GtkTreeIter *iter, gpointer search_data);
64 
65 static void gtva_update_column_names (GncTreeView *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, gchar *key, gpointer user_data);
90 
91 
93 {
94  AccountViewInfo avi;
95 
97  gpointer filter_data;
98  GSourceFunc filter_destroy;
99 
100  GtkTreeViewColumn *name_column;
101  GtkTreeViewColumn *code_column;
102  GtkTreeViewColumn *desc_column;
103  GtkTreeViewColumn *present_report_column;
104  GtkTreeViewColumn *balance_report_column;
105  GtkTreeViewColumn *cleared_report_column;
106  GtkTreeViewColumn *reconciled_report_column;
107  GtkTreeViewColumn *future_min_report_column;
108  GtkTreeViewColumn *total_report_column;
109  GtkTreeViewColumn *notes_column;
110 
111  gboolean show_account_color;
112 
114 
115 #define GNC_TREE_VIEW_ACCOUNT_GET_PRIVATE(o) \
116  (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_TREE_VIEW_ACCOUNT, GncTreeViewAccountPrivate))
117 
118 
119 /************************************************************/
120 /* g_object required functions */
121 /************************************************************/
122 
123 static GObjectClass *parent_class = NULL;
124 
125 GType
126 gnc_tree_view_account_get_type (void)
127 {
128  static GType gnc_tree_view_account_type = 0;
129 
130  if (gnc_tree_view_account_type == 0)
131  {
132  static const GTypeInfo our_info =
133  {
134  sizeof (GncTreeViewAccountClass),
135  NULL,
136  NULL,
137  (GClassInitFunc) gnc_tree_view_account_class_init,
138  NULL,
139  NULL,
140  sizeof (GncTreeViewAccount),
141  0,
142  (GInstanceInitFunc) gnc_tree_view_account_init
143  };
144 
145  gnc_tree_view_account_type = g_type_register_static (
146  GNC_TYPE_TREE_VIEW, GNC_TREE_VIEW_ACCOUNT_NAME,
147  &our_info, 0);
148  }
149 
150  return gnc_tree_view_account_type;
151 }
152 
153 static void
154 gnc_tree_view_account_class_init (GncTreeViewAccountClass *klass)
155 {
156  GObjectClass *o_class;
157 
158  parent_class = g_type_class_peek_parent (klass);
159 
160  /* GObject signals */
161  o_class = G_OBJECT_CLASS (klass);
162  o_class->finalize = gnc_tree_view_account_finalize;
163 
164  g_type_class_add_private(klass, sizeof(GncTreeViewAccountPrivate));
165 
166  gnc_hook_add_dangler(HOOK_CURRENCY_CHANGED,
167  (GFunc)gtva_currency_changed_cb, NULL);
168 }
169 
170 /********************************************************************\
171  * gnc_init_account_view_info *
172  * initialize an account view info structure with default values *
173  * *
174  * Args: avi - structure to initialize *
175  * Returns: nothing *
176 \********************************************************************/
177 static void
178 gnc_init_account_view_info(AccountViewInfo *avi)
179 {
180  int i;
181 
182  for (i = 0; i < NUM_ACCOUNT_TYPES; i++)
183  avi->include_type[i] = TRUE;
184  avi->show_hidden = FALSE;
185 }
186 
187 static void
188 gnc_tree_view_account_init (GncTreeViewAccount *view)
189 {
191 
192  priv = GNC_TREE_VIEW_ACCOUNT_GET_PRIVATE(view);
193 
194  gnc_prefs_register_cb (GNC_PREFS_GROUP_GENERAL,
195  GNC_PREF_ACCOUNT_COLOR,
196  gnc_tree_view_account_color_update,
197  view);
198 
199  gnc_init_account_view_info(&priv->avi);
200 }
201 
202 static void
203 gnc_tree_view_account_finalize (GObject *object)
204 {
205  GncTreeViewAccount *account_view;
207 
208  ENTER("view %p", object);
209  g_return_if_fail (object != NULL);
210  g_return_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (object));
211 
212  account_view = GNC_TREE_VIEW_ACCOUNT (object);
213 
214  priv = GNC_TREE_VIEW_ACCOUNT_GET_PRIVATE(account_view);
215 
216  gnc_prefs_remove_cb_by_func (GNC_PREFS_GROUP_GENERAL,
217  GNC_PREF_ACCOUNT_COLOR,
218  gnc_tree_view_account_color_update,
219  account_view);
220  if (priv->filter_destroy)
221  {
222  priv->filter_destroy(priv->filter_data);
223  priv->filter_destroy = NULL;
224  }
225  priv->filter_fn = NULL;
226 
227  if (G_OBJECT_CLASS (parent_class)->finalize)
228  (* G_OBJECT_CLASS (parent_class)->finalize) (object);
229  LEAVE(" ");
230 }
231 
232 
233 /************************************************************
234  * Callbacks *
235  ************************************************************/
236 static void
237 gnc_tree_view_account_placeholder_toggled (GtkCellRendererToggle *cell,
238  const gchar *s_path_str,
239  gpointer user_data)
240 {
241  GncTreeViewAccount *tree_view;
242  GtkTreePath *s_path;
243  Account *account;
244  gboolean placeholder;
245 
246  /* Change the requested account */
247  tree_view = user_data;
248  s_path = gtk_tree_path_new_from_string (s_path_str);
249  account = gnc_tree_view_account_get_account_from_path (tree_view, s_path);
250  if (account)
251  {
252  placeholder = !gtk_cell_renderer_toggle_get_active (cell); // hasn't changed yet.
253  xaccAccountSetPlaceholder (account, placeholder);
254  }
255 
256  /* Clean up */
257  gtk_tree_path_free (s_path);
258 }
259 
260 
261 /************************************************************/
262 /* sort functions */
263 /************************************************************/
264 
265 static GtkTreeModel *
266 sort_cb_setup_w_iters (GtkTreeModel *f_model,
267  GtkTreeIter *f_iter_a,
268  GtkTreeIter *f_iter_b,
269  GtkTreeIter *iter_a,
270  GtkTreeIter *iter_b,
271  const Account **account_a,
272  const Account **account_b)
273 {
274  GtkTreeModel *model;
275 
276  model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
277  gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER(f_model),
278  iter_a,
279  f_iter_a);
280  gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER(f_model),
281  iter_b,
282  f_iter_b);
283  *account_a = gnc_tree_model_account_get_account (GNC_TREE_MODEL_ACCOUNT(model), iter_a);
284  *account_b = gnc_tree_model_account_get_account (GNC_TREE_MODEL_ACCOUNT(model), iter_b);
285  return model;
286 }
287 
288 static void
289 sort_cb_setup (GtkTreeModel *f_model,
290  GtkTreeIter *f_iter_a,
291  GtkTreeIter *f_iter_b,
292  const Account **account_a,
293  const Account **account_b)
294 {
295  GtkTreeIter iter_a, iter_b;
296 
297  sort_cb_setup_w_iters (f_model, f_iter_a, f_iter_b,
298  &iter_a, &iter_b, account_a, account_b);
299 }
300 
301 static gint
302 sort_by_string (GtkTreeModel *f_model,
303  GtkTreeIter *f_iter1,
304  GtkTreeIter *f_iter2,
305  gpointer user_data)
306 {
307  GtkTreeModel *model;
308  GtkTreeIter iter1, iter2;
309  const Account *account1, *account2;
310  gchar *str1, *str2;
311  gint column = GPOINTER_TO_INT(user_data);
312  gint result;
313 
314  model = sort_cb_setup_w_iters(f_model, f_iter1, f_iter2, &iter1, &iter2, &account1, &account2);
315 
316  /* Get the strings. */
317  gtk_tree_model_get(GTK_TREE_MODEL(model), &iter1, column, &str1, -1);
318  gtk_tree_model_get(GTK_TREE_MODEL(model), &iter2, column, &str2, -1);
319 
320  result = safe_utf8_collate(str1, str2);
321  g_free(str1);
322  g_free(str2);
323  if (result != 0)
324  return result;
325  return xaccAccountOrder(account1, account2);
326 }
327 
328 static gint
329 sort_by_code (GtkTreeModel *f_model,
330  GtkTreeIter *f_iter_a,
331  GtkTreeIter *f_iter_b,
332  gpointer user_data)
333 {
334  const Account *account_a, *account_b;
335 
336  sort_cb_setup (f_model, f_iter_a, f_iter_b, &account_a, &account_b);
337 
338  /* Default ordering uses this column first. */
339  return xaccAccountOrder(account_a, account_b);
340 }
341 
342 static gint
343 sort_by_xxx_value (xaccGetBalanceInCurrencyFn fn,
344  gboolean recurse,
345  GtkTreeModel *f_model,
346  GtkTreeIter *f_iter_a,
347  GtkTreeIter *f_iter_b,
348  gpointer user_data)
349 {
350  const Account *account_a, *account_b;
351  gnc_numeric balance_a, balance_b;
352  gint result;
353 
354  /* Find the accounts */
355  sort_cb_setup (f_model, f_iter_a, f_iter_b, &account_a, &account_b);
356 
357  /* Get balances */
358  balance_a = gnc_ui_account_get_balance_full(fn, account_a, recurse, NULL, NULL);
359  balance_b = gnc_ui_account_get_balance_full(fn, account_b, recurse, NULL, NULL);
360 
361  result = gnc_numeric_compare(balance_a, balance_b);
362  if (result != 0)
363  return result;
364  return xaccAccountOrder(account_a, account_b);
365 }
366 
367 static gint
368 sort_by_present_value (GtkTreeModel *f_model,
369  GtkTreeIter *f_iter_a,
370  GtkTreeIter *f_iter_b,
371  gpointer user_data)
372 {
373  return sort_by_xxx_value (xaccAccountGetPresentBalanceInCurrency, TRUE,
374  f_model, f_iter_a, f_iter_b, user_data);
375 }
376 
377 static gint
378 sort_by_balance_value (GtkTreeModel *f_model,
379  GtkTreeIter *f_iter_a,
380  GtkTreeIter *f_iter_b,
381  gpointer user_data)
382 {
383  return sort_by_xxx_value (xaccAccountGetBalanceInCurrency, TRUE,
384  f_model, f_iter_a, f_iter_b, user_data);
385 }
386 
387 static gint
388 sort_by_cleared_value (GtkTreeModel *f_model,
389  GtkTreeIter *f_iter_a,
390  GtkTreeIter *f_iter_b,
391  gpointer user_data)
392 {
393  return sort_by_xxx_value (xaccAccountGetClearedBalanceInCurrency, TRUE,
394  f_model, f_iter_a, f_iter_b, user_data);
395 }
396 
397 static gint
398 sort_by_reconciled_value (GtkTreeModel *f_model,
399  GtkTreeIter *f_iter_a,
400  GtkTreeIter *f_iter_b,
401  gpointer user_data)
402 {
403  return sort_by_xxx_value (xaccAccountGetReconciledBalanceInCurrency, TRUE,
404  f_model, f_iter_a, f_iter_b, user_data);
405 }
406 
407 static gint
408 sort_by_future_min_value (GtkTreeModel *f_model,
409  GtkTreeIter *f_iter_a,
410  GtkTreeIter *f_iter_b,
411  gpointer user_data)
412 {
413  return sort_by_xxx_value (xaccAccountGetProjectedMinimumBalanceInCurrency, TRUE,
414  f_model, f_iter_a, f_iter_b, user_data);
415 }
416 
417 static gint
418 sort_by_total_value (GtkTreeModel *f_model,
419  GtkTreeIter *f_iter_a,
420  GtkTreeIter *f_iter_b,
421  gpointer user_data)
422 {
423  return sort_by_xxx_value (xaccAccountGetBalanceInCurrency, TRUE,
424  f_model, f_iter_a, f_iter_b, user_data);
425 }
426 
427 static gint
428 sort_by_placeholder (GtkTreeModel *f_model,
429  GtkTreeIter *f_iter_a,
430  GtkTreeIter *f_iter_b,
431  gpointer user_data)
432 {
433  const Account *account_a, *account_b;
434  gboolean flag_a, flag_b;
435 
436  /* Find the accounts */
437  sort_cb_setup (f_model, f_iter_a, f_iter_b, &account_a, &account_b);
438 
439  /* Get the placeholder flags. */
440  flag_a = xaccAccountGetPlaceholder(account_a);
441  flag_b = xaccAccountGetPlaceholder(account_b);
442 
443  if (flag_a > flag_b)
444  return -1;
445  else if (flag_a < flag_b)
446  return 1;
447  return xaccAccountOrder(account_a, account_b);
448 }
449 
450 static gint
451 sort_by_xxx_period_value (GtkTreeModel *f_model,
452  GtkTreeIter *f_iter_a,
453  GtkTreeIter *f_iter_b,
454  gboolean recurse)
455 {
456  Account *acct1, *acct2;
457  time64 t1, t2;
458  gnc_numeric b1, b2;
459  gint result;
460 
461  sort_cb_setup (f_model, f_iter_a, f_iter_b,
462  (const Account **)&acct1, (const Account **)&acct2);
463 
464  t1 = gnc_accounting_period_fiscal_start();
465  t2 = gnc_accounting_period_fiscal_end();
466 
467  b1 = xaccAccountGetBalanceChangeForPeriod(acct1, t1, t2, recurse);
468  b2 = xaccAccountGetBalanceChangeForPeriod(acct2, t1, t2, recurse);
469 
470  result = gnc_numeric_compare(b1, b2);
471  if (result != 0)
472  return result;
473  return xaccAccountOrder(acct1, acct2);
474 }
475 
476 static gint
477 sort_by_balance_period_value (GtkTreeModel *f_model,
478  GtkTreeIter *f_iter_a,
479  GtkTreeIter *f_iter_b,
480  gpointer user_data)
481 {
482  return sort_by_xxx_period_value (f_model, f_iter_a, f_iter_b, FALSE);
483 }
484 
485 static gint
486 sort_by_total_period_value (GtkTreeModel *f_model,
487  GtkTreeIter *f_iter_a,
488  GtkTreeIter *f_iter_b,
489  gpointer user_data)
490 {
491  return sort_by_xxx_period_value (f_model, f_iter_a, f_iter_b, TRUE);
492 }
493 
494 /************************************************************/
495 /* Tax_Info data function */
496 /************************************************************/
497 
498 /*
499  * The tax-info column in the account tree view is based on the
500  * combination of two columns in the account tree model. The data
501  * function displays only the the data in the
502  * GNC_TREE_MODEL_ACCOUNT_COL_TAX_INFO model column if the row is
503  * expanded; otherwise it combines it with the data
504  * in the GNC_TREE_MODEL_ACCOUNT_COL_TAX_INFO_SUB_ACCT model column.
505  */
506 static void
507 tax_info_data_func (GtkTreeViewColumn *col,
508  GtkCellRenderer *renderer,
509  GtkTreeModel *model,
510  GtkTreeIter *iter,
511  gpointer view)
512 {
513  gchar *tax_info = NULL;
514  GtkTreePath *path;
515 
516  gtk_tree_model_get(model,
517  iter,
518  GNC_TREE_MODEL_ACCOUNT_COL_TAX_INFO,
519  &tax_info,
520  -1);
521 
522  path = gtk_tree_model_get_path(model, iter);
523  if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(view), path))
524  g_object_set(renderer, "text",
525  (tax_info == NULL ? "" : tax_info), NULL);
526  else
527  {
528  gchar *tax_info_sub_acct = NULL;
529 
530  gtk_tree_model_get(model,
531  iter,
532  GNC_TREE_MODEL_ACCOUNT_COL_TAX_INFO_SUB_ACCT,
533  &tax_info_sub_acct,
534  -1);
535  if ((g_strcmp0 (tax_info_sub_acct, "") == 0) ||
536  (tax_info_sub_acct == NULL))
537  g_object_set(renderer, "text",
538  (tax_info == NULL ? "" : tax_info), NULL);
539  else
540  {
541  if ((g_strcmp0 (tax_info, "") == 0) ||
542  (tax_info == NULL))
543  g_object_set(renderer, "text",
544  (tax_info_sub_acct == NULL ? "" : tax_info_sub_acct),
545  NULL);
546  else
547  {
548  gchar *combined_tax_info;
549  combined_tax_info = g_strdup_printf ("%s; %s",
550  (tax_info == NULL ? "" : tax_info),
551  (tax_info_sub_acct == NULL ? "" :
552  tax_info_sub_acct));
553  g_object_set(renderer, "text", combined_tax_info, NULL);
554  g_free(combined_tax_info);
555  }
556  }
557  g_free(tax_info_sub_acct);
558  }
559  g_free(tax_info);
560  gtk_tree_path_free(path);
561 }
562 
563 /************************************************************/
564 /* acc_color data function */
565 /************************************************************/
566 /*
567  * The account-color column in the account tree view is obtained
568  * from the GNC_TREE_MODEL_ACCOUNT_COL_COLOR_ACCOUNT which is
569  * checked for a valid color string to set the background color
570  * of the cell.
571  */
572 static void
573 update_cell_renderers (GList *renderers, gchar *account_color)
574 {
575  GtkCellRenderer *cell;
576  GList *node;
577 
578  /* Update the cell background in the list of renderers */
579  for (node = renderers; node; node = node->next)
580  {
581  cell = node->data;
582  g_object_set (cell, "cell-background", account_color, NULL);
583  }
584 }
585 
586 /* Colorizes a cell in the account tree view if
587  * - a color is assigned to the given account
588  * - the user enabled account colorization in the preferences
589  * Only the account color column is special: it will always
590  * be colored if a valid color was set, regardless of the
591  * preference setting.
592  */
593 static void
594 acc_color_data_func (GtkTreeViewColumn *col,
595  GtkCellRenderer *renderer,
596  GtkTreeModel *model,
597  GtkTreeIter *iter,
598  gpointer view)
599 {
601  gchar *acc_color = NULL, *acc_cond_color = NULL;
602  gchar *item;
603  GdkColor color;
604  gchar *column_name;
605  GList *renderers;
606 
607  gtk_tree_model_get(model,
608  iter,
609  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_ACCOUNT,
610  &item,
611  -1);
612 
613  /* Check if color was set for the account */
614  if ((item) && (*item != '\0'))
615  acc_color = g_strstrip(g_strdup(item));
616  g_free (item);
617 
618  /* Test if the color string represents a valid color */
619  if (acc_color && (!gdk_color_parse(acc_color, &color)))
620  {
621  g_free (acc_color);
622  acc_color = NULL;
623  }
624 
625  /* Determine whether columns other than the
626  * Account Color column should be colored. */
627  priv = GNC_TREE_VIEW_ACCOUNT_GET_PRIVATE(view);
628  if (priv->show_account_color)
629  acc_cond_color = acc_color;
630 
631  column_name = g_object_get_data(G_OBJECT(col), PREF_NAME);
632  renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (col));
633 
634  /* Account Color column is always colored, other columns only conditionally. */
635  if (g_strcmp0(column_name, "account-color") == 0)
636  update_cell_renderers (renderers, acc_color);
637  else
638  update_cell_renderers (renderers, acc_cond_color);
639 
640  g_list_free (renderers);
641  g_free (acc_color);
642 }
643 
649 static void
650 gnc_tree_view_account_color_update (gpointer gsettings, gchar *key, gpointer user_data)
651 {
653  GncTreeViewAccount *view;
654 
655  g_return_if_fail(GNC_IS_TREE_VIEW_ACCOUNT(user_data));
656  view = user_data;
657  priv = GNC_TREE_VIEW_ACCOUNT_GET_PRIVATE(view);
658  if (g_strcmp0 (key, GNC_PREF_ACCOUNT_COLOR) == 0)
659  priv->show_account_color = gnc_prefs_get_bool(GNC_PREFS_GROUP_GENERAL, key);
660 }
661 
662 /************************************************************/
663 /* New View Creation */
664 /************************************************************/
665 
666 /*
667  * Create a new account tree view with (optional) top level root node.
668  * This view will be based on a model that is common to all view of
669  * the same set of books, but will have its own private filter on that
670  * model.
671  */
672 GtkTreeView *
673 gnc_tree_view_account_new_with_root (Account *root, gboolean show_root)
674 {
675  GncTreeView *view;
676  GtkTreeModel *model, *f_model, *s_model;
677  GtkTreePath *virtual_root_path = NULL;
678  const gchar *sample_type, *sample_commodity;
680  GtkTreeViewColumn *tax_info_column, *acc_color_column;
681  GtkCellRenderer *renderer;
682 
683  ENTER(" ");
684  /* Create our view */
685  view = g_object_new (GNC_TYPE_TREE_VIEW_ACCOUNT,
686  "name", "account_tree", NULL);
687 
688  priv = GNC_TREE_VIEW_ACCOUNT_GET_PRIVATE(GNC_TREE_VIEW_ACCOUNT (view));
689 
690  /* Get the show_account_color value from gsettings */
691  priv->show_account_color = gnc_prefs_get_bool(GNC_PREFS_GROUP_GENERAL, GNC_PREF_ACCOUNT_COLOR);
692 
693  /* Create/get a pointer to the existing model for this set of books. */
694  model = gnc_tree_model_account_new (root);
695 
696  /* Set up the view private filter layer on the common model. */
697  if (!show_root)
698  virtual_root_path = gtk_tree_path_new_first ();
699  f_model = gtk_tree_model_filter_new (model, virtual_root_path);
700  /* A GncTreeModelAccount is based on a GncTreeModel, which is a
701  * GObject that provides a GtkTreeModel interface. */
702  g_object_unref(G_OBJECT(model));
703  if (virtual_root_path)
704  gtk_tree_path_free(virtual_root_path);
705 
706  /* Set up the view private sort layer on the common model. */
707  s_model = gtk_tree_model_sort_new_with_model(f_model);
708  g_object_unref(G_OBJECT(f_model));
709  gtk_tree_view_set_model (GTK_TREE_VIEW (view), s_model);
710  g_object_unref(G_OBJECT(s_model));
711 
712  /* Set default visibilities */
713  gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(view), FALSE);
714 
716  sample_commodity = gnc_commodity_get_fullname(gnc_default_currency());
717 
718  priv->name_column
719  = gnc_tree_view_add_text_column(view, _("Account Name"), "name",
720  GNC_STOCK_ACCOUNT, "Expenses:Entertainment",
721  GNC_TREE_MODEL_ACCOUNT_COL_NAME,
722  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
723  sort_by_string);
724 
725  renderer = gnc_tree_view_column_get_renderer(priv->name_column);
726 
727  gtk_tree_view_column_set_cell_data_func(priv->name_column,
728  renderer,
729  acc_color_data_func,
730  GTK_TREE_VIEW(view),
731  NULL);
732 
733  gnc_tree_view_add_text_column(view, _("Type"), "type", NULL, sample_type,
734  GNC_TREE_MODEL_ACCOUNT_COL_TYPE,
735  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
736  sort_by_string);
737 
738  gnc_tree_view_add_text_column(view, _("Commodity"), "commodity", NULL,
739  sample_commodity,
740  GNC_TREE_MODEL_ACCOUNT_COL_COMMODITY,
741  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
742  sort_by_string);
743  priv->code_column
744  = gnc_tree_view_add_text_column(view, _("Account Code"), "account-code", NULL,
745  "1-123-1234",
746  GNC_TREE_MODEL_ACCOUNT_COL_CODE,
747  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
748  sort_by_code);
749  priv->desc_column
750  = gnc_tree_view_add_text_column(view, _("Description"), "description", NULL,
751  "Sample account description.",
752  GNC_TREE_MODEL_ACCOUNT_COL_DESCRIPTION,
753  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
754  sort_by_string);
755 
756  gnc_tree_view_add_numeric_column(view, _("Last Num"), "lastnum", "12345",
757  GNC_TREE_MODEL_ACCOUNT_COL_LASTNUM,
758  GNC_TREE_VIEW_COLUMN_COLOR_NONE,
759  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
760  sort_by_string);
761 
762  gnc_tree_view_add_numeric_column(view, _("Present"), "present",
763  SAMPLE_ACCOUNT_VALUE,
764  GNC_TREE_MODEL_ACCOUNT_COL_PRESENT,
765  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_PRESENT,
766  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
767  sort_by_present_value);
768  priv->present_report_column
769  = gnc_tree_view_add_numeric_column(view, _("Present (Report)"), "present_report",
770  SAMPLE_ACCOUNT_VALUE,
771  GNC_TREE_MODEL_ACCOUNT_COL_PRESENT_REPORT,
772  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_PRESENT,
773  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
774  sort_by_present_value);
775 
776  gnc_tree_view_add_numeric_column(view, _("Balance"), "balance",
777  SAMPLE_ACCOUNT_VALUE,
778  GNC_TREE_MODEL_ACCOUNT_COL_BALANCE,
779  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_BALANCE,
780  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
781  sort_by_balance_value);
782  priv->balance_report_column
783  = gnc_tree_view_add_numeric_column(view, _("Balance (Report)"), "balance_report",
784  SAMPLE_ACCOUNT_VALUE,
785  GNC_TREE_MODEL_ACCOUNT_COL_BALANCE_REPORT,
786  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_BALANCE,
787  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
788  sort_by_balance_value);
789 
790  gnc_tree_view_add_numeric_column(view, _("Balance (Period)"), "balance-period",
791  SAMPLE_ACCOUNT_VALUE,
792  GNC_TREE_MODEL_ACCOUNT_COL_BALANCE_PERIOD,
793  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_BALANCE_PERIOD,
794  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
795  sort_by_balance_period_value);
796 
797  gnc_tree_view_add_numeric_column(view, _("Cleared"), "cleared",
798  SAMPLE_ACCOUNT_VALUE,
799  GNC_TREE_MODEL_ACCOUNT_COL_CLEARED,
800  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_CLEARED,
801  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
802  sort_by_cleared_value);
803  priv->cleared_report_column
804  = gnc_tree_view_add_numeric_column(view, _("Cleared (Report)"), "cleared_report",
805  SAMPLE_ACCOUNT_VALUE,
806  GNC_TREE_MODEL_ACCOUNT_COL_CLEARED_REPORT,
807  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_CLEARED,
808  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
809  sort_by_cleared_value);
810 
811  gnc_tree_view_add_numeric_column(view, _("Reconciled"), "reconciled",
812  SAMPLE_ACCOUNT_VALUE,
813  GNC_TREE_MODEL_ACCOUNT_COL_RECONCILED,
814  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_RECONCILED,
815  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
816  sort_by_reconciled_value);
817  priv->reconciled_report_column
818  = gnc_tree_view_add_numeric_column(view, _("Reconciled (Report)"), "reconciled_report",
819  SAMPLE_ACCOUNT_VALUE,
820  GNC_TREE_MODEL_ACCOUNT_COL_RECONCILED_REPORT,
821  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_RECONCILED,
822  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
823  sort_by_reconciled_value);
824 
825  gnc_tree_view_add_text_column(view, _("Last Reconcile Date"), "last-recon-date", NULL,
826  "Last Reconcile Date",
827  GNC_TREE_MODEL_ACCOUNT_COL_RECONCILED_DATE,
828  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
829  sort_by_string);
830 
831  gnc_tree_view_add_numeric_column(view, _("Future Minimum"), "future_min",
832  SAMPLE_ACCOUNT_VALUE,
833  GNC_TREE_MODEL_ACCOUNT_COL_FUTURE_MIN,
834  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_FUTURE_MIN,
835  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
836  sort_by_future_min_value);
837  priv->future_min_report_column
838  = gnc_tree_view_add_numeric_column(view, _("Future Minimum (Report)"), "future_min_report",
839  SAMPLE_ACCOUNT_VALUE,
840  GNC_TREE_MODEL_ACCOUNT_COL_FUTURE_MIN_REPORT,
841  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_FUTURE_MIN,
842  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
843  sort_by_future_min_value);
844 
845  gnc_tree_view_add_numeric_column(view, _("Total"), "total",
846  SAMPLE_ACCOUNT_VALUE,
847  GNC_TREE_MODEL_ACCOUNT_COL_TOTAL,
848  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_TOTAL,
849  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
850  sort_by_total_value);
851  priv->total_report_column
852  = gnc_tree_view_add_numeric_column(view, _("Total (Report)"), "total_report",
853  SAMPLE_ACCOUNT_VALUE,
854  GNC_TREE_MODEL_ACCOUNT_COL_TOTAL_REPORT,
855  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_TOTAL,
856  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
857  sort_by_total_value);
858 
859  gnc_tree_view_add_numeric_column(view, _("Total (Period)"), "total-period",
860  SAMPLE_ACCOUNT_VALUE,
861  GNC_TREE_MODEL_ACCOUNT_COL_TOTAL_PERIOD,
862  GNC_TREE_MODEL_ACCOUNT_COL_COLOR_TOTAL_PERIOD,
863  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
864  sort_by_total_period_value);
865 
866  /* Translators: The C is the column title and stands for Color, this should be one character */
867  acc_color_column
868  = gnc_tree_view_add_text_column(view, _("C"), "account-color", NULL,
869  "xx",
870  GNC_TREE_VIEW_COLUMN_DATA_NONE,
871  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
872  NULL);
873 
874  renderer = gnc_tree_view_column_get_renderer(acc_color_column);
875 
876  /* Add the full title to the object for menu creation */
877  g_object_set_data_full(G_OBJECT(acc_color_column), REAL_TITLE,
878  g_strdup(_("Account Color")), g_free);
879 
880  gtk_tree_view_column_set_cell_data_func(acc_color_column,
881  renderer,
882  acc_color_data_func,
883  GTK_TREE_VIEW(view),
884  NULL);
885  priv->notes_column
886  = gnc_tree_view_add_text_column(view, _("Notes"), "notes", NULL,
887  "Sample account notes.",
888  GNC_TREE_MODEL_ACCOUNT_COL_NOTES,
889  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
890  sort_by_string);
891  tax_info_column
892  = gnc_tree_view_add_text_column(view, _("Tax Info"), "tax-info", NULL,
893  "Sample tax info.",
894  GNC_TREE_MODEL_ACCOUNT_COL_TAX_INFO,
895  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
896  sort_by_string);
897 
898  renderer = gnc_tree_view_column_get_renderer(tax_info_column);
899  gtk_tree_view_column_set_cell_data_func(tax_info_column,
900  renderer,
901  tax_info_data_func,
902  GTK_TREE_VIEW(view),
903  NULL);
904 
905  gnc_tree_view_add_toggle_column(view, _("Placeholder"),
906  /* Translators: This string has a context prefix; the translation
907  must only contain the part after the | character. */
908  Q_("Column letter for 'Placeholder'|P"),
909  "placeholder",
910  GNC_TREE_MODEL_ACCOUNT_COL_PLACEHOLDER,
911  GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
912  sort_by_placeholder,
913  gnc_tree_view_account_placeholder_toggled);
914 
915  /* Update column titles to use the currency name. */
916  gtva_update_column_names(view);
917 
918  /* By default only the first column is visible. */
920  gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (f_model),
921  gnc_tree_view_account_filter_helper,
922  view,
923  NULL);
924 
925  /* Default the sorting to account name */
926  gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(s_model),
927  GNC_TREE_MODEL_ACCOUNT_COL_NAME,
928  GTK_SORT_ASCENDING);
929 
930  /* Set account find-as-you-type search function */
931  gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW(view), gnc_tree_view_search_compare, NULL, NULL);
932 
933  gtk_widget_show(GTK_WIDGET(view));
934  LEAVE("%p", view);
935  return GTK_TREE_VIEW(view);
936 }
937 
938 /*
939  * Create a new account tree view with (optional) top level root node.
940  * This view will be based on a model that is common to all view of
941  * the same set of books, but will have its own private filter on that
942  * model.
943  */
944 GtkTreeView *
945 gnc_tree_view_account_new (gboolean show_root)
946 {
947  Account *root;
948 
949  root = gnc_book_get_root_account (gnc_get_current_book ());
950  return gnc_tree_view_account_new_with_root (root, show_root);
951 }
952 
953 /************************************************************/
954 /* Auxiliary Functions */
955 /************************************************************/
956 
957 #define debug_path(fn, path) { \
958  gchar *path_string = gtk_tree_path_to_string(path); \
959  fn("tree path %s", path_string); \
960  g_free(path_string); \
961  }
962 
963 static GtkTreePath *
964 gnc_tree_view_account_get_path_from_account (GncTreeViewAccount *view,
965  Account *account)
966 {
967  GtkTreeModel *model, *f_model, *s_model;
968  GtkTreePath *path, *f_path, *s_path;
969 
970  ENTER("view %p, account %p (%s)", view, account, xaccAccountGetName(account));
971 
972  if (account == NULL)
973  {
974  LEAVE("no account");
975  return NULL;
976  }
977 
978  /* Reach down to the real model and get a path for this account */
979  s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
980  f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
981  model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
982  path = gnc_tree_model_account_get_path_from_account (GNC_TREE_MODEL_ACCOUNT(model), account);
983  if (path == NULL)
984  {
985  LEAVE("no path");
986  return NULL;
987  }
988 
989  /* convert back to a filtered path */
990  f_path = gtk_tree_model_filter_convert_child_path_to_path (GTK_TREE_MODEL_FILTER (f_model), path);
991  gtk_tree_path_free(path);
992  if (!f_path)
993  {
994  LEAVE("no filter path");
995  return NULL;
996  }
997 
998  /* convert back to a sorted path */
999  s_path = gtk_tree_model_sort_convert_child_path_to_path (GTK_TREE_MODEL_SORT (s_model), f_path);
1000  gtk_tree_path_free(f_path);
1001  debug_path(LEAVE, s_path);
1002  return s_path;
1003 }
1004 
1005 static gboolean
1006 gnc_tree_view_account_get_iter_from_account (GncTreeViewAccount *view,
1007  Account *account,
1008  GtkTreeIter *s_iter)
1009 {
1010  GtkTreeModel *model, *f_model, *s_model;
1011  GtkTreeIter iter, f_iter;
1012 
1013  g_return_val_if_fail(GNC_IS_TREE_VIEW_ACCOUNT(view), FALSE);
1014  g_return_val_if_fail(account != NULL, FALSE);
1015  g_return_val_if_fail(s_iter != NULL, FALSE);
1016 
1017  ENTER("view %p, account %p (%s)", view, account, xaccAccountGetName(account));
1018 
1019  /* Reach down to the real model and get an iter for this account */
1020  s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
1021  f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
1022  model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
1024  GNC_TREE_MODEL_ACCOUNT(model), account, &iter))
1025  {
1026  LEAVE("model_get_iter_from_account failed");
1027  return FALSE;
1028  }
1029 
1030  /* convert back to a sort iter */
1031  gtk_tree_model_filter_convert_child_iter_to_iter (
1032  GTK_TREE_MODEL_FILTER(f_model), &f_iter, &iter);
1033  gtk_tree_model_sort_convert_child_iter_to_iter (GTK_TREE_MODEL_SORT(s_model),
1034  s_iter, &f_iter);
1035  LEAVE(" ");
1036  return TRUE;
1037 }
1038 
1039 gint
1041  Account *account)
1042 {
1043  GtkTreeModel *s_model;
1044  GtkTreeIter s_iter;
1045  gint num_children;
1046 
1047  ENTER("view %p, account %p (%s)", view, account, xaccAccountGetName(account));
1048 
1049  if (account == NULL)
1050  {
1051  LEAVE("no account");
1052  return 0;
1053  }
1054 
1055  if (!gnc_tree_view_account_get_iter_from_account (view, account, &s_iter))
1056  {
1057  LEAVE("view_get_iter_from_account failed");
1058  return 0;
1059  }
1060 
1061  /* Any children? */
1062  s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
1063  num_children = gtk_tree_model_iter_n_children(s_model, &s_iter);
1064  LEAVE("%d children", num_children);
1065  return num_children;
1066 }
1067 
1068 
1069 /************************************************************/
1070 /* Account Tree View Filter Functions */
1071 /************************************************************/
1072 
1073 /*
1074  * Get a copy of the account view info structure in use by the
1075  * specified tree.
1076  */
1077 void
1079  AccountViewInfo *avi)
1080 {
1082 
1083  g_return_if_fail(GNC_IS_TREE_VIEW_ACCOUNT(account_view));
1084  g_return_if_fail(avi != NULL);
1085 
1086  priv = GNC_TREE_VIEW_ACCOUNT_GET_PRIVATE(account_view);
1087 
1088  *avi = priv->avi;
1089 }
1090 
1091 /*
1092  * Set the account view info data in use by the specified tree to
1093  * match the callers request.
1094  *
1095  * DRH - COMPATABILITY WARNING
1096  *
1097  * This function does not do anything with the 'include_type' field.
1098  * Should there be a automatic filter for backward compatability
1099  * that uses these flags, or should all uses of this be converted to
1100  * a GtkTreeModelFilter?
1101  *
1102  * CAS - For now, I'll try the automatic filter approach by making
1103  * this function use GtkTreeModelFilter.
1104  */
1105 void
1107  AccountViewInfo *avi)
1108 {
1110  gint i;
1111  guint sel_bits = 0;
1112 
1113  ENTER("%p", account_view);
1114  g_return_if_fail(GNC_IS_TREE_VIEW_ACCOUNT(account_view));
1115  g_return_if_fail(avi != NULL);
1116 
1117  priv = GNC_TREE_VIEW_ACCOUNT_GET_PRIVATE(account_view);
1118  priv->avi = *avi;
1119 
1120  for (i = 0; i < NUM_ACCOUNT_TYPES; i++)
1121  {
1122  sel_bits |= avi->include_type[i] ? (1 << i) : 0;
1123  }
1124 
1126  account_view, gnc_tree_view_account_filter_by_view_info,
1127  &priv->avi, NULL);
1128 
1129  LEAVE(" ");
1130 }
1131 
1132 static gboolean
1133 gnc_tree_view_account_filter_helper (GtkTreeModel *model,
1134  GtkTreeIter *iter,
1135  gpointer data)
1136 {
1137  Account *account;
1138  GncTreeViewAccount *view = data;
1140 
1141  g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (model), FALSE);
1142  g_return_val_if_fail (iter != NULL, FALSE);
1143 
1145  GNC_TREE_MODEL_ACCOUNT(model), iter);
1146 
1147  priv = GNC_TREE_VIEW_ACCOUNT_GET_PRIVATE(view);
1148  if (priv->filter_fn)
1149  return priv->filter_fn(account, priv->filter_data);
1150  else return TRUE;
1151 }
1152 
1153 /*
1154  * Set an GtkTreeModel visible filter on this account. This filter will be
1155  * called for each account that the tree is about to show, and the
1156  * account will be passed to the callback function.
1157  *
1158  * Use NULL as func to remove filter.
1159  */
1160 void
1163  gpointer data,
1164  GSourceFunc destroy)
1165 {
1167 
1168  ENTER("view %p, filter func %p, data %p, destroy %p",
1169  view, func, data, destroy);
1170 
1171  g_return_if_fail(GNC_IS_TREE_VIEW_ACCOUNT(view));
1172 
1173  priv = GNC_TREE_VIEW_ACCOUNT_GET_PRIVATE(view);
1174  if (priv->filter_destroy)
1175  {
1176  priv->filter_destroy(priv->filter_data);
1177  }
1178  priv->filter_destroy = destroy;
1179  priv->filter_data = data;
1180  priv->filter_fn = func;
1181 
1183  LEAVE(" ");
1184 }
1185 
1186 /*
1187  * Forces the entire account tree to be re-evaluated for visibility.
1188  */
1189 void
1191 {
1192  GtkTreeModel *f_model, *s_model;
1193 
1194  g_return_if_fail(GNC_IS_TREE_VIEW_ACCOUNT(view));
1195 
1196  s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
1197  f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
1198  gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (f_model));
1199 }
1200 
1201 gboolean
1202 gnc_tree_view_account_filter_by_view_info(Account* acct, gpointer data)
1203 {
1204  GNCAccountType acct_type;
1205  AccountViewInfo* avi = (AccountViewInfo*)data;
1206 
1207  g_return_val_if_fail(GNC_IS_ACCOUNT(acct), FALSE);
1208  acct_type = xaccAccountGetType(acct);
1209 
1210  if (!avi->include_type[acct_type]) return FALSE;
1211  if (!avi->show_hidden && xaccAccountIsHidden(acct)) return FALSE;
1212  return TRUE;
1213 }
1214 
1215 /************************************************************/
1216 /* Account Tree View Get/Set Functions */
1217 /************************************************************/
1218 
1219 /*
1220  * Retrieve the selected account from an account tree view. The
1221  * account tree must be in single selection mode.
1222  */
1223 Account *
1225  GtkTreePath *s_path)
1226 {
1227  GtkTreeModel *model, *f_model, *s_model;
1228  GtkTreePath *path, *f_path;
1229  GtkTreeIter iter;
1230  Account *account;
1231 
1232  ENTER("view %p", view);
1233  g_return_val_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (view), NULL);
1234  g_return_val_if_fail (s_path != NULL, NULL);
1235 
1236  s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
1237  f_path = gtk_tree_model_sort_convert_path_to_child_path (
1238  GTK_TREE_MODEL_SORT (s_model), s_path);
1239  if (!f_path)
1240  {
1241  LEAVE("no filter path");
1242  return NULL;
1243  }
1244 
1245  f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
1246  path = gtk_tree_model_filter_convert_path_to_child_path (
1247  GTK_TREE_MODEL_FILTER (f_model), f_path);
1248  gtk_tree_path_free(f_path);
1249  if (!path)
1250  {
1251  LEAVE("no path");
1252  return NULL;
1253  }
1254 
1255  model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
1256  if (!gtk_tree_model_get_iter (model, &iter, path))
1257  {
1258  LEAVE("no iter");
1259  return NULL;
1260  }
1261 
1262  account = iter.user_data;
1263  gtk_tree_path_free(path);
1264  LEAVE("account %p (%s)", account, xaccAccountGetName (account));
1265  return account;
1266 }
1267 
1268 
1269 Account *
1271  GtkTreeIter *s_iter)
1272 {
1273  GtkTreeModel *model, *f_model;
1274  GtkTreeIter iter, f_iter;
1275  Account *account;
1276 
1277  g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT(s_model), NULL);
1278  g_return_val_if_fail (s_iter != NULL, NULL);
1279 
1280  ENTER("model %p, iter %p", s_model, s_iter);
1281 
1282  gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT(s_model),
1283  &f_iter,
1284  s_iter);
1285  f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
1286  gtk_tree_model_filter_convert_iter_to_child_iter (
1287  GTK_TREE_MODEL_FILTER(f_model), &iter, &f_iter);
1288  model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
1290  GNC_TREE_MODEL_ACCOUNT(model), &iter);
1291  LEAVE("account %p (%s)", account, xaccAccountGetName (account));
1292  return account;
1293 }
1294 
1295 
1296 /*
1297  * Retrieve the selected account from an account tree view. The
1298  * account tree must be in single selection mode.
1299  */
1300 Account *
1302 {
1303  GtkTreeSelection *selection;
1304  GtkTreeModel *f_model, *s_model;
1305  GtkTreeIter iter, f_iter, s_iter;
1306  Account *account;
1307  GtkSelectionMode mode;
1308 
1309  ENTER("view %p", view);
1310  g_return_val_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (view), NULL);
1311 
1312  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(view));
1313  mode = gtk_tree_selection_get_mode(selection);
1314  if ((mode != GTK_SELECTION_SINGLE) && (mode != GTK_SELECTION_BROWSE))
1315  {
1316  return NULL;
1317  }
1318  if (!gtk_tree_selection_get_selected (selection, &s_model, &s_iter))
1319  {
1320  LEAVE("no account, get_selected failed");
1321  return FALSE;
1322  }
1323 
1324  gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (s_model),
1325  &f_iter, &s_iter);
1326 
1327  f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
1328  gtk_tree_model_filter_convert_iter_to_child_iter (
1329  GTK_TREE_MODEL_FILTER (f_model), &iter, &f_iter);
1330 
1331  account = iter.user_data;
1332  LEAVE("account %p (%s)", account, xaccAccountGetName (account));
1333  return account;
1334 }
1335 
1336 /*
1337  * Selects a single account in the account tree view. The account
1338  * tree must be in single selection mode.
1339  */
1340 void
1342  Account *account)
1343 {
1344  GtkTreeModel *model, *f_model, *s_model;
1345  GtkTreePath *path, *f_path, *s_path, *parent_path;
1346  GtkTreeSelection *selection;
1347 
1348  ENTER("view %p, account %p (%s)", view,
1349  account, xaccAccountGetName (account));
1350  g_return_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (view));
1351 
1352  /* Clear any existing selection. */
1353  selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
1354  gtk_tree_selection_unselect_all (selection);
1355 
1356  if (account == NULL)
1357  return;
1358 
1359  s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
1360  f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
1361  model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
1362 
1364  GNC_TREE_MODEL_ACCOUNT(model), account);
1365  if (path == NULL)
1366  {
1367  LEAVE("no path");
1368  return;
1369  }
1370  debug_path(DEBUG, path);
1371 
1372  f_path = gtk_tree_model_filter_convert_child_path_to_path (
1373  GTK_TREE_MODEL_FILTER (f_model), path);
1374  gtk_tree_path_free(path);
1375  if (f_path == NULL)
1376  {
1377  LEAVE("no filter path");
1378  return;
1379  }
1380  debug_path(DEBUG, f_path);
1381 
1382  s_path = gtk_tree_model_sort_convert_child_path_to_path (GTK_TREE_MODEL_SORT (s_model),
1383  f_path);
1384  gtk_tree_path_free(f_path);
1385  if (s_path == NULL)
1386  {
1387  LEAVE("no sort path");
1388  return;
1389  }
1390 
1391  /* gtk_tree_view requires that a row be visible before it can be selected */
1392  parent_path = gtk_tree_path_copy (s_path);
1393  if (gtk_tree_path_up (parent_path))
1394  {
1395  /* This function is misnamed. It expands the actual item
1396  * specified, not the path to the item specified. I.E. It expands
1397  * one level too many, thus the get of the parent. */
1398  gtk_tree_view_expand_to_path(GTK_TREE_VIEW(view), parent_path);
1399  }
1400  gtk_tree_path_free(parent_path);
1401 
1402  gtk_tree_selection_select_path (selection, s_path);
1403 
1404  /* give gtk+ a chance to resize the tree view first by handling pending
1405  * configure events */
1406  while (gtk_events_pending ())
1407  gtk_main_iteration ();
1408  gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW(view), s_path, NULL, FALSE, 0.0, 0.0);
1409  debug_path(LEAVE, s_path);
1410  gtk_tree_path_free(s_path);
1411 }
1412 
1413 /* Information re selection process */
1414 typedef struct
1415 {
1416  GList* return_list;
1419 
1420 /*
1421  * This helper function is called once for each row in the tree view
1422  * that is currently selected. Its task is to append the corresponding
1423  * account to the end of a glist.
1424  */
1425 static void
1426 get_selected_accounts_helper (GtkTreeModel *s_model,
1427  GtkTreePath *s_path,
1428  GtkTreeIter *s_iter,
1429  gpointer data)
1430 {
1431  GncTreeViewSelectionInfo *gtvsi = data;
1432  GtkTreeModel *f_model;
1433  GtkTreeIter iter, f_iter;
1434  Account *account;
1435 
1436  gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (s_model),
1437  &f_iter, s_iter);
1438 
1439  f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
1440  gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (f_model),
1441  &iter, &f_iter);
1442  account = iter.user_data;
1443 
1444  /* Only selected if it passes the filter */
1445  if (gtvsi->priv->filter_fn == NULL || gtvsi->priv->filter_fn(account, gtvsi->priv->filter_data))
1446  {
1447  gtvsi->return_list = g_list_append(gtvsi->return_list, account);
1448  }
1449 }
1450 
1451 /*
1452  * Given an account tree view, return a list of the selected accounts. The
1453  * account tree must be in multiple selection mode.
1454  *
1455  * Note: It is the responsibility of the caller to free the returned
1456  * list.
1457  */
1458 GList *
1460 {
1461  GtkTreeSelection *selection;
1463 
1464  g_return_val_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (view), NULL);
1465 
1466  info.return_list = NULL;
1467  info.priv = GNC_TREE_VIEW_ACCOUNT_GET_PRIVATE(view);
1468  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(view));
1469  gtk_tree_selection_selected_foreach(selection, get_selected_accounts_helper, &info);
1470  return info.return_list;
1471 }
1472 
1473 /*
1474  * Given an account tree view and a list of accounts, select those
1475  * accounts in the tree view.
1476  */
1477 void
1479  GList *account_list,
1480  gboolean show_last)
1481 {
1482  GtkTreeModel *model, *f_model, *s_model;
1483  GtkTreePath *path, *f_path, *s_path, *parent_path;
1484  GtkTreeSelection *selection;
1485  GList *element;
1486  Account *account;
1487 
1488  g_return_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (view));
1489 
1490  s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
1491  f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
1492  model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
1493 
1494  /* Clear any existing selection. */
1495  selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
1496  gtk_tree_selection_unselect_all (selection);
1497  gtk_tree_view_collapse_all (GTK_TREE_VIEW(view));
1498 
1499  /* Now go select what the user requested. */
1500  for (element = account_list; element; )
1501  {
1502  account = element->data;
1503  element = g_list_next(element);
1504 
1505  if (account == NULL)
1506  {
1507  /*
1508  * Oops. Someone must have deleted this account and not cleaned
1509  * up all references to it.
1510  */
1511  continue;
1512  }
1513 
1514  path = gnc_tree_model_account_get_path_from_account (GNC_TREE_MODEL_ACCOUNT(model), account);
1515  if (path == NULL)
1516  {
1517  /*
1518  * Oops. Someone must have deleted this account and not cleaned
1519  * up all references to it.
1520  */
1521  continue;
1522  }
1523 
1524  f_path = gtk_tree_model_filter_convert_child_path_to_path (GTK_TREE_MODEL_FILTER (f_model),
1525  path);
1526  gtk_tree_path_free(path);
1527  if (f_path == NULL)
1528  continue;
1529 
1530  s_path = gtk_tree_model_sort_convert_child_path_to_path (GTK_TREE_MODEL_SORT (s_model),
1531  f_path);
1532  gtk_tree_path_free(f_path);
1533  if (s_path == NULL)
1534  continue;
1535 
1536  /* gtk_tree_view requires that a row be visible before it can be selected */
1537  parent_path = gtk_tree_path_copy (s_path);
1538  if (gtk_tree_path_up (parent_path))
1539  {
1540  /* This function is misnamed. It expands the actual item
1541  * specified, not the path to the item specified. I.E. It
1542  * expands one level too many, thus the get of the parent. */
1543  gtk_tree_view_expand_to_path(GTK_TREE_VIEW(view), parent_path);
1544  }
1545  gtk_tree_path_free(parent_path);
1546 
1547  gtk_tree_selection_select_path (selection, s_path);
1548  if (show_last && (element == NULL))
1549  gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW(view), s_path, NULL, FALSE, 0.0, 0.0);
1550  gtk_tree_path_free(s_path);
1551  }
1552 }
1553 
1554 /*
1555  * Selects all sub-accounts of an acccount.
1556  */
1557 void
1559  Account *account)
1560 {
1561  GtkTreeModel *s_model;
1562  GtkTreeSelection *selection;
1563  GtkTreePath *sp_account, *sp_start, *sp_end;
1564  GtkTreeIter si_account, si_start, si_end;
1565  gboolean have_start, have_end;
1566  gint num_children;
1567 
1568  ENTER("view %p, account %p (%s)", view, account, xaccAccountGetName(account));
1569 
1570  g_return_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (view));
1571 
1572  if (account == NULL)
1573  {
1574  LEAVE("no account");
1575  return;
1576  }
1577 
1578  if (!gnc_tree_view_account_get_iter_from_account (view, account, &si_account))
1579  {
1580  LEAVE("view_get_iter_from_account failed");
1581  return;
1582  }
1583 
1584  /* Any children? */
1585  s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
1586  num_children = gtk_tree_model_iter_n_children(s_model, &si_account);
1587  if (num_children == 0)
1588  {
1589  LEAVE("no children");
1590  return;
1591  }
1592 
1593  /* Expand the tree. Required for selection to work */
1594  sp_account = gtk_tree_model_get_path (s_model, &si_account);
1595  gtk_tree_view_expand_row (GTK_TREE_VIEW(view), sp_account, TRUE);
1596 
1597  /* compute start/end paths */
1598  have_start = gtk_tree_model_iter_nth_child(s_model, &si_start, &si_account, 0);
1599  si_end = si_account;
1600  while (num_children)
1601  {
1602  GtkTreeIter tmp_iter = si_end;
1603  have_end = gtk_tree_model_iter_nth_child(s_model, &si_end, &tmp_iter,
1604  num_children - 1);
1605  if (have_end)
1606  num_children = gtk_tree_model_iter_n_children(s_model, &si_end);
1607  else
1608  num_children = 0;
1609  }
1610 
1611  if (have_start && have_end)
1612  {
1613  sp_start = gtk_tree_model_get_path (s_model, &si_start);
1614  sp_end = gtk_tree_model_get_path (s_model, &si_end);
1615 
1616  /* select everything between */
1617  selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
1618  gtk_tree_selection_select_range (selection, sp_start, sp_end);
1619 
1620  /* clean up */
1621  gtk_tree_path_free(sp_start);
1622  gtk_tree_path_free(sp_end);
1623  }
1624  gtk_tree_path_free(sp_account);
1625  LEAVE(" ");
1626  return;
1627 }
1628 
1629 void
1631  Account *account)
1632 {
1633  GtkTreePath *path;
1634 
1635  g_return_if_fail(view != NULL);
1636  g_return_if_fail(GNC_IS_TREE_VIEW_ACCOUNT(view));
1637  ENTER("view %p, account %p", view, account);
1638 
1639  path = gnc_tree_view_account_get_path_from_account(view, account);
1640  if (path)
1641  {
1642  gtk_tree_view_expand_to_path(GTK_TREE_VIEW(view), path);
1643  gtk_tree_path_free(path);
1644  }
1645  LEAVE(" ");
1646 }
1647 
1648 
1649 /*
1650  * Retrieve the account currently under the cursor.
1651  */
1652 Account *
1654 {
1655  GtkTreePath *s_path;
1656  Account *account;
1657 
1658  ENTER("view %p", view);
1659  g_return_val_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (view), NULL);
1660 
1661  gtk_tree_view_get_cursor (GTK_TREE_VIEW(view), &s_path, NULL);
1662  if (!s_path)
1663  {
1664  LEAVE("no account");
1665  return NULL;
1666  }
1667 
1668  account = gnc_tree_view_account_get_account_from_path (view, s_path);
1669  gtk_tree_path_free(s_path);
1670  LEAVE("account %p (%s)", account, xaccAccountGetName (account));
1671  return account;
1672 }
1673 
1674 
1675 /************************************************************/
1676 /* Account Tree View Add Column Functions */
1677 /************************************************************/
1678 
1679 static void
1680 gtva_update_column_name (GtkTreeViewColumn *column,
1681  const gchar *fmt,
1682  const gchar *mnemonic)
1683 {
1684  gchar *name;
1685 
1686  g_return_if_fail(column);
1687 
1688  name = g_strdup_printf(fmt, mnemonic);
1689  gtk_tree_view_column_set_title(column, name);
1690  g_free(name);
1691 }
1692 
1693 
1694 static void
1695 gtva_update_column_names (GncTreeView *view)
1696 {
1698  const gchar *mnemonic;
1699 
1700  priv = GNC_TREE_VIEW_ACCOUNT_GET_PRIVATE(view);
1702 
1703  gtva_update_column_name(priv->present_report_column,
1704  /* Translators: %s is a currency mnemonic.*/
1705  _("Present (%s)"), mnemonic);
1706  gtva_update_column_name(priv->balance_report_column,
1707  /* Translators: %s is a currency mnemonic.*/
1708  _("Balance (%s)"), mnemonic);
1709  gtva_update_column_name(priv->cleared_report_column,
1710  /* Translators: %s is a currency mnemonic.*/
1711  _("Cleared (%s)"), mnemonic);
1712  gtva_update_column_name(priv->reconciled_report_column,
1713  /* Translators: %s is a currency mnemonic.*/
1714  _("Reconciled (%s)"), mnemonic);
1715  gtva_update_column_name(priv->future_min_report_column,
1716  /* Translators: %s is a currency mnemonic.*/
1717  _("Future Minimum (%s)"), mnemonic);
1718  gtva_update_column_name(priv->total_report_column,
1719  /* Translators: %s is a currency mnemonic.*/
1720  _("Total (%s)"), mnemonic);
1723 }
1724 
1725 
1726 static void
1727 gtva_currency_changed_cb (void)
1728 {
1729  const GList *views, *ptr;
1730 
1731  views = gnc_gobject_tracking_get_list (GNC_TREE_VIEW_ACCOUNT_NAME);
1732  for (ptr = views; ptr; ptr = g_list_next(ptr))
1733  {
1734  gtva_update_column_names (ptr->data);
1735  }
1736 }
1737 /* Retrieve a specified account string property and put the result
1738  * into the tree column's text property.
1739  */
1740 static void
1741 account_cell_property_data_func (GtkTreeViewColumn *tree_column,
1742  GtkCellRenderer *cell,
1743  GtkTreeModel *s_model,
1744  GtkTreeIter *s_iter,
1745  gpointer key)
1746 {
1747  Account *account;
1748  gchar *string = NULL;
1749 
1750  g_return_if_fail (GTK_IS_TREE_MODEL_SORT (s_model));
1751  account = gnc_tree_view_account_get_account_from_iter(s_model, s_iter);
1752  qof_instance_get (QOF_INSTANCE (account),
1753  key, &string,
1754  NULL);
1755  if (string == NULL)
1756  string = "";
1757 
1758  g_object_set (G_OBJECT (cell), "text", string, "xalign", 0.0, NULL);
1759 }
1760 
1761 
1762 GtkTreeViewColumn *
1764  const gchar *column_title,
1765  const gchar *propname)
1766 {
1767  GtkCellRenderer *renderer;
1768  GtkTreeViewColumn *column;
1769 
1770  g_return_val_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (view), NULL);
1771  g_return_val_if_fail (propname != NULL, NULL);
1772 
1773  column = gnc_tree_view_add_text_column(GNC_TREE_VIEW(view), column_title,
1774  propname, NULL, "Sample text",
1775  -1, -1, NULL);
1776 
1777  /* This new kvp column has only had one renderer added to it so
1778  * far. Find that renderer. */
1779  renderer = gnc_tree_view_column_get_renderer(column);
1780  g_object_set (G_OBJECT (renderer), "xalign", 1.0, NULL);
1781 
1782  gtk_tree_view_column_set_cell_data_func (column, renderer,
1783  account_cell_property_data_func,
1784  g_strdup(propname), g_free);
1785  return column;
1786 }
1787 
1788 static void col_edited_helper(GtkCellRendererText *cell, gchar *path_string,
1789  gchar *new_text, gpointer _s_model)
1790 {
1791  Account *account;
1792  GtkTreeModel *s_model;
1793  GtkTreeIter s_iter;
1794  GncTreeViewAccountColumnTextEdited col_edited_cb;
1795  GtkTreeViewColumn *col;
1796 
1797  col_edited_cb = g_object_get_data(G_OBJECT(cell),
1798  "column_edited_callback");
1799  col = GTK_TREE_VIEW_COLUMN(g_object_get_data(G_OBJECT(cell),
1800  "column_view"));
1801  s_model = GTK_TREE_MODEL(_s_model);
1802 
1803  if (!gtk_tree_model_get_iter_from_string(s_model, &s_iter, path_string))
1804  return;
1805 
1806  account = gnc_tree_view_account_get_account_from_iter(s_model, &s_iter);
1807  col_edited_cb(account, col, new_text);
1808 }
1809 
1810 static void col_source_helper(GtkTreeViewColumn *col, GtkCellRenderer *cell,
1811  GtkTreeModel *s_model, GtkTreeIter *s_iter,
1812  gpointer _col_source_cb)
1813 {
1814  Account *account;
1815  gchar *text;
1816  GncTreeViewAccountColumnSource col_source_cb;
1817 
1818  g_return_if_fail (GTK_IS_TREE_MODEL_SORT (s_model));
1819  col_source_cb = (GncTreeViewAccountColumnSource) _col_source_cb;
1820  account = gnc_tree_view_account_get_account_from_iter(s_model, s_iter);
1821  text = col_source_cb(account, col, cell);
1822  g_object_set (G_OBJECT (cell), "text", text, "xalign", 1.0, NULL);
1823  g_free(text);
1824 }
1825 
1830 void
1831 gtva_setup_column_renderer_edited_cb(GncTreeViewAccount *account_view,
1832  GtkTreeViewColumn *column,
1833  GtkCellRenderer *renderer,
1834  GncTreeViewAccountColumnTextEdited col_edited_cb)
1835 {
1836  GtkTreeModel *s_model;
1837 
1838  if (col_edited_cb == NULL)
1839  {
1840  g_object_set(G_OBJECT(renderer), "editable", FALSE, NULL);
1841  g_object_set_data(G_OBJECT(renderer), "column_edited_callback", col_edited_cb);
1842  s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(account_view));
1843  g_signal_handlers_disconnect_by_func(G_OBJECT(renderer), col_edited_cb, s_model);
1844  g_object_set_data(G_OBJECT(renderer), "column_view", column);
1845  }
1846  else
1847  {
1848  g_object_set(G_OBJECT(renderer), "editable", TRUE, NULL);
1849  g_object_set_data(G_OBJECT(renderer), "column_edited_callback",
1850  col_edited_cb);
1851  s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(account_view));
1852  g_signal_connect(G_OBJECT(renderer), "edited",
1853  (GCallback) col_edited_helper, s_model);
1854  g_object_set_data(G_OBJECT(renderer), "column_view", column);
1855  }
1856 }
1857 
1858 GtkTreeViewColumn *
1860  const gchar *column_title,
1861  GncTreeViewAccountColumnSource
1862  col_source_cb,
1863  GncTreeViewAccountColumnTextEdited
1864  col_edited_cb)
1865 {
1866  GtkCellRenderer *renderer;
1867  GtkTreeViewColumn *column;
1868 
1869  g_return_val_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (account_view), NULL);
1870 
1871  renderer = gtk_cell_renderer_text_new ();
1872  g_object_set (G_OBJECT (renderer), "xalign", 1.0, NULL);
1873 
1874  column = gtk_tree_view_column_new_with_attributes (column_title,
1875  renderer, NULL);
1876  if (col_edited_cb)
1877  {
1878  gtva_setup_column_renderer_edited_cb(account_view, column,
1879  renderer, col_edited_cb);
1880  }
1881  gtk_tree_view_column_set_cell_data_func (column, renderer,
1882  col_source_helper,
1883  col_source_cb, NULL);
1884  gnc_tree_view_append_column (GNC_TREE_VIEW(account_view), column);
1885  return column;
1886 }
1887 
1888 
1889 /* BEGIN FILTER FUNCTIONS */
1890 #define FILTER_TREE_VIEW "types_tree_view"
1891 
1903 gboolean
1905  gpointer user_data)
1906 {
1907  AccountFilterDialog *fd = user_data;
1908  GNCAccountType acct_type;
1909  gnc_numeric total;
1910  gboolean result;
1911 
1912  ENTER("account %p:%s", account, xaccAccountGetName(account));
1913 
1914  if (!fd->show_hidden && xaccAccountIsHidden (account))
1915  {
1916  LEAVE(" hide: hidden");
1917  return FALSE;
1918  }
1919 
1920  if (!fd->show_zero_total)
1921  {
1922  total = xaccAccountGetBalanceInCurrency (account, NULL, TRUE);
1923  if (gnc_numeric_zero_p(total))
1924  {
1925  LEAVE(" hide: zero balance");
1926  return FALSE;
1927  }
1928  }
1929 
1930  if (!fd->show_unused)
1931  {
1932  if (xaccAccountCountSplits(account, TRUE) == 0)
1933  {
1934  LEAVE(" hide: unused");
1935  return FALSE;
1936  }
1937  }
1938 
1939  acct_type = xaccAccountGetType(account);
1940  result = (fd->visible_types & (1 << acct_type)) ? TRUE : FALSE;
1941  LEAVE(" %s", result ? "show" : "hide");
1942  return result;
1943 }
1944 
1952 void
1953 gppat_filter_show_hidden_toggled_cb (GtkToggleButton *button,
1954  AccountFilterDialog *fd)
1955 {
1956  g_return_if_fail(GTK_IS_TOGGLE_BUTTON(button));
1957 
1958  ENTER("button %p", button);
1959  fd->show_hidden = gtk_toggle_button_get_active(button);
1960  gnc_tree_view_account_refilter(fd->tree_view);
1961  LEAVE("show_hidden %d", fd->show_hidden);
1962 }
1963 
1971 void
1972 gppat_filter_show_zero_toggled_cb (GtkToggleButton *button,
1973  AccountFilterDialog *fd)
1974 {
1975  g_return_if_fail(GTK_IS_TOGGLE_BUTTON(button));
1976 
1977  ENTER("button %p", button);
1978  fd->show_zero_total = gtk_toggle_button_get_active(button);
1979  gnc_tree_view_account_refilter(fd->tree_view);
1980  LEAVE("show_zero %d", fd->show_zero_total);
1981 }
1982 
1990 void
1991 gppat_filter_show_unused_toggled_cb (GtkToggleButton *button,
1992  AccountFilterDialog *fd)
1993 {
1994  g_return_if_fail(GTK_IS_TOGGLE_BUTTON(button));
1995 
1996  ENTER("button %p", button);
1997  fd->show_unused = gtk_toggle_button_get_active(button);
1998  gnc_tree_view_account_refilter(fd->tree_view);
1999  LEAVE("show_unused %d", fd->show_unused);
2000 }
2001 
2010 void
2011 gppat_filter_clear_all_cb (GtkWidget *button,
2012  AccountFilterDialog *fd)
2013 {
2014  g_return_if_fail(GTK_IS_BUTTON(button));
2015 
2016  ENTER("button %p", button);
2017  fd->visible_types = 0;
2018  gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(fd->model));
2019  gnc_tree_view_account_refilter(fd->tree_view);
2020  LEAVE("types 0x%x", fd->visible_types);
2021 }
2022 
2029 void
2030 gppat_filter_select_all_cb (GtkWidget *button,
2031  AccountFilterDialog *fd)
2032 {
2033  g_return_if_fail(GTK_IS_BUTTON(button));
2034 
2035  ENTER("button %p", button);
2036  fd->visible_types = -1;
2037  gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(fd->model));
2038  gnc_tree_view_account_refilter(fd->tree_view);
2039  LEAVE("types 0x%x", fd->visible_types);
2040 }
2041 
2049 void
2051  AccountFilterDialog *fd)
2052 {
2053  ENTER("button %p", button);
2054  gppat_filter_select_all_cb(button, fd);
2055  LEAVE(" ");
2056 }
2057 
2069 static void
2070 gppat_filter_visible_set_func (GtkTreeViewColumn *column,
2071  GtkCellRenderer *renderer,
2072  GtkTreeModel *model,
2073  GtkTreeIter *iter,
2074  gpointer data)
2075 {
2076  AccountFilterDialog *fd = data;
2077  GNCAccountType type;
2078  gboolean active;
2079 
2080  gtk_tree_model_get(model, iter, GNC_TREE_MODEL_ACCOUNT_TYPES_COL_TYPE, &type, -1);
2081 
2082  active = (fd->visible_types & (1 << type)) ? TRUE : FALSE;
2083  g_object_set (G_OBJECT (renderer), "active", active, NULL);
2084 }
2085 
2091 static void
2092 gppat_filter_visible_toggled_cb (GtkCellRendererToggle *renderer,
2093  gchar *path_str,
2094  AccountFilterDialog *fd)
2095 {
2096  GtkTreeModel *model = fd->model;
2097  GtkTreeIter iter;
2098  GtkTreePath *path;
2099  GNCAccountType type;
2100 
2101  ENTER("toggled %p", path_str);
2102  path = gtk_tree_path_new_from_string(path_str);
2103 
2104  if (gtk_tree_model_get_iter(model, &iter, path))
2105  {
2106  gtk_tree_model_get(model, &iter, GNC_TREE_MODEL_ACCOUNT_TYPES_COL_TYPE, &type, -1);
2107  fd->visible_types ^= (1 << type);
2108  gnc_tree_view_account_refilter(fd->tree_view);
2109  }
2110  gtk_tree_path_free(path);
2111  LEAVE("types 0x%x", fd->visible_types);
2112 }
2113 
2124 void
2125 gppat_filter_response_cb (GtkWidget *dialog,
2126  gint response,
2127  AccountFilterDialog *fd)
2128 {
2129  gpointer gptemp;
2130 
2131  g_return_if_fail(GTK_IS_DIALOG(dialog));
2132 
2133  ENTER("dialog %p, response %d", dialog, response);
2134 
2135  if (response != GTK_RESPONSE_OK)
2136  {
2137  fd->visible_types = fd->original_visible_types;
2138  fd->show_hidden = fd->original_show_hidden;
2139  fd->show_zero_total = fd->original_show_zero_total;
2140  fd->show_unused = fd->original_show_unused;
2141  gnc_tree_view_account_refilter(fd->tree_view);
2142  }
2143 
2144  /* Clean up and delete dialog */
2145  gptemp = (gpointer *)fd->dialog;
2146  g_atomic_pointer_compare_and_exchange(&gptemp,
2147  dialog, NULL);
2148  fd->dialog = gptemp;
2149  gtk_widget_destroy(dialog);
2150  LEAVE("types 0x%x", fd->visible_types);
2151 }
2152 
2153 void
2154 account_filter_dialog_create(AccountFilterDialog *fd, GncPluginPage *page)
2155 {
2156  GtkWidget *dialog, *button;
2157  GtkTreeView *view;
2158  GtkCellRenderer *renderer;
2159  GtkBuilder *builder;
2160  gchar *title;
2161 
2162  ENTER("(fd %p, page %p)", fd, page);
2163 
2164  if (fd->dialog)
2165  {
2166  gtk_window_present(GTK_WINDOW(fd->dialog));
2167  LEAVE("existing dialog");
2168  return;
2169  }
2170 
2171  /* Create the dialog */
2172  builder = gtk_builder_new();
2173  gnc_builder_add_from_file (builder, "dialog-account.glade", "Filter By");
2174  dialog = GTK_WIDGET(gtk_builder_get_object (builder, "Filter By"));
2175  fd->dialog = dialog;
2176  gtk_window_set_transient_for(GTK_WINDOW(dialog),
2177  GTK_WINDOW(GNC_PLUGIN_PAGE(page)->window));
2178  /* Translators: The %s is the name of the plugin page */
2179  title = g_strdup_printf(_("Filter %s by..."),
2180  gnc_plugin_page_get_page_name(GNC_PLUGIN_PAGE(page)));
2181  gtk_window_set_title(GTK_WINDOW(dialog), title);
2182  g_free(title);
2183 
2184  /* Remember current state */
2185  fd->original_visible_types = fd->visible_types;
2186  fd->original_show_hidden = fd->show_hidden;
2187  fd->original_show_zero_total = fd->show_zero_total;
2188  fd->original_show_unused = fd->show_unused;
2189 
2190  /* Update the dialog widgets for the current state */
2191  button = GTK_WIDGET(gtk_builder_get_object (builder, "show_hidden"));
2192  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
2193  fd->show_hidden);
2194  button = GTK_WIDGET(gtk_builder_get_object (builder, "show_zero"));
2195  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
2196  fd->show_zero_total);
2197  button = GTK_WIDGET(gtk_builder_get_object (builder, "show_unused"));
2198  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
2199  fd->show_unused);
2200 
2201  /* Set up the tree view and model */
2202  view = GTK_TREE_VIEW(gtk_builder_get_object (builder, FILTER_TREE_VIEW));
2203 
2204  fd->model = gnc_tree_model_account_types_filter_using_mask
2205  (~(1 << ACCT_TYPE_ROOT));
2206  gtk_tree_view_set_model(view, fd->model);
2207  g_object_unref (fd->model);
2208 
2209  renderer = gtk_cell_renderer_toggle_new();
2210 
2211  g_signal_connect(renderer, "toggled",
2212  G_CALLBACK(gppat_filter_visible_toggled_cb), fd);
2213 
2214  gtk_tree_view_insert_column_with_data_func
2215  (view,
2216  -1, NULL, renderer,
2217  gppat_filter_visible_set_func, fd, NULL);
2218 
2219  gtk_tree_view_insert_column_with_attributes
2220  (view,
2221  -1, _("Account Types"), gtk_cell_renderer_text_new(),
2222  "text", GNC_TREE_MODEL_ACCOUNT_TYPES_COL_NAME, NULL);
2223 
2224  /* Wire up the rest of the callbacks */
2225  gtk_builder_connect_signals(builder, fd);
2226  g_object_unref(G_OBJECT(builder));
2227 
2228  /* Show it */
2229  gtk_widget_show_all(dialog);
2230  LEAVE(" ");
2231 }
2232 
2233 #define ACCT_COUNT "NumberOfOpenAccounts"
2234 #define ACCT_OPEN "OpenAccount%d"
2235 #define ACCT_SELECTED "SelectedAccount"
2236 #define SHOW_HIDDEN "ShowHidden"
2237 #define SHOW_ZERO "ShowZeroTotal"
2238 #define SHOW_UNUSED "ShowUnused"
2239 #define ACCT_TYPES "AccountTypes"
2240 
2241 typedef struct foo
2242 {
2243  GKeyFile *key_file;
2244  const gchar *group_name;
2245  int count;
2246 } bar_t;
2247 
2259 static void
2260 tree_save_expanded_row (GncTreeViewAccount *view,
2261  GtkTreePath *path,
2262  gpointer user_data)
2263 {
2264  Account *account;
2265  bar_t *bar = user_data;
2266  gchar *key;
2267  gchar *account_name;
2268 
2269  account = gnc_tree_view_account_get_account_from_path (view, path);
2270  if (account == NULL)
2271  return;
2272 
2273  account_name = gnc_account_get_full_name(account);
2274  if (account_name == NULL)
2275  return;
2276 
2277  key = g_strdup_printf(ACCT_OPEN, ++bar->count);
2278  g_key_file_set_string(bar->key_file, bar->group_name, key, account_name);
2279  g_free(key);
2280  g_free(account_name);
2281 }
2282 
2283 
2294 static void
2295 tree_save_selected_row (GncTreeViewAccount *view,
2296  gpointer user_data)
2297 {
2298  Account *account;
2299  bar_t *bar = user_data;
2300  gchar *account_name;
2301 
2303  if (account == NULL)
2304  return;
2305 
2306  account_name = gnc_account_get_full_name (account);
2307  if (account_name == NULL)
2308  return;
2309 
2310  g_key_file_set_string(bar->key_file, bar->group_name, ACCT_SELECTED,
2311  account_name);
2312  g_free(account_name);
2313 }
2314 
2315 void
2316 gnc_tree_view_account_save(GncTreeViewAccount *view,
2317  AccountFilterDialog *fd,
2318  GKeyFile *key_file, const gchar *group_name)
2319 {
2320  bar_t bar;
2321 
2322  g_return_if_fail (key_file != NULL);
2323  g_return_if_fail (group_name != NULL);
2324 
2325  ENTER("view %p, key_file %p, group_name %s", view, key_file,
2326  group_name);
2327 
2328  g_key_file_set_integer(key_file, group_name, ACCT_TYPES,
2329  fd->visible_types);
2330  g_key_file_set_boolean(key_file, group_name, SHOW_HIDDEN,
2331  fd->show_hidden);
2332  g_key_file_set_boolean(key_file, group_name, SHOW_ZERO,
2333  fd->show_zero_total);
2334  g_key_file_set_boolean(key_file, group_name, SHOW_UNUSED,
2335  fd->show_unused);
2336 
2337  bar.key_file = key_file;
2338  bar.group_name = group_name;
2339  bar.count = 0;
2340  tree_save_selected_row(view, &bar);
2341  gtk_tree_view_map_expanded_rows(
2342  GTK_TREE_VIEW(view), (GtkTreeViewMappingFunc) tree_save_expanded_row,
2343  &bar);
2344  g_key_file_set_integer(key_file, group_name, ACCT_COUNT, bar.count);
2345  LEAVE(" ");
2346 
2347 }
2348 
2356 static void
2357 tree_restore_expanded_row (GncTreeViewAccount *view,
2358  const gchar *account_name)
2359 {
2360  Account *account;
2361  QofBook *book;
2362 
2363  book = qof_session_get_book(gnc_get_current_session());
2364  account = gnc_account_lookup_by_full_name(gnc_book_get_root_account(book),
2365  account_name);
2366  if (account)
2368 }
2369 
2370 
2378 static void
2379 tree_restore_selected_row (GncTreeViewAccount *view,
2380  const gchar *account_name)
2381 {
2382  Account *account;
2383  QofBook *book;
2384 
2385  book = qof_session_get_book(gnc_get_current_session());
2386  account = gnc_account_lookup_by_full_name(gnc_book_get_root_account(book),
2387  account_name);
2388  if (account)
2390 }
2391 
2392 void
2393 gnc_tree_view_account_restore(GncTreeViewAccount *view,
2394  AccountFilterDialog *fd,
2395  GKeyFile *key_file, const gchar *group_name)
2396 {
2397  GError *error = NULL;
2398  gchar *key, *value;
2399  gint i, count;
2400  gboolean show;
2401 
2402  /* Filter information. Ignore missing keys. */
2403  show = g_key_file_get_boolean(key_file, group_name, SHOW_HIDDEN, &error);
2404  if (error)
2405  {
2406  g_warning("error reading group %s key %s: %s",
2407  group_name, SHOW_HIDDEN, error->message);
2408  g_error_free(error);
2409  error = NULL;
2410  show = TRUE;
2411  }
2412  fd->show_hidden = show;
2413 
2414  show = g_key_file_get_boolean(key_file, group_name, SHOW_ZERO, &error);
2415  if (error)
2416  {
2417  g_warning("error reading group %s key %s: %s",
2418  group_name, SHOW_ZERO, error->message);
2419  g_error_free(error);
2420  error = NULL;
2421  show = TRUE;
2422  }
2423  fd->show_zero_total = show;
2424 
2425  show = g_key_file_get_boolean(key_file, group_name, SHOW_UNUSED, &error);
2426  if (error)
2427  {
2428  g_warning("error reading group %s key %s: %s",
2429  group_name, SHOW_UNUSED, error->message);
2430  g_error_free(error);
2431  error = NULL;
2432  show = TRUE;
2433  }
2434  fd->show_unused = show;
2435 
2436  i = g_key_file_get_integer(key_file, group_name, ACCT_TYPES, &error);
2437  if (error)
2438  {
2439  g_warning("error reading group %s key %s: %s",
2440  group_name, ACCT_TYPES, error->message);
2441  g_error_free(error);
2442  error = NULL;
2443  i = -1;
2444  }
2445  fd->visible_types = i;
2446 
2447  /* Expanded accounts. Skip if count key missing. */
2448  count = g_key_file_get_integer(key_file, group_name, ACCT_COUNT, &error);
2449  if (error == NULL)
2450  {
2451  for (i = 1; i <= count; i++)
2452  {
2453  key = g_strdup_printf(ACCT_OPEN, i);
2454  value = g_key_file_get_string(key_file, group_name, key, &error);
2455  if (error)
2456  {
2457  g_warning("error reading group %s key %s: %s",
2458  group_name, key, error->message);
2459  g_error_free(error);
2460  error = NULL;
2461  }
2462  else
2463  {
2464  tree_restore_expanded_row(view, value);
2465  g_free(value);
2466  }
2467  g_free(key);
2468  }
2469  }
2470  else
2471  {
2472  g_warning("error reading group %s key %s: %s",
2473  group_name, ACCT_COUNT, error->message);
2474  g_error_free(error);
2475  }
2476 
2477  /* Selected account (if any) */
2478  value = g_key_file_get_string(key_file, group_name, ACCT_SELECTED, NULL);
2479  if (value)
2480  {
2481  tree_restore_selected_row(view, value);
2482  g_free(value);
2483  }
2484 
2485  /* Update tree view for any changes */
2487 }
2488 
2489 // @@fixme -- factor this app-not-gui-specific-logic out.
2490 void
2491 gnc_tree_view_account_name_edited_cb(Account *account, GtkTreeViewColumn *col, const gchar *new_name)
2492 {
2493  // check for accounts with the same name among our parent's children.
2494  // should probably factor this consistency check out to the account
2495  // itself....
2496  {
2497  Account *parent = gnc_account_get_parent(account);
2498  Account *existing = gnc_account_lookup_by_name(parent, new_name);
2499  if (existing != NULL && existing != account)
2500  {
2501  PERR("account with the same name [%s] already exists.", new_name);
2502  return;
2503  }
2504  }
2505  xaccAccountSetName(account, new_name);
2506 }
2507 
2508 void
2509 gnc_tree_view_account_code_edited_cb(Account *account, GtkTreeViewColumn *col, const gchar *new_code)
2510 {
2511  if (g_strcmp0(xaccAccountGetCode(account), new_code) == 0)
2512  return;
2513  xaccAccountSetCode(account, new_code);
2514 }
2515 
2516 void
2517 gnc_tree_view_account_description_edited_cb(Account *account, GtkTreeViewColumn *col, const gchar *new_desc)
2518 {
2519  if (g_strcmp0(xaccAccountGetDescription(account), new_desc) == 0)
2520  return;
2521  xaccAccountSetDescription(account, new_desc);
2522 }
2523 
2524 void
2525 gnc_tree_view_account_notes_edited_cb(Account *account, GtkTreeViewColumn *col, const gchar *new_notes)
2526 {
2527  if (g_strcmp0(xaccAccountGetNotes(account), new_notes) == 0)
2528  return;
2529  xaccAccountSetNotes(account, new_notes);
2530 }
2531 
2532 static void
2533 gtva_set_column_editor(GncTreeViewAccount *view,
2534  GtkTreeViewColumn *column,
2535  GncTreeViewAccountColumnTextEdited edited_cb)
2536 {
2537  GList *renderers_orig, *renderers;
2538  GtkCellRenderer *renderer;
2539 
2540  // look for the first text-renderer; on the 0th column of the account tree,
2541  // there are two renderers: pixbuf and text. So find the text one.
2542  for (renderers_orig = renderers = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
2543  renderers && !GTK_IS_CELL_RENDERER_TEXT(renderers->data);
2544  renderers = renderers->next);
2545  renderer = GTK_CELL_RENDERER(renderers->data);
2546  g_list_free(renderers_orig);
2547  g_return_if_fail(renderer != NULL);
2548  gtva_setup_column_renderer_edited_cb(GNC_TREE_VIEW_ACCOUNT(view), column, renderer, edited_cb);
2549 }
2550 
2551 void
2552 gnc_tree_view_account_set_name_edited(GncTreeViewAccount *view,
2553  GncTreeViewAccountColumnTextEdited edited_cb)
2554 {
2556  priv = GNC_TREE_VIEW_ACCOUNT_GET_PRIVATE(view);
2557  gtva_set_column_editor(view, priv->name_column, edited_cb);
2558 }
2559 
2560 void
2561 gnc_tree_view_account_set_code_edited(GncTreeViewAccount *view,
2562  GncTreeViewAccountColumnTextEdited edited_cb)
2563 {
2565  priv = GNC_TREE_VIEW_ACCOUNT_GET_PRIVATE(view);
2566  gtva_set_column_editor(view, priv->code_column, edited_cb);
2567 }
2568 
2569 void
2570 gnc_tree_view_account_set_description_edited(GncTreeViewAccount *view,
2571  GncTreeViewAccountColumnTextEdited edited_cb)
2572 {
2574  priv = GNC_TREE_VIEW_ACCOUNT_GET_PRIVATE(view);
2575  gtva_set_column_editor(view, priv->desc_column, edited_cb);
2576 }
2577 
2578 void
2579 gnc_tree_view_account_set_notes_edited(GncTreeViewAccount *view,
2580  GncTreeViewAccountColumnTextEdited edited_cb)
2581 {
2583  priv = GNC_TREE_VIEW_ACCOUNT_GET_PRIVATE(view);
2584  gtva_set_column_editor(view, priv->notes_column, edited_cb);
2585 }
2586 
2587 static gboolean gnc_tree_view_search_compare (GtkTreeModel *model, gint column, const gchar *key, GtkTreeIter *iter, gpointer search_data)
2588 {
2589  gchar *normalized_key;
2590  gchar *case_normalized_key = NULL;
2591  gboolean match = FALSE;
2592 
2593  normalized_key = g_utf8_normalize (key, -1, G_NORMALIZE_ALL);
2594  if (normalized_key)
2595  case_normalized_key = g_utf8_casefold (normalized_key, -1);
2596  if (case_normalized_key)
2597  {
2598  int i;
2599 
2600  for (i=0;i<3;i++)
2601  {
2602  gchar *normalized_string;
2603  gchar *case_normalized_string = NULL;
2604  gchar *str = NULL;
2605 
2606  switch (i)
2607  {
2608  case 0:
2609  gtk_tree_model_get(model,iter,GNC_TREE_MODEL_ACCOUNT_COL_NAME,&str,-1);
2610  break;
2611  case 1:
2612  gtk_tree_model_get(model,iter,GNC_TREE_MODEL_ACCOUNT_COL_CODE,&str,-1);
2613  break;
2614  case 2:
2615  gtk_tree_model_get(model,iter,GNC_TREE_MODEL_ACCOUNT_COL_DESCRIPTION,&str,-1);
2616  break;
2617  }
2618 
2619  if (!str)
2620  continue;
2621 
2622  normalized_string = g_utf8_normalize (str, -1, G_NORMALIZE_ALL);
2623  if (normalized_string)
2624  case_normalized_string = g_utf8_casefold (normalized_string, -1);
2625  if (case_normalized_string&&NULL!=strstr(case_normalized_string,case_normalized_key))
2626  match=TRUE;
2627 
2628  g_free (str);
2629  g_free (normalized_string);
2630  g_free (case_normalized_string);
2631 
2632  if (match)
2633  break;
2634  }
2635  }
2636 
2637  g_free (normalized_key);
2638  g_free (case_normalized_key);
2639 
2640  // inverted return (FALSE means a match)
2641  return !match;
2642 }
Account * gnc_account_get_parent(const Account *acc)
Definition: Account.c:2623
void gnc_tree_view_account_get_view_info(GncTreeViewAccount *account_view, AccountViewInfo *avi)
GtkTreeViewColumn * gnc_tree_view_account_add_property_column(GncTreeViewAccount *view, const gchar *column_title, const gchar *propname)
void qof_instance_get(const QofInstance *inst, const gchar *first_param,...)
Wrapper for g_object_get.
const GList * gnc_gobject_tracking_get_list(const gchar *name)
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
gulong gnc_prefs_register_cb(const char *group, const gchar *pref_name, gpointer func, gpointer user_data)
Definition: gnc-prefs.c:128
GList * gnc_tree_view_account_get_selected_accounts(GncTreeViewAccount *view)
Account * gnc_tree_view_account_get_cursor_account(GncTreeViewAccount *view)
GtkTreeViewColumn * gnc_tree_view_add_text_column(GncTreeView *view, const gchar *column_title, const gchar *pref_name, const gchar *stock_icon_name, const gchar *sizing_text, gint model_data_column, gint model_visibility_column, GtkTreeIterCompareFunc column_sort_fn)
void xaccAccountSetNotes(Account *acc, const char *str)
Definition: Account.c:2368
int safe_utf8_collate(const char *da, const char *db)
GNCAccountType xaccAccountGetType(const Account *acc)
Definition: Account.c:3009
void gppat_filter_response_cb(GtkWidget *dialog, gint response, AccountFilterDialog *fd)
const char * xaccAccountGetCode(const Account *acc)
Definition: Account.c:3086
common utilities for manipulating a GtkTreeView within gnucash
#define DEBUG(format, args...)
Definition: qoflog.h:255
const gchar * gnc_plugin_page_get_page_name(GncPluginPage *page)
Account * gnc_tree_model_account_get_account(GncTreeModelAccount *model, GtkTreeIter *iter)
void xaccAccountSetCode(Account *acc, const char *str)
Definition: Account.c:2249
void gppat_filter_select_all_cb(GtkWidget *button, AccountFilterDialog *fd)
gboolean(* gnc_tree_view_account_filter_func)(Account *account, gpointer data)
gboolean gnc_numeric_zero_p(gnc_numeric a)
void gnc_tree_view_account_expand_to_account(GncTreeViewAccount *view, Account *account)
void gnc_tree_view_account_set_view_info(GncTreeViewAccount *account_view, AccountViewInfo *avi)
void gnc_tree_view_set_show_column_menu(GncTreeView *view, gboolean visible)
gint gnc_numeric_compare(gnc_numeric a, gnc_numeric b)
void gppat_filter_clear_all_cb(GtkWidget *button, AccountFilterDialog *fd)
#define PERR(format, args...)
Definition: qoflog.h:237
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)
#define ENTER(format, args...)
Definition: qoflog.h:261
gboolean gnc_tree_model_account_get_iter_from_account(GncTreeModelAccount *model, Account *account, GtkTreeIter *iter)
gnc_commodity * gnc_default_report_currency(void)
Definition: gnc-ui-util.c:972
void gnc_tree_view_account_set_selected_accounts(GncTreeViewAccount *view, GList *account_list, gboolean show_last)
gnc_commodity * gnc_default_currency(void)
Definition: gnc-ui-util.c:939
void gppat_filter_show_hidden_toggled_cb(GtkToggleButton *button, AccountFilterDialog *fd)
gboolean xaccAccountIsHidden(const Account *acc)
Definition: Account.c:3982
Account * gnc_account_lookup_by_name(const Account *parent, const char *name)
Definition: Account.c:2803
int xaccAccountOrder(const Account *aa, const Account *ab)
Definition: Account.c:2132
gint gnc_tree_view_append_column(GncTreeView *view, GtkTreeViewColumn *column)
GtkTreeModel implementation for gnucash account tree.
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)
void gnc_tree_view_account_set_filter(GncTreeViewAccount *view, gnc_tree_view_account_filter_func func, gpointer data, GSourceFunc destroy)
GtkCellRenderer * gnc_tree_view_column_get_renderer(GtkTreeViewColumn *column)
QofBook * qof_session_get_book(const QofSession *session)
gchar * gnc_account_get_full_name(const Account *account)
Definition: Account.c:3038
Account handling public routines.
void gnc_tree_view_account_select_subaccounts(GncTreeViewAccount *view, Account *account)
void xaccAccountSetPlaceholder(Account *acc, gboolean val)
Definition: Account.c:3923
void gnc_tree_view_account_refilter(GncTreeViewAccount *view)
Gobject helper routines.
GtkTreeView implementation for gnucash account tree.
GtkTreeModel * gnc_tree_model_account_new(Account *root)
GtkTreeViewColumn * gnc_tree_view_account_add_custom_column(GncTreeViewAccount *account_view, const gchar *column_title, GncTreeViewAccountColumnSource col_source_cb, GncTreeViewAccountColumnTextEdited col_edited_cb)
GtkTreeView * gnc_tree_view_account_new_with_root(Account *root, gboolean show_root)
const char * xaccAccountGetDescription(const Account *acc)
Definition: Account.c:3093
GtkTreeView * gnc_tree_view_account_new(gboolean show_root)
void gnc_tree_view_configure_columns(GncTreeView *view)
General utilities for dealing with accounting periods.
gboolean gnc_plugin_page_account_tree_filter_accounts(Account *account, gpointer user_data)
Account * gnc_tree_view_account_get_account_from_iter(GtkTreeModel *s_model, GtkTreeIter *s_iter)
const char * gnc_commodity_get_fullname(const gnc_commodity *cm)
Account * gnc_account_lookup_by_full_name(const Account *any_acc, const gchar *name)
Definition: Account.c:2915
Account * gnc_tree_view_account_get_account_from_path(GncTreeViewAccount *view, GtkTreePath *s_path)
All type declarations for the whole Gnucash engine.
GNCAccountType
Definition: Account.h:96
GtkTreeModel implementation to display account types in a GtkTreeView.
GLib helper routines.
Generic api to store and retrieve preferences.
gint64 xaccAccountCountSplits(const Account *acc, gboolean include_children)
Definition: Account.c:3725
void gnc_tree_view_account_set_selected_account(GncTreeViewAccount *view, Account *account)
void gppat_filter_show_unused_toggled_cb(GtkToggleButton *button, AccountFilterDialog *fd)
gint gnc_tree_view_account_count_children(GncTreeViewAccount *view, Account *account)
GtkTreePath * gnc_tree_model_account_get_path_from_account(GncTreeModelAccount *model, Account *account)
gboolean xaccAccountGetPlaceholder(const Account *acc)
Definition: Account.c:3912
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Definition: gnc-prefs.c:196
Account * gnc_tree_view_account_get_selected_account(GncTreeViewAccount *view)
#define LEAVE(format, args...)
Definition: qoflog.h:271
gint64 time64
Definition: gnc-date.h:83
void xaccAccountSetDescription(Account *acc, const char *str)
Definition: Account.c:2268
const char * xaccAccountGetName(const Account *acc)
Definition: Account.c:3031
const char * xaccAccountGetTypeStr(GNCAccountType type)
Definition: Account.c:4137
void xaccAccountSetName(Account *acc, const char *str)
Definition: Account.c:2229
Commodity handling public routines.
void gppat_filter_select_default_cb(GtkWidget *button, AccountFilterDialog *fd)
const gchar * QofLogModule
Definition: qofid.h:89
void gnc_prefs_remove_cb_by_func(const gchar *group, const gchar *pref_name, gpointer func, gpointer user_data)
Definition: gnc-prefs.c:148
const char * xaccAccountGetNotes(const Account *acc)
Definition: Account.c:3121
void gppat_filter_show_zero_toggled_cb(GtkToggleButton *button, AccountFilterDialog *fd)