GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Modules | Files | Data Structures | Typedefs | Enumerations | Functions
Registers, Ledgers and Journals

Modules

 Split Register
 GnuCash-specific ledger and journal displays based on Register Core.
 
 Register Core
 An infrastructure for building a modular matrix of cells like a spreadsheet or checkbook register.
 

Files

file  split-register.h
 API for checkbook register display area.
 

Data Structures

struct  split_register
 The type, style and table for the register. More...
 

Typedefs

typedef struct split_register SplitRegister
 A split register created with gnc_split_register_new.
 
typedef struct sr_info SRInfo
 
typedef GtkWidget *(* SRGetParentCallback )(gpointer user_data)
 

Enumerations

enum  CursorClass { CURSOR_CLASS_NONE = -1, CURSOR_CLASS_SPLIT, CURSOR_CLASS_TRANS, NUM_CURSOR_CLASSES }
 

Functions

SplitRegistergnc_split_register_new (SplitRegisterType type, SplitRegisterStyle style, gboolean use_double_line, gboolean is_template)
 
void gnc_split_register_destroy (SplitRegister *reg)
 
void gnc_split_register_config (SplitRegister *reg, SplitRegisterType type, SplitRegisterStyle style, gboolean use_double_line)
 
void gnc_split_register_set_auto_complete (SplitRegister *reg, gboolean do_auto_complete)
 
void gnc_split_register_set_read_only (SplitRegister *reg, gboolean read_only)
 
void gnc_split_register_set_template_account (SplitRegister *reg, Account *template_account)
 
void gnc_split_register_set_data (SplitRegister *reg, gpointer user_data, SRGetParentCallback get_parent)
 
CursorClass gnc_split_register_get_current_cursor_class (SplitRegister *reg)
 
CursorClass gnc_split_register_get_cursor_class (SplitRegister *reg, VirtualCellLocation vcell_loc)
 
Transactiongnc_split_register_get_current_trans (SplitRegister *reg)
 
Splitgnc_split_register_get_current_trans_split (SplitRegister *reg, VirtualCellLocation *vcell_loc)
 
Splitgnc_split_register_get_current_split (SplitRegister *reg)
 
Splitgnc_split_register_get_blank_split (SplitRegister *reg)
 
gboolean gnc_split_register_get_split_virt_loc (SplitRegister *reg, Split *split, VirtualCellLocation *vcell_loc)
 
gboolean gnc_split_register_get_split_amount_virt_loc (SplitRegister *reg, Split *split, VirtualLocation *virt_loc)
 
Splitgnc_split_register_duplicate_current (SplitRegister *reg)
 
void gnc_split_register_copy_current (SplitRegister *reg)
 
void gnc_split_register_cut_current (SplitRegister *reg)
 
void gnc_split_register_paste_current (SplitRegister *reg)
 
void gnc_split_register_delete_current_split (SplitRegister *reg)
 
void gnc_split_register_delete_current_trans (SplitRegister *reg)
 
void gnc_split_register_void_current_trans (SplitRegister *reg, const char *reason)
 
void gnc_split_register_unvoid_current_trans (SplitRegister *reg)
 
void gnc_split_register_empty_current_trans_except_split (SplitRegister *reg, Split *split)
 
void gnc_split_register_empty_current_trans (SplitRegister *reg)
 
void gnc_split_register_cancel_cursor_split_changes (SplitRegister *reg)
 
void gnc_split_register_cancel_cursor_trans_changes (SplitRegister *reg)
 
void gnc_split_register_load (SplitRegister *reg, GList *slist, Account *default_account)
 
gboolean gnc_split_register_save (SplitRegister *reg, gboolean do_commit)
 
void gnc_split_register_redraw (SplitRegister *reg)
 
gboolean gnc_split_register_changed (SplitRegister *reg)
 
void gnc_split_register_show_present_divider (SplitRegister *reg, gboolean show_present)
 
void gnc_split_register_expand_current_trans (SplitRegister *reg, gboolean expand)
 
void gnc_split_register_collapse_current_trans (SplitRegister *reg)
 
gboolean gnc_split_register_current_trans_expanded (SplitRegister *reg)
 
const char * gnc_split_register_get_debit_string (SplitRegister *reg)
 
const char * gnc_split_register_get_credit_string (SplitRegister *reg)
 
gboolean gnc_split_register_handle_exchange (SplitRegister *reg, gboolean force_dialog)
 
gboolean gnc_split_register_begin_edit_or_warn (SRInfo *info, Transaction *trans)
 
enum  SplitRegisterType {
  BANK_REGISTER, CASH_REGISTER, ASSET_REGISTER, CREDIT_REGISTER,
  LIABILITY_REGISTER, INCOME_REGISTER, EXPENSE_REGISTER, EQUITY_REGISTER,
  STOCK_REGISTER, CURRENCY_REGISTER, RECEIVABLE_REGISTER, PAYABLE_REGISTER,
  TRADING_REGISTER, NUM_SINGLE_REGISTER_TYPES, GENERAL_LEDGER = NUM_SINGLE_REGISTER_TYPES, INCOME_LEDGER,
  PORTFOLIO_LEDGER, SEARCH_LEDGER, NUM_REGISTER_TYPES
}
 Register types. More...
 
enum  SplitRegisterStyle { REG_STYLE_LEDGER, REG_STYLE_AUTO_LEDGER, REG_STYLE_JOURNAL }
 

Cell Names

T* cells are transaction summary cells

#define ACTN_CELL   "action"
 
#define BALN_CELL   "balance"
 
#define CRED_CELL   "credit"
 
#define DATE_CELL   "date"
 
#define DDUE_CELL   "date-due"
 
#define DEBT_CELL   "debit"
 
#define DESC_CELL   "description"
 
#define FCRED_CELL   "credit-formula"
 
#define FDEBT_CELL   "debit-formula"
 
#define MEMO_CELL   "memo"
 
#define MXFRM_CELL   "transfer"
 
#define NOTES_CELL   "notes"
 
#define NUM_CELL   "num"
 
#define TNUM_CELL   "trans-num"
 
#define PRIC_CELL   "price"
 
#define RATE_CELL   "exchrate"
 
#define RECN_CELL   "reconcile"
 
#define SHRS_CELL   "shares"
 
#define TBALN_CELL   "trans-balance"
 
#define TCRED_CELL   "trans-credit"
 
#define TDEBT_CELL   "trans-debit"
 
#define TSHRS_CELL   "trans-shares"
 
#define TYPE_CELL   "split-type"
 
#define XFRM_CELL   "account"
 
#define VNOTES_CELL   "void-notes"
 
#define RBALN_CELL   "reg-run-balance"
 

Cursor Names

Cursors ending in 'NUM_ACTN' use the split action field for the NUM_CELL rather than the transaction number field which is shown in the TNUM_CELL

#define CURSOR_SINGLE_LEDGER   "cursor-single-ledger"
 
#define CURSOR_DOUBLE_LEDGER   "cursor-double-ledger"
 
#define CURSOR_DOUBLE_LEDGER_NUM_ACTN   "cursor-double-ledger-num-actn"
 
#define CURSOR_SINGLE_JOURNAL   "cursor-single-journal"
 
#define CURSOR_DOUBLE_JOURNAL   "cursor-double-journal"
 
#define CURSOR_DOUBLE_JOURNAL_NUM_ACTN   "cursor-double-journal-num-actn"
 
#define CURSOR_SPLIT   "cursor-split"
 

Detailed Description

Typedef Documentation

typedef GtkWidget*(* SRGetParentCallback)(gpointer user_data)

Callback function type

Definition at line 265 of file split-register.h.

Enumeration Type Documentation

Types of cursors

Definition at line 233 of file split-register.h.

234 {
235  CURSOR_CLASS_NONE = -1,
236  CURSOR_CLASS_SPLIT,
237  CURSOR_CLASS_TRANS,
238  NUM_CURSOR_CLASSES
239 } CursorClass;
CursorClass

Register styles

Definition at line 178 of file split-register.h.

