~siretart/gnucash/ubuntu-fullsource

« back to all changes in this revision

Viewing changes to src/register/ledger-core/gnc-ledger-display.c

  • Committer: Reinhard Tartler
  • Date: 2008-08-03 07:25:46 UTC
  • Revision ID: siretart@tauware.de-20080803072546-y6p8xda8zpfi62ys
import gnucash_2.2.4.orig.tar.gz

The original tarball had the md5sum: 27e660297dc5b8ce574515779d05a5a5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 *                                                                  *
 
8
 * This program is free software; you can redistribute it and/or    *
 
9
 * modify it under the terms of the GNU General Public License as   *
 
10
 * published by the Free Software Foundation; either version 2 of   *
 
11
 * the License, or (at your option) any later version.              *
 
12
 *                                                                  *
 
13
 * This program is distributed in the hope that it will be useful,  *
 
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
 
16
 * GNU General Public License for more details.                     *
 
17
 *                                                                  *
 
18
 * You should have received a copy of the GNU General Public License*
 
19
 * along with this program; if not, write to the Free Software      *
 
20
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.        *
 
21
 *                                                                  *
 
22
\********************************************************************/
 
23
 
 
24
#include "config.h"
 
25
 
 
26
#include <time.h>
 
27
 
 
28
#include "Account.h"
 
29
#include "Query.h"
 
30
#include "QueryCore.h"
 
31
#include "QueryNew.h"
 
32
#include "SX-book.h"
 
33
#include "Transaction.h"
 
34
#include "gnc-component-manager.h"
 
35
#include "gnc-book.h"
 
36
#include "gnc-date.h"
 
37
#include "gnc-engine.h"
 
38
#include "gnc-event.h"
 
39
#include "gnc-gconf-utils.h"
 
40
#include "gnc-ledger-display.h"
 
41
#include "gnc-ui-util.h"
 
42
#include "split-register-control.h"
 
43
#include "split-register-model.h"
 
44
 
 
45
 
 
46
#define REGISTER_SINGLE_CM_CLASS     "register-single"
 
47
#define REGISTER_SUBACCOUNT_CM_CLASS "register-subaccount"
 
48
#define REGISTER_GL_CM_CLASS         "register-gl"
 
49
#define REGISTER_TEMPLATE_CM_CLASS   "register-template"
 
50
 
 
51
 
 
52
struct gnc_ledger_display
 
53
{
 
54
  GUID leader;
 
55
 
 
56
  Query *query;
 
57
 
 
58
  GNCLedgerDisplayType ld_type;
 
59
 
 
60
  SplitRegister *reg;
 
61
 
 
62
  gboolean loading;
 
63
  gboolean use_double_line_default;
 
64
 
 
65
  GNCLedgerDisplayDestroy destroy;
 
66
  GNCLedgerDisplayGetParent get_parent;
 
67
 
 
68
  gpointer user_data;
 
69
 
 
70
  gint component_id;
 
71
};
 
72
 
 
73
 
 
74
/** GLOBALS *********************************************************/
 
75
static QofLogModule log_module = GNC_MOD_LEDGER;
 
76
 
 
77
 
 
78
/** Declarations ****************************************************/
 
79
static GNCLedgerDisplay *
 
80
gnc_ledger_display_internal (Account *lead_account, Query *q,
 
81
                             GNCLedgerDisplayType ld_type,
 
82
                             SplitRegisterType reg_type,
 
83
                             SplitRegisterStyle style,
 
84
                             gboolean use_double_line,
 
85
                             gboolean is_template);
 
86
static void gnc_ledger_display_refresh_internal (GNCLedgerDisplay *ld,
 
87
                                                 GList *splits);
 
88
 
 
89
 
 
90
/** Implementations *************************************************/
 
91
 
 
92
Account *
 
93
gnc_ledger_display_leader (GNCLedgerDisplay *ld)
 
94
{
 
95
  if (!ld)
 
96
    return NULL;
 
97
 
 
98
  return xaccAccountLookup (&ld->leader, gnc_get_current_book ());
 
99
}
 
100
 
 
101
GNCLedgerDisplayType
 
