GnuCash c935c2f+
Loading...
Searching...
No Matches
split-register-load.c
1/********************************************************************\
2 * split-register-load.c -- split register loading code *
3 * Copyright (C) 1998-2000 Linas Vepstas <linas@linas.org> *
4 * Copyright (C) 2000 Dave Peticolas *
5 * *
6 * This program is free software; you can redistribute it and/or *
7 * modify it under the terms of the GNU General Public License as *
8 * published by the Free Software Foundation; either version 2 of *
9 * the License, or (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License*
17 * along with this program; if not, contact: *
18 * *
19 * Free Software Foundation Voice: +1-617-542-5942 *
20 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
21 * Boston, MA 02110-1301, USA gnu@gnu.org *
22 * *
23\********************************************************************/
24
25#include <config.h>
26
27#include <glib/gi18n.h>
28#include <stdbool.h>
29#include <stdio.h>
30
31#include "Account.h"
32#include "Transaction.h"
33#include "account-quickfill.h"
34#include "combocell.h"
35#include "completioncell.h"
36#include "gnc-component-manager.h"
37#include "qof.h"
38#include "gnc-ui-util.h"
39#include "gnc-gui-query.h"
40#include "numcell.h"
41#include "quickfillcell.h"
42#include "doclinkcell.h"
43#include "recncell.h"
44#include "split-register.h"
45#include "split-register-p.h"
46#include "engine-helpers.h"
47#include "gnc-prefs.h"
48#include "pricecell.h"
49
50
51/* This static indicates the debugging module that this .o belongs to. */
52static QofLogModule log_module = GNC_MOD_LEDGER;
53
54
55static void gnc_split_register_load_xfer_cells (SplitRegister* reg,
56 Account* base_account);
57
58static void
59gnc_split_register_load_recn_cells (SplitRegister* reg)
60{
61 RecnCell* cell;
62 const char* s;
63
64 if (!reg) return;
65
66 cell = (RecnCell*)
67 gnc_table_layout_get_cell (reg->table->layout, RECN_CELL);
68
69 if (!cell) return;
70
71 s = gnc_get_reconcile_valid_flags();
73 gnc_recn_cell_set_flag_order (cell, gnc_get_reconcile_flag_order());
74 gnc_recn_cell_set_string_getter (cell, gnc_get_reconcile_str);
75}
76
77static void
78gnc_split_register_load_doclink_cells (SplitRegister* reg)
79{
80 Doclinkcell *cell;
81 const char * s;
82
83 if (!reg) return;
84
85 cell = (Doclinkcell *)
86 gnc_table_layout_get_cell (reg->table->layout, DOCLINK_CELL);
87
88 if (!cell) return;
89
90 /* FIXME: These should get moved to an i18n function */
93 gnc_doclink_cell_set_flag_order (cell, gnc_get_doclink_flag_order ());
94 gnc_doclink_cell_set_string_getter (cell, gnc_get_doclink_str);
95 gnc_doclink_cell_set_read_only (cell, TRUE);
96}
97
98static void
99gnc_split_register_load_type_cells (SplitRegister* reg)
100{
101 RecnCell* cell;
102
103 if (!reg) return;
104
105 cell = (RecnCell*)
106 gnc_table_layout_get_cell (reg->table->layout, TYPE_CELL);
107
108 if (!cell) return;
109
110 /* FIXME: These should get moved to an i18n function */
111 gnc_recn_cell_set_valid_flags (cell, "IP?", 'I');
112 gnc_recn_cell_set_flag_order (cell, "IP");
113 gnc_recn_cell_set_read_only (cell, TRUE);
114}
115
116static void
117gnc_split_register_load_desc_cells (SplitRegister* reg)
118{
119 CompletionCell *cell;
120
121 if (!reg) return;
122
123 cell = (CompletionCell *)
124 gnc_table_layout_get_cell (reg->table->layout, DESC_CELL);
125
126 if (!cell) return;
127
129}
130
193static void
194gnc_split_register_add_transaction (SplitRegister* reg,
195 Transaction* trans,
196 Split* split,
197 CellBlock* lead_cursor,
198 CellBlock* split_cursor,
199 gboolean visible_splits,
200 gboolean start_primary_color,
201 gboolean add_empty,
202 Transaction* find_trans,
203 Split* find_split,
204 CursorClass find_class,
205 int* new_split_row,
206 VirtualCellLocation* vcell_loc)
207{
208 GList* node;
209
210 g_return_if_fail (reg);
211 g_return_if_fail (vcell_loc);
212
213 if (split == find_split)
214 *new_split_row = vcell_loc->virt_row;
215
216 /* Set the "leading" virtual cell. */
217 gnc_table_set_vcell (reg->table, lead_cursor, xaccSplitGetGUID (split),
218 TRUE, start_primary_color, *vcell_loc);
219 vcell_loc->virt_row++;
220
221 /* Continue setting up virtual cells in a column, using a row for each
222 * split in the transaction. */
223 for (node = xaccTransGetSplitList (trans); node; node = node->next)
224 {
225 Split* secondary = node->data;
226
227 if (!xaccTransStillHasSplit (trans, secondary)) continue;
228 if (secondary == find_split && find_class == CURSOR_CLASS_SPLIT)
229 *new_split_row = vcell_loc->virt_row;
230
231 gnc_table_set_vcell (reg->table, split_cursor,
232 xaccSplitGetGUID (secondary),
233 visible_splits, TRUE, *vcell_loc);
234 vcell_loc->virt_row++;
235 }
236
237 /* If requested, add an empty split row at the end. */
238 if (add_empty)
239 {
240 if (find_trans == trans && find_split == NULL &&
241 find_class == CURSOR_CLASS_SPLIT)
242 *new_split_row = vcell_loc->virt_row;
243
244 gnc_table_set_vcell (reg->table, split_cursor, xaccSplitGetGUID (NULL),
245 FALSE, TRUE, *vcell_loc);
246 vcell_loc->virt_row++;
247 }
248}
249
250static gint
251_find_split_with_parent_txn (gconstpointer a, gconstpointer b)
252{
253 Split* split = (Split*)a;
254 Transaction* txn = (Transaction*)b;
255
256 return xaccSplitGetParent (split) == txn ? 0 : 1;
257}
258
259static void
260add_quickfill_completions (TableLayout* layout, Transaction* trans,
261 Split* split, gboolean has_last_num)
262{
263 gnc_quickfill_cell_add_completion (
264 (QuickFillCell*) gnc_table_layout_get_cell (layout, NOTES_CELL),
265 xaccTransGetNotes (trans));
266
267 if (!has_last_num)
268 gnc_num_cell_set_last_num (
269 (NumCell*) gnc_table_layout_get_cell (layout, NUM_CELL),
270 gnc_get_num_action (trans, split));
271
272 for (GList *n = xaccTransGetSplitList (trans); n; n = n->next)
273 {
274 Split *s = n->data;
275
276 if (!xaccTransStillHasSplit (trans, s))
277 continue;
278
279 gnc_quickfill_cell_add_completion (
280 (QuickFillCell*) gnc_table_layout_get_cell (layout, MEMO_CELL),
281 xaccSplitGetMemo (s));
282 }
283}
284
285static Split*
286create_blank_split (Account* default_account, SRInfo* info)
287{
288 gboolean currency_from_account = TRUE;
289 Split* blank_split = NULL;
290 /* Determine the proper currency to use for this transaction.
291 * if default_account != NULL and default_account->commodity is
292 * a currency, then use that. Otherwise use the default currency.
293 */
294 gnc_commodity* currency = gnc_account_or_default_currency (default_account,
295 &currency_from_account);
296
297 if (default_account != NULL && !currency_from_account)
298 {
299 /* If we don't have a currency then pop up a warning dialog */
300 gnc_info_dialog (NULL, "%s",
301 _ ("Could not determine the account currency. "
302 "Using the default currency provided by your system."));
303 }
304
305 gnc_suspend_gui_refresh();
306 Transaction *pending_trans = xaccTransLookup (&info->pending_trans_guid,
307 gnc_get_current_book());
308
309 if (!pending_trans)
310 {
311 pending_trans = xaccMallocTransaction (gnc_get_current_book());
312 xaccTransBeginEdit (pending_trans);
313 xaccTransSetCurrency (pending_trans, currency);
315 info->last_date_entered);
316 info->pending_trans_guid = *xaccTransGetGUID (pending_trans);
317 }
318
319 blank_split = xaccMallocSplit (gnc_get_current_book());
320 xaccSplitSetParent (blank_split, pending_trans);
321 /* We don't want to commit this transaction yet, because the split
322 doesn't even belong to an account yet. But, we don't want to
323 set this transaction as the pending transaction either, because
324 we want to pretend that it hasn't been changed. We depend on
325 some other code (somewhere) to commit this transaction if we
326 really edit it, even though it's not marked as the pending
327 transaction. */
328
329 info->blank_split_guid = *xaccSplitGetGUID (blank_split);
330 info->blank_split_edited = FALSE;
331 info->auto_complete = FALSE;
332 DEBUG ("created new blank_split=%p", blank_split);
333
334 gnc_resume_gui_refresh();
335 return blank_split;
336}
337
338static void
339change_account_separator (SRInfo* info, Table* table, SplitRegister* reg)
340{
341 info->separator_changed = FALSE;
342
343 /* set the completion character for the xfer cells */
345 (ComboCell*) gnc_table_layout_get_cell (table->layout, MXFRM_CELL),
346 gnc_get_account_separator());
347
349 (ComboCell*) gnc_table_layout_get_cell (table->layout, XFRM_CELL),
350 gnc_get_account_separator());
351
352 /* set the confirmation callback for the reconcile cell */
353 gnc_recn_cell_set_confirm_cb (
354 (RecnCell*) gnc_table_layout_get_cell (table->layout, RECN_CELL),
355 gnc_split_register_recn_cell_confirm, reg);
356}
357
358static void
359update_info (SRInfo* info, SplitRegister* reg)
360{
361 /* Set up the hint transaction, split, transaction split, and column. */
362 info->cursor_hint_trans = gnc_split_register_get_current_trans (reg);
363 info->cursor_hint_split = gnc_split_register_get_current_split (reg);
364 info->cursor_hint_trans_split =
366 info->cursor_hint_cursor_class =
368
369 if (!info->first_pass && !info->quickfill_setup)
370 info->quickfill_setup = TRUE;
371
372 info->hint_set_by_traverse = FALSE;
373 info->traverse_to_new = FALSE;
374 info->exact_traversal = FALSE;
375 info->first_pass = FALSE;
376 info->reg_loaded = TRUE;
377}
378
379static void
380add_completions_from_pre_filter_slist (TableLayout* layout, GList *pre_filter_slist,
381 gboolean first_pass, gboolean quickfill_setup,
382 gboolean has_last_num)
383{
384 GList *node;
385
386 for (node = pre_filter_slist; node; node = node->next)
387 {
388 Split *split = node->data;
389 Transaction *trans = xaccSplitGetParent (split);
390
392 (CompletionCell*) gnc_table_layout_get_cell (layout, DESC_CELL),
394
395 if (!first_pass && !quickfill_setup)
396 add_quickfill_completions (layout, trans, split, has_last_num);
397 }
398}
399
400void
401gnc_split_register_load (SplitRegister* reg, GList* slist,
402 GList* pre_filter_slist, Account* default_account)
403{
404 SRInfo* info;
405 Transaction* pending_trans;
406 CursorBuffer* cursor_buffer;
407 GHashTable* trans_table = NULL;
408 CellBlock* cursor_header;
409 CellBlock* lead_cursor;
410 CellBlock* split_cursor;
411 Transaction* blank_trans;
412 Transaction* find_trans;
413 Transaction* trans;
414 CursorClass find_class;
415 Split* find_trans_split;
416 Split* blank_split;
417 Split* find_split;
418 Split* split;
419 Table* table;
420 GList* node;
421 gnc_commodity *account_comm = NULL;
422
423 gboolean start_primary_color = TRUE;
424 gboolean found_pending = FALSE;
425 gboolean need_divider_upper = FALSE;
426 gboolean found_divider_upper = FALSE;
427 gboolean found_divider = FALSE;
428 gboolean has_last_num = FALSE;
429 gboolean multi_line;
430 gboolean dynamic;
431 gboolean we_own_slist = FALSE;
432 gboolean use_autoreadonly = qof_book_uses_autoreadonly (
433 gnc_get_current_book());
434 gboolean future_after_blank = gnc_prefs_get_bool (
435 GNC_PREFS_GROUP_GENERAL_REGISTER,
436 GNC_PREF_FUTURE_AFTER_BLANK);
437 gboolean added_blank_trans = FALSE;
438
439 VirtualCellLocation vcell_loc;
440 VirtualLocation save_loc;
441
442 int new_trans_split_row = -1;
443 int new_trans_row = -1;
444 int new_split_row = -1;
445 time64 present, autoreadonly_time = 0;
446
447 g_return_if_fail (reg);
448 table = reg->table;
449 g_return_if_fail (table);
450 info = gnc_split_register_get_info (reg);
451 g_return_if_fail (info);
452
453 ENTER ("reg=%p, slist=%p, default_account=%p", reg, slist, default_account);
454
455 blank_split = xaccSplitLookup (&info->blank_split_guid,
456 gnc_get_current_book());
457
458 pending_trans = xaccTransLookup (&info->pending_trans_guid,
459 gnc_get_current_book());
460
461 if (default_account)
462 account_comm = gnc_account_get_currency_or_parent (default_account);
463
464 if (!account_comm)
465 account_comm = gnc_default_currency ();
466
467 /* Bug 742089: Set the debit and credit cells' print_info to the account */
469 ((PriceCell*) gnc_table_layout_get_cell (table->layout, DEBT_CELL),
470 gnc_commodity_print_info (account_comm, FALSE));
471
473 ((PriceCell*) gnc_table_layout_get_cell (table->layout, CRED_CELL),
474 gnc_commodity_print_info (account_comm, FALSE));
475
477 ((PriceCell*) gnc_table_layout_get_cell (reg->table->layout, PRIC_CELL),
478 gnc_commodity_print_info (account_comm, FALSE));
479
480 /* Only test for linked document glyths once */
481 if (info->first_pass)
482 {
483 gnc_doclink_cell_set_use_glyphs
484 ((Doclinkcell *) gnc_table_layout_get_cell (table->layout, DOCLINK_CELL));
485 }
486
487 /* make sure we have a blank split */
488 if (blank_split == NULL)
489 blank_split = create_blank_split (default_account, info);
490
491 blank_trans = xaccSplitGetParent (blank_split);
492
493 DEBUG ("blank_split=%p, blank_trans=%p, pending_trans=%p",
494 blank_split, blank_trans, pending_trans);
495
496 info->default_account = *xaccAccountGetGUID (default_account);
497
498 // gnc_table_leave_update (table, table->current_cursor_loc);
499
500 multi_line = (reg->style == REG_STYLE_JOURNAL);
501 dynamic = (reg->style == REG_STYLE_AUTO_LEDGER);
502
503 lead_cursor = gnc_split_register_get_passive_cursor (reg);
504 split_cursor = gnc_table_layout_get_cursor (table->layout, CURSOR_SPLIT);
505
506 /* figure out where we are going to. */
507 if (info->traverse_to_new)
508 {
509 find_trans = blank_trans;
510 find_split = NULL;
511 find_trans_split = blank_split;
512 find_class = CURSOR_CLASS_SPLIT;
513 }
514 else
515 {
516 find_trans = info->cursor_hint_trans;
517 find_split = info->cursor_hint_split;
518 find_trans_split = info->cursor_hint_trans_split;
519 find_class = info->cursor_hint_cursor_class;
520 }
521
522 save_loc = table->current_cursor_loc;
523
524 /* If the current cursor has changed we save the values for later
525 * possible restoration. */
526 if (gnc_table_current_cursor_changed (table, TRUE) &&
527 (find_split == gnc_split_register_get_current_split (reg)))
528 {
529 cursor_buffer = gnc_cursor_buffer_new();
530 gnc_table_save_current_cursor (table, cursor_buffer);
531 }
532 else
533 cursor_buffer = NULL;
534
535 /* disable move callback -- we don't want the cascade of
536 * callbacks while we are fiddling with loading the register */
537 gnc_table_control_allow_move (table->control, FALSE);
538
539 /* invalidate the cursor */
540 {
541 VirtualLocation virt_loc;
542
543 gnc_virtual_location_init (&virt_loc);
545 }
546
547 /* make sure that the header is loaded */
548 vcell_loc.virt_row = 0;
549 vcell_loc.virt_col = 0;
550 cursor_header = gnc_table_layout_get_cursor (table->layout, CURSOR_HEADER);
551 gnc_table_set_vcell (table, cursor_header, NULL, TRUE, TRUE, vcell_loc);
552 vcell_loc.virt_row++;
553
554 /* get the current time and reset the dividing row */
555 present = gnc_time64_get_today_end();
556 if (use_autoreadonly)
557 {
558 GDate* d = qof_book_get_autoreadonly_gdate (gnc_get_current_book());
559 // "d" is NULL if use_autoreadonly is FALSE
560 autoreadonly_time = d ? gdate_to_time64 (*d) : 0;
561 g_date_free (d);
562 }
563
564 if (info->first_pass)
565 {
566 if (default_account)
567 {
568 const char* last_num = xaccAccountGetLastNum (default_account);
569
570 if (last_num)
571 {
572 NumCell* cell;
573
574 cell = (NumCell*) gnc_table_layout_get_cell (table->layout, NUM_CELL);
575 gnc_num_cell_set_last_num (cell, last_num);
576 has_last_num = TRUE;
577 }
578 }
579
580 /* load up account names into the transfer combobox menus */
581 gnc_split_register_load_xfer_cells (reg, default_account);
582 gnc_split_register_load_desc_cells (reg);
583 gnc_split_register_load_doclink_cells (reg);
584 gnc_split_register_load_recn_cells (reg);
585 gnc_split_register_load_type_cells (reg);
586 }
587
588 if (info->separator_changed)
589 change_account_separator (info, table, reg);
590
591 table->model->dividing_row_upper = -1;
592 table->model->dividing_row = -1;
593 table->model->dividing_row_lower = -1;
594
595 // Ensure that the transaction and splits being edited are in the split
596 // list we're about to load.
597 if (pending_trans != NULL)
598 {
599 for (node = xaccTransGetSplitList (pending_trans); node; node = node->next)
600 {
601 Split* pending_split = (Split*)node->data;
602 if (!xaccTransStillHasSplit (pending_trans, pending_split)) continue;
603 if (g_list_find (slist, pending_split) != NULL)
604 continue;
605
606 if (g_list_find_custom (slist, pending_trans,
607 _find_split_with_parent_txn) != NULL)
608 continue;
609
610 if (!we_own_slist)
611 {
612 // lazy-copy
613 slist = g_list_copy (slist);
614 we_own_slist = TRUE;
615 }
616 slist = g_list_append (slist, pending_split);
617 }
618 }
619
620 if (multi_line)
621 trans_table = g_hash_table_new (g_direct_hash, g_direct_equal);
622
623 // View reversed add blank transaction at the top
624 if (table->model->reverse_sort && !future_after_blank)
625 {
626 if (blank_trans == find_trans)
627 new_trans_row = vcell_loc.virt_row;
628
629 if (blank_split == find_trans_split)
630 new_trans_split_row = vcell_loc.virt_row;
631
632 /* go to blank on first pass */
633 if (info->first_pass)
634 {
635 save_loc.vcell_loc = vcell_loc;
636 save_loc.phys_row_offset = 0;
637 save_loc.phys_col_offset = 0;
638 }
639
640 // used in the setting the rows insensitive
641 table->model->blank_trans_row = vcell_loc.virt_row;
642
643 gnc_split_register_add_transaction (reg,
644 blank_trans, blank_split,
645 lead_cursor, split_cursor,
646 multi_line, start_primary_color,
647 info->blank_split_edited,
648 find_trans, find_split,
649 find_class, &new_split_row,
650 &vcell_loc);
651
652 if (!multi_line)
653 start_primary_color = !start_primary_color;
654
655 added_blank_trans = TRUE;
656 }
657
658 gnc_completion_cell_clear_menu (
659 (CompletionCell*) gnc_table_layout_get_cell (reg->table->layout, DESC_CELL));
660
662 (CompletionCell*) gnc_table_layout_get_cell (reg->table->layout, DESC_CELL),
663 table->model->reverse_sort);
664
665 if (!info->first_pass && pre_filter_slist)
666 {
667 add_completions_from_pre_filter_slist (reg->table->layout, pre_filter_slist,
668 info->first_pass, info->quickfill_setup,
669 has_last_num);
670 }
671
672 /* populate the table */
673 for (node = slist; node; node = node->next)
674 {
675 split = node->data;
676 trans = xaccSplitGetParent (split);
677
678 if (!xaccTransStillHasSplit (trans, split))
679 continue;
680
681 if (pending_trans == trans)
682 found_pending = TRUE;
683 /* If the transaction has only one split, and it's not our
684 * pending_trans, then it's another register's blank split and
685 * we don't want to see it.
686 */
687 else if (xaccTransCountSplits (trans) == 1 &&
688 xaccSplitGetAccount (split) == NULL)
689 continue;
690
691 /* Do not load splits from the blank transaction. */
692 if (trans == blank_trans)
693 continue;
694
695 if (multi_line)
696 {
697 /* Skip this split if its transaction has already been loaded. */
698 if (g_hash_table_lookup (trans_table, trans))
699 continue;
700
701 g_hash_table_insert (trans_table, trans, trans);
702 }
703
704 if (info->show_present_divider &&
705 use_autoreadonly &&
706 !found_divider_upper)
707 {
708 if (((table->model->reverse_sort && xaccTransGetDate(trans) < autoreadonly_time) ||
709 (!table->model->reverse_sort && xaccTransGetDate (trans) >= autoreadonly_time)))
710 {
711 table->model->dividing_row_upper = vcell_loc.virt_row;
712 found_divider_upper = TRUE;
713 }
714 else
715 {
716 need_divider_upper = TRUE;
717 }
718 }
719
720 if (info->show_present_divider && !found_divider &&
721 ((table->model->reverse_sort && xaccTransGetDate (trans) < present) ||
722 (!table->model->reverse_sort && xaccTransGetDate (trans) > present)))
723 {
724 gint count_blank_splits = 1;
725 gint virt_row_offset = 2;
726 gboolean show_lower_divider = FALSE;
727
728 if (table->model->reverse_sort)
729 {
730 count_blank_splits = xaccTransCountSplits (blank_trans);
731
732 if (count_blank_splits > 1)
733 count_blank_splits ++;
734
735 if (table->model->reverse_sort && future_after_blank)
736 virt_row_offset = 0;
737 }
738
739 if ((table->model->reverse_sort && vcell_loc.virt_row != count_blank_splits + virt_row_offset) ||
740 !table->model->reverse_sort)
741 {
742 table->model->dividing_row = vcell_loc.virt_row; // blue top
743 show_lower_divider = TRUE;
744 }
745
746 found_divider = TRUE;
747
748 if (future_after_blank)
749 {
750 if (blank_trans == find_trans)
751 new_trans_row = vcell_loc.virt_row;
752
753 if (blank_split == find_trans_split)
754 new_trans_split_row = vcell_loc.virt_row;
755
756 /* go to blank on first pass */
757 if (info->first_pass)
758 {
759 save_loc.vcell_loc = vcell_loc;
760 save_loc.phys_row_offset = 0;
761 save_loc.phys_col_offset = 0;
762 }
763
764 // used in the setting the rows insensitive
765 table->model->blank_trans_row = vcell_loc.virt_row;
766
767 gnc_split_register_add_transaction (reg,
768 blank_trans, blank_split,
769 lead_cursor, split_cursor,
770 multi_line, start_primary_color,
771 info->blank_split_edited,
772 find_trans, find_split,
773 find_class, &new_split_row,
774 &vcell_loc);
775
776
777 if (show_lower_divider)
778 table->model->dividing_row_lower = vcell_loc.virt_row; // blue bottom
779
780 if (!multi_line)
781 start_primary_color = !start_primary_color;
782
783 added_blank_trans = TRUE;
784 }
785 }
786
787 /* On first load the split list is empty so fill up the quickfill cells
788 * only on the next load. */
789 if (!info->first_pass && !pre_filter_slist && !info->quickfill_setup)
790 add_quickfill_completions (reg->table->layout, trans, split, has_last_num);
791
792 if (!info->first_pass && !pre_filter_slist)
793 {
795 (CompletionCell*) gnc_table_layout_get_cell (reg->table->layout, DESC_CELL),
797 }
798
799 if (trans == find_trans)
800 new_trans_row = vcell_loc.virt_row;
801
802 if (split == find_trans_split)
803 new_trans_split_row = vcell_loc.virt_row;
804
805 gnc_split_register_add_transaction (reg, trans, split,
806 lead_cursor, split_cursor,
807 multi_line, start_primary_color,
808 TRUE,
809 find_trans, find_split, find_class,
810 &new_split_row, &vcell_loc);
811
812 if (!multi_line)
813 start_primary_color = !start_primary_color;
814 }
815
816 if (multi_line)
817 g_hash_table_destroy (trans_table);
818
819 /* add the blank split at the end. */
820 if (pending_trans == blank_trans)
821 found_pending = TRUE;
822
823 /* No upper divider yet? Store it now */
824 if (info->show_present_divider &&
825 use_autoreadonly &&
826 !found_divider_upper && need_divider_upper)
827 {
828 table->model->dividing_row_upper = vcell_loc.virt_row;
829 }
830
831 /* If we didn't find the pending transaction, it was removed
832 * from the account. */
833 if (!found_pending)
834 {
835 info->pending_trans_guid = *guid_null();
836 if (xaccTransIsOpen (pending_trans))
837 xaccTransCommitEdit (pending_trans);
838 else if (pending_trans)
839 g_assert_not_reached();
840
841 pending_trans = NULL;
842 }
843
844 if (!added_blank_trans)
845 {
846 if (blank_trans == find_trans)
847 new_trans_row = vcell_loc.virt_row;
848
849 if (blank_split == find_trans_split)
850 new_trans_split_row = vcell_loc.virt_row;
851
852 /* go to blank on first pass */
853 if (info->first_pass)
854 {
855 save_loc.vcell_loc = vcell_loc;
856 save_loc.phys_row_offset = 0;
857 save_loc.phys_col_offset = 0;
858 }
859
860 // used in the setting the rows insensitive
861 table->model->blank_trans_row = vcell_loc.virt_row;
862
863 gnc_split_register_add_transaction (reg, blank_trans, blank_split,
864 lead_cursor, split_cursor,
865 multi_line, start_primary_color,
866 info->blank_split_edited,
867 find_trans, find_split,
868 find_class, &new_split_row,
869 &vcell_loc);
870
871 if (future_after_blank)
872 {
873 table->model->dividing_row_lower = vcell_loc.virt_row;
874 }
875 }
876
877 /* go to blank on first pass */
878 if (info->first_pass)
879 {
880 new_split_row = -1;
881 new_trans_split_row = -1;
882 new_trans_row = -1;
883 }
884
885 /* resize the table to the sizes we just counted above */
886 /* num_virt_cols is always one. */
887 gnc_table_set_size (table, vcell_loc.virt_row, 1);
888
889 /* restore the cursor to its rightful position */
890 {
891 VirtualLocation trans_split_loc;
892
893 if (new_split_row > 0)
894 save_loc.vcell_loc.virt_row = new_split_row;
895 else if (new_trans_split_row > 0)
896 save_loc.vcell_loc.virt_row = new_trans_split_row;
897 else if (new_trans_row > 0)
898 save_loc.vcell_loc.virt_row = new_trans_row;
899
900 trans_split_loc = save_loc;
901
902 gnc_split_register_get_trans_split (reg, save_loc.vcell_loc,
903 &trans_split_loc.vcell_loc);
904
905 if (dynamic || multi_line || info->trans_expanded)
906 {
908 table, trans_split_loc.vcell_loc,
909 gnc_split_register_get_active_cursor (reg));
910 gnc_split_register_set_trans_visible (reg, trans_split_loc.vcell_loc,
911 TRUE, multi_line);
912
913 info->trans_expanded = (reg->style == REG_STYLE_LEDGER);
914 }
915 else
916 {
917 save_loc = trans_split_loc;
918 info->trans_expanded = FALSE;
919 }
920
921 if (gnc_table_find_close_valid_cell (table, &save_loc, FALSE))
922 {
924 new_split_row = save_loc.vcell_loc.virt_row;
925
926 if (find_split == gnc_split_register_get_current_split (reg))
927 gnc_table_restore_current_cursor (table, cursor_buffer);
928 }
929 }
930 gnc_cursor_buffer_destroy (cursor_buffer);
931 cursor_buffer = NULL;
932
933 update_info (info, reg);
934
935 gnc_split_register_set_cell_fractions (
937
939
940 // if in reverse order, always show the first transaction
941 if (table->model->reverse_sort)
942 {
943 VirtualCellLocation vc_loc;
944 vc_loc.virt_row = 0;
945 vc_loc.virt_col = 0;
946 gnc_split_register_show_trans (reg, vc_loc);
947 }
948 else
949 gnc_split_register_show_trans (reg, table->current_cursor_loc.vcell_loc);
950
951 /* enable callback for cursor user-driven moves */
952 gnc_table_control_allow_move (table->control, TRUE);
953
954 if (we_own_slist)
955 g_list_free (slist);
956
957 LEAVE (" ");
958}
959
960/* ===================================================================== */
961
962#define QKEY "split_reg_shared_quickfill"
963
964static gboolean
965skip_cb (Account* account, gpointer x)
966{
967 /* commented out as per Bug#340885 Comments 1 and 2, option (2).
968 if (xaccAccountIsHidden(account))
969 return TRUE;
970 */
971 return xaccAccountGetPlaceholder (account);
972}
973
974static void
975gnc_split_register_load_xfer_cells (SplitRegister* reg, Account* base_account)
976{
977 Account* root = NULL;
978 QuickFill* qf;
979 ComboCell* cell;
980 GtkListStore* store;
981
982 if (base_account)
983 root = gnc_account_get_root (base_account);
984 if (root == NULL)
985 root = gnc_get_current_root_account();
986 if (root == NULL)
987 return;
988
989 qf = gnc_get_shared_account_name_quickfill (root, QKEY, skip_cb, NULL);
990 store = gnc_get_shared_account_name_list_store (root, QKEY, skip_cb, NULL);
991
992 cell = (ComboCell*)
993 gnc_table_layout_get_cell (reg->table->layout, XFRM_CELL);
995 gnc_combo_cell_use_list_store_cache (cell, store);
996
997 cell = (ComboCell*)
998 gnc_table_layout_get_cell (reg->table->layout, MXFRM_CELL);
1000 gnc_combo_cell_use_list_store_cache (cell, store);
1001}
1002
1003/* ====================== END OF FILE ================================== */
Account handling public routines.
API for Transactions and Splits (journal entries)
Create an account-name quick-fill.
Generic api to store and retrieve preferences.
utility functions for the GnuCash UI
QuickFill * gnc_get_shared_account_name_quickfill(Account *root, const char *key, AccountBoolCB cb, gpointer cb_data)
Create/fetch a quickfill of account names.
Account * gnc_account_get_root(Account *acc)
This routine returns the root account of the account tree that the specified account belongs to.
Definition Account.cpp:2942
gnc_commodity * gnc_account_get_currency_or_parent(const Account *account)
Returns a gnc_commodity that is a currency, suitable for being a Transaction's currency.
Definition Account.cpp:3415
#define xaccAccountGetGUID(X)
Definition Account.h:252
const char * xaccAccountGetLastNum(const Account *acc)
Get the last num field of an Account.
Definition Account.cpp:4683
GDate * qof_book_get_autoreadonly_gdate(const QofBook *book)
Returns the GDate that is the threshold for auto-read-only.
Definition qofbook.cpp:1006
gboolean qof_book_uses_autoreadonly(const QofBook *book)
Returns TRUE if the auto-read-only feature should be used, otherwise FALSE.
Definition qofbook.cpp:974
void gnc_combo_cell_set_complete_char(ComboCell *cell, gunichar complete_char)
Sets a character used for special completion processing.
void gnc_combo_cell_use_quickfill_cache(ComboCell *cell, QuickFill *shared_qf)
Tell the combocell to use a shared QuickFill object.
void gnc_completion_cell_add_menu_item(CompletionCell *cell, const char *menustr)
Add a menu item to the hash table list.
void gnc_doclink_cell_set_valid_flags(Doclinkcell *cell, const char *flags, char default_flag)
note that
void gnc_completion_cell_reverse_sort(CompletionCell *cell, gboolean is_reversed)
Register the sort direction.
void gnc_price_cell_set_print_info(PriceCell *cell, GNCPrintAmountInfo print_info)
set the printing context of the price cell
Definition pricecell.c:272
void gnc_recn_cell_set_valid_flags(RecnCell *cell, const char *flags, char default_flag)
note that chars is copied into the RecnCell directly, but remains the "property" of the caller.
Definition recncell.c:196
void gnc_completion_cell_set_sort_enabled(CompletionCell *cell, gboolean enabled)
Enable sorting of the menu item's contents.
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Definition gnc-date.h:87
time64 gdate_to_time64(GDate d)
Turns a GDate into a time64, returning the first second of the day.
time64 gnc_time64_get_today_end(void)
The gnc_time64_get_today_end() routine returns a time64 value corresponding to the last second of tod...
gboolean xaccAccountGetPlaceholder(const Account *acc)
Get the "placeholder" flag for an account.
Definition Account.cpp:4119
void xaccTransCommitEdit(Transaction *trans)
The xaccTransCommitEdit() method indicates that the changes to the transaction and its splits are com...
const char * xaccTransGetDescription(const Transaction *trans)
Gets the transaction Description.
gboolean xaccTransIsOpen(const Transaction *trans)
The xaccTransIsOpen() method returns TRUE if the transaction is open for editing.
#define xaccTransGetGUID(X)
Transaction * xaccTransLookup(const GncGUID *guid, QofBook *book)
The xaccTransLookup() subroutine will return the transaction associated with the given id,...
const char * xaccTransGetNotes(const Transaction *trans)
Gets the transaction Notes.
Transaction * xaccMallocTransaction(QofBook *book)
The xaccMallocTransaction() will malloc memory and initialize it.
void xaccTransSetDatePostedSecsNormalized(Transaction *trans, time64 time)
This function sets the posted date of the transaction, specified by a time64 (see ctime(3)).
void xaccTransSetCurrency(Transaction *trans, gnc_commodity *curr)
Set a new currency on a transaction.
SplitList * xaccTransGetSplitList(const Transaction *trans)
The xaccTransGetSplitList() method returns a GList of the splits in a transaction.
int xaccTransCountSplits(const Transaction *trans)
Returns the number of splits in this transaction.
void xaccTransBeginEdit(Transaction *trans)
The xaccTransBeginEdit() method must be called before any changes are made to a transaction or any of...
time64 xaccTransGetDate(const Transaction *trans)
Retrieve the posted date of the transaction.
const GncGUID * guid_null(void)
Returns a GncGUID which is guaranteed to never reference any entity.
Definition guid.cpp:165
const char * gnc_get_doclink_flag_order(void)
Get a string containing document link flag order.
const char * gnc_get_doclink_valid_flags(void)
Get a string containing documentation link valid flags.
gnc_commodity * gnc_account_or_default_currency(const Account *account, gboolean *currency_from_account_found)
Returns a gnc_commodity that is a currency, suitable for being a Transaction's currency.
gnc_commodity * gnc_default_currency(void)
Return the default currency set by the user.
const char * gnc_get_doclink_str(char link_flag)
Get a string representing the document link type.
#define DEBUG(format, args...)
Print a debugging message.
Definition qoflog.h:264
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition qoflog.h:282
#define ENTER(format, args...)
Print a function entry debugging message.
Definition qoflog.h:272
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Get a boolean value from the preferences backend.
void gnc_split_register_load(SplitRegister *reg, GList *slist, GList *pre_filter_slist, Account *default_account)
Populates the rows of a register.
Split * gnc_split_register_get_current_split(SplitRegister *reg)
Returns the split at which the cursor is currently located.
Split * gnc_split_register_get_current_trans_split(SplitRegister *reg, VirtualCellLocation *trans_split_loc)
Gets the anchoring split of the transaction at the current cursor location, which may be on the trans...
Transaction * gnc_split_register_get_current_trans(SplitRegister *reg)
Gets the transaction at the current cursor location, which may be on the transaction itself or on any...
void gnc_split_register_set_trans_visible(SplitRegister *reg, VirtualCellLocation vcell_loc, gboolean visible, gboolean only_blank_split)
Set the visibility of the split rows belonging to a transaction located at vcell_loc.
CursorClass
Types of cursors.
CursorClass gnc_split_register_get_current_cursor_class(SplitRegister *reg)
Returns the class of a register's current cursor.
void gnc_table_refresh_gui(Table *table, gboolean do_scroll)
Refresh the whole GUI from the table.
void gnc_table_move_cursor_gui(Table *table, VirtualLocation new_virt_loc)
will move the cursor and its GUI to the indicated location.
void gnc_table_set_virt_cell_cursor(Table *table, VirtualCellLocation vcell_loc, CellBlock *cursor)
Set the cellblock handler for a virtual cell.
void gnc_table_set_size(Table *table, int virt_rows, int virt_cols)
The gnc_table_set_size() method will resize the table to the indicated dimensions.
gboolean gnc_table_find_close_valid_cell(Table *table, VirtualLocation *virt_loc, gboolean exact_pointer)
Find a close valid cell.
#define CURSOR_HEADER
Standard Cursor Names.
void gnc_table_set_vcell(Table *table, CellBlock *cursor, gconstpointer vcell_data, gboolean visible, gboolean start_primary_color, VirtualCellLocation vcell_loc)
Indicate what handler should be used for a given virtual block.
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
Split * xaccSplitLookup(const GncGUID *guid, QofBook *book)
The xaccSplitLookup() subroutine will return the split associated with the given id,...
Definition Split.cpp:1091
#define xaccSplitGetGUID(X)
Definition Split.h:579
Split * xaccMallocSplit(QofBook *book)
Constructor.
Account * xaccSplitGetAccount(const Split *split)
Returns the account of this split, which was set through xaccAccountInsertSplit().
const char * xaccSplitGetMemo(const Split *split)
Returns the memo string.
private declarations for SplitRegister
API for checkbook register display area.
STRUCTS.
The ComboCell object implements a cell handler with a "combination-box" pull-down menu in it.
Definition combocell.h:53
The CompletionCell object implements a cell handler with a "combination-box" pull-down menu in it.
The Doclinkcell object implements a cell handler that will cycle through a series of single-character...
Definition doclinkcell.h:53
The NumCell object implements a number handling cell.
Definition numcell.h:40
The PriceCell object implements a cell handler that stores a single double-precision value,...
Definition pricecell.h:55
The QuickFillCell implements a text cell with quick-fill capabilities.
The RecnCell object implements a cell handler that will cycle through a series of single-character va...
Definition recncell.h:48