179 {
180  REG_STYLE_LEDGER,
181  REG_STYLE_AUTO_LEDGER,
182  REG_STYLE_JOURNAL
SplitRegisterStyle

Register types.

"registers" are single-account display windows. "ledgers" are multiple-account display windows

Definition at line 152 of file split-register.h.

153 {
154  BANK_REGISTER,
155  CASH_REGISTER,
156  ASSET_REGISTER,
157  CREDIT_REGISTER,
158  LIABILITY_REGISTER,
159  INCOME_REGISTER,
160  EXPENSE_REGISTER,
161  EQUITY_REGISTER,
162  STOCK_REGISTER,
163  CURRENCY_REGISTER,
164  RECEIVABLE_REGISTER,
165  PAYABLE_REGISTER,
166  TRADING_REGISTER,
167  NUM_SINGLE_REGISTER_TYPES,
168 
169  GENERAL_LEDGER = NUM_SINGLE_REGISTER_TYPES,
170  INCOME_LEDGER,
171  PORTFOLIO_LEDGER,
172  SEARCH_LEDGER,
173 
174  NUM_REGISTER_TYPES
SplitRegisterType
Register types.

Function Documentation

void gnc_split_register_cancel_cursor_split_changes ( SplitRegister reg)

Cancels any changes made to the current cursor, reloads the cursor from the engine, reloads the table from the cursor, and updates the GUI. The change flags are cleared.

Definition at line 1300 of file split-register.c.

1301 {
1302  VirtualLocation virt_loc;
1303 
1304  if (reg == NULL)
1305  return;
1306 
1307  virt_loc = reg->table->current_cursor_loc;
1308 
1309  if (!gnc_table_current_cursor_changed (reg->table, FALSE))
1310  return;
1311 
1312  /* We're just cancelling the current split here, not the transaction.
1313  * When cancelling edits, reload the cursor from the transaction. */
1314  gnc_table_clear_current_cursor_changes (reg->table);
1315 
1316  if (gnc_table_find_close_valid_cell (reg->table, &virt_loc, FALSE))
1317  gnc_table_move_cursor_gui (reg->table, virt_loc);
1318 
1319  gnc_table_refresh_gui (reg->table, TRUE);
1320 }
void gnc_split_register_cancel_cursor_trans_changes ( SplitRegister reg)

Cancels any changes made to the current pending transaction, reloads the table from the engine, and updates the GUI. The change flags are cleared.

Definition at line 1323 of file split-register.c.

1324 {
1325  SRInfo *info = gnc_split_register_get_info (reg);
1326  Transaction *pending_trans;
1327 
1328  pending_trans = xaccTransLookup (&info->pending_trans_guid,
1329  gnc_get_current_book ());
1330 
1331  /* Get the currently open transaction, rollback the edits on it, and
1332  * then repaint everything. To repaint everything, make a note of
1333  * all of the accounts that will be affected by this rollback. */
1334  if (!xaccTransIsOpen (pending_trans))
1335  {
1337  return;
1338  }
1339 
1340  if (!pending_trans)
1341  return;
1342 
1343  gnc_suspend_gui_refresh ();
1344 
1345  xaccTransRollbackEdit (pending_trans);
1346 
1347  info->pending_trans_guid = *guid_null ();
1348 
1349  gnc_resume_gui_refresh ();
1351 }
void gnc_split_register_cancel_cursor_split_changes(SplitRegister *reg)
gboolean xaccTransIsOpen(const Transaction *trans)
Definition: Transaction.c:1819
Transaction * xaccTransLookup(const GncGUID *guid, QofBook *book)
Definition: Transaction.c:1024
void gnc_split_register_redraw(SplitRegister *reg)
const GncGUID * guid_null(void)
void xaccTransRollbackEdit(Transaction *trans)
Definition: Transaction.c:1661
gboolean gnc_split_register_changed ( SplitRegister reg)

Returns TRUE if the register has changed cells.

Definition at line 2345 of file split-register.c.

2346 {
2347  SRInfo *info = gnc_split_register_get_info (reg);
2348  Transaction *pending_trans;
2349 
2350  ENTER("reg=%p", reg);
2351 
2352  if (reg == NULL)
2353  {
2354  LEAVE("no register");
2355  return FALSE;
2356  }
2357 
2358  if (gnc_table_current_cursor_changed (reg->table, FALSE))
2359  {
2360  LEAVE("cursor changed");
2361  return TRUE;
2362  }
2363 
2364  pending_trans = xaccTransLookup (&info->pending_trans_guid,
2365  gnc_get_current_book ());
2366  if (xaccTransIsOpen (pending_trans))
2367  {
2368  LEAVE("open and pending txn");
2369  return TRUE;
2370  }
2371 
2372  LEAVE("register unchanged");
2373  return FALSE;
2374 }
gboolean xaccTransIsOpen(const Transaction *trans)
Definition: Transaction.c:1819
#define ENTER(format, args...)
Definition: qoflog.h:261
Transaction * xaccTransLookup(const GncGUID *guid, QofBook *book)
Definition: Transaction.c:1024
#define LEAVE(format, args...)
Definition: qoflog.h:271
void gnc_split_register_collapse_current_trans ( SplitRegister reg)

Mark the current transaction as collapsed, and do callbacks.

void gnc_split_register_config ( SplitRegister reg,
SplitRegisterType  type,
SplitRegisterStyle  style,
gboolean  use_double_line 
)

Sets a split register's type, style or line use.

Parameters
rega SplitRegister
typea SplitRegisterType to use for the register
stylea SplitRegisterStyle to use for the register
use_double_lineTRUE to show two lines for transactions, FALSE for one

Definition at line 2753 of file split-register.c.

2757 {
2758  if (!reg) return;
2759 
2760  /* If shrinking the transaction split, put the cursor on the first row of the trans */
2761  if (reg->use_double_line && !use_double_line)
2762  {
2763  VirtualLocation virt_loc = reg->table->current_cursor_loc;
2764  if (gnc_table_find_close_valid_cell (reg->table, &virt_loc, FALSE))
2765  {
2766  if (virt_loc.phys_row_offset)
2767  {
2768  gnc_table_move_vertical_position (reg->table, &virt_loc, -virt_loc.phys_row_offset);
2769  gnc_table_move_cursor_gui (reg->table, virt_loc);
2770  }
2771  }
2772  else
2773  {
2774  /* WTF? Go to a known safe location. */
2775  virt_loc.vcell_loc.virt_row = 1;
2776  virt_loc.vcell_loc.virt_col = 0;
2777  virt_loc.phys_row_offset = 0;
2778  virt_loc.phys_col_offset = 0;
2779  gnc_table_move_cursor_gui (reg->table, virt_loc);
2780  }
2781  }
2782 
2783  reg->type = newtype;
2784 
2785  if (reg->type >= NUM_SINGLE_REGISTER_TYPES)
2786  newstyle = REG_STYLE_JOURNAL;
2787 
2788  reg->style = newstyle;
2789  reg->use_double_line = use_double_line;
2790 
2791  gnc_table_realize_gui (reg->table);
2792 }
gboolean gnc_table_move_vertical_position(Table *table, VirtualLocation *virt_loc, int phys_row_offset)
gboolean use_double_line
void gnc_split_register_copy_current ( SplitRegister reg)

Makes a copy of the current entity, either a split or a transaction, so that it can be pasted later.

Definition at line 811 of file split-register.c.

812 {
813  gnc_split_register_copy_current_internal (reg, FALSE);
814 }
gboolean gnc_split_register_current_trans_expanded ( SplitRegister reg)

Return TRUE if current trans is expanded and style is REG_STYLE_LEDGER.

Definition at line 254 of file split-register.c.

255 {
256  SRInfo *info = gnc_split_register_get_info (reg);
257 
258  if (!reg)
259  return FALSE;
260 
261  if (reg->style == REG_STYLE_AUTO_LEDGER ||
262  reg->style == REG_STYLE_JOURNAL)
263  return TRUE;
264 
265  return info->trans_expanded;
266 }
void gnc_split_register_cut_current ( SplitRegister reg)

Equivalent to copying the current entity and the deleting it with the approriate delete method.

Definition at line 817 of file split-register.c.

818 {
819  SRInfo *info = gnc_split_register_get_info (reg);
820  CursorClass cursor_class;
821  Transaction *trans;
822  Split *blank_split;
823  gboolean changed;
824  Split *split;
825 
826  blank_split = xaccSplitLookup (&info->blank_split_guid,
827  gnc_get_current_book ());
830 
831  /* This shouldn't happen, but be paranoid. */
832  if (trans == NULL)
833  return;
834 
835  cursor_class = gnc_split_register_get_current_cursor_class (reg);
836 
837  /* Can't do anything with this. */
838  if (cursor_class == CURSOR_CLASS_NONE)
839  return;
840 
841  /* This shouldn't happen, but be paranoid. */
842  if ((split == NULL) && (cursor_class == CURSOR_CLASS_TRANS))
843  return;
844 
845  changed = gnc_table_current_cursor_changed (reg->table, FALSE);
846 
847  /* See if we were asked to cut an unchanged blank split. Don't. */
848  if (!changed && ((split == NULL) || (split == blank_split)))
849  return;
850 
851  gnc_split_register_copy_current_internal (reg, TRUE);
852 
853  if (cursor_class == CURSOR_CLASS_SPLIT)
855  else
857 }
Transaction * gnc_split_register_get_current_trans(SplitRegister *reg)
Split * gnc_split_register_get_current_split(SplitRegister *reg)
void gnc_split_register_delete_current_split(SplitRegister *reg)
Split * xaccSplitLookup(const GncGUID *guid, QofBook *book)
Definition: Split.c:1104
CursorClass
Definition: SplitP.h:71
CursorClass gnc_split_register_get_current_cursor_class(SplitRegister *reg)
void gnc_split_register_delete_current_trans(SplitRegister *reg)
void gnc_split_register_delete_current_split ( SplitRegister reg)

Deletes the split associated with the current cursor, if both are non-NULL. Deleting the blank split just clears cursor values.

Definition at line 1029 of file split-register.c.

1030 {
1031  SRInfo *info = gnc_split_register_get_info (reg);
1032  Transaction *pending_trans;
1033  Transaction *trans;
1034  Split *blank_split;
1035  Split *split;
1036 
1037  if (!reg) return;
1038 
1039  blank_split = xaccSplitLookup (&info->blank_split_guid,
1040  gnc_get_current_book ());
1041 
1042  pending_trans = xaccTransLookup (&info->pending_trans_guid,
1043  gnc_get_current_book ());
1044 
1045  /* get the current split based on cursor position */
1047  if (split == NULL)
1048  return;
1049 
1050  /* If we are deleting the blank split, just cancel. The user is
1051  * allowed to delete the blank split as a method for discarding
1052  * any edits they may have made to it. */
1053  if (split == blank_split)
1054  {
1056  return;
1057  }
1058 
1059  gnc_suspend_gui_refresh ();
1060 
1061  trans = xaccSplitGetParent(split);
1062 
1063  /* Check pending transaction */
1064  if (trans == pending_trans)
1065  {
1066  g_assert(xaccTransIsOpen(trans));
1067  }
1068  else
1069  {
1070  g_assert(!pending_trans);
1071  if (gnc_split_register_begin_edit_or_warn(info, trans))
1072  {
1073  gnc_resume_gui_refresh ();
1074  return;
1075  }
1076  }
1077  xaccSplitDestroy (split);
1078 
1079  gnc_resume_gui_refresh ();
1081 }
void gnc_split_register_cancel_cursor_split_changes(SplitRegister *reg)
gboolean xaccTransIsOpen(const Transaction *trans)
Definition: Transaction.c:1819
gboolean xaccSplitDestroy(Split *split)
Definition: Split.c:1492
Split * gnc_split_register_get_current_split(SplitRegister *reg)
Transaction * xaccSplitGetParent(const Split *split)
Definition: Split.c:1903
Transaction * xaccTransLookup(const GncGUID *guid, QofBook *book)
Definition: Transaction.c:1024
void gnc_split_register_redraw(SplitRegister *reg)
Split * xaccSplitLookup(const GncGUID *guid, QofBook *book)
Definition: Split.c:1104
Definition: SplitP.h:71
void gnc_split_register_delete_current_trans ( SplitRegister reg)

Deletes the transaction associated with the current cursor, if both are non-NULL.

Definition at line 1084 of file split-register.c.

1085 {
1086  SRInfo *info = gnc_split_register_get_info (reg);
1087  Transaction *pending_trans;
1088  Transaction *trans;
1089  Split *blank_split;
1090  Split *split;
1091  gboolean was_open;
1092 
1093  ENTER("reg=%p", reg);
1094  if (!reg)
1095  {
1096  LEAVE("no register");
1097  return;
1098  }
1099 
1100  blank_split = xaccSplitLookup (&info->blank_split_guid,
1101  gnc_get_current_book ());
1102  pending_trans = xaccTransLookup (&info->pending_trans_guid,
1103  gnc_get_current_book ());
1104 
1105  /* get the current split based on cursor position */
1107  if (split == NULL)
1108  {
1109  LEAVE("no split");
1110  return;
1111  }
1112 
1113  gnc_suspend_gui_refresh ();
1114  trans = xaccSplitGetParent(split);
1115 
1116  /* If we just deleted the blank split, clean up. The user is
1117  * allowed to delete the blank split as a method for discarding
1118  * any edits they may have made to it. */
1119  if (split == blank_split)
1120  {
1121  DEBUG("deleting blank split");
1122  info->blank_split_guid = *guid_null();
1123  info->auto_complete = FALSE;
1124  }
1125  else
1126  {
1127  info->trans_expanded = FALSE;
1128  }
1129 
1130  /* Check pending transaction */
1131  if (trans == pending_trans)
1132  {
1133  DEBUG("clearing pending trans");
1134  info->pending_trans_guid = *guid_null();
1135  pending_trans = NULL;
1136  }
1137 
1138  was_open = xaccTransIsOpen(trans);
1139  xaccTransDestroy(trans);
1140  if (was_open)
1141  {
1142  DEBUG("committing");
1143  xaccTransCommitEdit(trans);
1144  }
1145  gnc_resume_gui_refresh ();
1146  LEAVE(" ");
1147 }
gboolean xaccTransIsOpen(const Transaction *trans)
Definition: Transaction.c:1819
Split * gnc_split_register_get_current_split(SplitRegister *reg)
#define DEBUG(format, args...)
Definition: qoflog.h:255
Transaction * xaccSplitGetParent(const Split *split)
Definition: Split.c:1903
#define ENTER(format, args...)
Definition: qoflog.h:261
void xaccTransDestroy(Transaction *trans)
Definition: Transaction.c:1402
Transaction * xaccTransLookup(const GncGUID *guid, QofBook *book)
Definition: Transaction.c:1024
Split * xaccSplitLookup(const GncGUID *guid, QofBook *book)
Definition: Split.c:1104
void xaccTransCommitEdit(Transaction *trans)
Definition: Transaction.c:1579
Definition: SplitP.h:71
const GncGUID * guid_null(void)
#define LEAVE(format, args...)
Definition: qoflog.h:271
void gnc_split_register_destroy ( SplitRegister reg)

Destroys a split register.

Parameters
rega SplitRegister

Definition at line 2913 of file split-register.c.

2914 {
2915  g_return_if_fail(reg);
2916 
2917  ENTER("reg=%p", reg);
2918 
2919  gnc_prefs_remove_cb_by_func (GNC_PREFS_GROUP_GENERAL,
2920  GNC_PREF_ACCOUNTING_LABELS,
2921  split_register_pref_changed,
2922  reg);
2923  gnc_prefs_remove_cb_by_func (GNC_PREFS_GROUP_GENERAL,
2924  GNC_PREF_ACCOUNT_SEPARATOR,
2925  split_register_pref_changed,
2926  reg);
2927  gnc_book_option_remove_cb(OPTION_NAME_NUM_FIELD_SOURCE,
2928  split_register_book_option_changed,
2929  reg);
2930  gnc_split_register_cleanup (reg);
2931 
2932  gnc_table_destroy (reg->table);
2933  reg->table = NULL;
2934 
2935  /* free the memory itself */
2936  g_free (reg);
2937  LEAVE(" ");
2938 }
#define ENTER(format, args...)
Definition: qoflog.h:261
#define LEAVE(format, args...)
Definition: qoflog.h:271
void gnc_prefs_remove_cb_by_func(const gchar *group, const gchar *pref_name, gpointer func, gpointer user_data)
Definition: gnc-prefs.c:148
Split* gnc_split_register_duplicate_current ( SplitRegister reg)

Duplicates either the current transaction or the current split depending on the register mode and cursor position. Returns the split just created, or the 'main' split of the transaction just created, or NULL if nothing happened.

Definition at line 391 of file split-register.c.

392 {
393  SRInfo *info = gnc_split_register_get_info(reg);
394  CursorClass cursor_class;
395  Transaction *trans;
396  Split *return_split;
397  Split *trans_split;
398  Split *blank_split;
399  gboolean changed;
400  Split *split;
401 
402  ENTER("reg=%p", reg);
403 
404  blank_split = xaccSplitLookup(&info->blank_split_guid,
405  gnc_get_current_book ());
408  trans_split = gnc_split_register_get_current_trans_split (reg, NULL);
409 
410  /* This shouldn't happen, but be paranoid. */
411  if (trans == NULL)
412  {
413  LEAVE("no transaction");
414  return NULL;
415  }
416 
417  cursor_class = gnc_split_register_get_current_cursor_class (reg);
418 
419  /* Can't do anything with this. */
420  if (cursor_class == CURSOR_CLASS_NONE)
421  {
422  LEAVE("no cursor class");
423  return NULL;
424  }
425 
426  /* This shouldn't happen, but be paranoid. */
427  if ((split == NULL) && (cursor_class == CURSOR_CLASS_TRANS))
428  {
429  LEAVE("no split with transaction class");
430  return NULL;
431  }
432 
433  changed = gnc_table_current_cursor_changed (reg->table, FALSE);
434 
435  /* See if we were asked to duplicate an unchanged blank split.
436  * There's no point in doing that! */
437  if (!changed && ((split == NULL) || (split == blank_split)))
438  {
439  LEAVE("skip unchanged blank split");
440  return NULL;
441  }
442 
443  gnc_suspend_gui_refresh ();
444 
445  /* If the cursor has been edited, we are going to have to commit
446  * it before we can duplicate. Make sure the user wants to do that. */
447  if (changed)
448  {
449  GtkWidget *dialog, *window;
450  gint response;
451  const char *title = _("Save transaction before duplicating?");
452  const char *message =
453  _("The current transaction has been changed. Would you like to "
454  "record the changes before duplicating the transaction, or "
455  "cancel the duplication?");
456 
457  window = gnc_split_register_get_parent(reg);
458  dialog = gtk_message_dialog_new(GTK_WINDOW(window),
459  GTK_DIALOG_DESTROY_WITH_PARENT,
460  GTK_MESSAGE_QUESTION,
461  GTK_BUTTONS_CANCEL,
462  "%s", title);
463  gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
464  "%s", message);
465  gtk_dialog_add_button(GTK_DIALOG(dialog),
466  _("_Record"), GTK_RESPONSE_ACCEPT);
467  response = gnc_dialog_run(GTK_DIALOG(dialog), GNC_PREF_WARN_REG_TRANS_DUP);
468  gtk_widget_destroy(dialog);
469 
470  if (response != GTK_RESPONSE_ACCEPT)
471  {
472  gnc_resume_gui_refresh ();
473  LEAVE("save cancelled");
474  return NULL;
475  }
476 
477  gnc_split_register_save (reg, TRUE);
478 
479  /* If the split is NULL, then we were on a blank split row
480  * in an expanded transaction. The new split (created by
481  * gnc_split_register_save above) will be the last split in the
482  * current transaction, as it was just added. */
483  if (split == NULL)
484  split = xaccTransGetSplit (trans, xaccTransCountSplits (trans) - 1);
485  }
486 
487  /* Ok, we are now ready to make the copy. */
488 
489  if (cursor_class == CURSOR_CLASS_SPLIT)
490  {
491  Split *new_split;
492  char *out_num;
493  gboolean new_act_num = FALSE;
494 
495  /* We are on a split in an expanded transaction.
496  * Just copy the split and add it to the transaction.
497  * However, if the split-action field is being used as the register
498  * number, and the action field is a number, request a new value or
499  * cancel. Need to get next number and update account last num from
500  * split account not register account, which may be the same or not */
501 
503  && gnc_strisnum (gnc_get_num_action (NULL, split)))
504  {
505  Account *account = xaccSplitGetAccount (split);
506  const char *in_num = NULL;
507  const char* title = _("New Split Information");
508  time64 date = info->last_date_entered;
509 
510  if (account)
511  in_num = xaccAccountGetLastNum (account);
512  else
513  in_num = gnc_get_num_action (NULL, split);
514  if (!gnc_dup_trans_dialog (gnc_split_register_get_parent (reg),
515  title, FALSE, &date, in_num, &out_num, NULL, NULL))
516  {
517  gnc_resume_gui_refresh ();
518  LEAVE("dup cancelled");
519  return NULL;
520  }
521  new_act_num = TRUE;
522  }
523 
524  new_split = xaccMallocSplit (gnc_get_current_book ());
525 
526  xaccTransBeginEdit (trans);
527  xaccSplitSetParent (new_split, trans);
528  gnc_copy_split_onto_split (split, new_split, FALSE);
529  if (new_act_num) /* if new number supplied by user dialog */
530  gnc_set_num_action (NULL, new_split, out_num, NULL);
531  xaccTransCommitEdit (trans);
532 
533  if (new_act_num && gnc_strisnum (out_num))
534  {
535  Account *account = xaccSplitGetAccount (new_split);
536 
537  /* If current register is for account, set last num */
538  if (xaccAccountEqual(account,
539  gnc_split_register_get_default_account(reg),
540  TRUE))
541  {
542  NumCell *num_cell;
543  num_cell = (NumCell *) gnc_table_layout_get_cell (reg->table->layout,
544  NUM_CELL);
545  if (gnc_num_cell_set_last_num (num_cell, out_num))
546  gnc_split_register_set_last_num (reg, out_num);
547  }
548  else
549  {
550  xaccAccountSetLastNum (account, out_num);
551  }
552  }
553 
554  return_split = new_split;
555 
556  info->cursor_hint_split = new_split;
557  info->cursor_hint_cursor_class = CURSOR_CLASS_SPLIT;
558  if (new_act_num)
559  g_free (out_num);
560  }
561  else
562  {
563  NumCell *num_cell;
564  Transaction *new_trans;
565  int trans_split_index;
566  int split_index;
567  const char *in_num = NULL;
568  const char *in_tnum = NULL;
569  char *out_num;
570  char *out_tnum;
571  time64 date;
572  gboolean use_autoreadonly = qof_book_uses_autoreadonly(gnc_get_current_book());
573 
574  /* We are on a transaction row. Copy the whole transaction. */
575 
576  date = info->last_date_entered;
577  if (gnc_strisnum (gnc_get_num_action (trans, trans_split)))
578  {
579  Account *account = gnc_split_register_get_default_account (reg);
580 
581  if (account)
582  in_num = xaccAccountGetLastNum (account);
583  else
584  in_num = gnc_get_num_action (trans, trans_split);
585  in_tnum = (reg->use_tran_num_for_num_field
586  ? NULL
587  : gnc_get_num_action (trans, NULL));
588  }
589 
590  if (!gnc_dup_trans_dialog (gnc_split_register_get_parent (reg), NULL,
591  TRUE, &date, in_num, &out_num, in_tnum, &out_tnum))
592  {
593  gnc_resume_gui_refresh ();
594  LEAVE("dup cancelled");
595  return NULL;
596  }
597 
598  if (use_autoreadonly)
599  {
600  GDate d;
601  GDate *readonly_threshold = qof_book_get_autoreadonly_gdate(gnc_get_current_book());
602  gnc_gdate_set_time64 (&d, date);
603  if (g_date_compare(&d, readonly_threshold) < 0)
604  {
605  GtkWidget *dialog = gtk_message_dialog_new(NULL,
606  0,
607  GTK_MESSAGE_ERROR,
608  GTK_BUTTONS_OK,
609  "%s", _("Cannot store a transaction at this date"));
610  gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
611  "%s", _("The entered date of the duplicated transaction is older than the \"Read-Only Threshold\" set for this book. "
612  "This setting can be changed in File -> Properties -> Accounts."));
613  gtk_dialog_run(GTK_DIALOG(dialog));
614  gtk_widget_destroy(dialog);
615 
616  g_date_free(readonly_threshold);
617  return NULL;
618  }
619  g_date_free(readonly_threshold);
620  }
621 
622  split_index = xaccTransGetSplitIndex(trans, split);
623  trans_split_index = xaccTransGetSplitIndex(trans, trans_split);
624 
625  /* we should *always* find the split, but be paranoid */
626  if (split_index < 0)
627  {
628  gnc_resume_gui_refresh ();
629  LEAVE("no split");
630  return NULL;
631  }
632 
633  new_trans = xaccMallocTransaction (gnc_get_current_book ());
634 
635  xaccTransBeginEdit (new_trans);
636  gnc_copy_trans_onto_trans (trans, new_trans, FALSE, FALSE);
637  xaccTransSetDatePostedSecsNormalized (new_trans, date);
638  /* We also must set a new DateEntered on the new entry
639  * because otherwise the ordering is not deterministic */
640  xaccTransSetDateEnteredSecs(new_trans, gnc_time(NULL));
641 
642  /* set per book option */
643  gnc_set_num_action (new_trans, NULL, out_num, out_tnum);
644  if (!reg->use_tran_num_for_num_field)
645  {
646  /* find split in new_trans that equals trans_split and set
647  * split_action to out_num */
648  gnc_set_num_action (NULL,
649  xaccTransGetSplit (new_trans, trans_split_index),
650  out_num, NULL);
651  /* note that if the transaction has multiple splits to the register
652  * account, only the anchor split will be set with user input. The
653  * user will have to adjust other splits manually. */
654  }
655  xaccTransCommitEdit (new_trans);
656 
657  num_cell = (NumCell *) gnc_table_layout_get_cell (reg->table->layout,
658  NUM_CELL);
659  if (gnc_num_cell_set_last_num (num_cell, out_num))
660  gnc_split_register_set_last_num (reg, out_num);
661 
662  g_free (out_num);
663  if (!reg->use_tran_num_for_num_field)
664  g_free (out_tnum);
665 
666  /* This shouldn't happen, but be paranoid. */
667  if (split_index >= xaccTransCountSplits (new_trans))
668  split_index = 0;
669 
670  return_split = xaccTransGetSplit (new_trans, split_index);
671  trans_split = xaccTransGetSplit (new_trans, trans_split_index);
672 
673  info->cursor_hint_trans = new_trans;
674  info->cursor_hint_split = return_split;
675  info->cursor_hint_trans_split = trans_split;
676  info->cursor_hint_cursor_class = CURSOR_CLASS_TRANS;
677 
678  info->trans_expanded = FALSE;
679  }
680 
681  /* Refresh the GUI. */
682  gnc_resume_gui_refresh ();
683 
684  LEAVE(" ");
685  return return_split;
686 }
void gnc_copy_trans_onto_trans(Transaction *from, Transaction *to, gboolean use_cut_semantics, gboolean do_commit)
Transaction * gnc_split_register_get_current_trans(SplitRegister *reg)
Transaction * xaccMallocTransaction(QofBook *book)
Definition: Transaction.c:513
const char * xaccAccountGetLastNum(const Account *acc)
Definition: Account.c:4472
void xaccTransSetDatePostedSecsNormalized(Transaction *trans, time64 time)
Definition: Transaction.c:1920
Split * xaccTransGetSplit(const Transaction *trans, int i)
Definition: Transaction.c:2144
gboolean use_tran_num_for_num_field
Split * gnc_split_register_get_current_split(SplitRegister *reg)
Split * gnc_split_register_get_current_trans_split(SplitRegister *reg, VirtualCellLocation *trans_split_loc)
gboolean gnc_split_register_save(SplitRegister *reg, gboolean do_commit)
#define ENTER(format, args...)
Definition: qoflog.h:261
gboolean gnc_strisnum(const gchar *s)
void xaccAccountSetLastNum(Account *acc, const char *num)
Definition: Account.c:4481
int xaccTransCountSplits(const Transaction *trans)
Definition: Transaction.c:2170
GDate * qof_book_get_autoreadonly_gdate(const QofBook *book)
Split * xaccSplitLookup(const GncGUID *guid, QofBook *book)
Definition: Split.c:1104
void xaccTransCommitEdit(Transaction *trans)
Definition: Transaction.c:1579
gboolean xaccAccountEqual(const Account *aa, const Account *ab, gboolean check_guids)
Definition: Account.c:1475
void xaccTransBeginEdit(Transaction *trans)
Definition: Transaction.c:1380
int xaccTransGetSplitIndex(const Transaction *trans, const Split *split)
Definition: Transaction.c:2154
Split * xaccMallocSplit(QofBook *book)
Definition: Split.c:582
CursorClass
Definition: SplitP.h:71
CursorClass gnc_split_register_get_current_cursor_class(SplitRegister *reg)
Account * xaccSplitGetAccount(const Split *s)
Definition: Split.c:968
#define LEAVE(format, args...)
Definition: qoflog.h:271
time64 gnc_time(time64 *tbuf)
get the current local time
gint64 time64
Definition: gnc-date.h:83
void xaccTransSetDateEnteredSecs(Transaction *trans, time64 secs)
Definition: Transaction.c:1951
gboolean qof_book_uses_autoreadonly(const QofBook *book)
void gnc_gdate_set_time64(GDate *gd, time64 time)
void gnc_split_register_empty_current_trans_except_split ( SplitRegister reg,
Split split 
)