102
gnc_ledger_display_type (GNCLedgerDisplay *ld)
 
103
{
 
104
  if (!ld)
 
105
    return -1;
 
106
 
 
107
  return ld->ld_type;
 
108
}
 
109
 
 
110
void
 
111
gnc_ledger_display_set_user_data (GNCLedgerDisplay *ld, gpointer user_data)
 
112
{
 
113
  if (!ld)
 
114
    return;
 
115
 
 
116
  ld->user_data = user_data;
 
117
}
 
118
 
 
119
gpointer
 
120
gnc_ledger_display_get_user_data (GNCLedgerDisplay *ld)
 
121
{
 
122
  if (!ld)
 
123
    return NULL;
 
124
 
 
125
  return ld->user_data;
 
126
}
 
127
 
 
128
void
 
129
gnc_ledger_display_set_handlers (GNCLedgerDisplay *ld,
 
130
                                 GNCLedgerDisplayDestroy destroy,
 
131
                                 GNCLedgerDisplayGetParent get_parent)
 
132
{
 
133
  if (!ld)
 
134
    return;
 
135
 
 
136
  ld->destroy = destroy;
 
137
  ld->get_parent = get_parent;
 
138
}
 
139
 
 
140
SplitRegister *
 
141
gnc_ledger_display_get_split_register (GNCLedgerDisplay *ld)
 
142
{
 
143
  if (!ld)
 
144
    return NULL;
 
145
 
 
146
  return ld->reg;
 
147
}
 
148
 
 
149
Query *
 
150
gnc_ledger_display_get_query (GNCLedgerDisplay *ld)
 
151
{
 
152
  if (!ld)
 
153
    return NULL;
 
154
 
 
155
  return ld->query;
 
156
}
 
157
 
 
158
static gboolean
 
159
find_by_leader (gpointer find_data, gpointer user_data)
 
160
{
 
161
  Account *account = find_data;
 
162
  GNCLedgerDisplay *ld = user_data;
 
163
 
 
164
  if (!account || !ld)
 
165
    return FALSE;
 
166
 
 
167
  return (account == gnc_ledger_display_leader (ld));
 
168
}
 
169
 
 
170
static gboolean
 
171
find_by_query (gpointer find_data, gpointer user_data)
 
172
{
 
173
  Query *q = find_data;
 
174
  GNCLedgerDisplay *ld = user_data;
 
175
 
 
176
  if (!q || !ld)
 
177
    return FALSE;
 
178
 
 
179
  return ld->query == q;
 
180
}
 
181
 
 
182
static gboolean
 
183
find_by_reg (gpointer find_data, gpointer user_data)
 
184
{
 
185
  SplitRegister *reg = find_data;
 
186
  GNCLedgerDisplay *ld = user_data;
 
187
 
 
188
  if (!reg || !ld)
 
189
    return FALSE;
 
190
 
 
191
  return ld->reg == reg;
 
192
}
 
193
 
 
194
static SplitRegisterStyle
 
195
gnc_get_default_register_style (GNCAccountType type)
 
196
{
 
197
  SplitRegisterStyle new_style = REG_STYLE_LEDGER;
 
198
  gchar *style_string;
 
199
 
 
200
  switch (type) {
 
201
#if 0
 
202
  case ACCT_TYPE_PAYABLE:
 
203
  case ACCT_TYPE_RECEIVABLE:
 
204
    new_style = REG_STYLE_LEDGER;
 
205
    break;
 
206
#endif
 
207
 
 
208
  default:
 
209
    style_string = gnc_gconf_get_string(GCONF_GENERAL_REGISTER,
 
210
                                        "default_style", NULL);
 
211
    if (safe_strcmp(style_string, "journal") == 0)
 
212
      new_style = REG_STYLE_JOURNAL;
 
213
    else if (safe_strcmp(style_string, "auto_ledger") == 0)
 
214
      new_style = REG_STYLE_AUTO_LEDGER;
 
215
    else
 
216
      new_style = REG_STYLE_LEDGER;
 
217
 
 
218
    if (style_string != NULL)
 
219
      g_free(style_string);
 
220
 
 
221
    break;
 
222
  }
 
223
 
 
224
  return new_style;
 
225
}
 
