GnuCash  4.11-243-g1cac132214+
gnc-ledger-display2.c
1 /********************************************************************\
2  * gnc-ledger-display.c -- utilities for dealing with multiple *
3  * register/ledger windows in GnuCash *
4  * *
5  * Copyright (C) 1997 Robin D. Clark *
6  * Copyright (C) 1997, 1998 Linas Vepstas *
7  * Copyright (C) 2012 Robert Fewell *
8  * *
9  * This program is free software; you can redistribute it and/or *
10  * modify it under the terms of the GNU General Public License as *
11  * published by the Free Software Foundation; either version 2 of *
12  * the License, or (at your option) any later version. *
13  * *
14  * This program is distributed in the hope that it will be useful, *
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17  * GNU General Public License for more details. *
18  * *
19  * You should have received a copy of the GNU General Public License*
20  * along with this program; if not, write to the Free Software *
21  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
22  * *
23 \********************************************************************/
24 
25 #include <config.h>
26 
27 #include <time.h>
28 
29 #include "Account.h"
30 #include "Query.h"
31 #include "qof.h"
32 #include "SX-book.h"
33 #include "Transaction.h"
34 #include "gnc-component-manager.h"
35 #include "gnc-date.h"
36 #include "gnc-engine.h"
37 #include "gnc-event.h"
38 #include "gnc-ledger-display2.h"
39 #include "gnc-prefs.h"
40 #include "gnc-ui-util.h"
41 
42 #include "split-register-control.h"
43 #include "split-register-model.h"
44 
46 
47 
48 #define REGISTER_SINGLE_CM_CLASS "register-single"
49 #define REGISTER_SUBACCOUNT_CM_CLASS "register-subaccount"
50 #define REGISTER_GL_CM_CLASS "register-gl"
51 #define REGISTER_TEMPLATE_CM_CLASS "register-template"
52 
53 #define GNC_PREF_DOUBLE_LINE_MODE "double-line-mode"
54 #define GNC_PREF_MAX_TRANS "max-transactions"
55 #define GNC_PREF_DEFAULT_STYLE_LEDGER "default-style-ledger"
56 #define GNC_PREF_DEFAULT_STYLE_AUTOLEDGER "default-style-autoledger"
57 #define GNC_PREF_DEFAULT_STYLE_JOURNAL "default-style-journal"
58 
59 
61 {
62  GncGUID leader;
63 
64  Query *query;
65 
66  GNCLedgerDisplay2Type ld_type;
67 
68  GncTreeModelSplitReg *model; //FIXME Might get rid of this and use function to find.
69  GncTreeViewSplitReg *view;
70 
71  gboolean refresh_ok;
72 
73  gboolean loading;
74  gboolean use_double_line_default;
75 
76  GNCLedgerDisplay2Destroy destroy;
77  GNCLedgerDisplay2GetParent get_parent;
78 
79  gpointer user_data;
80 
81  gint component_id;
82 };
83 
84 
86 static QofLogModule log_module = GNC_MOD_LEDGER;
87 
88 
90 static GNCLedgerDisplay2 *
91 gnc_ledger_display2_internal (Account *lead_account, Query *q,
92  GNCLedgerDisplay2Type ld_type,
93  SplitRegisterType2 reg_type,
94  SplitRegisterStyle2 style,
95  gboolean use_double_line,
96  gboolean is_template,
97  gboolean mismatched_commodities);
98 
99 static void gnc_ledger_display2_refresh_internal (GNCLedgerDisplay2 *ld, GList *splits);
100 
101 static void gnc_ledger_display2_refresh_cb (GncTreeModelSplitReg *model, gpointer item, gpointer user_data);
102 
105 Account *
106 gnc_ledger_display2_leader (GNCLedgerDisplay2 *ld)
107 {
108  if (!ld)
109  return NULL;
110 
111  return xaccAccountLookup (&ld->leader, gnc_get_current_book ());
112 }
113 
114 GNCLedgerDisplay2Type
115 gnc_ledger_display2_type (GNCLedgerDisplay2 *ld)
116 {
117  if (!ld)
118  return -1;
119 
120  return ld->ld_type;
121 }
122 
123 void
124 gnc_ledger_display2_set_user_data (GNCLedgerDisplay2 *ld, gpointer user_data)
125 {
126  if (!ld)
127  return;
128 
129  ld->user_data = user_data;
130 }
131 
132 gpointer
133 gnc_ledger_display2_get_user_data (GNCLedgerDisplay2 *ld)
134 {
135  if (!ld)
136  return NULL;
137 
138  return ld->user_data;
139 }
140 
141 void
142 gnc_ledger_display2_set_handlers (GNCLedgerDisplay2 *ld,
143  GNCLedgerDisplay2Destroy destroy,
144  GNCLedgerDisplay2GetParent get_parent)
145 {
146  if (!ld)
147  return;
148 
149  ld->destroy = destroy;
150  ld->get_parent = get_parent;
151 }
152 
155 {
156  if (!ld)
157  return NULL;
158 
159  return ld->model;
160 }
161 
162 Query *
163 gnc_ledger_display2_get_query (GNCLedgerDisplay2 *ld)
164 {
165  if (!ld)
166  return NULL;
167 
168  return ld->query;
169 }
170 
171 static gboolean
172 find_by_leader (gpointer find_data, gpointer user_data)
173 {
174  Account *account = find_data;
175  GNCLedgerDisplay2 *ld = user_data;
176 
177  if (!account || !ld)
178  return FALSE;
179 
180  return (account == gnc_ledger_display2_leader (ld));
181 }
182 
183 static gboolean
184 find_by_query (gpointer find_data, gpointer user_data)
185 {
186  Query *q = find_data;
187  GNCLedgerDisplay2 *ld = user_data;
188 
189  if (!q || !ld)
190  return FALSE;
191 
192  return ld->query == q;
193 }
194 
195 
196 static gboolean
197 find_by_reg (gpointer find_data, gpointer user_data)
198 {
200  GNCLedgerDisplay2 *ld = user_data;
201 
202  if (!model || !ld)
203  return FALSE;
204 
205  return ld->model == model;
206 }
207 
208 static SplitRegisterStyle2
209 gnc_get_default_register_style (GNCAccountType type)
210 {
211  SplitRegisterStyle2 new_style = REG2_STYLE_LEDGER;
212 
213  if (gnc_prefs_get_bool (GNC_PREFS_GROUP_GENERAL_REGISTER,
214  GNC_PREF_DEFAULT_STYLE_JOURNAL))
215  new_style = REG2_STYLE_JOURNAL;
216  else if (gnc_prefs_get_bool (GNC_PREFS_GROUP_GENERAL_REGISTER,
217  GNC_PREF_DEFAULT_STYLE_AUTOLEDGER))
218  new_style = REG2_STYLE_AUTO_LEDGER;
219 
220  return new_style;
221 }
222 
223 static gpointer
224 look_for_portfolio_cb (Account *account, gpointer data)
225 {
226  return xaccAccountIsPriced(account) ? (gpointer) PORTFOLIO_LEDGER2 : NULL;
227 }
228 
229 static SplitRegisterType2
230 gnc_get_reg_type (Account *leader, GNCLedgerDisplay2Type ld_type)
231 {
232  GNCAccountType account_type;
233  SplitRegisterType2 reg_type;
234 
235  if (ld_type == LD2_GL)
236  return GENERAL_JOURNAL2;
237 
238  account_type = xaccAccountGetType (leader);
239 
240  if (ld_type == LD2_SINGLE)
241  {
242  switch (account_type)
243  {
244  case ACCT_TYPE_BANK:
245  return BANK_REGISTER2;
246 
247  case ACCT_TYPE_CASH:
248  return CASH_REGISTER2;
249 
250  case ACCT_TYPE_ASSET:
251  return ASSET_REGISTER2;
252 
253  case ACCT_TYPE_CREDIT:
254  return CREDIT_REGISTER2;
255 
256  case ACCT_TYPE_LIABILITY:
257  return LIABILITY_REGISTER2;
258 
259  case ACCT_TYPE_PAYABLE:
260  return PAYABLE_REGISTER2;
261 
263  return RECEIVABLE_REGISTER2;
264 
265  case ACCT_TYPE_STOCK:
266  case ACCT_TYPE_MUTUAL:
267  return STOCK_REGISTER2;
268 
269  case ACCT_TYPE_INCOME:
270  return INCOME_REGISTER2;
271 
272  case ACCT_TYPE_EXPENSE:
273  return EXPENSE_REGISTER2;
274 
275  case ACCT_TYPE_EQUITY:
276  return EQUITY_REGISTER2;
277 
278  case ACCT_TYPE_CURRENCY:
279  return CURRENCY_REGISTER2;
280 
281  case ACCT_TYPE_TRADING:
282  return TRADING_REGISTER2;
283 
284  default:
285  PERR ("unknown account type %d\n", account_type);
286  return BANK_REGISTER2;
287  }
288  }
289 
290  if (ld_type != LD2_SUBACCOUNT)
291  {
292  PERR ("unknown ledger type %d\n", ld_type);
293  return BANK_REGISTER2;
294  }
295 
296  switch (account_type)
297  {
298  case ACCT_TYPE_BANK:
299  case ACCT_TYPE_CASH:
300  case ACCT_TYPE_ASSET:
301  case ACCT_TYPE_CREDIT:
302  case ACCT_TYPE_LIABILITY:
304  case ACCT_TYPE_PAYABLE:
305  {
306  /* If any of the sub-accounts have ACCT_TYPE_STOCK or
307  * ACCT_TYPE_MUTUAL types, then we must use the PORTFOLIO_LEDGER
308  * ledger. Otherwise, a plain old GENERAL_JOURNAL will do. */
309  gpointer ret;
310  reg_type = GENERAL_JOURNAL2;
311 
312  ret = gnc_account_foreach_descendant_until(leader, look_for_portfolio_cb, NULL);
313  if (ret) reg_type = PORTFOLIO_LEDGER2;
314  break;
315  }
316 
317  case ACCT_TYPE_STOCK:
318  case ACCT_TYPE_MUTUAL:
319  case ACCT_TYPE_CURRENCY:
320  reg_type = PORTFOLIO_LEDGER2;
321  break;
322 
323  case ACCT_TYPE_INCOME:
324  case ACCT_TYPE_EXPENSE:
325  reg_type = INCOME_LEDGER2;
326  break;
327 
328  case ACCT_TYPE_EQUITY:
329  case ACCT_TYPE_TRADING:
330  reg_type = GENERAL_JOURNAL2;
331  break;
332 
333  default:
334  PERR ("unknown account type:%d", account_type);
335  reg_type = GENERAL_JOURNAL2;
336  break;
337  }
338 
339  return reg_type;
340 }
341 
342 /* Returns a boolean of whether this display should be single or double lined
343  * mode by default */
344 gboolean
346 {
347  return (gld->use_double_line_default ||
348  gnc_prefs_get_bool(GNC_PREFS_GROUP_GENERAL_REGISTER, GNC_PREF_DOUBLE_LINE_MODE));
349 }
350 
351 /* Opens up a register window to display a single account */
352 GNCLedgerDisplay2 *
354 {
355  SplitRegisterType2 reg_type;
356  GNCAccountType acc_type = xaccAccountGetType (account);
357  gboolean use_double_line;
358  GNCLedgerDisplay2 *ld;
359 
360  ENTER("account=%p", account);
361 
362  switch (acc_type)
363  {
364  case ACCT_TYPE_PAYABLE:
366  use_double_line = TRUE;
367  break;
368  default:
369  use_double_line = FALSE;
370  break;
371  }
372 
373  reg_type = gnc_get_reg_type (account, LD2_SINGLE);
374 
375  ld = gnc_ledger_display2_internal (account, NULL, LD2_SINGLE, reg_type,
376  gnc_get_default_register_style(acc_type),
377  use_double_line, FALSE, FALSE);
378  LEAVE("%p", ld);
379  return ld;
380 }
381 
382 /* Opens up a register window to display an account, and all of its
383  * children, in the same window */
384 GNCLedgerDisplay2 *
385 gnc_ledger_display2_subaccounts (Account *account, gboolean mismatched_commodities)
386 {
387  SplitRegisterType2 reg_type;
388  GNCLedgerDisplay2 *ld;
389 
390  ENTER("account=%p", account);
391 
392  reg_type = gnc_get_reg_type (account, LD2_SUBACCOUNT);
393 
394  ld = gnc_ledger_display2_internal (account, NULL, LD2_SUBACCOUNT,
395  reg_type, REG2_STYLE_JOURNAL, FALSE,
396  FALSE,mismatched_commodities);
397  LEAVE("%p", ld);
398  return ld;
399 }
400 
401 /* Opens up a general journal window. */
402 GNCLedgerDisplay2 *
404 {
405  Query *query;
406  time64 start;
407  struct tm tm;
408  GNCLedgerDisplay2 *ld;
409 
410  ENTER(" ");
411 
412  query = qof_query_create_for (GNC_ID_SPLIT);
413 
414  qof_query_set_book (query, gnc_get_current_book());
415 
416  /* In lieu of not "mis-using" some portion of the infrastructure by writing
417  * a bunch of new code, we just filter out the accounts of the template
418  * transactions. While these are in a separate Account trees just for this
419  * reason, the query engine makes no distinction between Account trees.
420  * See Gnome Bug 86302.
421  * -- jsled */
422  {
423  Account *tRoot;
424  GList *al;
425 
426  tRoot = gnc_book_get_template_root( gnc_get_current_book() );
427  al = gnc_account_get_descendants( tRoot );
428 
429  if (g_list_length(al) != 0)
430  xaccQueryAddAccountMatch( query, al, QOF_GUID_MATCH_NONE, QOF_QUERY_AND );
431 
432  g_list_free (al);
433  al = NULL;
434  tRoot = NULL;
435  }
436 
438  tm.tm_mon--; /* Default the register to the last month's worth of transactions. */
439  start = gnc_mktime (&tm);
440  xaccQueryAddDateMatchTT (query,
441  TRUE, start,
442  FALSE, 0,
443  QOF_QUERY_AND);
444 
445  ld = gnc_ledger_display2_internal (NULL, query, LD2_GL, GENERAL_JOURNAL2,
446  REG2_STYLE_JOURNAL, FALSE, FALSE, FALSE);
447  LEAVE("%p", ld);
448  return ld;
449 }
450 
459 GNCLedgerDisplay2 *
461 {
462  QofBook *book;
463  Query *q;
464  GNCLedgerDisplay2 *ld;
465  GncTreeModelSplitReg *model;
466  Account *root, *acct;
467  gboolean isTemplateModeTrue;
468 
469  ENTER("id=%s", id ? id : "(null)");
470 
471  acct = NULL;
472  isTemplateModeTrue = TRUE;
473 
474  q = qof_query_create_for(GNC_ID_SPLIT);
475 
476  book = gnc_get_current_book ();
477  qof_query_set_book (q, book);
478 
479  if ( id != NULL )
480  {
481  root = gnc_book_get_template_root (book);
482  acct = gnc_account_lookup_by_name(root, id);
483  g_assert( acct );
484  xaccQueryAddSingleAccountMatch (q, acct, QOF_QUERY_AND);
485  }
486 
487  ld = gnc_ledger_display2_internal (NULL, q, LD2_GL,
488  SEARCH_LEDGER2,
489  REG2_STYLE_JOURNAL,
490  FALSE,
491  isTemplateModeTrue,
492  FALSE);
493 
494 
496  if ( acct )
497  {
499  }
500 
501  LEAVE("%p", ld);
502  return ld;
503 }
504 
505 GtkWidget *
506 gnc_ledger_display2_get_parent( GNCLedgerDisplay2 *ld )
507 {
508  if ( ld == NULL )
509  return NULL;
510 
511  if ( ld->get_parent == NULL )
512  return NULL;
513 
514  return ld->get_parent( ld );
515 }
516 
517 static GtkWidget *
518 gnc_ledger_display2_parent (void *user_data)
519 {
520  GNCLedgerDisplay2 *ld = user_data;
521  return gnc_ledger_display2_get_parent( ld );
522 }
523 
524 #ifdef skip
525 //FIXME Not used ?
526 static void
527 gnc_ledger_display2_set_watches (GNCLedgerDisplay2 *ld, GList *splits)
528 {
529  GList *node;
530 
531  gnc_gui_component_clear_watches (ld->component_id);
532 
533  gnc_gui_component_watch_entity_type (ld->component_id,
534  GNC_ID_ACCOUNT,
535  QOF_EVENT_MODIFY | QOF_EVENT_DESTROY
536  | GNC_EVENT_ITEM_CHANGED);
537 
538  for (node = splits; node; node = node->next)
539  {
540  Split *split = node->data;
541  Transaction *trans = xaccSplitGetParent (split);
542 
543  gnc_gui_component_watch_entity (ld->component_id,
544  xaccTransGetGUID (trans),
545  QOF_EVENT_MODIFY);
546  }
547 }
548 #endif
549 
550 static void
551 refresh_handler (GHashTable *changes, gpointer user_data)
552 {
553  GNCLedgerDisplay2 *ld = user_data;
554  const EventInfo *info;
555  gboolean has_leader;
556  GList *splits;
557 
558  ENTER("changes=%p, user_data=%p", changes, user_data);
559 
560  if (ld->loading)
561  {
562  LEAVE("already loading");
563  return;
564  }
565 
566  has_leader = (ld->ld_type == LD2_SINGLE || ld->ld_type == LD2_SUBACCOUNT);
567 
568  if (has_leader)
569  {
570  Account *leader = gnc_ledger_display2_leader (ld);
571  if (!leader)
572  {
573  gnc_close_gui_component (ld->component_id);
574  LEAVE("no leader");
575  return;
576  }
577  }
578 
579  if (changes && has_leader)
580  {
581  info = gnc_gui_get_entity_events (changes, &ld->leader);
582  if (info && (info->event_mask & QOF_EVENT_DESTROY))
583  {
584  gnc_close_gui_component (ld->component_id);
585  LEAVE("destroy");
586  return;
587  }
588  }
589 
590  /* Its not clear if we should re-run the query, or if we should
591  * just use qof_query_last_run(). Its possible that the dates
592  * changed, requiring a full new query. Similar considerations
593  * needed for multi-user mode.
594  */
595  splits = qof_query_run (ld->query);
596 
597 //FIXME Not Needed ? gnc_ledger_display2_set_watches (ld, splits);
598 // gnc_ledger_display2_set_watches (ld, splits);
599 
600  //preference changes come this way
601  gnc_ledger_display2_refresh_internal (ld, splits);
602 
603  LEAVE(" ");
604 }
605 
606 static void
607 close_handler (gpointer user_data)
608 {
609  GNCLedgerDisplay2 *ld = user_data;
610 
611  if (!ld)
612  return;
613 
614  ENTER(" ");
615 
616  gnc_unregister_gui_component (ld->component_id);
617 
618  if (ld->destroy)
619  ld->destroy (ld);
620 
622  ld->model = NULL;
623  ld->view = NULL;
624 
625  qof_query_destroy (ld->query);
626  ld->query = NULL;
627 
628  LEAVE(" ");
629  g_free (ld);
630 }
631 
632 static void
633 gnc_ledger_display2_make_query (GNCLedgerDisplay2 *ld,
634  gint limit,
635  SplitRegisterType2 type)
636 {
637  Account *leader;
638  GList *accounts;
639 
640  if (!ld)
641  return;
642 
643  switch (ld->ld_type)
644  {
645  case LD2_SINGLE:
646  case LD2_SUBACCOUNT:
647  break;
648 
649  case LD2_GL:
650  return;
651 
652  default:
653  PERR ("unknown ledger type: %d", ld->ld_type);
654  return;
655  }
656 
657  qof_query_destroy (ld->query);
658  ld->query = qof_query_create_for(GNC_ID_SPLIT);
659 
660  /* This is a bit of a hack. The number of splits should be
661  * configurable, or maybe we should go back a time range instead
662  * of picking a number, or maybe we should be able to exclude
663  * based on reconciled status. Anyway, this works for now. */
664  if ((limit != 0) && (type != SEARCH_LEDGER2))
665  qof_query_set_max_results (ld->query, limit);
666 
667  qof_query_set_book (ld->query, gnc_get_current_book());
668 
669  leader = gnc_ledger_display2_leader (ld);
670 
671  if (ld->ld_type == LD2_SUBACCOUNT)
672  accounts = gnc_account_get_descendants (leader);
673  else
674  accounts = NULL;
675 
676  accounts = g_list_prepend (accounts, leader);
677 
678  xaccQueryAddAccountMatch (ld->query, accounts,
679  QOF_GUID_MATCH_ANY, QOF_QUERY_AND);
680 
681  g_list_free (accounts);
682 }
683 
684 /* Opens up a ledger window for an arbitrary query. */
685 GNCLedgerDisplay2 *
687  SplitRegisterStyle2 style)
688 {
689  GNCLedgerDisplay2 *ld;
690 
691  ENTER("query=%p", query);
692 
693  ld = gnc_ledger_display2_internal (NULL, query, LD2_GL, type, style,
694  FALSE, FALSE, FALSE);
695  LEAVE("%p", ld);
696  return ld;
697 }
698 
699 static GNCLedgerDisplay2 *
700 gnc_ledger_display2_internal (Account *lead_account, Query *q,
701  GNCLedgerDisplay2Type ld_type,
702  SplitRegisterType2 reg_type,
703  SplitRegisterStyle2 style,
704  gboolean use_double_line,
705  gboolean is_template,
706  gboolean mismatched_commodities)
707 {
708  GNCLedgerDisplay2 *ld;
709  gint limit;
710  const char *klass;
711 // GList *splits;
712  gboolean display_subaccounts = FALSE;
713  gboolean is_gl = FALSE;
714 
715  switch (ld_type)
716  {
717  case LD2_SINGLE:
718  klass = REGISTER_SINGLE_CM_CLASS;
719 
720  if (reg_type >= NUM_SINGLE_REGISTER_TYPES2)
721  {
722  PERR ("single-account register with wrong split register type");
723  return NULL;
724  }
725 
726  if (!lead_account)
727  {
728  PERR ("single-account register with no account specified");
729  return NULL;
730  }
731 
732  if (q)
733  {
734  PWARN ("single-account register with external query");
735  q = NULL;
736  }
737 
738  ld = gnc_find_first_gui_component (klass, find_by_leader, lead_account);
739  if (ld)
740  return ld;
741 
742  break;
743 
744  case LD2_SUBACCOUNT:
745  klass = REGISTER_SUBACCOUNT_CM_CLASS;
746 
747  if (!lead_account)
748  {
749  PERR ("sub-account register with no lead account");
750  return NULL;
751  }
752 
753  if (q)
754  {
755  PWARN ("account register with external query");
756  q = NULL;
757  }
758 
759  ld = gnc_find_first_gui_component (klass, find_by_leader, lead_account);
760  if (ld)
761  return ld;
762 
763  display_subaccounts = TRUE;
764  break;
765 
766  case LD2_GL:
767  klass = REGISTER_GL_CM_CLASS;
768 
769  if (!q)
770  {
771  PWARN ("general journal with no query");
772  }
773 
774  is_gl = TRUE;
775  break;
776 
777  default:
778  PERR ("bad ledger type: %d", ld_type);
779  return NULL;
780 
781  }
782 
783  ld = g_new (GNCLedgerDisplay2, 1);
784 
785  ld->leader = *xaccAccountGetGUID (lead_account);
786  ld->query = NULL;
787  ld->ld_type = ld_type;
788  ld->loading = FALSE;
789  ld->refresh_ok = FALSE;
790  ld->destroy = NULL;
791  ld->get_parent = NULL;
792  ld->user_data = NULL;
793 
794  limit = gnc_prefs_get_float(GNC_PREFS_GROUP_GENERAL_REGISTER, GNC_PREF_MAX_TRANS);
795 
796  /* set up the query filter */
797  if (q)
798  ld->query = qof_query_copy (q);
799  else
800  gnc_ledger_display2_make_query (ld, limit, reg_type);
801 
802  ld->component_id = gnc_register_gui_component (klass,
803  refresh_handler,
804  close_handler, ld);
805 
806  /******************************************************************\
807  * The main register window itself *
808  \******************************************************************/
809 
810  ld->use_double_line_default = use_double_line;
811 
812  ld->model = gnc_tree_model_split_reg_new (reg_type, style, use_double_line, is_template, mismatched_commodities);
813 
814  gnc_tree_model_split_reg_set_data (ld->model, ld, gnc_ledger_display2_parent);
815  gnc_tree_model_split_reg_set_display (ld->model, display_subaccounts, is_gl);
816 
817  // This sets up a call back to reload after changes
818  g_signal_connect (G_OBJECT (ld->model), "refresh_trans",
819  G_CALLBACK (gnc_ledger_display2_refresh_cb), ld );
820 
821 //FIXME Not Needed ? gnc_ledger_display2_set_watches (ld, splits);
822 // gnc_ledger_display2_set_watches (ld, splits);
823 
824  // Populate the model with an empty split
825  // An empty model could cause our gui callbacks to crash
826  gnc_ledger_display2_refresh_internal (ld, NULL);
827 
828  return ld;
829 }
830 
831 void
832 gnc_ledger_display2_set_split_view_register (GNCLedgerDisplay2 *ledger_display, GncTreeViewSplitReg *view)
833 {
834  if (!ledger_display)
835  return;
836 
837  ledger_display->view = view;
838 }
839 
841 gnc_ledger_display2_get_split_view_register (GNCLedgerDisplay2 *ledger_display)
842 {
843  if (!ledger_display)
844  return NULL;
845 
846  return ledger_display->view;
847 }
848 
849 void
850 gnc_ledger_display2_set_query (GNCLedgerDisplay2 *ledger_display, Query *q)
851 {
852  if (!ledger_display || !q)
853  return;
854 
855  g_return_if_fail (ledger_display->ld_type == LD2_GL);
856 
857  qof_query_destroy (ledger_display->query);
858  ledger_display->query = qof_query_copy (q);
859 }
860 
861 GNCLedgerDisplay2 *
863 {
864  GNCLedgerDisplay2 *ledger_display;
865  GncTreeModelSplitReg *model;
866 
867  if (!q)
868  return NULL;
869 
870  ledger_display = gnc_find_first_gui_component (REGISTER_GL_CM_CLASS, find_by_query, q);
871 
872  if (ledger_display)
873  {
874  model = ledger_display->model;
875  // To get a new search page from a general journal, search register is a LD2_GL also.
876  if (model->type == GENERAL_JOURNAL2)
877  ledger_display = NULL;
878  }
879  return ledger_display;
880 }
881 
882 /********************************************************************\
883  * refresh only the indicated register window *
884 \********************************************************************/
885 
886 static void
887 gnc_ledger_display2_refresh_internal (GNCLedgerDisplay2 *ld, GList *splits)
888 {
889  GtkTreeModel *s_model, *model;
890 
891  if (!ld || ld->loading)
892  return;
893 
894  if (!(ld->refresh_ok)) // We use this to test for the view available
895  {
896  ld->loading = TRUE;
898  ld->loading = FALSE;
899  }
900  else
901  {
902  /* This is used for the reloading of registers to refresh them and to update the search_ledger */
903  ld->loading = TRUE;
904 
905  s_model = gtk_tree_view_get_model (GTK_TREE_VIEW (ld->view)); // this is the sort model
906  model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (s_model)); // this is the model
907 
908  g_object_ref (s_model);
909  g_object_ref (model);
910 
911  gnc_tree_view_split_reg_block_selection (ld->view, TRUE); // This blocks the tree selection
912  gtk_tree_view_set_model (GTK_TREE_VIEW (ld->view), NULL); // Detach sort model from view
913  gnc_tree_model_split_reg_load (ld->model, splits, gnc_ledger_display2_leader (ld)); //reload splits
914  gtk_tree_view_set_model (GTK_TREE_VIEW (ld->view), GTK_TREE_MODEL (s_model)); // Re-attach sort model to view
915  gnc_tree_view_split_reg_block_selection (ld->view, FALSE); // This unblocks the tree selection
916 
917  g_object_unref (model);
918  g_object_unref (s_model);
919 
920  /* Set the default selection start position */
921  gnc_tree_view_split_reg_default_selection (ld->view);
922 
923  ld->loading = FALSE;
924  }
925 }
926 
927 void
928 gnc_ledger_display2_refilter (GNCLedgerDisplay2 *ld)
929 {
930  ENTER("ld=%p", ld);
931 
932  /* Set the default selection start position and refilter */
933  gnc_tree_view_split_reg_default_selection (ld->view);
934 
935  LEAVE(" ");
936 }
937 
938 void
939 gnc_ledger_display2_refresh_sched (GNCLedgerDisplay2 *ld, GList *splits)
940 {
941  ENTER("ld=%p", ld);
942 
943  if (!ld)
944  {
945  LEAVE("no display");
946  return;
947  }
948 
949  if (ld->loading)
950  {
951  LEAVE("already loading");
952  return;
953  }
954  gnc_ledger_display2_refresh_internal (ld, splits);
955  LEAVE(" ");
956 }
957 
958 void
959 gnc_ledger_display2_refresh (GNCLedgerDisplay2 *ld)
960 {
961  ENTER("ld=%p", ld);
962 
963  if (!ld)
964  {
965  LEAVE("no display");
966  return;
967  }
968 
969  if (ld->loading)
970  {
971  LEAVE("already loading");
972  return;
973  }
974 
975  // Update the query before refresh
976  gnc_tree_model_split_reg_update_query (ld->model, ld->query);
977  gnc_ledger_display2_refresh_internal (ld, qof_query_run (ld->query));
978  LEAVE(" ");
979 }
980 
981 void
982 gnc_ledger_display2_refresh_by_split_register (GncTreeModelSplitReg *model)
983 {
984  GNCLedgerDisplay2 *ld;
985 
986  if (!model)
987  return;
988 
989  ld = gnc_find_first_gui_component (REGISTER_SINGLE_CM_CLASS,
990  find_by_reg, model);
991  if (ld)
992  {
994  return;
995  }
996 
997  ld = gnc_find_first_gui_component (REGISTER_SUBACCOUNT_CM_CLASS,
998  find_by_reg, model);
999  if (ld)
1000  {
1002  return;
1003  }
1004 
1005  ld = gnc_find_first_gui_component (REGISTER_GL_CM_CLASS,
1006  find_by_reg, model);
1007  if (ld)
1008  {
1010  return;
1011  }
1012 
1013  ld = gnc_find_first_gui_component (REGISTER_TEMPLATE_CM_CLASS,
1014  find_by_reg, model);
1015  if (ld)
1016  {
1018  }
1019 }
1020 
1021 void
1022 gnc_ledger_display2_set_split_view_refresh (GNCLedgerDisplay2 *ld, gboolean ok)
1023 {
1024  if (!ld)
1025  return;
1026 
1027  ld->refresh_ok = ok;
1028 }
1029 
1030 /* This is used to reload after any changes made */
1031 static void
1032 gnc_ledger_display2_refresh_cb (GncTreeModelSplitReg *model, gpointer item, gpointer user_data)
1033 {
1034  GNCLedgerDisplay2 *ld = user_data;
1035 
1036  /* Refresh the view when idle */
1037  g_idle_add ((GSourceFunc)gnc_ledger_display2_refresh, ld);
1038 }
1039 
1040 void
1041 gnc_ledger_display2_close (GNCLedgerDisplay2 *ld)
1042 {
1043  if (!ld)
1044  return;
1045 
1046  gnc_close_gui_component (ld->component_id);
1047 }
SplitRegisterType2
Register types.
void gnc_ledger_display2_refilter(GNCLedgerDisplay2 *ld)
Refilter the register.
Date and Time handling routines.
void gnc_ledger_display2_set_user_data(GNCLedgerDisplay2 *ld, gpointer user_data)
get and set the user data associated with the ledger
gboolean xaccAccountIsPriced(const Account *acc)
Returns true if the account is a stock, mutual fund or currency, otherwise false. ...
Definition: Account.cpp:4712
utility functions for the GnuCash UI
Expense accounts are used to denote expenses.
Definition: Account.h:146
void gnc_ledger_display2_refresh(GNCLedgerDisplay2 *ld)
redisplay/redraw only the indicated window.
void gnc_tree_model_split_reg_set_display(GncTreeModelSplitReg *model, gboolean subacc, gboolean gl)
Set display general journal and show sub accounts.
GNCAccountType xaccAccountGetType(const Account *acc)
Returns the account&#39;s account type.
Definition: Account.cpp:3279
void gnc_ledger_display2_set_split_view_register(GNCLedgerDisplay2 *ledger_display, GncTreeViewSplitReg *view)
Set and Get the tree view used by the ledger display.
void gnc_ledger_display2_set_query(GNCLedgerDisplay2 *ledger_display, Query *q)
Set the query used for a register.
Mutual Fund accounts will typically be shown in registers which show three columns: price...
Definition: Account.h:128
GNCLedgerDisplay2 * gnc_ledger_display2_subaccounts(Account *account, gboolean mismatched_commodities)
opens up a register window to display the parent account and all of its children. ...
gboolean gnc_ledger_display2_default_double_line(GNCLedgerDisplay2 *gld)
Returns a boolean of whether this display should be single or double lined mode by default...
gpointer gnc_account_foreach_descendant_until(const Account *acc, AccountCb2 thunk, gpointer user_data)
This method will traverse all children of this accounts and their descendants, calling &#39;func&#39; on each...
Definition: Account.cpp:3253
TableControl specialized for the SplitRegister.
SplitRegisterType2 type
FIXME ? This may be the wrong place for these, may be the view ?
QofQuery * qof_query_copy(QofQuery *q)
Make a copy of the indicated query.
Definition: qofquery.cpp:1002
Account * gnc_book_get_template_root(const QofBook *book)
Returns the template group from the book.
Definition: SX-book.c:65
GNCLedgerDisplay2 * gnc_ledger_display2_template_gl(char *id)
Displays a template ledger.
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
TableModels specialized for SplitRegister and template SplitRegister.
void gnc_tm_get_today_start(struct tm *tm)
The gnc_tm_get_today_start() routine takes a pointer to a struct tm and fills it in with the first se...
Definition: gnc-date.cpp:1332
These expect a single object and expect the QofAccessFunc returns GncGUID*.
Definition: qofquerycore.h:113
#define PERR(format, args...)
Log a serious error.
Definition: qoflog.h:244
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
The cash account type is used to denote a shoe-box or pillowcase stuffed with * cash.
Definition: Account.h:113
GNCLedgerDisplay2 * gnc_ledger_display2_gl(void)
opens up a general ledger window
Account used to record multiple commodity transactions.
Definition: Account.h:158
void qof_query_set_max_results(QofQuery *q, int n)
Set the maximum number of results that should be returned.
Definition: qofquery.cpp:1272
GNCLedgerDisplay2 * gnc_ledger_display2_find_by_query(Query *q)
If the given ledger display still exists, return it.
GncTreeModelSplitReg * gnc_tree_model_split_reg_new(SplitRegisterType2 reg_type, SplitRegisterStyle2 style, gboolean use_double_line, gboolean is_template, gboolean mismatched_commodities)
Create new model and set options for register.
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:3083
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:250
Stock accounts will typically be shown in registers which show three columns: price, number of shares, and value.
Definition: Account.h:125
#define xaccAccountGetGUID(X)
Definition: Account.h:248
Account handling public routines.
void qof_query_destroy(QofQuery *query)
Frees the resources associate with a Query object.
Income accounts are used to denote income.
Definition: Account.h:143
Account * gnc_ledger_display2_leader(GNCLedgerDisplay2 *ld)
Implementations.
void qof_query_set_book(QofQuery *query, QofBook *book)
Set the book to be searched.
void gnc_tree_model_split_reg_set_data(GncTreeModelSplitReg *model, gpointer user_data, SRGetParentCallback2 get_parent)
Sets the user data and callback hooks for the register.
Anchor Scheduled Transaction info in a book.
void gnc_ledger_display2_close(GNCLedgerDisplay2 *ld)
close the window
The bank account type denotes a savings or checking account held at a bank.
Definition: Account.h:110
void gnc_tree_model_split_reg_update_query(GncTreeModelSplitReg *model, Query *query)
Update the query for the register.
void gnc_ledger_display2_refresh_sched(GNCLedgerDisplay2 *ld, GList *splits)
This is used to load the register for the schedule.
time64 gnc_mktime(struct tm *time)
calculate seconds from the epoch given a time struct
Definition: gnc-date.cpp:230
GncTreeModelSplitReg * gnc_ledger_display2_get_split_model_register(GNCLedgerDisplay2 *ld)
return the split register associated with a ledger display
A/P account type.
Definition: Account.h:154
Additional event handling code.
void gnc_tree_model_split_reg_load(GncTreeModelSplitReg *model, GList *slist, Account *default_account)
Load the model from a slist and set default account for register.
asset (and liability) accounts indicate generic, generalized accounts that are none of the above...
Definition: Account.h:119
GNCLedgerDisplay2 * gnc_ledger_display2_query(Query *query, SplitRegisterType2 type, SplitRegisterStyle2 style)
display a general ledger for an arbitrary query
All type declarations for the whole Gnucash engine.
GtkWidget * gnc_ledger_display2_get_parent(GNCLedgerDisplay2 *ld)
Returns the parent of a given ledger display.
The currency account type indicates that the account is a currency trading account.
Definition: Account.h:132
GNCAccountType
The account types are used to determine how the transaction data in the account is displayed...
Definition: Account.h:105
Defines a single register/ledger instance.
SplitRegisterStyle2
Register styles.
#define xaccTransGetGUID(X)
Definition: Transaction.h:793
Generic api to store and retrieve preferences.
GList * gnc_account_get_descendants(const Account *account)
This routine returns a flat list of all of the accounts that are descendants of the specified account...
Definition: Account.cpp:3036
GList * qof_query_run(QofQuery *query)
Perform the query, return the results.
liability (and asset) accounts indicate generic, generalized accounts that are none of the above...
Definition: Account.h:122
void gnc_ledger_display2_set_handlers(GNCLedgerDisplay2 *ld, GNCLedgerDisplay2Destroy destroy, GNCLedgerDisplay2GetParent get_parent)
set the handlers used by the ledger display
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Get a boolean value from the preferences backend.
A/R account type.
Definition: Account.h:152
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
void gnc_tree_model_split_reg_set_template_account(GncTreeModelSplitReg *model, Account *template_account)
Sets the template account.
The instance data structure for an account tree model.
gint64 time64
Many systems, including Microsoft Windows and BSD-derived Unixes like Darwin, are retaining the int-3...
Definition: gnc-date.h:93
GNCLedgerDisplay2 * gnc_ledger_display2_simple(Account *account)
opens up a register window to display a single account
Public declarations for GncLedgerDisplay2 class.
Equity account is used to balance the balance sheet.
Definition: Account.h:149
API for Transactions and Splits (journal entries)
The type used to store guids in C.
Definition: guid.h:75
void gnc_tree_model_split_reg_destroy(GncTreeModelSplitReg *model)
Destroy the model.
Query * gnc_ledger_display2_get_query(GNCLedgerDisplay2 *ld)
return the query associated with a ledger
The Credit card account is used to denote credit (e.g.
Definition: Account.h:116
gdouble gnc_prefs_get_float(const gchar *group, const gchar *pref_name)
Get an float value from the preferences backend.
Account * xaccAccountLookup(const GncGUID *guid, QofBook *book)
The xaccAccountLookup() subroutine will return the account associated with the given id...
Definition: Account.cpp:2050