Deletes the non-transaction splits associated wih the current cursor, if both are non-NULL.

Definition at line 1247 of file split-register.c.

1249 {
1250  SRInfo *info;
1251  Transaction *trans;
1252  Transaction *pending;
1253  int i = 0;
1254  Split *s;
1255 
1256  if ((reg == NULL) || (split == NULL))
1257  return;
1258 
1259  gnc_suspend_gui_refresh ();
1260  info = gnc_split_register_get_info(reg);
1261  pending = xaccTransLookup(&info->pending_trans_guid, gnc_get_current_book());
1262 
1263  trans = xaccSplitGetParent(split);
1264  if (!pending)
1265  {
1266  if (gnc_split_register_begin_edit_or_warn(info, trans))
1267  {
1268  gnc_resume_gui_refresh ();
1269  return;
1270  }
1271  }
1272  else if (pending == trans)
1273  {
1274  g_assert(xaccTransIsOpen(trans));
1275  }
1276  else g_assert_not_reached();
1277 
1278  while ((s = xaccTransGetSplit(trans, i)) != NULL)
1279  {
1280  if (s != split)
1281  xaccSplitDestroy(s);
1282  else i++;
1283  }
1284 
1285  gnc_resume_gui_refresh ();
1287 }
Split * xaccTransGetSplit(const Transaction *trans, int i)
Definition: Transaction.c:2144
gboolean xaccTransIsOpen(const Transaction *trans)
Definition: Transaction.c:1819
gboolean xaccSplitDestroy(Split *split)
Definition: Split.c:1492
Transaction * xaccSplitGetParent(const Split *split)
Definition: Split.c:1903
Transaction * xaccTransLookup(const GncGUID *guid, QofBook *book)
Definition: Transaction.c:1024
void gnc_split_register_redraw(SplitRegister *reg)
Definition: SplitP.h:71
void gnc_split_register_expand_current_trans ( SplitRegister reg,
gboolean  expand 
)