226
 
 
227
static gpointer
 
228
look_for_portfolio_cb (Account *account, gpointer data)
 
229
{
 
230
    return xaccAccountIsPriced(account) ? (gpointer) PORTFOLIO_LEDGER : NULL;
 
231
}
 
232
 
 
233
static SplitRegisterType
 
234
gnc_get_reg_type (Account *leader, GNCLedgerDisplayType ld_type)
 
235
{
 
236
  GNCAccountType account_type;
 
237
  SplitRegisterType reg_type;
 
238
 
 
239
  if (ld_type == LD_GL)
 
240
    return GENERAL_LEDGER;
 
241
 
 
242
  account_type = xaccAccountGetType (leader);
 
243
 
 
244
  if (ld_type == LD_SINGLE)
 
245
  {
 
246
    switch (account_type)
 
247
    {
 
248
      case ACCT_TYPE_BANK:
 
249
        return BANK_REGISTER;
 
250
 
 
251
      case ACCT_TYPE_CASH:
 
252
        return CASH_REGISTER;
 
253
 
 
254
      case ACCT_TYPE_ASSET:
 
255
        return ASSET_REGISTER;
 
256
 
 
257
      case ACCT_TYPE_CREDIT:
 
258
        return CREDIT_REGISTER;
 
259
 
 
260
      case ACCT_TYPE_LIABILITY:
 
261
        return LIABILITY_REGISTER;
 
262
 
 
263
      case ACCT_TYPE_PAYABLE:
 
264
        return PAYABLE_REGISTER;
 
265
 
 
266
      case ACCT_TYPE_RECEIVABLE:
 
267
        return RECEIVABLE_REGISTER;
 
268
 
 
269
      case ACCT_TYPE_STOCK:
 
270
      case ACCT_TYPE_MUTUAL:
 
271
        return STOCK_REGISTER;
 
272
 
 
273
      case ACCT_TYPE_INCOME:
 
274
        return INCOME_REGISTER;
 
275
 
 
276
      case ACCT_TYPE_EXPENSE:
 
277
        return EXPENSE_REGISTER;
 
278
 
 
279
      case ACCT_TYPE_EQUITY:
 
280
        return EQUITY_REGISTER;
 
281
 
 
282
      case ACCT_TYPE_CURRENCY:
 
283
        return CURRENCY_REGISTER;
 
284
 
 
285
      default:
 
286
        PERR ("unknown account type %d\n", account_type);
 
287
        return BANK_REGISTER;
 
288
    }
 
289
  }
 
290
 
 
291
  if (ld_type != LD_SUBACCOUNT)
 
292
  {
 
293
    PERR ("unknown ledger type %d\n", ld_type);
 
294
    return BANK_REGISTER;
 
295
  }
 
296
 
 
297
  switch (account_type)
 
298
  {
 
299
    case ACCT_TYPE_BANK:
 
300
    case ACCT_TYPE_CASH:
 
301
    case ACCT_TYPE_ASSET:
 
302
    case ACCT_TYPE_CREDIT:
 
303
    case ACCT_TYPE_LIABILITY:
 
304
    case ACCT_TYPE_RECEIVABLE:
 
305
    case ACCT_TYPE_PAYABLE:
 
306
    {
 
307
      /* If any of the sub-accounts have ACCT_TYPE_STOCK or
 
308
       * ACCT_TYPE_MUTUAL types, then we must use the PORTFOLIO_LEDGER
 
309
       * ledger. Otherwise, a plain old GENERAL_LEDGER will do. */
 
310
      gpointer ret;
 
311
      reg_type = GENERAL_LEDGER;
 
312
 
 
313
      ret = gnc_account_foreach_descendant_until(leader, look_for_portfolio_cb, NULL);
 
314
      if (ret) reg_type = PORTFOLIO_LEDGER;
 
315
      break;
 
316
    }
 
317
 
 
318
    case ACCT_TYPE_STOCK:
 
319
    case ACCT_TYPE_MUTUAL:
 
320
    case ACCT_TYPE_CURRENCY:
 
321
      reg_type = PORTFOLIO_LEDGER;
 
322
      break;
 
323
 
 
324
    case ACCT_TYPE_INCOME:
 
325
    case ACCT_TYPE_EXPENSE:
 
326
      reg_type = INCOME_LEDGER;
 
327
      break;
 
328
 
 
329
    case ACCT_TYPE_EQUITY:
 
330
      reg_type = GENERAL_LEDGER;
 
331
      break;
 
332
 
 
333
    default:
 
334
      PERR ("unknown account type:%d", account_type);
 
335
      reg_type = GENERAL_LEDGER;
 
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
 
345
gnc_ledger_display_default_double_line (GNCLedgerDisplay *gld)
 
346
{
 
347
  return (gld->use_double_line_default ||
 
348
          gnc_gconf_get_bool(GCONF_GENERAL_REGISTER, "double_line_mode", NULL));
 
349
}
 
350
 
 
351
/* Opens up a register window to display a single account */
 
352
GNCLedgerDisplay *
 
353
gnc_ledger_display_simple (Account *account)
 
354
{
 
355
  SplitRegisterType reg_type;
 
356
  GNCAccountType acc_type = xaccAccountGetType (account);
 
357
  gboolean use_double_line;
 
358
 
 
359
  switch (acc_type) {
 
360
  case ACCT_TYPE_PAYABLE:
 
361
  case ACCT_TYPE_RECEIVABLE:
 
362
    use_double_line = TRUE;
 
363
    break;
 
364
  default:
 
365
    use_double_line = FALSE;
 
366
    break;
 
367
  }
 
368
 
 
369
  reg_type = gnc_get_reg_type (account, LD_SINGLE);
 
370
 
 
371
  return gnc_ledger_display_internal (account, NULL, LD_SINGLE, reg_type,
 
372
                                      gnc_get_default_register_style(acc_type),
 
373
                                      use_double_line, FALSE);
 
374
}
 
375
 
 
376
/* Opens up a register window to display an account, and all of its
 
377
 *   children, in the same window */
 
378
GNCLedgerDisplay *
 
379
gnc_ledger_display_subaccounts (Account *account)
 
380
{
 
381
  SplitRegisterType reg_type;
 
382
 
 
383
  reg_type = gnc_get_reg_type (account, LD_SUBACCOUNT);
 
384
 
 
385
  return gnc_ledger_display_internal (account, NULL, LD_SUBACCOUNT,
 
386
                                      reg_type, REG_STYLE_JOURNAL, FALSE,
 
387
                                      FALSE);
 
388
}
 
389
 
 
390
/* Opens up a general ledger window. */
 
391
GNCLedgerDisplay *
 
392
gnc_ledger_display_gl (void)
 
393
{
 
394
  Query *query;
 
395
  time_t start;
 
396
  struct tm tm;
 
397
 
 
398
  query = xaccMallocQuery ();
 
399
 
 
400
  xaccQuerySetBook (query, gnc_get_current_book());
 
401
 
 
402
  /* In lieu of not "mis-using" some portion of the infrastructure by writing
 
403
   * a bunch of new code, we just filter out the accounts of the template
 
404
   * transactions.  While these are in a seperate Account trees just for this
 
405
   * reason, the query engine makes no distinction between Account trees.
 
406
   * See Gnome Bug 86302.
 
407
   *         -- jsled */
 
408
  {
 
409
    Account *tRoot;
 
410
    GList *al;
 
411
    
 
412
    tRoot = gnc_book_get_template_root( gnc_get_current_book() );
 
413
    al = gnc_account_get_descendants( tRoot );
 
414
    xaccQueryAddAccountMatch( query, al, GUID_MATCH_NONE, QUERY_AND );
 
415
    g_list_free (al);
 
416
    al = NULL;
 
417
    tRoot = NULL;
 
418
  }
 
419
 
 
420
  gnc_tm_get_today_start(&tm);
 
421
  tm.tm_mon--; /* Default the register to the last month's worth of transactions. */
 
422
  start = mktime (&tm);
 
423
  xaccQueryAddDateMatchTT (query, 
 
424
                           TRUE, start, 
 
425
                           FALSE, 0, 
 
426
                           QUERY_AND);
 
427
 
 
428
  return gnc_ledger_display_internal (NULL, query, LD_GL,
 
429
                                      GENERAL_LEDGER,
 
430
                                      REG_STYLE_JOURNAL, FALSE, FALSE);
 
431
}
 
432
 
 
433
/**
 
434
 * @param id: The string version of the GUID of the context of template
 
435
 * transaction being edited in this template GL.  As used by scheduled
 
436
 * transactions, this is the GUID of the SX itself which is magically the
 
437
 * *name* of the (template) account which contains the transactions for this
 
438
 * scheduled transaction.  That's right.  The stringified GUID of the SX is
 
439
 * the name of the SX'es template account.
 
440
 **/
 
441
GNCLedgerDisplay *
 
442
gnc_ledger_display_template_gl (char *id)
 
443
{
 
444
  GNCBook *book;
 
445
  Query *q;
 
446
  GNCLedgerDisplay *ld;
 
447
  SplitRegister *sr;
 
448
  Account *root, *acct;
 
449
  gboolean isTemplateModeTrue;
 
450
 
 
451
  acct = NULL;
 
452
  isTemplateModeTrue = TRUE;
 
453
 
 
454
  q = xaccMallocQuery ();
 
455
 
 
456
  book = gnc_get_current_book ();
 
457
  xaccQuerySetBook (q, book);
 
458
 
 
459
  if ( id != NULL ) {
 
460
    root = gnc_book_get_template_root (book);
 
461
    acct = gnc_account_lookup_by_name(root, id);
 
462
    g_assert( acct );
 
463
    xaccQueryAddSingleAccountMatch (q, acct, QUERY_AND);
 
464
  }
 
465
 
 
466
  ld = gnc_ledger_display_internal (NULL, q, LD_GL,
 
467
                                    SEARCH_LEDGER,
 
468
                                    REG_STYLE_JOURNAL,
 
469
                                    FALSE,
 
470
                                    isTemplateModeTrue);
 
471
 
 
472
  sr = gnc_ledger_display_get_split_register (ld);
 
473
  if ( acct ) {
 
474
    gnc_split_register_set_template_account (sr, acct);
 
475
  }
 
476
 
 
477
  return ld;
 
478
}
 
479
 
 
480
gncUIWidget
 
481
gnc_ledger_display_get_parent( GNCLedgerDisplay *ld )
 
482
{
 
483
  if ( ld == NULL )
 
484
    return NULL;
 
485
 
 
486
  if ( ld->get_parent == NULL )
 
487
    return NULL;
 
488
 
 
489
  return ld->get_parent( ld );
 
490
}
 
491
 
 
492
static gncUIWidget
 
493
gnc_ledger_display_parent (void *user_data)
 
494
{
 
495
  GNCLedgerDisplay *ld = user_data;
 
496
  return gnc_ledger_display_get_parent( ld );
 
497
}
 
498
 
 
499
static void
 
500
gnc_ledger_display_set_watches (GNCLedgerDisplay *ld, GList *splits)
 
501
{
 
502
  GList *node;
 
503
 
 
504
  gnc_gui_component_clear_watches (ld->component_id);
 
505
 
 
506
  gnc_gui_component_watch_entity_type (ld->component_id,
 
507
                                       GNC_ID_ACCOUNT,
 
508
                                       QOF_EVENT_MODIFY | QOF_EVENT_DESTROY
 
509
                                       | GNC_EVENT_ITEM_CHANGED);
 
510
 
 
511
  for (node = splits; node; node = node->next)
 
512
  {
 
513
    Split *split = node->data;
 
514
    Transaction *trans = xaccSplitGetParent (split);
 
515
 
 
516
    gnc_gui_component_watch_entity (ld->component_id,
 
517
                                    xaccTransGetGUID (trans),
 
518
                                    QOF_EVENT_MODIFY);
 
519
  }
 
520
}
 
521
 
 
522
static void
 
523
refresh_handler (GHashTable *changes, gpointer user_data)
 
524
{
 
525
  GNCLedgerDisplay *ld = user_data;
 
526
  const EventInfo *info;
 
527
  gboolean has_leader;
 
528
  GList *splits;
 
529
 
 
530
  if (ld->loading)
 
531
    return;
 
532
 
 
533
  has_leader = (ld->ld_type == LD_SINGLE || ld->ld_type == LD_SUBACCOUNT);
 
534
 
 
535
  if (has_leader)
 
536
  {
 
537
    Account *leader = gnc_ledger_display_leader (ld);
 
538
    if (!leader)
 
539
    {
 
540
      gnc_close_gui_component (ld->component_id);
 
541
      return;
 
542
    }
 
543
  }
 
544
 
 
545
  if (changes && has_leader)
 
546
  {
 
547
    info = gnc_gui_get_entity_events (changes, &ld->leader);
 
548
    if (info && (info->event_mask & QOF_EVENT_DESTROY))
 
549
    {
 
550
      gnc_close_gui_component (ld->component_id);
 
551
      return;
 
552
    }
 
553
  }
 
554
 
 
555
  /* Its not clear if we should re-run the query, or if we should
 
556
   * just use qof_query_last_run().  Its possible that the dates
 
557
   * changed, requiring a full new query.  Similar considerations
 
558
   * needed for multi-user mode.
 
559
   */
 
560
  splits = qof_query_run (ld->query);
 
561
 
 
562
  gnc_ledger_display_set_watches (ld, splits);
 
563
 
 
564
  gnc_ledger_display_refresh_internal (ld, splits);
 
565
}
 
566
 
 
567
static void
 
568
close_handler (gpointer user_data)
 
569
{
 
570
  GNCLedgerDisplay *ld = user_data;
 
571
 
 
572
  if (!ld)
 
573
    return;
 
574
 
 
575
  gnc_unregister_gui_component (ld->component_id);
 
576
 
 
577
  if (ld->destroy)
 
578
      ld->destroy (ld);
 
579
 
 
580
  gnc_split_register_destroy (ld->reg);
 
581
  ld->reg = NULL;
 
582
 
 
583
  xaccFreeQuery (ld->query);
 
584
  ld->query = NULL;
 
585
 
 
586
  g_free (ld);
 
587
}
 
588
 
 
589
static void
 
590
gnc_ledger_display_make_query (GNCLedgerDisplay *ld,
 
591
                               gint limit,
 
592
                               SplitRegisterType type)
 
593
{
 
594
  Account *leader;
 
595
  GList *accounts;
 
596
 
 
597
  if (!ld)
 
598
    return;
 
599
 
 
600
  switch (ld->ld_type)
 
601
  {
 
602
    case LD_SINGLE:
 
603
    case LD_SUBACCOUNT:
 
604
      break;
 
605
 
 
606
    case LD_GL:
 
607
      return;
 
608
 
 
609
    default:
 
610
      PERR ("unknown ledger type: %d", ld->ld_type);
 
611
      return;
 
612
  }
 
613
 
 
614
  xaccFreeQuery (ld->query);
 
615
  ld->query = xaccMallocQuery ();
 
616
 
 
617
  /* This is a bit of a hack. The number of splits should be
 
618
   * configurable, or maybe we should go back a time range instead
 
619
   * of picking a number, or maybe we should be able to exclude
 
620
   * based on reconciled status. Anyway, this works for now. */
 
621
  if ((limit != 0) && (type != SEARCH_LEDGER))
 
622
    xaccQuerySetMaxSplits (ld->query, limit);
 
623
 
 
624
  xaccQuerySetBook (ld->query, gnc_get_current_book());
 
625
 
 
626
  leader = gnc_ledger_display_leader (ld);
 
627
 
 
628
  if (ld->ld_type == LD_SUBACCOUNT)
 
629
    accounts = gnc_account_get_descendants (leader);
 
630
  else
 
631
    accounts = NULL;
 
632
 
 
633
  accounts = g_list_prepend (accounts, leader);
 
634
 
 
635
  xaccQueryAddAccountMatch (ld->query, accounts,
 
636
                            GUID_MATCH_ANY, QUERY_AND);
 
637
 
 
638
  g_list_free (accounts);
 
639
}
 
640
 
 
641
/* Opens up a ledger window for an arbitrary query. */
 
642
GNCLedgerDisplay *
 
643
gnc_ledger_display_query (Query *query, SplitRegisterType type,
 
644
                          SplitRegisterStyle style)
 
645
{
 
646
  return gnc_ledger_display_internal (NULL, query, LD_GL, type, style,
 
647
                                      FALSE, FALSE);
 
648
}
 
649
 
 
650
static GNCLedgerDisplay *
 
651
gnc_ledger_display_internal (Account *lead_account, Query *q,
 
652
                             GNCLedgerDisplayType ld_type,
 
653
                             SplitRegisterType reg_type,
 
654
                             SplitRegisterStyle style,
 
655
                             gboolean use_double_line,
 
656
                             gboolean is_template )
 
657
{
 
658
  GNCLedgerDisplay *ld;
 
659
  gint limit;
 
660
  const char *class;
 
661
  GList *splits;
 
662
 
 
663
  switch (ld_type)
 
664
  {
 
665
    case LD_SINGLE:
 
666
      class = REGISTER_SINGLE_CM_CLASS;
 
667
 
 
668
      if (reg_type >= NUM_SINGLE_REGISTER_TYPES)
 
669
      {
 
670
        PERR ("single-account register with wrong split register type");
 
671
        return NULL;
 
672
      }
 
673
 
 
674
      if (!lead_account)
 
675
      {
 
676
        PERR ("single-account register with no account specified");
 
677
        return NULL;
 
678
      }
 
679
 
 
680
      if (q)
 
681
      {
 
682
        PWARN ("single-account register with external query");
 
683
        q = NULL;
 
684
      }
 
685
 
 
686
      ld = gnc_find_first_gui_component (class, find_by_leader, lead_account);
 
687
      if (ld)
 
688
        return ld;
 
689
 
 
690
      break;
 
691
 
 
692
    case LD_SUBACCOUNT:
 
693
      class = REGISTER_SUBACCOUNT_CM_CLASS;
 
694
 
 
695
      if (!lead_account)
 
696
      {
 
697
        PERR ("sub-account register with no lead account");
 
698
        return NULL;
 
699
      }
 
700
 
 
701
      if (q)
 
702
      {
 
703
        PWARN ("account register with external query");
 
704
        q = NULL;
 
705
      }
 
706
 
 
707
      ld = gnc_find_first_gui_component (class, find_by_leader, lead_account);
 
708
      if (ld)
 
709
        return ld;
 
710
 
 
711
      break;
 
712
 
 
713
    case LD_GL:
 
714
      class = REGISTER_GL_CM_CLASS;
 
715
 
 
716
      if (!q)
 
717
      {
 
718
        PWARN ("general ledger with no query");
 
719
      }
 
720
 
 
721
      break;
 
722
 
 
723
    default:
 
724
      PERR ("bad ledger type: %d", ld_type);
 
725
      return NULL;
 
726
 
 
727
  }
 
728
 
 
729
  ld = g_new (GNCLedgerDisplay, 1);
 
730
 
 
731
  ld->leader = *xaccAccountGetGUID (lead_account);
 
732
  ld->query = NULL;
 
733
  ld->ld_type = ld_type;
 
734
  ld->loading = FALSE;
 
735
  ld->destroy = NULL;
 
736
  ld->get_parent = NULL;
 
737
  ld->user_data = NULL;
 
738
 
 
739
  limit = gnc_gconf_get_float(GCONF_GENERAL_REGISTER, "max_transactions", NULL);
 
740
 
 
741
  /* set up the query filter */
 
742
  if (q)
 
743
    ld->query = xaccQueryCopy (q);
 
744
  else
 
745
    gnc_ledger_display_make_query (ld, limit, reg_type);
 
746
 
 
747
  ld->component_id = gnc_register_gui_component (class,
 
748
                                                 refresh_handler,
 
749
                                                 close_handler, ld);
 
750
 
 
751
  /******************************************************************\
 
752
   * The main register window itself                                *
 
753
  \******************************************************************/
 
754
 
 
755
  ld->use_double_line_default = use_double_line;
 
756
  ld->reg = gnc_split_register_new (reg_type, style, use_double_line,
 
757
                                    is_template);
 
758
 
 
759
  gnc_split_register_set_data (ld->reg, ld, gnc_ledger_display_parent);
 
760
 
 
761
  splits = qof_query_run (ld->query);
 
762
 
 
763
  gnc_ledger_display_set_watches (ld, splits);
 
764
 
 
765
  gnc_ledger_display_refresh_internal (ld, splits);
 
766
 
 
767
  return ld;
 
768
}
 
769
 
 
770
void
 
771
gnc_ledger_display_set_query (GNCLedgerDisplay *ledger_display, Query *q)
 
772
{
 
773
  if (!ledger_display || !q)
 
774
    return;
 
775
 
 
776
  g_return_if_fail (ledger_display->ld_type == LD_GL);
 
777
 
 
778
  xaccFreeQuery (ledger_display->query);
 
779
  ledger_display->query = xaccQueryCopy (q);
 
780
}
 
781
 
 
782
GNCLedgerDisplay *
 
783
gnc_ledger_display_find_by_query (Query *q)
 
784
{
 
785
  if (!q)
 
786
    return NULL;
 
787
 
 
788
  return gnc_find_first_gui_component (REGISTER_GL_CM_CLASS, find_by_query, q);
 
789
}
 
790
 
 
791
/********************************************************************\
 
792
 * refresh only the indicated register window                       *
 
793
\********************************************************************/
 
794
 
 
795
static void
 
796
gnc_ledger_display_refresh_internal (GNCLedgerDisplay *ld, GList *splits)
 
797
{
 
798
  if (!ld || ld->loading)
 
799
    return;
 
800
 
 
801
  if (!gnc_split_register_full_refresh_ok (ld->reg))
 
802
    return;
 
803
 
 
804
  ld->loading = TRUE;
 
805
 
 
806
  gnc_split_register_load (ld->reg, splits,
 
807
                           gnc_ledger_display_leader (ld));
 
808
 
 
809
  ld->loading = FALSE;
 
810
}
 
811
 
 
812
void
 
813
gnc_ledger_display_refresh (GNCLedgerDisplay *ld)
 
814
{
 
815
  if (!ld || ld->loading)
 
816
    return;
 
817
 
 
818
  gnc_ledger_display_refresh_internal (ld, xaccQueryGetSplits (ld->query));
 
819
}
 
820
 
 
821
void
 
822
gnc_ledger_display_refresh_by_split_register (SplitRegister *reg)
 
823
{
 
824
  GNCLedgerDisplay *ld;
 
825
 
 
826
  if (!reg)
 
827
    return;
 
828
 
 
829
  ld = gnc_find_first_gui_component (REGISTER_SINGLE_CM_CLASS,
 
830
                                     find_by_reg, reg);
 
831
  if (ld)
 
832
  {
 
833
    gnc_ledger_display_refresh (ld);
 
834
    return;
 
835
  }
 
836
 
 
837
  ld = gnc_find_first_gui_component (REGISTER_SUBACCOUNT_CM_CLASS,
 
838
                                     find_by_reg, reg);
 
839
  if (ld)
 
840
  {
 
841
    gnc_ledger_display_refresh (ld);
 
842
    return;
 
843
  }
 
844
 
 
845
  ld = gnc_find_first_gui_component (REGISTER_GL_CM_CLASS,
 
846
                                     find_by_reg, reg);
 
847
  if (ld)
 
848
  {
 
849
    gnc_ledger_display_refresh (ld);
 
850
    return;
 
851
  }
 
852
 
 
853
  ld = gnc_find_first_gui_component (REGISTER_TEMPLATE_CM_CLASS,
 
854
                                     find_by_reg, reg );
 
855
  if (ld)
 
856
  {
 
857
    gnc_ledger_display_refresh (ld);
 
858
  }
 
859
}
 
860
 
 
861
void
 
862
gnc_ledger_display_close (GNCLedgerDisplay *ld)
 
863
{
 
864
  if (!ld)
 
865
    return;
 
866
 
 
867
  gnc_close_gui_component (ld->component_id);
 
868
}