Expand the current transaction if it is collapsed.

Definition at line 194 of file split-register.c.

195 {
196  SRInfo *info = gnc_split_register_get_info (reg);
197  VirtualLocation virt_loc;
198 
199  if (!reg)
200  return;
201 
202  if (reg->style == REG_STYLE_AUTO_LEDGER ||
203  reg->style == REG_STYLE_JOURNAL)
204  return;
205 
206  /* ok, so I just wanted an excuse to use exclusive-or */
207  if (!(expand ^ info->trans_expanded))
208  return;
209 
210  if (!expand)
211  {
212  virt_loc = reg->table->current_cursor_loc;
213  gnc_split_register_get_trans_split (reg, virt_loc.vcell_loc,
214  &virt_loc.vcell_loc);
215 
216  if (gnc_table_find_close_valid_cell (reg->table, &virt_loc, FALSE))
217  gnc_table_move_cursor_gui (reg->table, virt_loc);
218  else
219  {
220  PERR ("Can't find place to go!");
221  return;
222  }
223  }
224 
225  info->trans_expanded = expand;
226 
227  gnc_table_set_virt_cell_cursor (reg->table,
228  reg->table->current_cursor_loc.vcell_loc,
229  gnc_split_register_get_active_cursor (reg));
230 
231  gnc_split_register_set_trans_visible(
232  reg, reg->table->current_cursor_loc.vcell_loc, expand, FALSE);
233 
234  virt_loc = reg->table->current_cursor_loc;
235  if (!expand || !gnc_table_virtual_loc_valid (reg->table, virt_loc, FALSE))
236  {
237  if (gnc_table_find_close_valid_cell (reg->table, &virt_loc, FALSE))
238  gnc_table_move_cursor_gui (reg->table, virt_loc);
239  else
240  {
241  PERR ("Can't find place to go!");
242  return;
243  }
244  }
245 
246  gnc_table_refresh_gui (reg->table, TRUE);
247 
248  if (expand)
249  gnc_split_register_show_trans (reg,
250  reg->table->current_cursor_loc.vcell_loc);
251 }
#define PERR(format, args...)
Definition: qoflog.h:237
Split* gnc_split_register_get_blank_split ( SplitRegister reg)

Gets the blank split for a register.

Parameters
rega SplitRegister
Returns
the Split used as the blank split, or NULL if there currently isn't one

Definition at line 303 of file split-register.c.

304 {
305  SRInfo *info = gnc_split_register_get_info (reg);
306 
307  if (!reg) return NULL;
308 
309  return xaccSplitLookup (&info->blank_split_guid, gnc_get_current_book ());
310 }
Split * xaccSplitLookup(const GncGUID *guid, QofBook *book)
Definition: Split.c:1104
const char* gnc_split_register_get_credit_string ( SplitRegister reg)

Return the credit string used in the register.

Definition at line 2322 of file split-register.c.

2323 {
2324  SRInfo *info = gnc_split_register_get_info (reg);
2325 
2326  if (!reg)
2327  return NULL;
2328 
2329  if (info->credit_str)
2330  return info->credit_str;
2331 
2332  info->credit_str =
2333  gnc_get_credit_string
2334  (gnc_split_register_type_to_account_type (reg->type));
2335 
2336  if (info->credit_str)
2337  return info->credit_str;
2338 
2339  info->credit_str = g_strdup (_("Credit"));
2340 
2341  return info->credit_str;
2342 }
CursorClass gnc_split_register_get_current_cursor_class ( SplitRegister reg)

Returns the class of a register's current cursor.

Parameters
rega SplitRegister
Returns
the CursorClass of the current cursor

Definition at line 545 of file split-register-util.c.

546 {
547  Table *table;
548 
549  if (reg == NULL)
550  return CURSOR_CLASS_NONE;
551 
552  table = reg->table;
553  if (table == NULL)
554  return CURSOR_CLASS_NONE;
555 
556  return gnc_split_register_cursor_class (reg, table->current_cursor);
557 }
Split* gnc_split_register_get_current_split ( SplitRegister reg)

Returns the split at which the cursor is currently located.

Parameters
rega SplitRegister
Returns
the Split at the cursor location, or the anchoring split if the cursor is currently on a transaction

Definition at line 293 of file split-register.c.

294 {
295  if (reg == NULL)
296  return NULL;
297 
298  return gnc_split_register_get_split(
299  reg, reg->table->current_cursor_loc.vcell_loc);
300 }
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 of its splits.

Parameters
rega SplitRegister
Returns
the Transaction at the cursor location, or NULL

Definition at line 269 of file split-register.c.

270 {
271  Split *split;
272  VirtualCellLocation vcell_loc;
273 
274  if (reg == NULL)
275  return NULL;
276 
278  if (split != NULL)
279  return xaccSplitGetParent(split);
280 
281  /* Split is blank. Assume it is the blank split of a multi-line
282  * transaction. Go back one row to find a split in the transaction. */
283  vcell_loc = reg->table->current_cursor_loc.vcell_loc;
284 
285  vcell_loc.virt_row--;
286 
287  split = gnc_split_register_get_split (reg, vcell_loc);
288 
289  return xaccSplitGetParent (split);
290 }
Split * gnc_split_register_get_current_split(SplitRegister *reg)
Transaction * xaccSplitGetParent(const Split *split)
Definition: Split.c:1903
Definition: SplitP.h:71
Split* gnc_split_register_get_current_trans_split ( SplitRegister reg,
VirtualCellLocation vcell_loc 
)

Gets the anchoring split of the transaction at the current cursor location, which may be on the transaction itself or on any of its splits.

Parameters
rega SplitRegister
vcell_loca pointer to be filled with the location of the transaction's virtual cell
Returns
the anchoring Split of the transaction

Definition at line 186 of file split-register-util.c.

188 {
189  VirtualCellLocation vcell_loc;
190 
191  if (reg == NULL)
192  return NULL;
193 
194  vcell_loc = reg->table->current_cursor_loc.vcell_loc;
195 
196  return gnc_split_register_get_trans_split (reg, vcell_loc, trans_split_loc);
197 }
CursorClass gnc_split_register_get_cursor_class ( SplitRegister reg,
VirtualCellLocation  vcell_loc 
)

Returns the class of the cursor at the given virtual cell location.

Parameters
rega SplitRegister
vcell_locthe location of a virtual cell
Returns
the CursorClass of the cursor at vcell_loc

Definition at line 524 of file split-register-util.c.

526 {
527  VirtualCell *vcell;
528  Table *table;
529 
530  if (reg == NULL)
531  return CURSOR_CLASS_NONE;
532 
533  table = reg->table;
534  if (table == NULL)
535  return CURSOR_CLASS_NONE;
536 
537  vcell = gnc_table_get_virtual_cell (table, vcell_loc);
538  if (vcell == NULL)
539  return CURSOR_CLASS_NONE;
540 
541  return gnc_split_register_cursor_class (reg, vcell->cellblock);
542 }
const char* gnc_split_register_get_debit_string ( SplitRegister reg)

Return the debit string used in the register.

Definition at line 2299 of file split-register.c.

2300 {
2301  SRInfo *info = gnc_split_register_get_info (reg);
2302 
2303  if (!reg)
2304  return NULL;
2305 
2306  if (info->debit_str)
2307  return info->debit_str;
2308 
2309  info->debit_str =
2310  gnc_get_debit_string
2311  (gnc_split_register_type_to_account_type (reg->type));
2312 
2313  if (info->debit_str)
2314  return info->debit_str;
2315 
2316  info->debit_str = g_strdup (_("Debit"));
2317 
2318  return info->debit_str;
2319 }
gboolean gnc_split_register_get_split_amount_virt_loc ( SplitRegister reg,
Split split,
VirtualLocation virt_loc 
)

Searches the split register for the given split and determines the location of either its credit (if non-zero) or debit cell.

Parameters
rega SplitRegister
splitthe Split to find
virt_loca pointer to be filled with the amount cell's location
Returns
TRUE if the split was found and the location has been stored at virt_loc, FALSE otherwise

Definition at line 353 of file split-register.c.

355 {
356  VirtualLocation v_loc;
357  CursorClass cursor_class;
358  const char *cell_name;
359  gnc_numeric value;
360 
361  if (!gnc_split_register_get_split_virt_loc (reg, split, &v_loc.vcell_loc))
362  return FALSE;
363 
364  cursor_class = gnc_split_register_get_cursor_class (reg, v_loc.vcell_loc);
365 
366  value = xaccSplitGetValue (split);
367 
368  switch (cursor_class)
369  {
370  case CURSOR_CLASS_SPLIT:
371  case CURSOR_CLASS_TRANS:
372  cell_name = (gnc_numeric_negative_p (value)) ? CRED_CELL : DEBT_CELL;
373  break;
374  default:
375  return FALSE;
376  }
377 
378  if (!gnc_table_get_cell_location (reg->table, cell_name,
379  v_loc.vcell_loc, &v_loc))
380  return FALSE;
381 
382  if (virt_loc == NULL)
383  return TRUE;
384 
385  *virt_loc = v_loc;
386 
387  return TRUE;
388 }
CursorClass gnc_split_register_get_cursor_class(SplitRegister *reg, VirtualCellLocation vcell_loc)
gboolean gnc_numeric_negative_p(gnc_numeric a)
gboolean gnc_split_register_get_split_virt_loc(SplitRegister *reg, Split *split, VirtualCellLocation *vcell_loc)
CursorClass
gnc_numeric xaccSplitGetValue(const Split *split)
Definition: Split.c:1993
gboolean gnc_split_register_get_split_virt_loc ( SplitRegister reg,
Split split,
VirtualCellLocation vcell_loc 
)

Searches the split register for a given split. The search begins from the bottom row and works backwards. The location of the first virtual cell that matches will be returned in vcell_loc.

Parameters
rega SplitRegister
splitthe Split to find
vcell_loca pointer to be filled with the location of the matching virtual cell
Returns
TRUE if the split was found and the location has been stored at vcell_loc, FALSE otherwise

Definition at line 313 of file split-register.c.

315 {
316  Table *table;
317  int v_row;
318  int v_col;
319 
320  if (!reg || !split) return FALSE;
321 
322  table = reg->table;
323 
324  /* go backwards because typically you search for splits at the end
325  * and because we find split rows before transaction rows. */
326 
327  for (v_row = table->num_virt_rows - 1; v_row > 0; v_row--)
328  for (v_col = 0; v_col < table->num_virt_cols; v_col++)
329  {
330  VirtualCellLocation vc_loc = { v_row, v_col };
331  VirtualCell *vcell;
332  Split *s;
333 
334  vcell = gnc_table_get_virtual_cell (table, vc_loc);
335  if (!vcell || !vcell->visible)
336  continue;
337 
338  s = xaccSplitLookup (vcell->vcell_data, gnc_get_current_book ());
339 
340  if (s == split)
341  {
342  if (vcell_loc)
343  *vcell_loc = vc_loc;
344 
345  return TRUE;
346  }
347  }
348 
349  return FALSE;
350 }
Split * xaccSplitLookup(const GncGUID *guid, QofBook *book)
Definition: Split.c:1104
Definition: SplitP.h:71
gboolean gnc_split_register_handle_exchange ( SplitRegister reg,
gboolean  force_dialog 
)

Pop up the exchange-rate dialog, maybe, for the current split. If force_dialog is TRUE, the forces the dialog to to be called. If the dialog does not complete successfully, then return TRUE. Return FALSE in all other cases (meaning "move on")

Definition at line 1296 of file split-register-control.c.

1297 {
1298  SRInfo *info;
1299  Transaction *txn;
1300  Split *split, *osplit;
1301  Account *xfer_acc, *reg_acc;
1302  gnc_commodity *txn_cur, *xfer_com, *reg_com;
1303  gnc_numeric amount, exch_rate;
1304  XferDialog *xfer;
1305  gboolean expanded = FALSE;
1306  PriceCell *rate_cell;
1307  const char *message;
1308  CursorClass cursor_class;
1309 
1310  ENTER("reg=%p, force_dialog=%s", reg, force_dialog ? "TRUE" : "FALSE" );
1311 
1312  /* Make sure we NEED this for this type of register */
1313  if (!gnc_split_reg_has_rate_cell (reg->type))
1314  {
1315  if (force_dialog)
1316  {
1317  message = _("This register does not support editing exchange rates.");
1318  gnc_error_dialog(gnc_split_register_get_parent(reg), "%s", message);
1319  }
1320  LEAVE("no rate cell");
1321  return FALSE;
1322  }
1323 
1324  rate_cell = (PriceCell*) gnc_table_layout_get_cell(
1325  reg->table->layout, RATE_CELL);
1326  if (!rate_cell)
1327  {
1328  if (force_dialog)
1329  {
1330  message = _("This register does not support editing exchange rates.");
1331  gnc_error_dialog(gnc_split_register_get_parent(reg), "%s", message);
1332  }
1333  LEAVE("null rate cell");
1334  return FALSE;
1335  }
1336 
1337  /* See if we already have an exchange rate... */
1338  info = gnc_split_register_get_info (reg);
1339  exch_rate = gnc_price_cell_get_value (rate_cell);
1340  if (!gnc_numeric_zero_p(exch_rate) && !force_dialog &&
1341  info->rate_reset != RATE_RESET_REQD)
1342  {
1343  LEAVE("rate already non-zero");
1344  return FALSE;
1345  }
1346 
1347  /* Are we expanded? */
1349  cursor_class = gnc_split_register_get_current_cursor_class (reg);
1350 
1351  /* If we're expanded AND a transaction cursor, there is nothing to do */
1352  if (expanded && cursor_class == CURSOR_CLASS_TRANS)
1353  {
1354  if (force_dialog)
1355  {
1356  message = _("You need to select a split in order to modify its exchange "
1357  "rate.");
1358  gnc_error_dialog(gnc_split_register_get_parent(reg), "%s", message);
1359  }
1360  LEAVE("expanded with transaction cursor; nothing to do");
1361  return FALSE;
1362  }
1363 
1364  /* Grab the xfer account */
1365  xfer_acc = gnc_split_register_get_account_always(
1366  reg, expanded ? XFRM_CELL : MXFRM_CELL);
1367 
1368  /* If this is an un-expanded, multi-split transaction, then warn the user */
1369  if (force_dialog && !expanded && !xfer_acc)
1370  {
1371  message = _("You need to expand the transaction in order to modify its "
1372  "exchange rates.");
1373  gnc_error_dialog (gnc_split_register_get_parent (reg), "%s", message);
1374  LEAVE("%s", message);
1375  return TRUE;
1376  }
1377 
1378  /* No account -- don't run the dialog */
1379  if (!xfer_acc)
1380  {
1381  if (force_dialog)
1382  {
1383  message = _("The entered account could not be found.");
1384  gnc_error_dialog(gnc_split_register_get_parent(reg), "%s", message);
1385  }
1386  LEAVE("no xfer account");
1387  return FALSE;
1388  }
1389 
1390  /* Grab the txn currency and xfer commodity */
1392  txn_cur = xaccTransGetCurrency (txn);
1393  xfer_com = xaccAccountGetCommodity (xfer_acc);
1394 
1395  /* Grab the register account and commodity (may be used later) */
1396  reg_acc = gnc_split_register_get_default_account (reg);
1397  reg_com = xaccAccountGetCommodity (reg_acc);
1398 
1399  /* Grab the split and perhaps the "other" split (if it is a two-split txn) */
1401  osplit = xaccSplitGetOtherSplit (split);
1402 
1403  /* Check if the txn- and xfer- commodities are the same */
1404  if (gnc_commodity_equal (txn_cur, xfer_com))
1405  {
1406  /* If we're not forcing the dialog, then there is no reason to
1407  * go on. We're using the correct accounts.
1408  */
1409  if (!force_dialog)
1410  {
1411  LEAVE("txn and account currencies match, and not forcing");
1412  return FALSE;
1413  }
1414 
1415  /* Only proceed with two-split, basic, non-expanded registers */
1416  if (expanded || osplit == NULL)
1417  {
1418  message = _("The two currencies involved equal each other.");
1419  gnc_error_dialog(gnc_split_register_get_parent(reg), "%s", message);
1420  LEAVE("register is expanded or osplit == NULL; not forcing dialog");
1421  return FALSE;
1422  }
1423 
1424  /* If we're forcing, then compare the current account
1425  * commodity to the transaction currency.
1426  */
1427  xfer_acc = reg_acc;
1428  xfer_com = reg_com;
1429  if (gnc_commodity_equal (txn_cur, xfer_com))
1430  {
1431  message = _("The two currencies involved equal each other.");
1432  gnc_error_dialog(gnc_split_register_get_parent(reg), "%s", message);
1433  LEAVE("reg commodity == txn commodity; not forcing");
1434  return FALSE;
1435  }
1436  }
1437 
1438  /* If this is a non-expanded, two-split txn where BOTH splits need
1439  * conversion rates, then require the user to actually expand the
1440  * transaction in order to edit it.
1441  */
1442  if (!expanded && osplit &&
1443  gnc_split_register_split_needs_amount (reg, split) &&
1444  gnc_split_register_split_needs_amount (reg, osplit))
1445  {
1446  message = _("You need to expand the transaction in order to modify its "
1447  "exchange rates.");
1448  if (force_dialog)
1449  {
1450  gnc_error_dialog (gnc_split_register_get_parent (reg), "%s", message);
1451  }
1452  LEAVE("%s", message);
1453  return TRUE;
1454  }
1455 
1456  /* Strangely, if we're in a two-split, non-expanded txn, we need
1457  * to do something really special with the exchange rate! In
1458  * particular, we have to pick it up from the _other_ split --
1459  * right?
1460  * XXX: perhaps I should pop up an error here? Or maybe require the
1461  * user to go into expanded-mode?
1462  */
1463  if (!expanded && osplit && !gnc_commodity_equal(reg_com, txn_cur) &&
1464  !gnc_commodity_equal(reg_com, xfer_com))
1465  {
1466  gnc_numeric amt = xaccSplitGetAmount (osplit);
1467  gnc_numeric val = xaccSplitGetValue (osplit);
1468  exch_rate = gnc_numeric_div (amt, val, GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
1469  }
1470 
1471  /* Ok, we need to grab the exchange rate */
1472  amount = gnc_split_register_debcred_cell_value (reg);
1473 
1474  /*
1475  * If "amount" is zero then we don't need an exchange-rate.. Return
1476  * FALSE to let the user continue on.
1477  */
1478  if (gnc_numeric_zero_p (amount))
1479  {
1480  if (force_dialog)
1481  {
1482  message = _("The split's amount is zero, so no exchange rate is needed.");
1483  gnc_error_dialog(gnc_split_register_get_parent(reg), "%s", message);
1484  }
1485  LEAVE("amount is zero; no exchange rate needed");
1486  return FALSE;
1487  }
1488 
1489  /* If the exch_rate is zero, we're not forcing the dialog, and this is
1490  * _not_ the blank split, then return FALSE -- this is a "special"
1491  * gain/loss stock transaction.
1492  */
1493  if (gnc_numeric_zero_p(exch_rate) && !force_dialog && split &&
1494  info->rate_reset != RATE_RESET_REQD &&
1495  split != gnc_split_register_get_blank_split (reg))
1496  {
1497  LEAVE("gain/loss split; no exchange rate needed");
1498  return FALSE;
1499  }
1500 
1501  /* Show the exchange-rate dialog */
1502  xfer = gnc_split_register_xfer_dialog(reg, txn, split);
1503  gnc_xfer_dialog_is_exchange_dialog(xfer, &exch_rate);
1504  if (gnc_xfer_dialog_run_exchange_dialog(
1505  xfer, &exch_rate, amount, reg_acc, txn, xfer_com, expanded))
1506  {
1507  /* FIXME: How should the dialog be destroyed? */
1508  LEAVE("leaving rate unchanged");
1509  return TRUE;
1510  }
1511  /* FIXME: How should the dialog be destroyed? */
1512 
1513  /* Set the RATE_CELL on this cursor and mark it changed */
1514  gnc_price_cell_set_value (rate_cell, exch_rate);
1515  gnc_basic_cell_set_changed (&rate_cell->cell, TRUE);
1516  info->rate_account = xfer_acc;
1517  info->rate_reset = RATE_RESET_DONE;
1518  LEAVE("set rate=%s", gnc_num_dbg_to_string(exch_rate));
1519  return FALSE;
1520 }
Transaction * gnc_split_register_get_current_trans(SplitRegister *reg)
gchar * gnc_num_dbg_to_string(gnc_numeric n)
Split * gnc_split_register_get_current_split(SplitRegister *reg)
Split * gnc_split_register_get_blank_split(SplitRegister *reg)
gboolean gnc_commodity_equal(const gnc_commodity *a, const gnc_commodity *b)
gboolean gnc_numeric_zero_p(gnc_numeric a)
#define ENTER(format, args...)
Definition: qoflog.h:261
gnc_numeric gnc_numeric_div(gnc_numeric x, gnc_numeric y, gint64 denom, gint how)
gboolean gnc_split_register_current_trans_expanded(SplitRegister *reg)
CursorClass
Definition: SplitP.h:71
gnc_numeric xaccSplitGetValue(const Split *split)
Definition: Split.c:1993
CursorClass gnc_split_register_get_current_cursor_class(SplitRegister *reg)
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Definition: Account.c:3148
gnc_commodity * xaccTransGetCurrency(const Transaction *trans)
Definition: Transaction.c:1348
Split * xaccSplitGetOtherSplit(const Split *split)
Definition: Split.c:2086
#define LEAVE(format, args...)
Definition: qoflog.h:271
#define GNC_DENOM_AUTO
Definition: gnc-numeric.h:246
gnc_numeric xaccSplitGetAmount(const Split *split)
Definition: Split.c:1987
void gnc_split_register_load ( SplitRegister reg,
GList *  slist,
Account default_account 
)

Populates the rows of a register.

The rows are filled, based on the register style, with data associated with the given list of splits slist. In addition, an area for the user to begin entering new transactions is placed at the tail end of the register. This area is anchored by the "blank split".

The account default_account, if provided, is used to determine various default values for the blank split (such as currency, last check number, and transfer account) for the blank split.

Parameters
rega SplitRegister
slista list of splits
default_accountan account to provide defaults for the blank split

Definition at line 327 of file split-register-load.c.

329 {
330  SRInfo *info;
331  Transaction *pending_trans;
332  CursorBuffer *cursor_buffer;
333  GHashTable *trans_table = NULL;
334  CellBlock *cursor_header;
335  CellBlock *lead_cursor;
336  CellBlock *split_cursor;
337  Transaction *blank_trans;
338  Transaction *find_trans;
339  Transaction *trans;
340  CursorClass find_class;
341  Split *find_trans_split;
342  Split *blank_split;
343  Split *find_split;
344  Split *split;
345  Table *table;
346  GList *node;
347 
348  gboolean start_primary_color = TRUE;
349  gboolean found_pending = FALSE;
350  gboolean need_divider_upper = FALSE;
351  gboolean found_divider_upper = FALSE;
352  gboolean found_divider = FALSE;
353  gboolean has_last_num = FALSE;
354  gboolean multi_line;
355  gboolean dynamic;
356  gboolean we_own_slist = FALSE;
357  gboolean use_autoreadonly = qof_book_uses_autoreadonly(gnc_get_current_book());
358  gboolean future_after_blank = gnc_prefs_get_bool(GNC_PREFS_GROUP_GENERAL_REGISTER,
359  GNC_PREF_FUTURE_AFTER_BLANK);
360  gboolean added_blank_trans = FALSE;
361 
362  VirtualCellLocation vcell_loc;
363  VirtualLocation save_loc;
364 
365  int new_trans_split_row = -1;
366  int new_trans_row = -1;
367  int new_split_row = -1;
368  time64 present, autoreadonly_time = 0;
369 
370  g_return_if_fail(reg);
371  table = reg->table;
372  g_return_if_fail(table);
373  info = gnc_split_register_get_info (reg);
374  g_return_if_fail(info);
375 
376  ENTER("reg=%p, slist=%p, default_account=%p", reg, slist, default_account);
377 
378  blank_split = xaccSplitLookup (&info->blank_split_guid,
379  gnc_get_current_book ());
380 
381  pending_trans = xaccTransLookup (&info->pending_trans_guid,
382  gnc_get_current_book ());
383 
384  /* make sure we have a blank split */
385  if (blank_split == NULL)
386  {
387  /* Wouldn't it be a bug to open the new transaction if there was
388  * already a pending transaction?
389  */
390  g_assert(pending_trans == NULL);
391  blank_split = create_blank_split (default_account, info);
392  }
393  blank_trans = xaccSplitGetParent (blank_split);
394 
395  DEBUG("blank_split=%p, blank_trans=%p, pending_trans=%p",
396  blank_split, blank_trans, pending_trans);
397 
398  info->default_account = *xaccAccountGetGUID (default_account);
399 
400  // gnc_table_leave_update (table, table->current_cursor_loc);
401 
402  multi_line = (reg->style == REG_STYLE_JOURNAL);
403  dynamic = (reg->style == REG_STYLE_AUTO_LEDGER);
404 
405  lead_cursor = gnc_split_register_get_passive_cursor (reg);
406  split_cursor = gnc_table_layout_get_cursor (table->layout, CURSOR_SPLIT);
407 
408  /* figure out where we are going to. */
409  if (info->traverse_to_new)
410  {
411  find_trans = blank_trans;
412  find_split = NULL;
413  find_trans_split = blank_split;
414  find_class = CURSOR_CLASS_SPLIT;
415  }
416  else
417  {
418  find_trans = info->cursor_hint_trans;
419  find_split = info->cursor_hint_split;
420  find_trans_split = info->cursor_hint_trans_split;
421  find_class = info->cursor_hint_cursor_class;
422  }
423 
424  save_loc = table->current_cursor_loc;
425 
426  /* If the current cursor has changed we save the values for later
427  * possible restoration. */
428  if (gnc_table_current_cursor_changed (table, TRUE) &&
429  (find_split == gnc_split_register_get_current_split (reg)))
430  {
431  cursor_buffer = gnc_cursor_buffer_new ();
432  gnc_table_save_current_cursor (table, cursor_buffer);
433  }
434  else
435  cursor_buffer = NULL;
436 
437  /* disable move callback -- we don't want the cascade of
438  * callbacks while we are fiddling with loading the register */
439  gnc_table_control_allow_move (table->control, FALSE);
440 
441  /* invalidate the cursor */
442  {
443  VirtualLocation virt_loc;
444 
445  gnc_virtual_location_init(&virt_loc);
446  gnc_table_move_cursor_gui (table, virt_loc);
447  }
448 
449  /* make sure that the header is loaded */
450  vcell_loc.virt_row = 0;
451  vcell_loc.virt_col = 0;
452  cursor_header = gnc_table_layout_get_cursor (table->layout, CURSOR_HEADER);
453  gnc_table_set_vcell (table, cursor_header, NULL, TRUE, TRUE, vcell_loc);
454  vcell_loc.virt_row++;
455 
456  /* get the current time and reset the dividing row */
457  present = gnc_time64_get_today_end ();
458  if (use_autoreadonly)
459  {
460  GDate *d = qof_book_get_autoreadonly_gdate(gnc_get_current_book());
461  // "d" is NULL if use_autoreadonly is FALSE
462  autoreadonly_time = d ? timespecToTime64(gdate_to_timespec(*d)) : 0;
463  g_date_free(d);
464  }
465 
466  if (info->first_pass)
467  {
468  if (default_account)
469  {
470  const char *last_num = xaccAccountGetLastNum (default_account);
471 
472  if (last_num)
473  {
474  NumCell *cell;
475 
476  cell = (NumCell *) gnc_table_layout_get_cell(table->layout, NUM_CELL);
477  gnc_num_cell_set_last_num (cell, last_num);
478  has_last_num = TRUE;
479  }
480  }
481 
482  /* load up account names into the transfer combobox menus */
483  gnc_split_register_load_xfer_cells (reg, default_account);
484  gnc_split_register_load_recn_cells (reg);
485  gnc_split_register_load_type_cells (reg);
486  }
487 
488  if (info->separator_changed)
489  change_account_separator (info, table, reg);
490 
491  table->model->dividing_row_upper = -1;
492  table->model->dividing_row = -1;
493  table->model->dividing_row_lower = -1;
494 
495  // Ensure that the transaction and splits being edited are in the split
496  // list we're about to load.
497  if (pending_trans != NULL)
498  {
499  for (node = xaccTransGetSplitList(pending_trans); node; node = node->next)
500  {
501  Split *pending_split = (Split*)node->data;
502  if (!xaccTransStillHasSplit(pending_trans, pending_split)) continue;
503  if (g_list_find(slist, pending_split) != NULL)
504  continue;
505 
506  if (g_list_find_custom(slist, pending_trans,
507  _find_split_with_parent_txn) != NULL)
508  continue;
509 
510  if (!we_own_slist)
511  {
512  // lazy-copy
513  slist = g_list_copy(slist);
514  we_own_slist = TRUE;
515  }
516  slist = g_list_append(slist, pending_split);
517  }
518  }
519 
520  if (multi_line)
521  trans_table = g_hash_table_new (g_direct_hash, g_direct_equal);
522 
523  /* populate the table */
524  for (node = slist; node; node = node->next)
525  {
526  split = node->data;
527  trans = xaccSplitGetParent (split);
528 
529  if (!xaccTransStillHasSplit(trans, split))
530  continue;
531 
532  if (pending_trans == trans)
533  found_pending = TRUE;
534  /* If the transaction has only one split, and it's not our
535  * pending_trans, then it's another register's blank split and
536  * we don't want to see it.
537  */
538  else if (xaccTransCountSplits (trans) == 1 &&
539  xaccSplitGetAccount (split) == NULL)
540  continue;
541 
542 
543  /* Do not load splits from the blank transaction. */
544  if (trans == blank_trans)
545  continue;
546 
547  if (multi_line)
548  {
549  /* Skip this split if its transaction has already been loaded. */
550  if (g_hash_table_lookup (trans_table, trans))
551  continue;
552 
553  g_hash_table_insert (trans_table, trans, trans);
554  }
555 
556  if (info->show_present_divider &&
557  use_autoreadonly &&
558  !found_divider_upper)
559  {
560  if (xaccTransGetDate (trans) >= autoreadonly_time)
561  {
562  table->model->dividing_row_upper = vcell_loc.virt_row;
563  found_divider_upper = TRUE;
564  }
565  else
566  {
567  need_divider_upper = TRUE;
568  }
569  }
570 
571  if (info->show_present_divider &&
572  !found_divider &&
573  (xaccTransGetDate (trans) > present))
574  {
575  table->model->dividing_row = vcell_loc.virt_row;
576  found_divider = TRUE;
577 
578  if (future_after_blank)
579  {
580  if (blank_trans == find_trans)
581  new_trans_row = vcell_loc.virt_row;
582 
583  if (blank_split == find_trans_split)
584  new_trans_split_row = vcell_loc.virt_row;
585 
586  /* go to blank on first pass */
587  if (info->first_pass)
588  {
589  save_loc.vcell_loc = vcell_loc;
590  save_loc.phys_row_offset = 0;
591  save_loc.phys_col_offset = 0;
592  }
593 
594  gnc_split_register_add_transaction (reg,
595  blank_trans, blank_split,
596  lead_cursor, split_cursor,
597  multi_line, start_primary_color,
598  info->blank_split_edited,
599  find_trans, find_split,
600  find_class, &new_split_row,
601  &vcell_loc);
602 
603  table->model->dividing_row_lower = vcell_loc.virt_row;
604 
605  if (!multi_line)
606  start_primary_color = !start_primary_color;
607 
608  added_blank_trans = TRUE;
609  }
610  }
611 
612  /* If this is the first load of the register,
613  * fill up the quickfill cells. */
614  if (info->first_pass)
615  add_quickfill_completions(reg->table->layout, trans, split, has_last_num);
616 
617  if (trans == find_trans)
618  new_trans_row = vcell_loc.virt_row;
619 
620  if (split == find_trans_split)
621  new_trans_split_row = vcell_loc.virt_row;
622 
623  gnc_split_register_add_transaction (reg, trans, split,
624  lead_cursor, split_cursor,
625  multi_line, start_primary_color,
626  TRUE,
627  find_trans, find_split, find_class,
628  &new_split_row, &vcell_loc);
629 
630  if (!multi_line)
631  start_primary_color = !start_primary_color;
632  }
633 
634  if (multi_line)
635  g_hash_table_destroy (trans_table);
636 
637  /* add the blank split at the end. */
638  if (pending_trans == blank_trans)
639  found_pending = TRUE;
640 
641  /* No upper divider yet? Store it now */
642  if (info->show_present_divider &&
643  use_autoreadonly &&
644  !found_divider_upper && need_divider_upper)
645  {
646  table->model->dividing_row_upper = vcell_loc.virt_row;
647  found_divider_upper = TRUE;
648  }
649 
650  /* If we didn't find the pending transaction, it was removed
651  * from the account. */
652  if (!found_pending)
653  {
654  info->pending_trans_guid = *guid_null ();
655  if (xaccTransIsOpen (pending_trans))
656  xaccTransCommitEdit (pending_trans);
657  else if (pending_trans)
658  g_assert_not_reached();
659 
660  pending_trans = NULL;
661  }
662 
663  if (!added_blank_trans) {
664  if (blank_trans == find_trans)
665  new_trans_row = vcell_loc.virt_row;
666 
667  if (blank_split == find_trans_split)
668  new_trans_split_row = vcell_loc.virt_row;
669 
670  /* go to blank on first pass */
671  if (info->first_pass)
672  {
673  save_loc.vcell_loc = vcell_loc;
674  save_loc.phys_row_offset = 0;
675  save_loc.phys_col_offset = 0;
676  }
677 
678  gnc_split_register_add_transaction (reg, blank_trans, blank_split,
679  lead_cursor, split_cursor,
680  multi_line, start_primary_color,
681  info->blank_split_edited,
682  find_trans, find_split,
683  find_class, &new_split_row,
684  &vcell_loc);
685 
686  if (future_after_blank)
687  table->model->dividing_row_lower = vcell_loc.virt_row;
688  }
689 
690  /* go to blank on first pass */
691  if (info->first_pass)
692  {
693  new_split_row = -1;
694  new_trans_split_row = -1;
695  new_trans_row = -1;
696  }
697 
698  /* resize the table to the sizes we just counted above */
699  /* num_virt_cols is always one. */
700  gnc_table_set_size (table, vcell_loc.virt_row, 1);
701 
702  /* restore the cursor to its rightful position */
703  {
704  VirtualLocation trans_split_loc;
705 
706  if (new_split_row > 0)
707  save_loc.vcell_loc.virt_row = new_split_row;
708  else if (new_trans_split_row > 0)
709  save_loc.vcell_loc.virt_row = new_trans_split_row;
710  else if (new_trans_row > 0)
711  save_loc.vcell_loc.virt_row = new_trans_row;
712 
713  trans_split_loc = save_loc;
714 
715  gnc_split_register_get_trans_split (reg, save_loc.vcell_loc,
716  &trans_split_loc.vcell_loc);
717 
718  if (dynamic || multi_line || info->trans_expanded)
719  {
720  gnc_table_set_virt_cell_cursor(
721  table, trans_split_loc.vcell_loc,
722  gnc_split_register_get_active_cursor (reg));
723  gnc_split_register_set_trans_visible (reg, trans_split_loc.vcell_loc,
724  TRUE, multi_line);
725 
726  info->trans_expanded = (reg->style == REG_STYLE_LEDGER);
727  }
728  else
729  {
730  save_loc = trans_split_loc;
731  info->trans_expanded = FALSE;
732  }
733 
734  if (gnc_table_find_close_valid_cell (table, &save_loc, FALSE))
735  {
736  gnc_table_move_cursor_gui (table, save_loc);
737  new_split_row = save_loc.vcell_loc.virt_row;
738 
739  if (find_split == gnc_split_register_get_current_split (reg))
740  gnc_table_restore_current_cursor (table, cursor_buffer);
741  }
742  }
743  gnc_cursor_buffer_destroy (cursor_buffer);
744  cursor_buffer = NULL;
745 
746  update_info (info, reg);
747 
748  gnc_split_register_set_cell_fractions(
750 
751  gnc_table_refresh_gui (table, TRUE);
752 
753  gnc_split_register_show_trans (reg, table->current_cursor_loc.vcell_loc);
754 
755  /* enable callback for cursor user-driven moves */
756  gnc_table_control_allow_move (table->control, TRUE);
757 
758  if (we_own_slist)
759  g_list_free(slist);
760 
761  LEAVE(" ");
762 }
const char * xaccAccountGetLastNum(const Account *acc)
Definition: Account.c:4472
time64 timespecToTime64(Timespec ts)
time64 xaccTransGetDate(const Transaction *trans)
Definition: Transaction.c:2215
time64 gnc_time64_get_today_end(void)
gboolean xaccTransIsOpen(const Transaction *trans)
Definition: Transaction.c:1819
Split * gnc_split_register_get_current_split(SplitRegister *reg)
#define DEBUG(format, args...)
Definition: qoflog.h:255
Transaction * xaccSplitGetParent(const Split *split)
Definition: Split.c:1903
#define ENTER(format, args...)
Definition: qoflog.h:261
Transaction * xaccTransLookup(const GncGUID *guid, QofBook *book)
Definition: Transaction.c:1024
int xaccTransCountSplits(const Transaction *trans)
Definition: Transaction.c:2170
#define xaccAccountGetGUID(X)
Definition: Account.h:239
GDate * qof_book_get_autoreadonly_gdate(const QofBook *book)
Split * xaccSplitLookup(const GncGUID *guid, QofBook *book)
Definition: Split.c:1104
void xaccTransCommitEdit(Transaction *trans)
Definition: Transaction.c:1579
CursorClass
Definition: SplitP.h:71
Account * xaccSplitGetAccount(const Split *s)
Definition: Split.c:968
const GncGUID * guid_null(void)
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Definition: gnc-prefs.c:196
#define LEAVE(format, args...)
Definition: qoflog.h:271
gint64 time64
Definition: gnc-date.h:83
Timespec gdate_to_timespec(GDate d)
gboolean qof_book_uses_autoreadonly(const QofBook *book)
SplitList * xaccTransGetSplitList(const Transaction *trans)
Definition: Transaction.c:2164
SplitRegister* gnc_split_register_new ( SplitRegisterType  type,
SplitRegisterStyle  style,
gboolean  use_double_line,
gboolean  is_template 
)

Creates a new split register.

Parameters
typea SplitRegisterType to use for the new register
stylea SplitRegisterStyle to use for the new register
use_double_lineTRUE to show two lines for transactions, FALSE for one
is_templateTRUE for a new template, FALSE otherwise
Returns
a newly created SplitRegister

Definition at line 2729 of file split-register.c.

2733 {
2734  SplitRegister * reg;
2735  gboolean default_do_auto_complete = TRUE;
2736 
2737  reg = g_new0 (SplitRegister, 1);
2738 
2739  if (type >= NUM_SINGLE_REGISTER_TYPES)
2740  style = REG_STYLE_JOURNAL;
2741 
2742  gnc_split_register_init (reg,
2743  type,
2744  style,
2745  use_double_line,
2746  default_do_auto_complete,
2747  is_template);
2748 
2749  return reg;
2750 }
The type, style and table for the register.
void gnc_split_register_paste_current ( SplitRegister reg)

Pastes a previous copied entity onto the current entity, but only if the copied and current entity have the same type.

Definition at line 860 of file split-register.c.

861 {
862  SRInfo *info = gnc_split_register_get_info(reg);
863  CursorClass cursor_class;
864  Transaction *trans;
865  Transaction *blank_trans;
866  Split *blank_split;
867  Split *trans_split;
868  Split *split;
869 
870  ENTER("reg=%p", reg);
871 
872  if (copied_class == CURSOR_CLASS_NONE)
873  {
874  LEAVE("no copied cursor class");
875  return;
876  }
877 
878  blank_split = xaccSplitLookup (&info->blank_split_guid,
879  gnc_get_current_book ());
880  blank_trans = xaccSplitGetParent (blank_split);
883 
884  trans_split = gnc_split_register_get_current_trans_split (reg, NULL);
885 
886  /* This shouldn't happen, but be paranoid. */
887  if (trans == NULL)
888  {
889  LEAVE("no transaction");
890  return;
891  }
892 
893  cursor_class = gnc_split_register_get_current_cursor_class (reg);
894 
895  /* Can't do anything with this. */
896  if (cursor_class == CURSOR_CLASS_NONE)
897  {
898  LEAVE("no current cursor class");
899  return;
900  }
901 
902  /* This shouldn't happen, but be paranoid. */
903  if ((split == NULL) && (cursor_class == CURSOR_CLASS_TRANS))
904  {
905  g_warning("BUG DETECTED: transaction cursor with no anchoring split!");
906  LEAVE("transaction cursor with no anchoring split");
907  return;
908  }
909 
910  if (cursor_class == CURSOR_CLASS_SPLIT)
911  {
912  const char *message = _("You are about to overwrite an existing split. "
913  "Are you sure you want to do that?");
914 
915  if (copied_class == CURSOR_CLASS_TRANS)
916  {
917  /* An entire transaction was copied, but we're just on a split. */
918  LEAVE("can't copy trans to split");
919  return;
920  }
921 
922  /* Ask before overwriting an existing split. */
923  if (split != NULL &&
924  !gnc_verify_dialog (gnc_split_register_get_parent (reg),
925  FALSE, "%s", message))
926  {
927  LEAVE("user cancelled");
928  return;
929  }
930 
931  gnc_suspend_gui_refresh ();
932 
933  if (split == NULL)
934  {
935  /* We are on a null split in an expanded transaction. */
936  split = xaccMallocSplit(gnc_get_current_book ());
937  xaccSplitSetParent(split, trans);
938  }
939 
940  gnc_copy_split_scm_onto_split(copied_item, split,
941  gnc_get_current_book ());
942  }
943  else
944  {
945  const char *message = _("You are about to overwrite an existing "
946  "transaction. "
947  "Are you sure you want to do that?");
948  Account * copied_leader;
949  const GncGUID *new_guid;
950  int trans_split_index;
951  int split_index;
952  int num_splits;
953 
954  if (copied_class == CURSOR_CLASS_SPLIT)
955  {
956  LEAVE("can't copy split to transaction");
957  return;
958  }
959 
960  /* Ask before overwriting an existing transaction. */
961  if (split != blank_split &&
962  !gnc_verify_dialog(gnc_split_register_get_parent(reg),
963  FALSE, "%s", message))
964  {
965  LEAVE("user cancelled");
966  return;
967  }
968 
969  /* Open the transaction for editing. */
970  if (gnc_split_register_begin_edit_or_warn(info, trans))
971  {
972  LEAVE("can't begin editing");
973  return;
974  }
975 
976  gnc_suspend_gui_refresh ();
977 
978  DEBUG("Pasting txn, trans=%p, split=%p, blank_trans=%p, blank_split=%p",
979  trans, split, blank_trans, blank_split);
980 
981  split_index = xaccTransGetSplitIndex(trans, split);
982  trans_split_index = xaccTransGetSplitIndex(trans, trans_split);
983 
984  copied_leader = xaccAccountLookup(&copied_leader_guid,
985  gnc_get_current_book());
986  if (copied_leader && (gnc_split_register_get_default_account(reg) != NULL))
987  {
988  new_guid = &info->default_account;
989  gnc_copy_trans_scm_onto_trans_swap_accounts(copied_item, trans,
990  &copied_leader_guid,
991  new_guid, FALSE,
992  gnc_get_current_book ());
993  }
994  else
995  gnc_copy_trans_scm_onto_trans(copied_item, trans, FALSE,
996  gnc_get_current_book ());
997 
998  num_splits = xaccTransCountSplits(trans);
999  if (split_index >= num_splits)
1000  split_index = 0;
1001 
1002  if (trans == blank_trans)
1003  {
1004  /* In pasting, the blank split is deleted. Pick a new one. */
1005  blank_split = xaccTransGetSplit(trans, 0);
1006  info->blank_split_guid = *xaccSplitGetGUID (blank_split);
1007  info->blank_split_edited = TRUE;
1008  info->auto_complete = FALSE;
1009  DEBUG("replacement blank_split=%p", blank_split);
1010 
1011  /* NOTE: At this point, the blank transaction virtual cell is still
1012  * anchored by the old, deleted blank split. The register will
1013  * have to be reloaded (redrawn) to correct this. */
1014  }
1015 
1016  info->cursor_hint_trans = trans;
1017  info->cursor_hint_split = xaccTransGetSplit(trans, split_index);
1018  info->cursor_hint_trans_split = xaccTransGetSplit(trans,
1019  trans_split_index);
1020  info->cursor_hint_cursor_class = CURSOR_CLASS_TRANS;
1021  }
1022 
1023  /* Refresh the GUI. */
1024  gnc_resume_gui_refresh ();
1025  LEAVE(" ");
1026 }
Transaction * gnc_split_register_get_current_trans(SplitRegister *reg)
Split * xaccTransGetSplit(const Transaction *trans, int i)
Definition: Transaction.c:2144
Split * gnc_split_register_get_current_split(SplitRegister *reg)
#define DEBUG(format, args...)
Definition: qoflog.h:255
Split * gnc_split_register_get_current_trans_split(SplitRegister *reg, VirtualCellLocation *trans_split_loc)
Transaction * xaccSplitGetParent(const Split *split)
Definition: Split.c:1903
#define ENTER(format, args...)
Definition: qoflog.h:261
Definition: guid.h:65
int xaccTransCountSplits(const Transaction *trans)
Definition: Transaction.c:2170
Split * xaccSplitLookup(const GncGUID *guid, QofBook *book)
Definition: Split.c:1104
#define xaccSplitGetGUID(X)
Definition: Split.h:521
int xaccTransGetSplitIndex(const Transaction *trans, const Split *split)
Definition: Transaction.c:2154
Split * xaccMallocSplit(QofBook *book)
Definition: Split.c:582
CursorClass
Definition: SplitP.h:71
CursorClass gnc_split_register_get_current_cursor_class(SplitRegister *reg)
#define LEAVE(format, args...)
Definition: qoflog.h:271
Account * xaccAccountLookup(const GncGUID *guid, QofBook *book)
Definition: Account.c:1827
void gnc_split_register_redraw ( SplitRegister reg)

Causes a redraw of the register window associated with reg.

Definition at line 1354 of file split-register.c.

1355 {
1356  gnc_ledger_display_refresh_by_split_register (reg);
1357 }
gboolean gnc_split_register_save ( SplitRegister reg,
gboolean  do_commit 
)

Copy the contents of the current cursor to a split. The split and transaction that are updated are the ones associated with the current cursor (register entry) position. If the do_commit flag is set, the transaction will also be committed. If it is the blank transaction, and the do_commit flag is set, a refresh will result in a new blank transaction. The method returns TRUE if something was changed.

Definition at line 1562 of file split-register.c.

1563 {
1564  SRInfo *info = gnc_split_register_get_info (reg);
1565  Transaction *pending_trans;
1566  Transaction *blank_trans;
1567  Transaction *trans;
1568  Account *account;
1569  Split *blank_split;
1570  const char *memo;
1571  const char *desc;
1572  Split *split;
1573 
1574  ENTER("reg=%p, do_commit=%s", reg, do_commit ? "TRUE" : "FALSE");
1575 
1576  if (!reg)
1577  {
1578  LEAVE("no register");
1579  return FALSE;
1580  }
1581 
1582  blank_split = xaccSplitLookup (&info->blank_split_guid,
1583  gnc_get_current_book ());
1584 
1585  pending_trans = xaccTransLookup (&info->pending_trans_guid,
1586  gnc_get_current_book ());
1587 
1588  blank_trans = xaccSplitGetParent (blank_split);
1589 
1590  /* get the handle to the current split and transaction */
1593  if (trans == NULL)
1594  {
1595  LEAVE("no transaction");
1596  return FALSE;
1597  }
1598 
1599  /* use the changed flag to avoid heavy-weight updates
1600  * of the split & transaction fields. This will help
1601  * cut down on unnecessary register redraws. */
1602  if (!gnc_table_current_cursor_changed (reg->table, FALSE))
1603  {
1604  if (!do_commit)
1605  {
1606  LEAVE("commit unnecessary");
1607  return FALSE;
1608  }
1609 
1610  if (!xaccTransIsOpen(trans))
1611  {
1612  LEAVE("transaction not open");
1613  return FALSE;
1614  }
1615 
1616  if (trans == pending_trans ||
1617  (trans == blank_trans && info->blank_split_edited))
1618  {
1619  /* We are going to commit. */
1620 
1621  gnc_suspend_gui_refresh ();
1622 
1623  if (trans == blank_trans)
1624  {
1625  /* We have to clear the blank split before the
1626  * refresh or a new one won't be created. */
1627  info->last_date_entered = xaccTransGetDate (trans);
1628  info->blank_split_guid = *guid_null ();
1629  info->blank_split_edited = FALSE;
1630  info->auto_complete = FALSE;
1631  }
1632 
1633  /* We have to clear the pending guid *before* committing the
1634  * trans, because the event handler will find it otherwise. */
1635  if (trans == pending_trans)
1636  info->pending_trans_guid = *guid_null ();
1637 
1638  PINFO("committing trans (%p)", trans);
1639  xaccTransCommitEdit(trans);
1640 
1641  gnc_resume_gui_refresh ();
1642  }
1643  else
1644  DEBUG("leaving trans (%p) open", trans);
1645 
1646  LEAVE("unchanged cursor");
1647  return TRUE;
1648  }
1649 
1650  DEBUG("save split=%p", split);
1651  DEBUG("blank_split=%p, blank_trans=%p, pending_trans=%p, trans=%p",
1652  blank_split, blank_trans, pending_trans, trans);
1653 
1654  /* Act on any changes to the current cell before the save. */
1655  (void) gnc_split_register_check_cell (reg,
1656  gnc_table_get_current_cell_name (reg->table));
1657 
1658  if (!gnc_split_register_auto_calc (reg, split))
1659  {
1660  LEAVE("auto calc failed");
1661  return FALSE;
1662  }
1663 
1664  /* Validate the transfer account names */
1665  (void)gnc_split_register_get_account (reg, MXFRM_CELL);
1666  (void)gnc_split_register_get_account (reg, XFRM_CELL);
1667 
1668  /* Maybe deal with exchange-rate transfers */
1669  if (gnc_split_register_handle_exchange (reg, FALSE))
1670  {
1671  LEAVE("no exchange rate");
1672  return TRUE;
1673  }
1674 
1675  gnc_suspend_gui_refresh ();
1676 
1677  /* determine whether we should commit the pending transaction */
1678  if (pending_trans != trans)
1679  {
1680  // FIXME: How could the pending transaction not be open?
1681  // FIXME: For that matter, how could an open pending
1682  // transaction ever not be the current trans?
1683  if (xaccTransIsOpen (pending_trans))
1684  {
1685  g_warning("Impossible? commiting pending %p", pending_trans);
1686  xaccTransCommitEdit (pending_trans);
1687  }
1688  else if (pending_trans)
1689  {
1690  g_critical("BUG DETECTED! pending transaction (%p) not open",
1691  pending_trans);
1692  g_assert_not_reached();
1693  }
1694 
1695  if (trans == blank_trans)
1696  {
1697  /* Don't begin editing the blank trans, because it's
1698  already open, but mark it pending now. */
1699  g_assert(xaccTransIsOpen(blank_trans));
1700  /* This is now the pending transaction */
1701  info->pending_trans_guid = *xaccTransGetGUID(blank_trans);
1702  }
1703  else
1704  {
1705  PINFO("beginning edit of trans %p", trans);
1706  if (gnc_split_register_begin_edit_or_warn(info, trans))
1707  {
1708  gnc_resume_gui_refresh ();
1709  LEAVE("transaction opened elsewhere");
1710  return FALSE;
1711  }
1712  }
1713  pending_trans = trans;
1714  }
1715  g_assert(xaccTransIsOpen(trans));
1716 
1717  /* If we are saving a brand new transaction and the blank split hasn't
1718  * been edited, then we need to give it a default account. */
1719  /* Q: Why check 'split == blank_split'? Isn't 'trans == blank_trans'
1720  * even better? What if there were some way that we could be on
1721  * a row other than the transaction row or blank split row, but
1722  * the blank split still hasn't been edited? It seems to be assumed
1723  * that it isn't possible, but... -Charles, Jan 2009 */
1724  if (split == blank_split && !info->blank_split_edited)
1725  {
1726  /* If we've reached this point, it means that the blank split is
1727  * anchoring the transaction - see gnc_split_register_add_transaction()
1728  * for an explanation - and the transaction has been edited (as evidenced
1729  * by the earlier check for a changed cursor.) Since the blank split
1730  * itself has not been edited, we'll have to assign a default account. */
1731  account = gnc_split_register_get_default_account(reg);
1732  if (account)
1733  xaccSplitSetAccount(blank_split, account);
1734  xaccTransSetDateEnteredSecs(trans, gnc_time (NULL));
1735  }
1736 
1737  if (split == NULL)
1738  {
1739  /* If we were asked to save data for a row for which there is no
1740  * associated split, then assume that this was an "empty" row - see
1741  * gnc_split_register_add_transaction() for an explanation. This row
1742  * is used to add splits to an existing transaction, or to add the
1743  * 2nd through nth split rows to a brand new transaction.
1744  * xaccSRGetCurrent will handle this case, too. We will create
1745  * a new split, copy the row contents to that split, and append
1746  * the split to the pre-existing transaction. */
1747  Split *trans_split;
1748 
1749  split = xaccMallocSplit (gnc_get_current_book ());
1750  xaccTransAppendSplit (trans, split);
1751 
1752  gnc_table_set_virt_cell_data (reg->table,
1753  reg->table->current_cursor_loc.vcell_loc,
1754  xaccSplitGetGUID (split));
1755  DEBUG("assigned cell to new split=%p", split);
1756 
1757  trans_split = gnc_split_register_get_current_trans_split (reg, NULL);
1758  if ((info->cursor_hint_trans == trans) &&
1759  (info->cursor_hint_trans_split == trans_split) &&
1760  (info->cursor_hint_split == NULL))
1761  {
1762  info->cursor_hint_split = split;
1763  info->cursor_hint_cursor_class = CURSOR_CLASS_SPLIT;
1764  }
1765  }
1766 
1767  DEBUG("updating trans=%p", trans);
1768 
1769  {
1770  SRSaveData *sd;
1771 
1772  sd = gnc_split_register_save_data_new (
1773  trans, split, (info->trans_expanded ||
1774  reg->style == REG_STYLE_AUTO_LEDGER ||
1775  reg->style == REG_STYLE_JOURNAL));
1776  gnc_table_save_cells (reg->table, sd);
1777  gnc_split_register_save_data_destroy (sd);
1778  }
1779 
1780  memo = xaccSplitGetMemo (split);
1781  memo = memo ? memo : "(null)";
1782  desc = xaccTransGetDescription (trans);
1783  desc = desc ? desc : "(null)";
1784  PINFO ("finished saving split \"%s\" of trans \"%s\"", memo, desc);
1785 
1786  /* If the modified split is the "blank split", then it is now an
1787  * official part of the account. Set the blank split to NULL, so we
1788  * can be sure of getting a new blank split. Also, save the date
1789  * for the new blank split. */
1790  if (trans == blank_trans)
1791  {
1792  if (do_commit)
1793  {
1794  info->blank_split_guid = *guid_null ();
1795  info->auto_complete = FALSE;
1796  blank_split = NULL;
1797  info->last_date_entered = xaccTransGetDate (trans);
1798  }
1799  else
1800  info->blank_split_edited = TRUE;
1801  }
1802 
1803  /* If requested, commit the current transaction and set the pending
1804  * transaction to NULL. */
1805  if (do_commit)
1806  {
1807  g_assert(trans == blank_trans || trans == pending_trans);
1808  if (pending_trans == trans)
1809  {
1810  pending_trans = NULL;
1811  info->pending_trans_guid = *guid_null ();
1812  }
1813  xaccTransCommitEdit (trans);
1814  }
1815 
1816  gnc_table_clear_current_cursor_changes (reg->table);
1817 
1818  gnc_resume_gui_refresh ();
1819 
1820  LEAVE(" ");
1821  return TRUE;
1822 }
Transaction * gnc_split_register_get_current_trans(SplitRegister *reg)
#define xaccTransAppendSplit(t, s)
Definition: Transaction.h:357
time64 xaccTransGetDate(const Transaction *trans)
Definition: Transaction.c:2215
gboolean xaccTransIsOpen(const Transaction *trans)
Definition: Transaction.c:1819
#define PINFO(format, args...)
Definition: qoflog.h:249
Split * gnc_split_register_get_current_split(SplitRegister *reg)
#define DEBUG(format, args...)
Definition: qoflog.h:255
Split * gnc_split_register_get_current_trans_split(SplitRegister *reg, VirtualCellLocation *trans_split_loc)
Transaction * xaccSplitGetParent(const Split *split)
Definition: Split.c:1903
#define ENTER(format, args...)
Definition: qoflog.h:261
Transaction * xaccTransLookup(const GncGUID *guid, QofBook *book)
Definition: Transaction.c:1024
Split * xaccSplitLookup(const GncGUID *guid, QofBook *book)
Definition: Split.c:1104
const char * xaccTransGetDescription(const Transaction *trans)
Definition: Transaction.c:2184
void xaccTransCommitEdit(Transaction *trans)
Definition: Transaction.c:1579
#define xaccSplitGetGUID(X)
Definition: Split.h:521
Split * xaccMallocSplit(QofBook *book)
Definition: Split.c:582
#define xaccTransGetGUID(X)
Definition: Transaction.h:755
gboolean gnc_split_register_handle_exchange(SplitRegister *reg, gboolean force_dialog)
Definition: SplitP.h:71
const GncGUID * guid_null(void)
#define LEAVE(format, args...)
Definition: qoflog.h:271
time64 gnc_time(time64 *tbuf)
get the current local time
const char * xaccSplitGetMemo(const Split *split)
Definition: Split.c:1968
void xaccTransSetDateEnteredSecs(Transaction *trans, time64 secs)
Definition: Transaction.c:1951
void gnc_split_register_set_auto_complete ( SplitRegister reg,
gboolean  do_auto_complete 
)

Sets whether a register uses auto-completion.

Parameters
rega SplitRegister
do_auto_completeTRUE to use auto-completion, FALSE otherwise

Definition at line 2795 of file split-register.c.

2797 {
2798  g_return_if_fail(reg);
2799  reg->do_auto_complete = do_auto_complete;
2800 }
gboolean do_auto_complete
void gnc_split_register_set_data ( SplitRegister reg,
gpointer  user_data,
SRGetParentCallback  get_parent 
)

Sets the user data and callback hooks for the register.

void gnc_split_register_set_read_only ( SplitRegister reg,
gboolean  read_only 
)

Sets whether a register window is "read only".

Parameters
rega SplitRegister
read_onlyTRUE to use "read only" mode, FALSE otherwise

Definition at line 2941 of file split-register.c.

2942 {
2943  gnc_table_model_set_read_only (reg->table->model, read_only);
2944 }
void gnc_split_register_set_template_account ( SplitRegister reg,
Account template_account 
)

Set the template account for use in a template register.

Parameters
rega SplitRegister
template_accountthe account to use for the template

Definition at line 116 of file split-register-util.c.

118 {
119  SRInfo *info = gnc_split_register_get_info (reg);
120 
121  g_return_if_fail (reg != NULL);
122 
123  info->template_account = *xaccAccountGetGUID (template_account);
124 }
#define xaccAccountGetGUID(X)
Definition: Account.h:239
void gnc_split_register_show_present_divider ( SplitRegister reg,
gboolean  show_present 
)

If TRUE, visually indicate the demarcation between splits with post dates prior to the present, and after. This will only make sense if the splits are ordered primarily by post date.

Definition at line 2377 of file split-register.c.

2379 {
2380  SRInfo *info = gnc_split_register_get_info (reg);
2381 
2382  if (reg == NULL)
2383  return;
2384 
2385  info->show_present_divider = show_present;
2386 }
void gnc_split_register_unvoid_current_trans ( SplitRegister reg)

Unvoids the transaction associated with the current cursor, if non-NULL.

Definition at line 1200 of file split-register.c.

1201 {
1202  SRInfo *info = gnc_split_register_get_info (reg);
1203  Transaction *pending_trans;
1204  Transaction *trans;
1205  Split *blank_split;
1206  Split *split;
1207 
1208  if (!reg) return;
1209 
1210  blank_split = xaccSplitLookup (&info->blank_split_guid,
1211  gnc_get_current_book ());
1212  pending_trans = xaccTransLookup (&info->pending_trans_guid,
1213  gnc_get_current_book ());
1214 
1215  /* get the current split based on cursor position */
1217  if (split == NULL)
1218  return;
1219 
1220  /* Bail if trying to unvoid the blank split. */
1221  if (split == blank_split)
1222  return;
1223 
1224  /* not voided. */
1225  if (xaccSplitGetReconcile (split) != VREC)
1226  return;
1227 
1228  info->trans_expanded = FALSE;
1229 
1230  gnc_suspend_gui_refresh ();
1231 
1232  trans = xaccSplitGetParent(split);
1233 
1234  xaccTransUnvoid(trans);
1235 
1236  /* Check pending transaction */
1237  if (trans == pending_trans)
1238  {
1239  info->pending_trans_guid = *guid_null();
1240  pending_trans = NULL;
1241  }
1242 
1243  gnc_resume_gui_refresh ();
1244 }
Split * gnc_split_register_get_current_split(SplitRegister *reg)
char xaccSplitGetReconcile(const Split *split)
Definition: Split.c:1980
Transaction * xaccSplitGetParent(const Split *split)
Definition: Split.c:1903
#define VREC
Definition: Split.h:71
Transaction * xaccTransLookup(const GncGUID *guid, QofBook *book)
Definition: Transaction.c:1024
Split * xaccSplitLookup(const GncGUID *guid, QofBook *book)
Definition: Split.c:1104
void xaccTransUnvoid(Transaction *trans)
Definition: Transaction.c:2552
Definition: SplitP.h:71
const GncGUID * guid_null(void)
void gnc_split_register_void_current_trans ( SplitRegister reg,
const char *  reason 
)

Voids the transaction associated with the current cursor, if non-NULL.

Definition at line 1150 of file split-register.c.

1151 {
1152  SRInfo *info = gnc_split_register_get_info (reg);
1153  Transaction *pending_trans;
1154  Transaction *trans;
1155  Split *blank_split;
1156  Split *split;
1157 
1158  if (!reg) return;
1159 
1160  blank_split = xaccSplitLookup (&info->blank_split_guid,
1161  gnc_get_current_book ());
1162  pending_trans = xaccTransLookup (&info->pending_trans_guid,
1163  gnc_get_current_book ());
1164 
1165  /* get the current split based on cursor position */
1167  if (split == NULL)
1168  return;
1169 
1170  /* Bail if trying to void the blank split. */
1171  if (split == blank_split)
1172  return;
1173 
1174  /* already voided. */
1175  if (xaccSplitGetReconcile (split) == VREC)
1176  return;
1177 
1178  info->trans_expanded = FALSE;
1179 
1180  gnc_suspend_gui_refresh ();
1181 
1182  trans = xaccSplitGetParent(split);
1183  xaccTransVoid(trans, reason);
1184 
1185  /* Check pending transaction */
1186  if (trans == pending_trans)
1187  {
1188  info->pending_trans_guid = *guid_null();
1189  pending_trans = NULL;
1190  }
1191  if (xaccTransIsOpen(trans))
1192  {
1193  PERR("We should not be voiding an open transaction.");
1194  xaccTransCommitEdit(trans);
1195  }
1196  gnc_resume_gui_refresh ();
1197 }
gboolean xaccTransIsOpen(const Transaction *trans)
Definition: Transaction.c:1819
Split * gnc_split_register_get_current_split(SplitRegister *reg)
char xaccSplitGetReconcile(const Split *split)
Definition: Split.c:1980
Transaction * xaccSplitGetParent(const Split *split)
Definition: Split.c:1903
#define PERR(format, args...)
Definition: qoflog.h:237
#define VREC
Definition: Split.h:71
Transaction * xaccTransLookup(const GncGUID *guid, QofBook *book)
Definition: Transaction.c:1024
Split * xaccSplitLookup(const GncGUID *guid, QofBook *book)
Definition: Split.c:1104
void xaccTransVoid(Transaction *trans, const char *reason)
Definition: Transaction.c:2495
void xaccTransCommitEdit(Transaction *trans)
Definition: Transaction.c:1579
Definition: SplitP.h:71
const GncGUID * guid_null(void)