Branch data Line data Source code
1 : : /********************************************************************\
2 : : * gnc-split-reg.c -- A widget for the common register look-n-feel. *
3 : : * Copyright (C) 1997 Robin D. Clark *
4 : : * Copyright (C) 1997-1998 Linas Vepstas <linas@linas.org> *
5 : : * Copyright (C) 1998 Rob Browning <rlb@cs.utexas.edu> *
6 : : * Copyright (C) 1999-2000 Dave Peticolas <dave@krondo.com> *
7 : : * Copyright (C) 2001 Gnumatic, Inc. *
8 : : * Copyright (C) 2002,2006 Joshua Sled <jsled@asynchronous.org> *
9 : : * *
10 : : * This program is free software; you can redistribute it and/or *
11 : : * modify it under the terms of the GNU General Public License as *
12 : : * published by the Free Software Foundation; either version 2 of *
13 : : * the License, or (at your option) any later version. *
14 : : * *
15 : : * This program is distributed in the hope that it will be useful, *
16 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 : : * GNU General Public License for more details. *
19 : : * *
20 : : * You should have received a copy of the GNU General Public License*
21 : : * along with this program; if not, contact: *
22 : : * *
23 : : * Free Software Foundation Voice: +1-617-542-5942 *
24 : : * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
25 : : * Boston, MA 02110-1301, USA gnu@gnu.org *
26 : : \********************************************************************/
27 : :
28 : : #include <config.h>
29 : :
30 : : #include <gtk/gtk.h>
31 : : #include <glib/gi18n.h>
32 : : #include <time.h>
33 : :
34 : : #include "gnc-split-reg.h"
35 : :
36 : : #include "Account.h"
37 : : #include "qof.h"
38 : : #include "SX-book.h"
39 : : #include "dialog-account.h"
40 : : #include "dialog-doclink.h"
41 : : #include "dialog-doclink-utils.h"
42 : : #include "dialog-sx-editor.h"
43 : : #include "dialog-sx-from-trans.h"
44 : : #include "gnc-component-manager.h"
45 : : #include "gnc-date-edit.h"
46 : : #include "gnc-engine.h"
47 : : #include "gnc-euro.h"
48 : : #include "gnc-prefs.h"
49 : : #include "gnc-gui-query.h"
50 : : #include "gnc-gnome-utils.h"
51 : : #include "gnc-ledger-display.h"
52 : : #include "gnc-pricedb.h"
53 : : #include "gnc-ui-util.h"
54 : : #include "gnc-ui.h"
55 : : #include "gnc-uri-utils.h"
56 : : #include "gnc-filepath-utils.h"
57 : : #include "gnc-warnings.h"
58 : : #include "gnucash-sheet.h"
59 : : #include "gnucash-register.h"
60 : : #include "table-allgui.h"
61 : : #include "gnc-state.h"
62 : :
63 : : #include "dialog-utils.h"
64 : :
65 : : // static QofLogModule log_module = GNC_MOD_SX;
66 : : static QofLogModule log_module = GNC_MOD_GUI;
67 : :
68 : : /***** PROTOTYPES ***************************************************/
69 : : void gnc_split_reg_raise( GNCSplitReg *gsr );
70 : :
71 : : static GtkWidget* add_summary_label( GtkWidget *summarybar, gboolean pack_start,
72 : : const char *label_str, GtkWidget *extra );
73 : :
74 : : static void gsr_summarybar_set_arrow_draw (GNCSplitReg *gsr);
75 : :
76 : : static void gnc_split_reg_determine_read_only( GNCSplitReg *gsr, gboolean show_dialog );
77 : : static gboolean is_trans_readonly_and_warn (GtkWindow *parent, Transaction *trans);
78 : :
79 : : static GNCPlaceholderType gnc_split_reg_get_placeholder( GNCSplitReg *gsr );
80 : : static GtkWidget *gnc_split_reg_get_parent( GNCLedgerDisplay *ledger );
81 : :
82 : : static void gsr_create_table( GNCSplitReg *gsr );
83 : : static void gsr_setup_table( GNCSplitReg *gsr );
84 : : static void gsr_setup_status_widgets( GNCSplitReg *gsr );
85 : :
86 : : static void gsr_update_summary_label( GtkWidget *label,
87 : : xaccGetBalanceFn getter,
88 : : Account *leader,
89 : : GNCPrintAmountInfo print_info,
90 : : gnc_commodity *cmdty,
91 : : gboolean reverse,
92 : : gboolean euroFlag );
93 : :
94 : : static void gsr_redraw_all_cb (GnucashRegister *g_reg, gpointer data);
95 : :
96 : : static void gnc_split_reg_ld_destroy( GNCLedgerDisplay *ledger );
97 : :
98 : : static Transaction* create_balancing_transaction(QofBook *book, Account *account,
99 : : time64 statement_date, gnc_numeric balancing_amount);
100 : :
101 : : void gsr_default_enter_handler ( GNCSplitReg *w, gpointer ud );
102 : : void gsr_default_cancel_handler ( GNCSplitReg *w, gpointer ud );
103 : : void gsr_default_delete_handler ( GNCSplitReg *w, gpointer ud );
104 : : void gsr_default_reinit_handler ( GNCSplitReg *w, gpointer ud );
105 : : void gsr_default_dup_handler ( GNCSplitReg *w, gpointer ud );
106 : : void gsr_default_schedule_handler ( GNCSplitReg *w, gpointer ud );
107 : : void gsr_default_expand_handler ( GNCSplitReg *w, gpointer ud );
108 : : void gsr_default_blank_handler ( GNCSplitReg *w, gpointer ud );
109 : : void gsr_default_jump_handler ( GNCSplitReg *w, gpointer ud );
110 : : void gsr_default_cut_handler ( GNCSplitReg *w, gpointer ud );
111 : : void gsr_default_cut_txn_handler ( GNCSplitReg *w, gpointer ud );
112 : : void gsr_default_copy_handler ( GNCSplitReg *w, gpointer ud );
113 : : void gsr_default_copy_txn_handler ( GNCSplitReg *w, gpointer ud );
114 : : void gsr_default_paste_handler ( GNCSplitReg *w, gpointer ud );
115 : : void gsr_default_paste_txn_handler( GNCSplitReg *w, gpointer ud );
116 : : void gsr_default_void_txn_handler ( GNCSplitReg *w, gpointer ud );
117 : : void gsr_default_unvoid_txn_handler ( GNCSplitReg *w, gpointer ud );
118 : : void gsr_default_reverse_txn_handler ( GNCSplitReg *w, gpointer ud );
119 : : void gsr_default_doclink_handler ( GNCSplitReg *w );
120 : : void gsr_default_doclink_open_handler ( GNCSplitReg *w );
121 : : void gsr_default_doclink_remove_handler ( GNCSplitReg *w );
122 : : static void gsr_default_doclink_from_sheet_handler ( GNCSplitReg *w );
123 : :
124 : : static void gsr_emit_simple_signal ( GNCSplitReg *gsr, const char *sigName );
125 : : static void gsr_emit_help_changed ( GnucashRegister *reg, gpointer user_data );
126 : : static void gsr_emit_show_popup_menu ( GnucashRegister *reg, gpointer user_data );
127 : :
128 : : void gnc_split_reg_cut_cb(GtkWidget *w, gpointer data);
129 : : void gnc_split_reg_copy_cb(GtkWidget *w, gpointer data);
130 : : void gnc_split_reg_paste_cb(GtkWidget *w, gpointer data);
131 : :
132 : : void gnc_split_reg_cut_trans_cb(GtkWidget *w, gpointer data);
133 : : void gnc_split_reg_copy_trans_cb(GtkWidget *w, gpointer data);
134 : : void gnc_split_reg_paste_trans_cb(GtkWidget *w, gpointer data);
135 : : void gnc_split_reg_void_trans_cb(GtkWidget *w, gpointer data);
136 : : void gnc_split_reg_unvoid_trans_cb(GtkWidget *w, gpointer data);
137 : : void gnc_split_reg_reverse_trans_cb(GtkWidget *w, gpointer data);
138 : :
139 : : void gnc_split_reg_record_cb (GnucashRegister *reg, gpointer data);
140 : : void gnc_split_reg_reinitialize_trans_cb(GtkWidget *w, gpointer data);
141 : : void gnc_split_reg_delete_trans_cb(GtkWidget *w, gpointer data);
142 : : void gnc_split_reg_duplicate_trans_cb(GtkWidget *w, gpointer data);
143 : : void gnc_split_reg_recur_cb(GtkWidget *w, gpointer data);
144 : : void gnc_split_reg_record_trans_cb(GtkWidget *w, gpointer data);
145 : : void gnc_split_reg_cancel_trans_cb(GtkWidget *w, gpointer data);
146 : :
147 : : void gnc_split_reg_expand_trans_menu_cb(GtkWidget *widget, gpointer data);
148 : : void gnc_split_reg_expand_trans_toolbar_cb(GtkWidget *widget, gpointer data);
149 : : void gnc_split_reg_new_trans_cb(GtkWidget *widget, gpointer data);
150 : : void gnc_split_reg_jump_cb(GtkWidget *widget, gpointer data);
151 : :
152 : : void gnc_split_reg_style_ledger_cb (GtkWidget *w, gpointer data);
153 : : void gnc_split_reg_style_auto_ledger_cb (GtkWidget *w, gpointer data);
154 : : void gnc_split_reg_style_journal_cb (GtkWidget *w, gpointer data);
155 : : void gnc_split_reg_double_line_cb (GtkWidget *w, gpointer data);
156 : :
157 : : void gnc_split_reg_sort_standard_cb (GtkWidget *w, gpointer data);
158 : : void gnc_split_reg_sort_date_cb (GtkWidget *w, gpointer data);
159 : : void gnc_split_reg_sort_date_entered_cb (GtkWidget *w, gpointer data);
160 : : void gnc_split_reg_sort_date_reconciled_cb (GtkWidget *w, gpointer data);
161 : : void gnc_split_reg_sort_num_cb (GtkWidget *w, gpointer data);
162 : : void gnc_split_reg_sort_amount_cb (GtkWidget *w, gpointer data);
163 : : void gnc_split_reg_sort_memo_cb (GtkWidget *w, gpointer data);
164 : : void gnc_split_reg_sort_desc_cb (GtkWidget *w, gpointer data);
165 : : void gnc_split_reg_sort_action_cb (GtkWidget *w, gpointer data);
166 : : void gnc_split_reg_sort_notes_cb (GtkWidget *w, gpointer data);
167 : :
168 : :
169 : : void gnc_split_reg_size_allocate( GtkWidget *widget,
170 : : GtkAllocation *allocation,
171 : : gpointer user_data );
172 : :
173 : :
174 : : static void gnc_split_reg_init2( GNCSplitReg *gsr );
175 : : void gnc_split_reg_dispose(GObject *obj);
176 : :
177 : 0 : FROM_STRING_FUNC(SortType, ENUM_LIST_SORTTYPE)
178 : 0 : AS_STRING_FUNC(SortType, ENUM_LIST_SORTTYPE)
179 : :
180 : 0 : G_DEFINE_TYPE (GNCSplitReg, gnc_split_reg, GTK_TYPE_BOX)
181 : :
182 : : /* SIGNALS */
183 : : enum gnc_split_reg_signal_enum
184 : : {
185 : : ENTER_ENT_SIGNAL,
186 : : CANCEL_ENT_SIGNAL,
187 : : DELETE_ENT_SIGNAL,
188 : : REINIT_ENT_SIGNAL,
189 : : DUP_ENT_SIGNAL,
190 : : SCHEDULE_ENT_SIGNAL,
191 : : EXPAND_ENT_SIGNAL,
192 : : BLANK_SIGNAL,
193 : : JUMP_SIGNAL,
194 : : CUT_SIGNAL,
195 : : CUT_TXN_SIGNAL,
196 : : COPY_SIGNAL,
197 : : COPY_TXN_SIGNAL,
198 : : PASTE_SIGNAL,
199 : : PASTE_TXN_SIGNAL,
200 : : VOID_TXN_SIGNAL,
201 : : UNVOID_TXN_SIGNAL,
202 : : REVERSE_TXN_SIGNAL,
203 : : HELP_CHANGED_SIGNAL,
204 : : SHOW_POPUP_MENU_SIGNAL,
205 : : INCLUDE_DATE_SIGNAL,
206 : : LAST_SIGNAL
207 : : };
208 : :
209 : : static guint gnc_split_reg_signals[LAST_SIGNAL] = { 0 };
210 : :
211 : : static void
212 : 0 : gnc_split_reg_class_init( GNCSplitRegClass *klass )
213 : : {
214 : : int i;
215 : : GObjectClass *object_class;
216 : : static struct similar_signal_info
217 : : {
218 : : enum gnc_split_reg_signal_enum s;
219 : : const char *signal_name;
220 : : guint defaultOffset;
221 : : } signals[] =
222 : : {
223 : : { ENTER_ENT_SIGNAL, "enter_ent", G_STRUCT_OFFSET( GNCSplitRegClass, enter_ent_cb ) },
224 : : { CANCEL_ENT_SIGNAL, "cancel_ent", G_STRUCT_OFFSET( GNCSplitRegClass, cancel_ent_cb ) },
225 : : { DELETE_ENT_SIGNAL, "delete_ent", G_STRUCT_OFFSET( GNCSplitRegClass, delete_ent_cb ) },
226 : : { REINIT_ENT_SIGNAL, "reinit_ent", G_STRUCT_OFFSET( GNCSplitRegClass, reinit_ent_cb ) },
227 : : { DUP_ENT_SIGNAL, "dup_ent", G_STRUCT_OFFSET( GNCSplitRegClass, dup_ent_cb ) },
228 : : { SCHEDULE_ENT_SIGNAL, "schedule_ent", G_STRUCT_OFFSET( GNCSplitRegClass, schedule_ent_cb ) },
229 : : { EXPAND_ENT_SIGNAL, "expand_ent", G_STRUCT_OFFSET( GNCSplitRegClass, expand_ent_cb ) },
230 : : { BLANK_SIGNAL, "blank", G_STRUCT_OFFSET( GNCSplitRegClass, blank_cb ) },
231 : : { JUMP_SIGNAL, "jump", G_STRUCT_OFFSET( GNCSplitRegClass, jump_cb ) },
232 : : { CUT_SIGNAL, "cut", G_STRUCT_OFFSET( GNCSplitRegClass, cut_cb ) },
233 : : { CUT_TXN_SIGNAL, "cut_txn", G_STRUCT_OFFSET( GNCSplitRegClass, cut_txn_cb ) },
234 : : { COPY_SIGNAL, "copy", G_STRUCT_OFFSET( GNCSplitRegClass, copy_cb ) },
235 : : { COPY_TXN_SIGNAL, "copy_txn", G_STRUCT_OFFSET( GNCSplitRegClass, copy_txn_cb ) },
236 : : { PASTE_SIGNAL, "paste", G_STRUCT_OFFSET( GNCSplitRegClass, paste_cb ) },
237 : : { PASTE_TXN_SIGNAL, "paste_txn", G_STRUCT_OFFSET( GNCSplitRegClass, paste_txn_cb ) },
238 : : { VOID_TXN_SIGNAL, "void_txn", G_STRUCT_OFFSET( GNCSplitRegClass, void_txn_cb ) },
239 : : { UNVOID_TXN_SIGNAL, "unvoid_txn", G_STRUCT_OFFSET( GNCSplitRegClass, unvoid_txn_cb ) },
240 : : { REVERSE_TXN_SIGNAL, "reverse_txn", G_STRUCT_OFFSET( GNCSplitRegClass, reverse_txn_cb ) },
241 : : { HELP_CHANGED_SIGNAL, "help-changed", G_STRUCT_OFFSET( GNCSplitRegClass, help_changed_cb ) },
242 : : { SHOW_POPUP_MENU_SIGNAL, "show-popup-menu", G_STRUCT_OFFSET( GNCSplitRegClass, show_popup_menu_cb ) },
243 : : { LAST_SIGNAL, NULL, 0 }
244 : : };
245 : :
246 : 0 : object_class = (GObjectClass*) klass;
247 : :
248 : 0 : for ( i = 0; signals[i].s != LAST_SIGNAL; i++ )
249 : : {
250 : 0 : gnc_split_reg_signals[ signals[i].s ] =
251 : 0 : g_signal_new( signals[i].signal_name,
252 : : G_TYPE_FROM_CLASS(object_class),
253 : : G_SIGNAL_RUN_LAST,
254 : : signals[i].defaultOffset,
255 : : NULL, NULL,
256 : : g_cclosure_marshal_VOID__VOID,
257 : : G_TYPE_NONE, 0 );
258 : : }
259 : :
260 : : /* Setup the default handlers. */
261 : 0 : klass->enter_ent_cb = gsr_default_enter_handler;
262 : 0 : klass->cancel_ent_cb = gsr_default_cancel_handler;
263 : 0 : klass->delete_ent_cb = gsr_default_delete_handler;
264 : 0 : klass->reinit_ent_cb = gsr_default_reinit_handler;
265 : 0 : klass->dup_ent_cb = gsr_default_dup_handler;
266 : 0 : klass->schedule_ent_cb = gsr_default_schedule_handler;
267 : 0 : klass->expand_ent_cb = gsr_default_expand_handler;
268 : 0 : klass->blank_cb = gsr_default_blank_handler;
269 : 0 : klass->jump_cb = gsr_default_jump_handler;
270 : 0 : klass->cut_cb = gsr_default_cut_handler;
271 : 0 : klass->cut_txn_cb = gsr_default_cut_txn_handler;
272 : 0 : klass->copy_cb = gsr_default_copy_handler;
273 : 0 : klass->copy_txn_cb = gsr_default_copy_txn_handler;
274 : 0 : klass->paste_cb = gsr_default_paste_handler;
275 : 0 : klass->paste_txn_cb = gsr_default_paste_txn_handler;
276 : 0 : klass->void_txn_cb = gsr_default_void_txn_handler;
277 : 0 : klass->unvoid_txn_cb = gsr_default_unvoid_txn_handler;
278 : 0 : klass->reverse_txn_cb = gsr_default_reverse_txn_handler;
279 : :
280 : 0 : klass->help_changed_cb = NULL;
281 : 0 : klass->show_popup_menu_cb = NULL;
282 : :
283 : 0 : object_class->dispose = gnc_split_reg_dispose;
284 : 0 : }
285 : :
286 : : GtkWidget*
287 : 0 : gnc_split_reg_new( GNCLedgerDisplay *ld,
288 : : GtkWindow *parent,
289 : : gint numberOfLines,
290 : : gboolean read_only )
291 : : {
292 : : GNCSplitReg *gsrToRet;
293 : :
294 : 0 : ENTER("ld=%p, parent=%p, numberOfLines=%d, read_only=%s",
295 : : ld, parent, numberOfLines, read_only ? "TRUE" : "FALSE");
296 : :
297 : 0 : gsrToRet = g_object_new( gnc_split_reg_get_type(), NULL );
298 : :
299 : 0 : gsrToRet->numRows = numberOfLines;
300 : 0 : gsrToRet->read_only = read_only;
301 : :
302 : 0 : gsrToRet->ledger = ld;
303 : 0 : gsrToRet->window = GTK_WIDGET(parent);
304 : :
305 : 0 : gnc_split_reg_init2( gsrToRet );
306 : :
307 : 0 : LEAVE("%p", gsrToRet);
308 : 0 : return GTK_WIDGET( gsrToRet );
309 : : }
310 : :
311 : : static void
312 : 0 : gnc_split_reg_init( GNCSplitReg *gsr )
313 : : {
314 : 0 : gtk_orientable_set_orientation (GTK_ORIENTABLE(gsr), GTK_ORIENTATION_VERTICAL);
315 : :
316 : 0 : gsr->sort_type = BY_STANDARD;
317 : 0 : gsr->sort_rev = FALSE;
318 : 0 : gsr->sort_arrow_handler_id = 0;
319 : 0 : gsr->filter_text = NULL;
320 : 0 : gsr->width = -1;
321 : 0 : gsr->height = -1;
322 : 0 : gsr->numRows = 10;
323 : 0 : gsr->read_only = FALSE;
324 : 0 : }
325 : :
326 : : static void
327 : 0 : gnc_split_reg_pref_acc_labels (gpointer prefs, gchar *pref, gpointer user_data)
328 : : {
329 : 0 : GNCSplitReg *gsr = user_data;
330 : 0 : gnucash_register_refresh_from_prefs (gsr->reg);
331 : 0 : }
332 : :
333 : : static void
334 : 0 : gnc_split_reg_init2( GNCSplitReg *gsr )
335 : : {
336 : 0 : if ( !gsr ) return;
337 : :
338 : 0 : gnc_split_reg_determine_read_only( gsr, TRUE );
339 : :
340 : 0 : gsr_setup_status_widgets( gsr );
341 : : /* ordering is important here... setup_status before create_table */
342 : 0 : gsr_create_table( gsr );
343 : 0 : gsr_setup_table( gsr );
344 : :
345 : 0 : gnc_prefs_register_cb (GNC_PREFS_GROUP_GENERAL,
346 : : GNC_PREF_ACCOUNTING_LABELS,
347 : : gnc_split_reg_pref_acc_labels,
348 : : gsr);
349 : : }
350 : :
351 : : static
352 : : void
353 : 0 : gsr_setup_table( GNCSplitReg *gsr )
354 : : {
355 : : SplitRegister *sr;
356 : :
357 : 0 : ENTER("gsr=%p", gsr);
358 : :
359 : 0 : sr = gnc_ledger_display_get_split_register( gsr->ledger );
360 : 0 : gnc_split_register_show_present_divider( sr, TRUE );
361 : : /* events should be sufficient to redraw this */
362 : : /* gnc_ledger_display_refresh( gsr->ledger ); */
363 : :
364 : 0 : LEAVE(" ");
365 : 0 : }
366 : :
367 : : static void
368 : 0 : gsr_move_sort_and_filter_to_state_file (GNCSplitReg *gsr, GKeyFile* state_file, const gchar *state_section)
369 : : {
370 : : GNCLedgerDisplayType ledger_type;
371 : :
372 : : // Look for any old kvp entries and add them to .gcm file
373 : 0 : ledger_type = gnc_ledger_display_type (gsr->ledger);
374 : :
375 : : // General ledger should already be using .gcm file
376 : 0 : if ((ledger_type == LD_SINGLE) || (ledger_type == LD_SUBACCOUNT))
377 : : {
378 : 0 : Account *leader = gnc_ledger_display_leader (gsr->ledger);
379 : 0 : const char* kvp_filter = NULL;
380 : 0 : const char* kvp_sort_order = NULL;
381 : 0 : gboolean kvp_sort_reversed = FALSE;
382 : :
383 : 0 : kvp_filter = xaccAccountGetFilter (leader);
384 : 0 : if (kvp_filter)
385 : : {
386 : 0 : gchar *temp_filter_text = g_strdup (kvp_filter);
387 : : // make it conform to .gcm file list
388 : 0 : g_strdelimit (temp_filter_text, ",", ';');
389 : 0 : g_key_file_set_string (state_file, state_section, KEY_PAGE_FILTER,
390 : : temp_filter_text);
391 : 0 : g_free (temp_filter_text);
392 : 0 : xaccAccountSetFilter (leader, NULL);
393 : : }
394 : :
395 : 0 : kvp_sort_order = xaccAccountGetSortOrder (leader);
396 : 0 : if (kvp_sort_order)
397 : : {
398 : 0 : g_key_file_set_string (state_file, state_section,
399 : : KEY_PAGE_SORT, kvp_sort_order);
400 : 0 : xaccAccountSetSortOrder (leader, NULL);
401 : : }
402 : :
403 : 0 : kvp_sort_reversed = xaccAccountGetSortReversed (leader);
404 : 0 : if (kvp_sort_reversed)
405 : : {
406 : 0 : g_key_file_set_boolean (state_file, state_section,
407 : : KEY_PAGE_SORT_REV, kvp_sort_reversed);
408 : 0 : xaccAccountSetSortReversed (leader, FALSE);
409 : : }
410 : : }
411 : 0 : }
412 : :
413 : : gchar *
414 : 0 : gsr_get_register_state_section (GNCSplitReg *gsr)
415 : : {
416 : 0 : GNCLedgerDisplayType ledger_type = gnc_ledger_display_type (gsr->ledger);
417 : 0 : Account *account = gnc_ledger_display_leader (gsr->ledger);
418 : 0 : const GncGUID *guid = xaccAccountGetGUID (account);
419 : : gchar guidstr[GUID_ENCODING_LENGTH+1];
420 : : gchar *register_state_section;
421 : :
422 : 0 : guid_to_string_buff (guid, guidstr);
423 : :
424 : 0 : if (ledger_type == LD_SUBACCOUNT)
425 : 0 : register_state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", guidstr, "+", NULL);
426 : : else
427 : 0 : register_state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", guidstr, NULL);
428 : :
429 : 0 : return register_state_section;
430 : : }
431 : :
432 : : static
433 : : void
434 : 0 : gsr_create_table( GNCSplitReg *gsr )
435 : : {
436 : 0 : GtkWidget *register_widget = NULL;
437 : 0 : SplitRegister *sr = NULL;
438 : 0 : GKeyFile* state_file = gnc_state_get_current();
439 : : gchar *register_state_section;
440 : :
441 : : /* register_state_section is used to store per register state: column widths, sort order,... */
442 : 0 : register_state_section = gsr_get_register_state_section (gsr);
443 : :
444 : 0 : ENTER("gsr=%p", gsr);
445 : :
446 : 0 : sr = gnc_ledger_display_get_split_register (gsr->ledger);
447 : :
448 : 0 : gnc_ledger_display_set_user_data( gsr->ledger, (gpointer)gsr );
449 : 0 : gnc_ledger_display_set_handlers( gsr->ledger,
450 : : gnc_split_reg_ld_destroy,
451 : : gnc_split_reg_get_parent );
452 : :
453 : : /* FIXME: We'd really rather pass this down... */
454 : 0 : sr = gnc_ledger_display_get_split_register( gsr->ledger );
455 : 0 : register_widget = gnucash_register_new( sr->table, register_state_section );
456 : 0 : gsr->reg = GNUCASH_REGISTER( register_widget );
457 : :
458 : 0 : gtk_box_pack_start (GTK_BOX (gsr), GTK_WIDGET(gsr->reg), TRUE, TRUE, 0);
459 : 0 : gnucash_sheet_set_window (gnucash_register_get_sheet (gsr->reg), gsr->window);
460 : :
461 : : // setup the callback for when the doclink cell clicked on
462 : 0 : gnucash_register_set_open_doclink_cb (gsr->reg,
463 : : (GFunc)gsr_default_doclink_from_sheet_handler, gsr);
464 : :
465 : 0 : gtk_widget_show ( GTK_WIDGET(gsr->reg) );
466 : 0 : g_signal_connect (gsr->reg, "activate_cursor",
467 : : G_CALLBACK(gnc_split_reg_record_cb), gsr);
468 : 0 : g_signal_connect (gsr->reg, "redraw_all",
469 : : G_CALLBACK(gsr_redraw_all_cb), gsr);
470 : 0 : g_signal_connect (gsr->reg, "redraw_help",
471 : : G_CALLBACK(gsr_emit_help_changed), gsr);
472 : 0 : g_signal_connect (gsr->reg, "show_popup_menu",
473 : : G_CALLBACK(gsr_emit_show_popup_menu), gsr);
474 : :
475 : 0 : gsr_move_sort_and_filter_to_state_file (gsr, state_file, register_state_section);
476 : :
477 : 0 : g_free (register_state_section);
478 : 0 : LEAVE(" ");
479 : 0 : }
480 : :
481 : : static
482 : : void
483 : 0 : gsr_setup_status_widgets( GNCSplitReg *gsr )
484 : : {
485 : : SplitRegister *sr;
486 : : gboolean use_double_line;
487 : :
488 : 0 : sr = gnc_ledger_display_get_split_register( gsr->ledger );
489 : 0 : use_double_line = gnc_ledger_display_default_double_line( gsr->ledger );
490 : :
491 : : /* be sure to initialize the gui elements associated with the cursor */
492 : 0 : gnc_split_register_config( sr, sr->type, sr->style, use_double_line );
493 : 0 : }
494 : :
495 : : void
496 : 0 : gnc_split_reg_dispose(GObject *obj)
497 : : {
498 : 0 : GNCSplitReg *gsr = GNC_SPLIT_REG(obj);
499 : :
500 : 0 : if (gsr->filter_text)
501 : 0 : g_free (gsr->filter_text);
502 : 0 : gsr->filter_text = NULL;
503 : :
504 : 0 : gnc_prefs_remove_cb_by_func (GNC_PREFS_GROUP_GENERAL,
505 : : GNC_PREF_ACCOUNTING_LABELS,
506 : : gnc_split_reg_pref_acc_labels,
507 : : gsr);
508 : :
509 : 0 : if (gsr->reg)
510 : : {
511 : 0 : g_signal_handlers_disconnect_by_data (gsr->reg, gsr);
512 : 0 : gtk_widget_destroy (GTK_WIDGET (gsr->reg));
513 : : }
514 : 0 : gsr->reg = NULL;
515 : 0 : }
516 : :
517 : : /**
518 : : * Raise an existing register window to the front.
519 : : **/
520 : : void
521 : 0 : gnc_split_reg_raise( GNCSplitReg *gsr )
522 : : {
523 : 0 : if (gsr == NULL)
524 : 0 : return;
525 : :
526 : 0 : if (gsr->window == NULL)
527 : 0 : return;
528 : :
529 : 0 : gtk_window_present( GTK_WINDOW(gsr->window) );
530 : : }
531 : :
532 : :
533 : : /**
534 : : * Duplicate-code reduction function; retrieves, formats and updates the
535 : : * GtkLabel with the given amount.
536 : : **/
537 : : static
538 : : void
539 : 0 : gsr_update_summary_label( GtkWidget *label,
540 : : xaccGetBalanceFn getter,
541 : : Account *leader,
542 : : GNCPrintAmountInfo print_info,
543 : : gnc_commodity *cmdty,
544 : : gboolean reverse,
545 : : gboolean euroFlag )
546 : : {
547 : : gnc_numeric amount;
548 : : char string[256];
549 : 0 : const gchar *label_str = NULL;
550 : : GtkWidget *text_label, *hbox;
551 : : gchar *bidi_string;
552 : :
553 : 0 : if ( label == NULL )
554 : 0 : return;
555 : :
556 : 0 : hbox = g_object_get_data (G_OBJECT(label), "text_box");
557 : 0 : text_label = g_object_get_data (G_OBJECT(label), "text_label");
558 : 0 : label_str = gtk_label_get_text (GTK_LABEL(text_label));
559 : :
560 : 0 : amount = (*getter)( leader );
561 : :
562 : 0 : if ( reverse )
563 : : {
564 : 0 : amount = gnc_numeric_neg( amount );
565 : : }
566 : :
567 : 0 : xaccSPrintAmount( string, amount, print_info );
568 : :
569 : 0 : if ( euroFlag )
570 : : {
571 : 0 : strcat( string, " / " );
572 : 0 : xaccSPrintAmount( string + strlen( string ),
573 : : gnc_convert_to_euro( cmdty, amount ),
574 : 0 : gnc_commodity_print_info( gnc_get_euro(), TRUE ) );
575 : : }
576 : :
577 : 0 : gnc_set_label_color( label, amount );
578 : 0 : bidi_string = gnc_wrap_text_with_bidi_ltr_isolate (string);
579 : 0 : gtk_label_set_text( GTK_LABEL(label), bidi_string );
580 : 0 : g_free (bidi_string);
581 : :
582 : 0 : if (label_str)
583 : : {
584 : 0 : gchar *tooltip = g_strdup_printf ("%s %s", label_str, string);
585 : 0 : gtk_widget_set_tooltip_text (GTK_WIDGET(hbox), tooltip);
586 : 0 : g_free (tooltip);
587 : : }
588 : : }
589 : :
590 : : static
591 : : void
592 : 0 : gsr_redraw_all_cb (GnucashRegister *g_reg, gpointer data)
593 : : {
594 : 0 : GNCSplitReg *gsr = data;
595 : : gnc_commodity * commodity;
596 : : GNCPrintAmountInfo print_info;
597 : : gnc_numeric amount;
598 : : Account *leader;
599 : : gboolean reverse;
600 : : gboolean euro;
601 : :
602 : 0 : if ( gsr->summarybar == NULL )
603 : 0 : return;
604 : :
605 : 0 : leader = gnc_ledger_display_leader( gsr->ledger );
606 : :
607 : 0 : commodity = xaccAccountGetCommodity( leader );
608 : :
609 : : /* no EURO conversion, if account is already EURO or no EURO currency */
610 : 0 : if (commodity != NULL)
611 : 0 : euro = (gnc_is_euro_currency( commodity ) &&
612 : 0 : (strncasecmp(gnc_commodity_get_mnemonic(commodity), "EUR", 3)));
613 : : else
614 : 0 : euro = FALSE;
615 : :
616 : 0 : print_info = gnc_account_print_info( leader, TRUE );
617 : 0 : reverse = gnc_reverse_balance( leader );
618 : :
619 : 0 : if (gsr->balance_label != NULL) // only test the first as they are a group
620 : : {
621 : 0 : gsr_update_summary_label( gsr->balance_label,
622 : : xaccAccountGetPresentBalance,
623 : : leader, print_info, commodity, reverse, euro );
624 : 0 : gsr_update_summary_label( gsr->cleared_label,
625 : : xaccAccountGetClearedBalance,
626 : : leader, print_info, commodity, reverse, euro );
627 : 0 : gsr_update_summary_label( gsr->reconciled_label,
628 : : xaccAccountGetReconciledBalance,
629 : : leader, print_info, commodity, reverse, euro );
630 : 0 : gsr_update_summary_label( gsr->future_label,
631 : : xaccAccountGetBalance,
632 : : leader, print_info, commodity, reverse, euro );
633 : 0 : gsr_update_summary_label( gsr->projectedminimum_label,
634 : : xaccAccountGetProjectedMinimumBalance,
635 : : leader, print_info, commodity, reverse, euro );
636 : : }
637 : :
638 : : // Sort label
639 : 0 : if (gsr->sort_label != NULL)
640 : : {
641 : 0 : gchar *old_tt_text = gtk_widget_get_tooltip_text (GTK_WIDGET(gsr->sort_label));
642 : : gchar *new_tt_text;
643 : 0 : gchar *text = NULL;
644 : :
645 : 0 : switch (gsr->sort_type)
646 : : {
647 : 0 : case (0):
648 : 0 : text = _("None");
649 : 0 : break;
650 : 0 : case (1):
651 : 0 : text = _("Standard Order");
652 : 0 : break;
653 : 0 : case (2):
654 : 0 : text = _("Date");
655 : 0 : break;
656 : 0 : case (3):
657 : 0 : text = _("Date of Entry");
658 : 0 : break;
659 : 0 : case (4):
660 : 0 : text = _("Statement Date");
661 : 0 : break;
662 : 0 : case (5):
663 : 0 : text = _("Number");
664 : 0 : break;
665 : 0 : case (6):
666 : 0 : text = _("Amount");
667 : 0 : break;
668 : 0 : case (7):
669 : 0 : text = _("Memo");
670 : 0 : break;
671 : 0 : case (8):
672 : 0 : text = _("Description");
673 : 0 : break;
674 : 0 : case (9):
675 : 0 : text = _("Action");
676 : 0 : break;
677 : 0 : case (10):
678 : 0 : text = _("Notes");
679 : 0 : break;
680 : : }
681 : :
682 : 0 : if (gsr->sort_rev)
683 : 0 : gtk_widget_set_tooltip_text (GTK_WIDGET(gsr->sort_label), _("Descending"));
684 : : else
685 : 0 : gtk_widget_set_tooltip_text (GTK_WIDGET(gsr->sort_label), _("Ascending"));
686 : :
687 : 0 : new_tt_text = gtk_widget_get_tooltip_text (GTK_WIDGET(gsr->sort_label));
688 : :
689 : : // does the arrow need changing
690 : 0 : if (g_strcmp0 (old_tt_text, new_tt_text) != 0)
691 : 0 : gsr_summarybar_set_arrow_draw (gsr);
692 : :
693 : 0 : if (old_tt_text)
694 : 0 : g_free (old_tt_text);
695 : :
696 : 0 : if (new_tt_text)
697 : 0 : g_free (new_tt_text);
698 : :
699 : 0 : gtk_label_set_text (GTK_LABEL(gsr->sort_label), text);
700 : : }
701 : :
702 : : // Filter label
703 : 0 : if (gsr->filter_label != NULL)
704 : : {
705 : 0 : gchar *old_tt_text = gtk_widget_get_tooltip_text (GTK_WIDGET(gsr->filter_label));
706 : :
707 : : // check for a change in text
708 : 0 : if (g_strcmp0 (old_tt_text, gsr->filter_text) != 0)
709 : : {
710 : 0 : if (gsr->filter_text != NULL)
711 : 0 : gtk_label_set_text (GTK_LABEL(gsr->filter_label), _("Filtered"));
712 : : else
713 : 0 : gtk_label_set_text (GTK_LABEL(gsr->filter_label), "");
714 : :
715 : 0 : gtk_widget_set_tooltip_text (GTK_WIDGET(gsr->filter_label), gsr->filter_text);
716 : :
717 : : }
718 : 0 : g_free (old_tt_text);
719 : : }
720 : :
721 : 0 : if (gsr->shares_label == NULL && gsr->value_label == NULL)
722 : 0 : return;
723 : 0 : amount = xaccAccountGetBalance( leader );
724 : 0 : if (reverse)
725 : 0 : amount = gnc_numeric_neg( amount );
726 : :
727 : : /* Print the summary share amount */
728 : 0 : if (gsr->shares_label != NULL)
729 : : {
730 : : char string[256];
731 : 0 : print_info = gnc_account_print_info( leader, TRUE );
732 : 0 : xaccSPrintAmount( string, amount, print_info );
733 : 0 : gnc_set_label_color( gsr->shares_label, amount );
734 : 0 : gtk_label_set_text( GTK_LABEL(gsr->shares_label), string );
735 : : }
736 : :
737 : : /* Print the summary share value */
738 : 0 : if (gsr->value_label != NULL)
739 : : {
740 : : char string[256];
741 : 0 : QofBook *book = gnc_account_get_book (leader);
742 : 0 : GNCPriceDB *pricedb = gnc_pricedb_get_db (book);
743 : 0 : gnc_commodity *currency = gnc_default_currency ();
744 : : gnc_numeric value =
745 : 0 : gnc_pricedb_convert_balance_latest_price (pricedb, amount,
746 : : commodity, currency);
747 : 0 : print_info = gnc_commodity_print_info (currency, TRUE);
748 : 0 : xaccSPrintAmount (string, value, print_info);
749 : 0 : gnc_set_label_color (gsr->value_label, amount);
750 : 0 : gtk_label_set_text (GTK_LABEL (gsr->value_label), string);
751 : :
752 : : }
753 : : }
754 : :
755 : : static void
756 : 0 : gnc_split_reg_ld_destroy( GNCLedgerDisplay *ledger )
757 : : {
758 : 0 : GNCSplitReg *gsr = gnc_ledger_display_get_user_data( ledger );
759 : :
760 : 0 : if (gsr)
761 : : {
762 : : /* register_state_section is used to store per register state: column widths, sort order,... */
763 : 0 : gchar *register_state_section = gsr_get_register_state_section (gsr);
764 : 0 : SplitRegister *reg = gnc_ledger_display_get_split_register (ledger);
765 : :
766 : 0 : if (reg && reg->table)
767 : 0 : gnc_table_save_state (reg->table, register_state_section);
768 : :
769 : : /*
770 : : * Don't destroy the window here any more. The register no longer
771 : : * owns it.
772 : : */
773 : 0 : g_free (register_state_section);
774 : : }
775 : :
776 : 0 : gnc_ledger_display_set_user_data (ledger, NULL);
777 : 0 : g_object_unref (gsr);
778 : 0 : }
779 : :
780 : : void
781 : 0 : gsr_default_cut_handler( GNCSplitReg *gsr, gpointer data )
782 : : {
783 : 0 : gnucash_register_cut_clipboard( gsr->reg );
784 : 0 : }
785 : :
786 : : /**
787 : : * Cut the selection to the clipboard. This refers to the Split.
788 : : **/
789 : : void
790 : 0 : gnc_split_reg_cut_cb (GtkWidget *w, gpointer data)
791 : : {
792 : 0 : GNCSplitReg *gsr = data;
793 : 0 : gsr_emit_simple_signal( gsr, "cut" );
794 : 0 : }
795 : :
796 : : void
797 : 0 : gsr_default_copy_handler( GNCSplitReg *gsr, gpointer data )
798 : : {
799 : 0 : gnucash_register_copy_clipboard( gsr->reg );
800 : 0 : }
801 : :
802 : : /**
803 : : * Copy the selection to the clipboard. This refers to the Split.
804 : : **/
805 : : void
806 : 0 : gnc_split_reg_copy_cb (GtkWidget *w, gpointer data)
807 : : {
808 : 0 : GNCSplitReg *gsr = data;
809 : 0 : gsr_emit_simple_signal( gsr, "copy" );
810 : 0 : }
811 : :
812 : : void
813 : 0 : gsr_default_paste_handler( GNCSplitReg *gsr, gpointer data )
814 : : {
815 : 0 : gnucash_register_paste_clipboard( gsr->reg );
816 : 0 : }
817 : :
818 : : /**
819 : : * Paste the clipboard to the selection. This refers to the Split.
820 : : **/
821 : : void
822 : 0 : gnc_split_reg_paste_cb (GtkWidget *w, gpointer data)
823 : : {
824 : 0 : GNCSplitReg *gsr = data;
825 : 0 : gsr_emit_simple_signal( gsr, "paste" );
826 : 0 : }
827 : :
828 : : void
829 : 0 : gsr_default_cut_txn_handler (GNCSplitReg *gsr, gpointer data)
830 : : {
831 : : CursorClass cursor_class;
832 : : SplitRegister *reg;
833 : : Transaction *trans;
834 : : Split *split;
835 : : GtkWidget *dialog;
836 : : gint response;
837 : : const gchar *warning;
838 : :
839 : 0 : reg = gnc_ledger_display_get_split_register (gsr->ledger);
840 : :
841 : : /* get the current split based on cursor position */
842 : 0 : split = gnc_split_register_get_current_split (reg);
843 : 0 : if (split == NULL)
844 : : {
845 : 0 : gnc_split_register_cancel_cursor_split_changes (reg);
846 : 0 : return;
847 : : }
848 : :
849 : 0 : trans = xaccSplitGetParent (split);
850 : 0 : cursor_class = gnc_split_register_get_current_cursor_class (reg);
851 : :
852 : : /* test for blank_split reference pointing to split */
853 : 0 : if (gnc_split_register_is_blank_split (reg, split))
854 : 0 : gnc_split_register_change_blank_split_ref (reg, split);
855 : :
856 : : /* Cutting the blank split just cancels */
857 : : {
858 : 0 : Split *blank_split = gnc_split_register_get_blank_split (reg);
859 : :
860 : 0 : if (split == blank_split)
861 : : {
862 : 0 : gnc_split_register_cancel_cursor_trans_changes (reg);
863 : 0 : return;
864 : : }
865 : : }
866 : :
867 : 0 : if (cursor_class == CURSOR_CLASS_NONE)
868 : 0 : return;
869 : :
870 : : /* this is probably not required but leave as a double check */
871 : 0 : if (is_trans_readonly_and_warn (GTK_WINDOW(gsr->window), trans))
872 : 0 : return;
873 : :
874 : : /* On a split cursor, just delete the one split. */
875 : 0 : if (cursor_class == CURSOR_CLASS_SPLIT)
876 : : {
877 : 0 : const char *format = _("Cut the split '%s' from the transaction '%s'?");
878 : 0 : const char *recn_warn = _("You would be removing a reconciled split! "
879 : : "This is not a good idea as it will cause your "
880 : : "reconciled balance to be off.");
881 : 0 : const char *anchor_error = _("You cannot cut this split.");
882 : 0 : const char *anchor_split = _("This is the split anchoring this transaction "
883 : : "to the register. You may not remove it from "
884 : : "this register window. You may remove the "
885 : : "entire transaction from this window, or you "
886 : : "may navigate to a register that shows "
887 : : "another side of this same transaction and "
888 : : "remove the split from that register.");
889 : 0 : char *buf = NULL;
890 : : const char *memo;
891 : : const char *desc;
892 : : char recn;
893 : :
894 : 0 : if (reg->type != GENERAL_JOURNAL) // no anchoring split
895 : : {
896 : 0 : if (split == gnc_split_register_get_current_trans_split (reg, NULL))
897 : : {
898 : 0 : dialog = gtk_message_dialog_new (GTK_WINDOW(gsr->window),
899 : : GTK_DIALOG_MODAL
900 : : | GTK_DIALOG_DESTROY_WITH_PARENT,
901 : : GTK_MESSAGE_ERROR,
902 : : GTK_BUTTONS_OK,
903 : : "%s", anchor_error);
904 : 0 : gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG(dialog),
905 : : "%s", anchor_split);
906 : 0 : gtk_dialog_run (GTK_DIALOG(dialog));
907 : 0 : gtk_widget_destroy (dialog);
908 : 0 : return;
909 : : }
910 : : }
911 : 0 : memo = xaccSplitGetMemo (split);
912 : 0 : memo = (memo && *memo) ? memo : _("(no memo)");
913 : :
914 : 0 : desc = xaccTransGetDescription (trans);
915 : 0 : desc = (desc && *desc) ? desc : _("(no description)");
916 : :
917 : : /* ask for user confirmation before performing permanent damage */
918 : 0 : buf = g_strdup_printf (format, memo, desc);
919 : 0 : dialog = gtk_message_dialog_new (GTK_WINDOW(gsr->window),
920 : : GTK_DIALOG_MODAL
921 : : | GTK_DIALOG_DESTROY_WITH_PARENT,
922 : : GTK_MESSAGE_QUESTION,
923 : : GTK_BUTTONS_NONE,
924 : : "%s", buf);
925 : 0 : g_free (buf);
926 : 0 : recn = xaccSplitGetReconcile (split);
927 : 0 : if (recn == YREC || recn == FREC)
928 : : {
929 : 0 : gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG(dialog),
930 : : "%s", recn_warn);
931 : 0 : warning = GNC_PREF_WARN_REG_SPLIT_CUT_RECD;
932 : : }
933 : : else
934 : : {
935 : 0 : warning = GNC_PREF_WARN_REG_SPLIT_CUT;
936 : : }
937 : :
938 : 0 : gtk_dialog_add_button (GTK_DIALOG(dialog),
939 : 0 : _("_Cancel"), GTK_RESPONSE_CANCEL);
940 : 0 : gnc_gtk_dialog_add_button (dialog, _("_Cut Split"),
941 : : "edit-delete", GTK_RESPONSE_ACCEPT);
942 : 0 : response = gnc_dialog_run (GTK_DIALOG(dialog), warning);
943 : 0 : gtk_widget_destroy (dialog);
944 : 0 : if (response != GTK_RESPONSE_ACCEPT)
945 : 0 : return;
946 : :
947 : 0 : gnc_split_register_cut_current (reg);
948 : 0 : return;
949 : : }
950 : :
951 : : /* On a transaction cursor with 2 or fewer splits in single or double
952 : : * mode, we just delete the whole transaction, kerblooie */
953 : : {
954 : 0 : const char *title = _("Cut the current transaction?");
955 : 0 : const char *recn_warn = _("You would be removing a transaction "
956 : : "with reconciled splits! "
957 : : "This is not a good idea as it will cause your "
958 : : "reconciled balance to be off.");
959 : :
960 : 0 : dialog = gtk_message_dialog_new (GTK_WINDOW(gsr->window),
961 : : GTK_DIALOG_MODAL
962 : : | GTK_DIALOG_DESTROY_WITH_PARENT,
963 : : GTK_MESSAGE_WARNING,
964 : : GTK_BUTTONS_NONE,
965 : : "%s", title);
966 : 0 : if (xaccTransHasReconciledSplits (trans))
967 : : {
968 : 0 : gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG(dialog),
969 : : "%s", recn_warn);
970 : 0 : warning = GNC_PREF_WARN_REG_TRANS_CUT_RECD;
971 : : }
972 : : else
973 : : {
974 : 0 : warning = GNC_PREF_WARN_REG_TRANS_CUT;
975 : : }
976 : 0 : gtk_dialog_add_button (GTK_DIALOG(dialog),
977 : 0 : _("_Cancel"), GTK_RESPONSE_CANCEL);
978 : 0 : gnc_gtk_dialog_add_button (dialog, _("_Cut Transaction"),
979 : : "edit-delete", GTK_RESPONSE_ACCEPT);
980 : 0 : response = gnc_dialog_run (GTK_DIALOG(dialog), warning);
981 : 0 : gtk_widget_destroy (dialog);
982 : 0 : if (response != GTK_RESPONSE_ACCEPT)
983 : 0 : return;
984 : :
985 : 0 : gnc_split_register_cut_current (reg);
986 : 0 : return;
987 : : }
988 : : }
989 : :
990 : : /**
991 : : * Cut the current transaction to the clipboard.
992 : : **/
993 : : void
994 : 0 : gnc_split_reg_cut_trans_cb (GtkWidget *w, gpointer data)
995 : : {
996 : 0 : GNCSplitReg *gsr = data;
997 : 0 : gsr_emit_simple_signal( gsr, "cut_txn" );
998 : 0 : }
999 : :
1000 : : void
1001 : 0 : gsr_default_copy_txn_handler( GNCSplitReg *gsr, gpointer data )
1002 : : {
1003 : 0 : gnc_split_register_copy_current
1004 : : (gnc_ledger_display_get_split_register( gsr->ledger ));
1005 : 0 : }
1006 : :
1007 : : /**
1008 : : * Copy the current transaction to the clipboard.
1009 : : **/
1010 : : void
1011 : 0 : gnc_split_reg_copy_trans_cb(GtkWidget *w, gpointer data)
1012 : : {
1013 : 0 : GNCSplitReg *gsr = data;
1014 : 0 : gsr_emit_simple_signal( gsr, "copy_txn" );
1015 : 0 : }
1016 : :
1017 : : void
1018 : 0 : gsr_default_paste_txn_handler( GNCSplitReg *gsr, gpointer data )
1019 : : {
1020 : 0 : gnc_split_register_paste_current
1021 : : (gnc_ledger_display_get_split_register( gsr->ledger ));
1022 : 0 : }
1023 : :
1024 : : /**
1025 : : * Paste the transaction clipboard to the selection.
1026 : : **/
1027 : : void
1028 : 0 : gnc_split_reg_paste_trans_cb (GtkWidget *w, gpointer data)
1029 : : {
1030 : 0 : GNCSplitReg *gsr = data;
1031 : 0 : gsr_emit_simple_signal( gsr, "paste_txn" );
1032 : 0 : }
1033 : :
1034 : : /********************************************************************\
1035 : : * gnc_split_reg_void_trans_cb *
1036 : : * *
1037 : : * Args: widget - the widget that called us *
1038 : : * data - the data struct for this register *
1039 : : * Return: none *
1040 : : \********************************************************************/
1041 : : void
1042 : 0 : gsr_default_void_txn_handler (GNCSplitReg *gsr, gpointer data)
1043 : : {
1044 : : // Override this function.
1045 : 0 : }
1046 : :
1047 : : void
1048 : 0 : gnc_split_reg_void_trans_cb (GtkWidget *w, gpointer data)
1049 : : {
1050 : 0 : GNCSplitReg *gsr = data;
1051 : 0 : gsr_emit_simple_signal( gsr, "void_txn" );
1052 : 0 : }
1053 : :
1054 : : /********************************************************************\
1055 : : * gnc_split_reg_unvoid_trans_cb *
1056 : : * *
1057 : : * Args: widget - the widget that called us *
1058 : : * data - the data struct for this register *
1059 : : * Return: none *
1060 : : \********************************************************************/
1061 : : void
1062 : 0 : gsr_default_unvoid_txn_handler (GNCSplitReg *gsr, gpointer data)
1063 : : {
1064 : : // Override this function.
1065 : 0 : }
1066 : :
1067 : : void
1068 : 0 : gnc_split_reg_unvoid_trans_cb (GtkWidget *w, gpointer data)
1069 : : {
1070 : 0 : GNCSplitReg *gsr = data;
1071 : 0 : gsr_emit_simple_signal( gsr, "unvoid_txn" );
1072 : 0 : }
1073 : :
1074 : : /********************************************************************\
1075 : : * gnc_split_reg_reverse_trans_cb *
1076 : : * *
1077 : : * Args: widget - the widget that called us *
1078 : : * data - the data struct for this register *
1079 : : * Return: none *
1080 : : \********************************************************************/
1081 : : void
1082 : 0 : gsr_default_reverse_txn_handler (GNCSplitReg *gsr, gpointer data)
1083 : : {
1084 : : SplitRegister *reg;
1085 : : Transaction *trans, *new_trans;
1086 : :
1087 : 0 : reg = gnc_ledger_display_get_split_register( gsr->ledger );
1088 : 0 : trans = gnc_split_register_get_current_trans (reg);
1089 : 0 : if (trans == NULL)
1090 : 0 : return;
1091 : :
1092 : 0 : if (xaccTransGetReversedBy(trans))
1093 : : {
1094 : 0 : gnc_error_dialog (GTK_WINDOW (gsr->window), "%s",
1095 : : _("A reversing entry has already been created for this transaction."));
1096 : 0 : return;
1097 : : }
1098 : :
1099 : 0 : new_trans = xaccTransReverse(trans);
1100 : :
1101 : : /* Clear transaction level info */
1102 : 0 : xaccTransSetDatePostedSecsNormalized(new_trans, gnc_time (NULL));
1103 : 0 : xaccTransSetDateEnteredSecs(new_trans, gnc_time (NULL));
1104 : :
1105 : : /* Now jump to new trans */
1106 : 0 : gnc_split_reg_jump_to_split(gsr, xaccTransGetSplit(new_trans, 0));
1107 : : }
1108 : :
1109 : : void
1110 : 0 : gnc_split_reg_reverse_trans_cb (GtkWidget *w, gpointer data)
1111 : : {
1112 : 0 : GNCSplitReg *gsr = data;
1113 : 0 : gsr_emit_simple_signal( gsr, "reverse_txn" );
1114 : 0 : }
1115 : :
1116 : :
1117 : : static gboolean
1118 : 0 : is_trans_readonly_and_warn (GtkWindow *parent, Transaction *trans)
1119 : : {
1120 : : GtkWidget *dialog;
1121 : : const gchar *reason;
1122 : 0 : const gchar *title = _("Cannot modify or delete this transaction.");
1123 : : const gchar *message =
1124 : 0 : _("This transaction is marked read-only with the comment: '%s'");
1125 : :
1126 : 0 : if (!trans) return FALSE;
1127 : :
1128 : 0 : if (xaccTransIsReadonlyByPostedDate (trans))
1129 : : {
1130 : 0 : dialog = gtk_message_dialog_new(parent,
1131 : : 0,
1132 : : GTK_MESSAGE_ERROR,
1133 : : GTK_BUTTONS_OK,
1134 : : "%s", title);
1135 : 0 : gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
1136 : : "%s", _("The date of this transaction is older than the \"Read-Only Threshold\" set for this book. "
1137 : : "This setting can be changed in File->Properties->Accounts."));
1138 : 0 : gtk_dialog_run(GTK_DIALOG(dialog));
1139 : 0 : gtk_widget_destroy(dialog);
1140 : 0 : return TRUE;
1141 : : }
1142 : :
1143 : 0 : reason = xaccTransGetReadOnly (trans);
1144 : 0 : if (reason)
1145 : : {
1146 : 0 : dialog = gtk_message_dialog_new(parent,
1147 : : 0,
1148 : : GTK_MESSAGE_ERROR,
1149 : : GTK_BUTTONS_OK,
1150 : : "%s", title);
1151 : 0 : gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
1152 : : message, reason);
1153 : 0 : gtk_dialog_run(GTK_DIALOG(dialog));
1154 : 0 : gtk_widget_destroy(dialog);
1155 : 0 : return TRUE;
1156 : : }
1157 : 0 : return FALSE;
1158 : : }
1159 : :
1160 : :
1161 : : void
1162 : 0 : gsr_default_reinit_handler( GNCSplitReg *gsr, gpointer data )
1163 : : {
1164 : : VirtualCellLocation vcell_loc;
1165 : : SplitRegister *reg;
1166 : : Transaction *trans;
1167 : : Split *split;
1168 : : GtkWidget *dialog;
1169 : : gint response;
1170 : : const gchar *warning;
1171 : :
1172 : 0 : const char *title = _("Remove the splits from this transaction?");
1173 : 0 : const char *recn_warn = _("This transaction contains reconciled splits. "
1174 : : "Modifying it is not a good idea because that will "
1175 : : "cause your reconciled balance to be off.");
1176 : :
1177 : 0 : reg = gnc_ledger_display_get_split_register( gsr->ledger );
1178 : :
1179 : 0 : trans = gnc_split_register_get_current_trans (reg);
1180 : 0 : if (is_trans_readonly_and_warn(GTK_WINDOW(gsr->window), trans))
1181 : 0 : return;
1182 : 0 : dialog = gtk_message_dialog_new(GTK_WINDOW(gsr->window),
1183 : : GTK_DIALOG_DESTROY_WITH_PARENT,
1184 : : GTK_MESSAGE_WARNING,
1185 : : GTK_BUTTONS_NONE,
1186 : : "%s", title);
1187 : 0 : if (xaccTransHasReconciledSplits (trans))
1188 : : {
1189 : 0 : gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
1190 : : "%s", recn_warn);
1191 : 0 : warning = GNC_PREF_WARN_REG_SPLIT_DEL_ALL_RECD;
1192 : : }
1193 : : else
1194 : : {
1195 : 0 : warning = GNC_PREF_WARN_REG_SPLIT_DEL_ALL;
1196 : : }
1197 : :
1198 : 0 : gtk_dialog_add_button(GTK_DIALOG(dialog),
1199 : 0 : _("_Cancel"), GTK_RESPONSE_CANCEL);
1200 : 0 : gnc_gtk_dialog_add_button(dialog,
1201 : : /* Translators: This is the confirmation button in a warning dialog */
1202 : 0 : _("_Remove Splits"),
1203 : : "edit-delete", GTK_RESPONSE_ACCEPT);
1204 : 0 : response = gnc_dialog_run(GTK_DIALOG(dialog), warning);
1205 : 0 : gtk_widget_destroy (dialog);
1206 : 0 : if (response != GTK_RESPONSE_ACCEPT)
1207 : 0 : return;
1208 : :
1209 : : /*
1210 : : * Find the "transaction" split for the current transaction. This is
1211 : : * the split that appears at the top of the transaction in the
1212 : : * register.
1213 : : */
1214 : 0 : split = gnc_split_register_get_current_split (reg);
1215 : 0 : if (!gnc_split_register_get_split_virt_loc(reg, split, &vcell_loc))
1216 : 0 : return;
1217 : 0 : split = gnc_split_register_get_current_trans_split (reg, &vcell_loc);
1218 : 0 : gnc_split_register_empty_current_trans_except_split (reg, split);
1219 : : }
1220 : :
1221 : : /**
1222 : : * "Reinitializes" the current transaction.
1223 : : **/
1224 : : void
1225 : 0 : gnc_split_reg_reinitialize_trans_cb(GtkWidget *widget, gpointer data)
1226 : : {
1227 : 0 : GNCSplitReg *gsr = data;
1228 : 0 : gsr_emit_simple_signal( gsr, "reinit_ent" );
1229 : 0 : }
1230 : :
1231 : : /* Edit the document link for the current transaction. */
1232 : : void
1233 : 0 : gsr_default_doclink_handler (GNCSplitReg *gsr)
1234 : : {
1235 : 0 : SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger);
1236 : 0 : Split *split = gnc_split_register_get_current_split (reg);
1237 : : Transaction *trans;
1238 : : CursorClass cursor_class;
1239 : : gchar *uri;
1240 : : gchar *ret_uri;
1241 : :
1242 : : /* get the current split based on cursor position */
1243 : 0 : if (!split)
1244 : : {
1245 : 0 : gnc_split_register_cancel_cursor_split_changes (reg);
1246 : 0 : return;
1247 : : }
1248 : :
1249 : 0 : trans = xaccSplitGetParent (split);
1250 : 0 : cursor_class = gnc_split_register_get_current_cursor_class (reg);
1251 : :
1252 : 0 : if (cursor_class == CURSOR_CLASS_NONE)
1253 : 0 : return;
1254 : :
1255 : 0 : if (is_trans_readonly_and_warn (GTK_WINDOW(gsr->window), trans))
1256 : 0 : return;
1257 : :
1258 : : // fix an earlier error when storing relative paths before version 3.5
1259 : 0 : uri = gnc_doclink_convert_trans_link_uri (trans, gsr->read_only);
1260 : :
1261 : : ret_uri =
1262 : 0 : gnc_doclink_get_uri_dialog (GTK_WINDOW (gsr->window),
1263 : 0 : _("Change a Transaction Linked Document"),
1264 : : uri);
1265 : :
1266 : 0 : if (ret_uri && g_strcmp0 (uri, ret_uri) != 0)
1267 : 0 : xaccTransSetDocLink (trans, ret_uri);
1268 : :
1269 : 0 : g_free (ret_uri);
1270 : 0 : g_free (uri);
1271 : : }
1272 : :
1273 : : /* Opens the document link for the current transaction. */
1274 : : void
1275 : 0 : gsr_default_doclink_open_handler (GNCSplitReg *gsr)
1276 : : {
1277 : : CursorClass cursor_class;
1278 : 0 : SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger);
1279 : : Transaction *trans;
1280 : 0 : Split *split = gnc_split_register_get_current_split (reg);
1281 : : gchar *uri;
1282 : :
1283 : : /* get the current split based on cursor position */
1284 : 0 : if (!split)
1285 : : {
1286 : 0 : gnc_split_register_cancel_cursor_split_changes (reg);
1287 : 0 : return;
1288 : : }
1289 : :
1290 : 0 : trans = xaccSplitGetParent (split);
1291 : 0 : cursor_class = gnc_split_register_get_current_cursor_class (reg);
1292 : :
1293 : 0 : if (cursor_class == CURSOR_CLASS_NONE)
1294 : 0 : return;
1295 : :
1296 : : // fix an earlier error when storing relative paths before version 3.5
1297 : 0 : uri = gnc_doclink_convert_trans_link_uri (trans, gsr->read_only);
1298 : :
1299 : 0 : gnc_doclink_open_uri (GTK_WINDOW (gsr->window), uri);
1300 : 0 : g_free (uri);
1301 : : }
1302 : :
1303 : : /* Removes the document link for the current transaction. */
1304 : : void
1305 : 0 : gsr_default_doclink_remove_handler (GNCSplitReg *gsr)
1306 : : {
1307 : : CursorClass cursor_class;
1308 : 0 : SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger);
1309 : : Transaction *trans;
1310 : 0 : Split *split = gnc_split_register_get_current_split (reg);
1311 : :
1312 : : /* get the current split based on cursor position */
1313 : 0 : if (!split)
1314 : : {
1315 : 0 : gnc_split_register_cancel_cursor_split_changes (reg);
1316 : 0 : return;
1317 : : }
1318 : :
1319 : 0 : trans = xaccSplitGetParent (split);
1320 : 0 : cursor_class = gnc_split_register_get_current_cursor_class (reg);
1321 : :
1322 : 0 : if (cursor_class == CURSOR_CLASS_NONE)
1323 : 0 : return;
1324 : :
1325 : 0 : if (is_trans_readonly_and_warn (GTK_WINDOW(gsr->window), trans))
1326 : 0 : return;
1327 : :
1328 : 0 : xaccTransSetDocLink (trans, "");
1329 : : }
1330 : :
1331 : : static void
1332 : 0 : gsr_default_doclink_from_sheet_handler (GNCSplitReg *gsr)
1333 : : {
1334 : 0 : SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger);
1335 : : Transaction *trans;
1336 : : Split *split;
1337 : 0 : gchar *uri = NULL;
1338 : :
1339 : : /* get the current split based on cursor position */
1340 : 0 : split = gnc_split_register_get_current_split (reg);
1341 : 0 : if (!split)
1342 : 0 : return;
1343 : :
1344 : 0 : trans = xaccSplitGetParent (split);
1345 : :
1346 : : // fix an earlier error when storing relative paths before version 3.5
1347 : 0 : uri = gnc_doclink_convert_trans_link_uri (trans, gsr->read_only);
1348 : :
1349 : 0 : if (uri)
1350 : 0 : gnc_doclink_open_uri (GTK_WINDOW (gsr->window), uri);
1351 : :
1352 : 0 : g_free (uri);
1353 : : }
1354 : :
1355 : : void
1356 : 0 : gsr_default_delete_handler( GNCSplitReg *gsr, gpointer data )
1357 : : {
1358 : : CursorClass cursor_class;
1359 : : SplitRegister *reg;
1360 : : Transaction *trans;
1361 : : Split *split;
1362 : : GtkWidget *dialog;
1363 : : gint response;
1364 : : const gchar *warning;
1365 : :
1366 : 0 : reg = gnc_ledger_display_get_split_register( gsr->ledger );
1367 : :
1368 : : /* get the current split based on cursor position */
1369 : 0 : split = gnc_split_register_get_current_split(reg);
1370 : 0 : if (split == NULL)
1371 : : {
1372 : 0 : gnc_split_register_cancel_cursor_split_changes (reg);
1373 : 0 : return;
1374 : : }
1375 : :
1376 : 0 : trans = xaccSplitGetParent(split);
1377 : 0 : cursor_class = gnc_split_register_get_current_cursor_class (reg);
1378 : :
1379 : : /* test for blank_split reference pointing to split */
1380 : 0 : if (gnc_split_register_is_blank_split (reg, split))
1381 : 0 : gnc_split_register_change_blank_split_ref (reg, split);
1382 : :
1383 : : /* Deleting the blank split just cancels */
1384 : : {
1385 : 0 : Split *blank_split = gnc_split_register_get_blank_split (reg);
1386 : :
1387 : 0 : if (split == blank_split)
1388 : : {
1389 : 0 : gnc_split_register_cancel_cursor_trans_changes (reg);
1390 : 0 : return;
1391 : : }
1392 : : }
1393 : :
1394 : 0 : if (cursor_class == CURSOR_CLASS_NONE)
1395 : 0 : return;
1396 : :
1397 : 0 : if (is_trans_readonly_and_warn(GTK_WINDOW(gsr->window), trans))
1398 : 0 : return;
1399 : :
1400 : : /* On a split cursor, just delete the one split. */
1401 : 0 : if (cursor_class == CURSOR_CLASS_SPLIT)
1402 : : {
1403 : 0 : const char *format = _("Delete the split '%s' from the transaction '%s'?");
1404 : 0 : const char *recn_warn = _("You would be deleting a reconciled split! "
1405 : : "This is not a good idea as it will cause your "
1406 : : "reconciled balance to be off.");
1407 : 0 : const char *anchor_error = _("You cannot delete this split.");
1408 : 0 : const char *anchor_split = _("This is the split anchoring this transaction "
1409 : : "to the register. You may not delete it from "
1410 : : "this register window. You may delete the "
1411 : : "entire transaction from this window, or you "
1412 : : "may navigate to a register that shows "
1413 : : "another side of this same transaction and "
1414 : : "delete the split from that register.");
1415 : 0 : char *buf = NULL;
1416 : : const char *memo;
1417 : : const char *desc;
1418 : : char recn;
1419 : :
1420 : 0 : if (reg->type != GENERAL_JOURNAL) // no anchoring split
1421 : : {
1422 : 0 : if (split == gnc_split_register_get_current_trans_split (reg, NULL))
1423 : : {
1424 : 0 : dialog = gtk_message_dialog_new(GTK_WINDOW(gsr->window),
1425 : : GTK_DIALOG_MODAL
1426 : : | GTK_DIALOG_DESTROY_WITH_PARENT,
1427 : : GTK_MESSAGE_ERROR,
1428 : : GTK_BUTTONS_OK,
1429 : : "%s", anchor_error);
1430 : 0 : gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
1431 : : "%s", anchor_split);
1432 : 0 : gtk_dialog_run(GTK_DIALOG(dialog));
1433 : 0 : gtk_widget_destroy (dialog);
1434 : 0 : return;
1435 : : }
1436 : : }
1437 : :
1438 : 0 : memo = xaccSplitGetMemo (split);
1439 : 0 : memo = (memo && *memo) ? memo : _("(no memo)");
1440 : :
1441 : 0 : desc = xaccTransGetDescription (trans);
1442 : 0 : desc = (desc && *desc) ? desc : _("(no description)");
1443 : :
1444 : : /* ask for user confirmation before performing permanent damage */
1445 : 0 : buf = g_strdup_printf (format, memo, desc);
1446 : 0 : dialog = gtk_message_dialog_new(GTK_WINDOW(gsr->window),
1447 : : GTK_DIALOG_MODAL
1448 : : | GTK_DIALOG_DESTROY_WITH_PARENT,
1449 : : GTK_MESSAGE_QUESTION,
1450 : : GTK_BUTTONS_NONE,
1451 : : "%s", buf);
1452 : 0 : g_free(buf);
1453 : 0 : recn = xaccSplitGetReconcile (split);
1454 : 0 : if (recn == YREC || recn == FREC)
1455 : : {
1456 : 0 : gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
1457 : : "%s", recn_warn);
1458 : 0 : warning = GNC_PREF_WARN_REG_SPLIT_DEL_RECD;
1459 : : }
1460 : : else
1461 : : {
1462 : 0 : warning = GNC_PREF_WARN_REG_SPLIT_DEL;
1463 : : }
1464 : :
1465 : 0 : gtk_dialog_add_button(GTK_DIALOG(dialog),
1466 : 0 : _("_Cancel"), GTK_RESPONSE_CANCEL);
1467 : 0 : gnc_gtk_dialog_add_button(dialog, _("_Delete Split"),
1468 : : "edit-delete", GTK_RESPONSE_ACCEPT);
1469 : 0 : response = gnc_dialog_run(GTK_DIALOG(dialog), warning);
1470 : 0 : gtk_widget_destroy (dialog);
1471 : 0 : if (response != GTK_RESPONSE_ACCEPT)
1472 : 0 : return;
1473 : :
1474 : 0 : gnc_split_register_delete_current_split (reg);
1475 : 0 : return;
1476 : : }
1477 : :
1478 : 0 : g_return_if_fail(cursor_class == CURSOR_CLASS_TRANS);
1479 : :
1480 : : /* On a transaction cursor with 2 or fewer splits in single or double
1481 : : * mode, we just delete the whole transaction, kerblooie */
1482 : : {
1483 : 0 : const char *title = _("Delete the current transaction?");
1484 : 0 : const char *recn_warn = _("You would be deleting a transaction "
1485 : : "with reconciled splits! "
1486 : : "This is not a good idea as it will cause your "
1487 : : "reconciled balance to be off.");
1488 : :
1489 : 0 : dialog = gtk_message_dialog_new(GTK_WINDOW(gsr->window),
1490 : : GTK_DIALOG_MODAL
1491 : : | GTK_DIALOG_DESTROY_WITH_PARENT,
1492 : : GTK_MESSAGE_WARNING,
1493 : : GTK_BUTTONS_NONE,
1494 : : "%s", title);
1495 : 0 : if (xaccTransHasReconciledSplits (trans))
1496 : : {
1497 : 0 : gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
1498 : : "%s", recn_warn);
1499 : 0 : warning = GNC_PREF_WARN_REG_TRANS_DEL_RECD;
1500 : : }
1501 : : else
1502 : : {
1503 : 0 : warning = GNC_PREF_WARN_REG_TRANS_DEL;
1504 : : }
1505 : 0 : gtk_dialog_add_button(GTK_DIALOG(dialog),
1506 : 0 : _("_Cancel"), GTK_RESPONSE_CANCEL);
1507 : 0 : gnc_gtk_dialog_add_button(dialog, _("_Delete Transaction"),
1508 : : "edit-delete", GTK_RESPONSE_ACCEPT);
1509 : 0 : response = gnc_dialog_run(GTK_DIALOG(dialog), warning);
1510 : 0 : gtk_widget_destroy (dialog);
1511 : 0 : if (response != GTK_RESPONSE_ACCEPT)
1512 : 0 : return;
1513 : :
1514 : 0 : gnc_split_register_delete_current_trans (reg);
1515 : 0 : return;
1516 : : }
1517 : : }
1518 : :
1519 : : /**
1520 : : * Deletes the current transaction.
1521 : : **/
1522 : : void
1523 : 0 : gnc_split_reg_delete_trans_cb(GtkWidget *widget, gpointer data)
1524 : : {
1525 : 0 : GNCSplitReg *gsr = data;
1526 : 0 : gsr_emit_simple_signal( gsr, "delete_ent" );
1527 : 0 : }
1528 : :
1529 : : void
1530 : 0 : gsr_default_dup_handler( GNCSplitReg *gsr, gpointer data )
1531 : : {
1532 : 0 : gnc_split_register_duplicate_current
1533 : : (gnc_ledger_display_get_split_register( gsr->ledger ));
1534 : 0 : }
1535 : :
1536 : : /**
1537 : : * Duplicates the current transaction in the register.
1538 : : **/
1539 : : void
1540 : 0 : gnc_split_reg_duplicate_trans_cb(GtkWidget *w, gpointer data)
1541 : : {
1542 : 0 : GNCSplitReg *gsr = data;
1543 : 0 : gsr_emit_simple_signal( gsr, "dup_ent" );
1544 : 0 : }
1545 : :
1546 : : /**
1547 : : * Schedules the current transaction for recurring-entry.
1548 : : * If the selected transaction was created from a scheduled transaction,
1549 : : * opens the editor for that Scheduled Transaction.
1550 : : **/
1551 : : void
1552 : 0 : gsr_default_schedule_handler( GNCSplitReg *gsr, gpointer data )
1553 : : {
1554 : 0 : GncGUID *fromSXId = NULL;
1555 : 0 : SchedXaction *theSX = NULL;
1556 : : GList *sxElts;
1557 : 0 : SplitRegister *reg = gnc_ledger_display_get_split_register( gsr->ledger );
1558 : 0 : Transaction *pending_trans = gnc_split_register_get_current_trans (reg);
1559 : :
1560 : : /* If the transaction has a sched-xact KVP frame, then go to the editor
1561 : : * for the existing SX; otherwise, do the sx-from-trans dialog. */
1562 : :
1563 : 0 : qof_instance_get (QOF_INSTANCE (pending_trans),
1564 : : "from-sched-xaction", &fromSXId,
1565 : : NULL);
1566 : :
1567 : : /* Get the correct SX */
1568 : 0 : for ( sxElts = gnc_book_get_schedxactions (gnc_get_current_book())->sx_list;
1569 : 0 : (!theSX) && sxElts;
1570 : 0 : sxElts = sxElts->next )
1571 : : {
1572 : 0 : SchedXaction *sx = (SchedXaction*)sxElts->data;
1573 : 0 : theSX =
1574 : 0 : ((guid_equal (xaccSchedXactionGetGUID (sx), fromSXId))
1575 : 0 : ? sx : NULL);
1576 : : }
1577 : 0 : guid_free (fromSXId);
1578 : :
1579 : 0 : if ( theSX )
1580 : : {
1581 : 0 : gnc_ui_scheduled_xaction_editor_dialog_create(GTK_WINDOW(data), theSX, FALSE);
1582 : 0 : return;
1583 : : }
1584 : 0 : gnc_sx_create_from_trans(GTK_WINDOW(data), pending_trans);
1585 : : }
1586 : :
1587 : : void
1588 : 0 : gnc_split_reg_recur_cb(GtkWidget *w, gpointer data)
1589 : : {
1590 : 0 : GNCSplitReg *gsr = data;
1591 : 0 : gsr_emit_simple_signal( gsr, "schedule_ent" );
1592 : 0 : }
1593 : :
1594 : : /**
1595 : : * Records into the books the currently-selected transaction.
1596 : : **/
1597 : : void
1598 : 0 : gnc_split_reg_record_trans_cb (GtkWidget *w, gpointer data)
1599 : : {
1600 : 0 : GNCSplitReg *gsr = data;
1601 : 0 : gsr_emit_simple_signal( gsr, "enter_ent" );
1602 : 0 : }
1603 : :
1604 : : void
1605 : 0 : gsr_default_cancel_handler( GNCSplitReg *gsr, gpointer data )
1606 : : {
1607 : 0 : gnc_split_register_cancel_cursor_trans_changes
1608 : : (gnc_ledger_display_get_split_register( gsr->ledger ));
1609 : 0 : }
1610 : :
1611 : : /**
1612 : : * Cancels the edits of the currently-selected transaction.
1613 : : **/
1614 : : void
1615 : 0 : gnc_split_reg_cancel_trans_cb(GtkWidget *w, gpointer data)
1616 : : {
1617 : 0 : GNCSplitReg *gsr = data;
1618 : 0 : gsr_emit_simple_signal( gsr, "cancel_ent" );
1619 : 0 : }
1620 : :
1621 : : void
1622 : 0 : gsr_default_expand_handler( GNCSplitReg *gsr, gpointer data )
1623 : : {
1624 : : gint activeCount;
1625 : : gboolean expand;
1626 : : SplitRegister *reg;
1627 : :
1628 : 0 : if (!gsr)
1629 : 0 : return;
1630 : :
1631 : 0 : reg = gnc_ledger_display_get_split_register (gsr->ledger);
1632 : :
1633 : : /* These should all be in agreement. */
1634 : 0 : activeCount =
1635 : 0 : ( ( gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM(gsr->split_menu_check)) ? 1 : -1 )
1636 : 0 : + ( gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM(gsr->split_popup_check)) ? 1 : -1 )
1637 : 0 : + ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(gsr->split_button) )
1638 : 0 : ? 1 : -1 ) );
1639 : :
1640 : : /* If activeCount > 0, then there's more active than inactive; otherwise,
1641 : : * more inactive than active. Both determine which state the user is
1642 : : * attempting to get to. */
1643 : 0 : expand = ( activeCount < 0 );
1644 : :
1645 : : /* The ledger's invocation of 'redraw_all' will force the agreement in the
1646 : : * other split state widgets, so we neglect doing it here. */
1647 : 0 : gnc_split_register_expand_current_trans (reg, expand);
1648 : : }
1649 : :
1650 : : void
1651 : 0 : gnc_split_reg_expand_trans_menu_cb (GtkWidget *widget, gpointer data)
1652 : : {
1653 : 0 : GNCSplitReg *gsr = data;
1654 : 0 : gsr_emit_simple_signal( gsr, "expand_ent" );
1655 : 0 : }
1656 : :
1657 : : void
1658 : 0 : gnc_split_reg_expand_trans_toolbar_cb (GtkWidget *widget, gpointer data)
1659 : : {
1660 : 0 : GNCSplitReg *gsr = data;
1661 : 0 : gsr_emit_simple_signal( gsr, "expand_ent" );
1662 : 0 : }
1663 : :
1664 : : gboolean
1665 : 0 : gnc_split_reg_clear_filter_for_split (GNCSplitReg *gsr, Split *split)
1666 : : {
1667 : : VirtualCellLocation vcell_loc;
1668 : : SplitRegister *reg;
1669 : :
1670 : 0 : if (!gsr)
1671 : 0 : return FALSE;
1672 : :
1673 : 0 : reg = gnc_ledger_display_get_split_register (gsr->ledger);
1674 : :
1675 : 0 : if (!gnc_split_register_get_split_virt_loc (reg, split, &vcell_loc))
1676 : : {
1677 : 0 : gint response = gnc_ok_cancel_dialog (GTK_WINDOW(gsr->window),
1678 : : GTK_RESPONSE_CANCEL,
1679 : 0 : (_("Target split is currently hidden in this register.\n\n%s\n\n"
1680 : : "Select OK to temporarily clear filter and proceed,\n"
1681 : : "otherwise the last active cell will be selected.")),
1682 : : gsr->filter_text);
1683 : :
1684 : 0 : if (response == GTK_RESPONSE_OK)
1685 : 0 : return TRUE;
1686 : : }
1687 : 0 : return FALSE;
1688 : : }
1689 : :
1690 : : /**
1691 : : * move the cursor to the split, if present in register
1692 : : **/
1693 : : void
1694 : 0 : gnc_split_reg_jump_to_split(GNCSplitReg *gsr, Split *split)
1695 : : {
1696 : 0 : if (!gsr) return;
1697 : :
1698 : 0 : SplitRegister *reg = gnc_ledger_display_get_split_register( gsr->ledger );
1699 : :
1700 : : VirtualCellLocation vcell_loc;
1701 : 0 : if (gnc_split_register_get_split_virt_loc(reg, split, &vcell_loc))
1702 : 0 : gnucash_register_goto_virt_cell( gsr->reg, vcell_loc );
1703 : :
1704 : 0 : gnc_ledger_display_refresh( gsr->ledger );
1705 : : }
1706 : :
1707 : : /**
1708 : : * Move the cursor to the split in the non-blank amount column.
1709 : : **/
1710 : : void
1711 : 0 : gnc_split_reg_jump_to_split_amount(GNCSplitReg *gsr, Split *split)
1712 : : {
1713 : 0 : if (!gsr) return;
1714 : :
1715 : 0 : SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger);
1716 : :
1717 : : VirtualLocation virt_loc;
1718 : 0 : if (gnc_split_register_get_split_amount_virt_loc (reg, split, &virt_loc))
1719 : 0 : gnucash_register_goto_virt_loc (gsr->reg, virt_loc);
1720 : :
1721 : 0 : gnc_ledger_display_refresh (gsr->ledger);
1722 : : }
1723 : :
1724 : : void
1725 : 0 : gnc_split_reg_jump_to_blank (GNCSplitReg *gsr)
1726 : : {
1727 : 0 : SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger);
1728 : : VirtualCellLocation vcell_loc;
1729 : : Split *blank;
1730 : :
1731 : 0 : ENTER("gsr=%p", gsr);
1732 : :
1733 : 0 : blank = gnc_split_register_get_blank_split (reg);
1734 : 0 : if (blank == NULL)
1735 : : {
1736 : 0 : LEAVE("no blank split");
1737 : 0 : return;
1738 : : }
1739 : :
1740 : 0 : if (gnc_split_register_get_split_virt_loc (reg, blank, &vcell_loc))
1741 : : {
1742 : 0 : if ((vcell_loc.virt_row > 1) && (reg->style == REG_STYLE_JOURNAL))
1743 : 0 : vcell_loc.virt_row--; // highlight the date field
1744 : :
1745 : 0 : gnucash_register_goto_virt_cell (gsr->reg, vcell_loc);
1746 : : }
1747 : 0 : gnc_ledger_display_refresh (gsr->ledger);
1748 : 0 : LEAVE(" ");
1749 : : }
1750 : :
1751 : : void
1752 : 0 : gnc_split_reg_focus_on_sheet (GNCSplitReg *gsr)
1753 : : {
1754 : 0 : GnucashRegister *reg = gsr->reg;
1755 : 0 : GnucashSheet *sheet = gnucash_register_get_sheet (reg);
1756 : :
1757 : : // Make sure the sheet is the focus only when it is realized
1758 : 0 : if (!gtk_widget_has_focus(GTK_WIDGET(sheet)) && gtk_widget_get_realized (GTK_WIDGET(sheet)))
1759 : 0 : gtk_widget_grab_focus (GTK_WIDGET(sheet));
1760 : 0 : }
1761 : :
1762 : : void
1763 : 0 : gnc_split_reg_set_sheet_focus (GNCSplitReg *gsr, gboolean has_focus)
1764 : : {
1765 : 0 : GnucashRegister *reg = gsr->reg;
1766 : 0 : GnucashSheet *sheet = gnucash_register_get_sheet (reg);
1767 : 0 : gnucash_sheet_set_has_focus (sheet, has_focus);
1768 : 0 : }
1769 : :
1770 : : void
1771 : 0 : gnc_split_reg_balancing_entry(GNCSplitReg *gsr, Account *account,
1772 : : time64 statement_date, gnc_numeric balancing_amount)
1773 : : {
1774 : :
1775 : : Transaction *transaction;
1776 : : Split *split;
1777 : :
1778 : : // create transaction
1779 : 0 : transaction = create_balancing_transaction(gnc_get_current_book(),
1780 : : account, statement_date, balancing_amount);
1781 : :
1782 : : // jump to transaction
1783 : 0 : split = xaccTransFindSplitByAccount(transaction, account);
1784 : 0 : if (split == NULL)
1785 : : {
1786 : : // default behaviour: jump to blank split
1787 : 0 : g_warning("create_balancing_transaction failed");
1788 : 0 : gnc_split_reg_jump_to_blank(gsr);
1789 : : }
1790 : : else
1791 : : {
1792 : : // goto balancing transaction
1793 : 0 : gnc_split_reg_jump_to_split(gsr, split );
1794 : : }
1795 : 0 : }
1796 : :
1797 : : static Transaction*
1798 : 0 : create_balancing_transaction(QofBook *book, Account *account,
1799 : : time64 statement_date, gnc_numeric balancing_amount)
1800 : : {
1801 : :
1802 : : Transaction *trans;
1803 : : Split *split;
1804 : :
1805 : 0 : if (!account)
1806 : 0 : return NULL;
1807 : 0 : if (gnc_numeric_zero_p(balancing_amount))
1808 : 0 : return NULL;
1809 : :
1810 : 0 : xaccAccountBeginEdit(account);
1811 : :
1812 : 0 : trans = xaccMallocTransaction(book);
1813 : :
1814 : 0 : xaccTransBeginEdit(trans);
1815 : :
1816 : : // fill Transaction
1817 : 0 : xaccTransSetCurrency(trans, gnc_account_or_default_currency(account, NULL));
1818 : 0 : xaccTransSetDatePostedSecsNormalized(trans, statement_date);
1819 : 0 : xaccTransSetDescription(trans, _("Balancing entry from reconciliation"));
1820 : : /* We also must set a new DateEntered on the new entry
1821 : : * because otherwise the ordering is not deterministic */
1822 : 0 : xaccTransSetDateEnteredSecs(trans, gnc_time(NULL));
1823 : :
1824 : : // 1. Split
1825 : 0 : split = xaccMallocSplit(book);
1826 : 0 : xaccTransAppendSplit(trans, split);
1827 : 0 : xaccAccountInsertSplit(account, split);
1828 : 0 : xaccSplitSetAmount(split, balancing_amount);
1829 : 0 : xaccSplitSetValue(split, balancing_amount);
1830 : :
1831 : : // 2. Split (no account is defined: split goes to orphan account)
1832 : 0 : split = xaccMallocSplit(book);
1833 : 0 : xaccTransAppendSplit(trans, split);
1834 : :
1835 : 0 : balancing_amount = gnc_numeric_neg(balancing_amount);
1836 : 0 : xaccSplitSetAmount(split, balancing_amount);
1837 : 0 : xaccSplitSetValue(split, balancing_amount);
1838 : :
1839 : 0 : xaccTransCommitEdit(trans);
1840 : 0 : xaccAccountCommitEdit(account);
1841 : 0 : return trans;
1842 : : }
1843 : :
1844 : : void
1845 : 0 : gsr_default_blank_handler( GNCSplitReg *gsr, gpointer data )
1846 : : {
1847 : : SplitRegister *reg;
1848 : :
1849 : 0 : ENTER("gsr=%p, gpointer=%p", gsr, data);
1850 : :
1851 : 0 : reg = gnc_ledger_display_get_split_register (gsr->ledger);
1852 : :
1853 : 0 : if (gnc_split_register_save (reg, TRUE))
1854 : 0 : gnc_split_register_redraw (reg);
1855 : :
1856 : 0 : gnc_split_reg_jump_to_blank (gsr);
1857 : 0 : LEAVE(" ");
1858 : 0 : }
1859 : :
1860 : : void
1861 : 0 : gnc_split_reg_new_trans_cb (GtkWidget *widget, gpointer data)
1862 : : {
1863 : 0 : GNCSplitReg *gsr = data;
1864 : 0 : gsr_emit_simple_signal( gsr, "blank" );
1865 : 0 : }
1866 : :
1867 : : void
1868 : 0 : gsr_default_jump_handler( GNCSplitReg *gsr, gpointer data )
1869 : : {
1870 : 0 : g_assert_not_reached();
1871 : : }
1872 : :
1873 : : void
1874 : 0 : gnc_split_reg_jump_cb( GtkWidget *widget, gpointer data )
1875 : : {
1876 : 0 : GNCSplitReg *gsr = data;
1877 : 0 : gsr_emit_simple_signal( gsr, "jump" );
1878 : 0 : }
1879 : :
1880 : : void
1881 : 0 : gnc_split_reg_change_style (GNCSplitReg *gsr, SplitRegisterStyle style, gboolean refresh)
1882 : : {
1883 : 0 : SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger);
1884 : :
1885 : 0 : if (style == reg->style)
1886 : 0 : return;
1887 : :
1888 : 0 : gnc_split_register_config (reg, reg->type, style, reg->use_double_line);
1889 : 0 : if (refresh)
1890 : 0 : gnc_ledger_display_refresh (gsr->ledger);
1891 : : }
1892 : :
1893 : : void
1894 : 0 : gnc_split_reg_style_ledger_cb (GtkWidget *w, gpointer data)
1895 : : {
1896 : 0 : GNCSplitReg *gsr = data;
1897 : :
1898 : 0 : if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM(w)))
1899 : 0 : return;
1900 : :
1901 : 0 : gnc_split_reg_change_style (gsr, REG_STYLE_LEDGER, TRUE);
1902 : : }
1903 : :
1904 : : void
1905 : 0 : gnc_split_reg_style_auto_ledger_cb (GtkWidget *w, gpointer data)
1906 : : {
1907 : 0 : GNCSplitReg *gsr = data;
1908 : :
1909 : 0 : if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM(w)))
1910 : 0 : return;
1911 : :
1912 : 0 : gnc_split_reg_change_style (gsr, REG_STYLE_AUTO_LEDGER, TRUE);
1913 : : }
1914 : :
1915 : : void
1916 : 0 : gnc_split_reg_style_journal_cb (GtkWidget *w, gpointer data)
1917 : : {
1918 : 0 : GNCSplitReg *gsr = data;
1919 : :
1920 : 0 : if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM(w)))
1921 : 0 : return;
1922 : :
1923 : 0 : gnc_split_reg_change_style (gsr, REG_STYLE_JOURNAL, TRUE);
1924 : : }
1925 : :
1926 : : void
1927 : 0 : gnc_split_reg_double_line_cb (GtkWidget *w, gpointer data)
1928 : : {
1929 : 0 : GNCSplitReg *gsr = data;
1930 : 0 : SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger);
1931 : : gboolean use_double_line;
1932 : :
1933 : 0 : use_double_line = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM(w));
1934 : 0 : if ( use_double_line == reg->use_double_line )
1935 : 0 : return;
1936 : :
1937 : 0 : gnc_split_register_config( reg, reg->type, reg->style, use_double_line );
1938 : 0 : gnc_ledger_display_refresh( gsr->ledger );
1939 : : }
1940 : :
1941 : : static void
1942 : 0 : gnc_split_reg_sort_force( GNCSplitReg *gsr, SortType sort_code, gboolean force )
1943 : : {
1944 : 0 : Query *query = gnc_ledger_display_get_query( gsr->ledger );
1945 : 0 : gboolean show_present_divider = FALSE;
1946 : 0 : GSList *p1 = NULL, *p2 = NULL, *p3 = NULL, *standard;
1947 : : SplitRegister *reg;
1948 : :
1949 : 0 : if ((gsr->sort_type == sort_code) && !force)
1950 : 0 : return;
1951 : :
1952 : 0 : standard = g_slist_prepend( NULL, QUERY_DEFAULT_SORT );
1953 : :
1954 : 0 : switch (sort_code)
1955 : : {
1956 : 0 : case BY_STANDARD:
1957 : 0 : p1 = standard;
1958 : 0 : show_present_divider = TRUE;
1959 : 0 : break;
1960 : 0 : case BY_DATE:
1961 : 0 : p1 = g_slist_prepend (p1, TRANS_DATE_POSTED);
1962 : 0 : p1 = g_slist_prepend (p1, SPLIT_TRANS);
1963 : 0 : p2 = standard;
1964 : 0 : show_present_divider = TRUE;
1965 : 0 : break;
1966 : 0 : case BY_DATE_ENTERED:
1967 : 0 : p1 = g_slist_prepend (p1, TRANS_DATE_ENTERED);
1968 : 0 : p1 = g_slist_prepend (p1, SPLIT_TRANS);
1969 : 0 : p2 = standard;
1970 : 0 : break;
1971 : 0 : case BY_DATE_RECONCILED:
1972 : 0 : p1 = g_slist_prepend (p1, SPLIT_RECONCILE);
1973 : 0 : p2 = g_slist_prepend (p2, SPLIT_DATE_RECONCILED);
1974 : 0 : p3 = standard;
1975 : 0 : break;
1976 : 0 : case BY_NUM:
1977 : 0 : p1 = g_slist_prepend (p1, TRANS_NUM);
1978 : 0 : p1 = g_slist_prepend (p1, SPLIT_TRANS);
1979 : 0 : p2 = standard;
1980 : 0 : break;
1981 : 0 : case BY_AMOUNT:
1982 : 0 : p1 = g_slist_prepend (p1, SPLIT_VALUE);
1983 : 0 : p2 = standard;
1984 : 0 : break;
1985 : 0 : case BY_MEMO:
1986 : 0 : p1 = g_slist_prepend (p1, SPLIT_MEMO);
1987 : 0 : p2 = standard;
1988 : 0 : break;
1989 : 0 : case BY_DESC:
1990 : 0 : p1 = g_slist_prepend (p1, TRANS_DESCRIPTION);
1991 : 0 : p1 = g_slist_prepend (p1, SPLIT_TRANS);
1992 : 0 : p2 = standard;
1993 : 0 : break;
1994 : 0 : case BY_ACTION:
1995 : 0 : p1 = g_slist_prepend (p1, SPLIT_ACTION);
1996 : 0 : p2 = standard;
1997 : 0 : break;
1998 : 0 : case BY_NOTES:
1999 : 0 : p1 = g_slist_prepend (p1, TRANS_NOTES);
2000 : 0 : p1 = g_slist_prepend (p1, SPLIT_TRANS);
2001 : 0 : p2 = standard;
2002 : 0 : break;
2003 : 0 : default:
2004 : 0 : g_slist_free (standard);
2005 : 0 : g_return_if_fail (FALSE);
2006 : : break;
2007 : : }
2008 : :
2009 : 0 : qof_query_set_sort_order( query, p1, p2, p3 );
2010 : 0 : reg = gnc_ledger_display_get_split_register( gsr->ledger );
2011 : 0 : gnc_split_register_show_present_divider( reg, show_present_divider );
2012 : 0 : gsr->sort_type = sort_code;
2013 : 0 : gnc_ledger_display_refresh( gsr->ledger );
2014 : : }
2015 : :
2016 : : static void
2017 : 0 : gnc_split_reg_sort( GNCSplitReg *gsr, SortType sort_code )
2018 : : {
2019 : 0 : gnc_split_reg_sort_force( gsr, sort_code, FALSE );
2020 : 0 : }
2021 : :
2022 : : void
2023 : 0 : gnc_split_reg_sort_standard_cb(GtkWidget *w, gpointer data)
2024 : : {
2025 : 0 : GNCSplitReg *gsr = data;
2026 : 0 : gnc_split_reg_sort(gsr, BY_STANDARD);
2027 : 0 : }
2028 : :
2029 : : void
2030 : 0 : gnc_split_reg_sort_date_cb(GtkWidget *w, gpointer data)
2031 : : {
2032 : 0 : GNCSplitReg *gsr = data;
2033 : 0 : gnc_split_reg_sort(gsr, BY_DATE);
2034 : 0 : }
2035 : :
2036 : : void
2037 : 0 : gnc_split_reg_sort_date_entered_cb(GtkWidget *w, gpointer data)
2038 : : {
2039 : 0 : GNCSplitReg *gsr = data;
2040 : 0 : gnc_split_reg_sort(gsr, BY_DATE_ENTERED);
2041 : 0 : }
2042 : :
2043 : : void
2044 : 0 : gnc_split_reg_sort_date_reconciled_cb(GtkWidget *w, gpointer data)
2045 : : {
2046 : 0 : GNCSplitReg *gsr = data;
2047 : 0 : gnc_split_reg_sort(gsr, BY_DATE_RECONCILED);
2048 : 0 : }
2049 : :
2050 : : void
2051 : 0 : gnc_split_reg_sort_num_cb(GtkWidget *w, gpointer data)
2052 : : {
2053 : 0 : GNCSplitReg *gsr = data;
2054 : 0 : gnc_split_reg_sort(gsr, BY_NUM);
2055 : 0 : }
2056 : :
2057 : : void
2058 : 0 : gnc_split_reg_sort_amount_cb(GtkWidget *w, gpointer data)
2059 : : {
2060 : 0 : GNCSplitReg *gsr = data;
2061 : 0 : gnc_split_reg_sort(gsr, BY_AMOUNT);
2062 : 0 : }
2063 : :
2064 : : void
2065 : 0 : gnc_split_reg_sort_memo_cb(GtkWidget *w, gpointer data)
2066 : : {
2067 : 0 : GNCSplitReg *gsr = data;
2068 : 0 : gnc_split_reg_sort(gsr, BY_MEMO);
2069 : 0 : }
2070 : :
2071 : : void
2072 : 0 : gnc_split_reg_sort_desc_cb(GtkWidget *w, gpointer data)
2073 : : {
2074 : 0 : GNCSplitReg *gsr = data;
2075 : 0 : gnc_split_reg_sort(gsr, BY_DESC);
2076 : 0 : }
2077 : :
2078 : : void
2079 : 0 : gnc_split_reg_sort_action_cb(GtkWidget *w, gpointer data)
2080 : : {
2081 : 0 : GNCSplitReg *gsr = data;
2082 : 0 : gnc_split_reg_sort(gsr, BY_ACTION);
2083 : 0 : }
2084 : :
2085 : : void
2086 : 0 : gnc_split_reg_sort_notes_cb(GtkWidget *w, gpointer data)
2087 : : {
2088 : 0 : GNCSplitReg *gsr = data;
2089 : 0 : gnc_split_reg_sort(gsr, BY_NOTES);
2090 : 0 : }
2091 : :
2092 : :
2093 : : void
2094 : 0 : gnc_split_reg_set_sort_reversed(GNCSplitReg *gsr, gboolean rev, gboolean refresh)
2095 : : {
2096 : : /* Note: sort_reversed is the boolean opposite of sort_increasing
2097 : : * so when rev == true, we're sorting decreasing
2098 : : * In other words, qof_query_set_sort_increasing should
2099 : : * always use the inverse of rev.
2100 : : */
2101 : 0 : SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger);
2102 : 0 : Query *query = gnc_ledger_display_get_query( gsr->ledger );
2103 : :
2104 : 0 : gnc_split_register_set_reverse_sort (reg, rev);
2105 : :
2106 : 0 : qof_query_set_sort_increasing (query, !rev, !rev, !rev);
2107 : 0 : gsr->sort_rev = rev;
2108 : :
2109 : 0 : if (refresh)
2110 : 0 : gnc_ledger_display_refresh( gsr->ledger );
2111 : 0 : }
2112 : :
2113 : : static gboolean
2114 : 0 : gnc_split_reg_record (GNCSplitReg *gsr)
2115 : : {
2116 : 0 : ENTER("gsr=%p", gsr);
2117 : :
2118 : 0 : SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger);
2119 : :
2120 : 0 : if (!gnc_split_register_save (reg, TRUE))
2121 : : {
2122 : 0 : LEAVE("no save");
2123 : 0 : return FALSE;
2124 : : }
2125 : :
2126 : : /* Explicit redraw shouldn't be needed,
2127 : : * since gui_refresh events should handle this. */
2128 : : /* gnc_split_register_redraw (reg); */
2129 : 0 : LEAVE(" ");
2130 : 0 : return TRUE;
2131 : : }
2132 : :
2133 : : static gboolean
2134 : 0 : gnc_split_reg_match_trans_row( VirtualLocation virt_loc,
2135 : : gpointer user_data )
2136 : : {
2137 : 0 : GNCSplitReg *gsr = user_data;
2138 : : CursorClass cursor_class;
2139 : : SplitRegister *sr;
2140 : :
2141 : 0 : sr = gnc_ledger_display_get_split_register (gsr->ledger);
2142 : 0 : cursor_class = gnc_split_register_get_cursor_class (sr, virt_loc.vcell_loc);
2143 : :
2144 : 0 : return (cursor_class == CURSOR_CLASS_TRANS);
2145 : : }
2146 : :
2147 : : static void
2148 : 0 : gnc_split_reg_goto_next_trans_row (GNCSplitReg *gsr)
2149 : : {
2150 : 0 : ENTER("gsr=%p", gsr);
2151 : 0 : gnucash_register_goto_next_matching_row( gsr->reg,
2152 : : gnc_split_reg_match_trans_row,
2153 : : gsr );
2154 : 0 : LEAVE(" ");
2155 : 0 : }
2156 : :
2157 : : void
2158 : 0 : gnc_split_reg_enter( GNCSplitReg *gsr, gboolean next_transaction )
2159 : : {
2160 : 0 : SplitRegister *sr = gnc_ledger_display_get_split_register( gsr->ledger );
2161 : : gboolean goto_blank;
2162 : :
2163 : 0 : ENTER("gsr=%p, next_transaction=%s", gsr, next_transaction ? "TRUE" : "FALSE");
2164 : :
2165 : 0 : goto_blank = gnc_prefs_get_bool(GNC_PREFS_GROUP_GENERAL_REGISTER,
2166 : : GNC_PREF_ENTER_MOVES_TO_END);
2167 : :
2168 : : /* If we are in single or double line view and we hit enter
2169 : : * on the blank split, go to the blank split instead of the
2170 : : * next row. This prevents the cursor from jumping around
2171 : : * when you are entering transactions. */
2172 : 0 : if ( !goto_blank && !next_transaction )
2173 : : {
2174 : 0 : SplitRegisterStyle style = sr->style;
2175 : :
2176 : 0 : if (style == REG_STYLE_LEDGER)
2177 : : {
2178 : : Split *blank_split;
2179 : :
2180 : 0 : blank_split = gnc_split_register_get_blank_split(sr);
2181 : 0 : if (blank_split != NULL)
2182 : : {
2183 : : Split *current_split;
2184 : :
2185 : 0 : current_split = gnc_split_register_get_current_split(sr);
2186 : :
2187 : 0 : if (blank_split == current_split)
2188 : 0 : goto_blank = TRUE;
2189 : : }
2190 : : }
2191 : : }
2192 : : /* First record the transaction. This will perform a refresh. */
2193 : 0 : if (!gnc_split_reg_record (gsr))
2194 : : {
2195 : : /* we may come here from the transfer cell if we decline to create a
2196 : : * new account, make sure the sheet has the focus if the record is FALSE
2197 : : * which results in no cursor movement. */
2198 : 0 : gnc_split_reg_focus_on_sheet (gsr);
2199 : :
2200 : : /* if there are no changes, just enter was pressed, proceed to move
2201 : : * other wise lets not move. */
2202 : 0 : if (gnc_table_current_cursor_changed (sr->table, FALSE))
2203 : : {
2204 : 0 : LEAVE(" ");
2205 : 0 : return;
2206 : : }
2207 : : }
2208 : :
2209 : 0 : if (!goto_blank && next_transaction)
2210 : 0 : gnc_split_register_expand_current_trans (sr, FALSE);
2211 : :
2212 : : /* Now move. */
2213 : 0 : if (goto_blank)
2214 : 0 : gnc_split_reg_jump_to_blank( gsr );
2215 : 0 : else if (next_transaction)
2216 : 0 : gnc_split_reg_goto_next_trans_row( gsr );
2217 : : else
2218 : 0 : gnucash_register_goto_next_virt_row( gsr->reg );
2219 : 0 : LEAVE(" ");
2220 : : }
2221 : :
2222 : : void
2223 : 0 : gsr_default_enter_handler( GNCSplitReg *gsr, gpointer data )
2224 : : {
2225 : 0 : gnc_split_reg_enter( gsr, FALSE );
2226 : 0 : }
2227 : :
2228 : : void
2229 : 0 : gnc_split_reg_record_cb (GnucashRegister *reg, gpointer data)
2230 : : {
2231 : 0 : gsr_emit_simple_signal( (GNCSplitReg*)data, "enter_ent" );
2232 : 0 : }
2233 : :
2234 : : void
2235 : 0 : gnc_split_reg_size_allocate (GtkWidget *widget,
2236 : : GtkAllocation *allocation,
2237 : : gpointer user_data)
2238 : : {
2239 : 0 : GNCSplitReg *gsr = user_data;
2240 : 0 : gsr->width = allocation->width;
2241 : 0 : gtk_window_set_default_size( GTK_WINDOW(gsr->window), gsr->width, 0 );
2242 : 0 : }
2243 : :
2244 : : static
2245 : : GtkWidget*
2246 : 0 : add_summary_label (GtkWidget *summarybar, gboolean pack_start, const char *label_str, GtkWidget *extra)
2247 : : {
2248 : : GtkWidget *hbox;
2249 : : GtkWidget *text_label, *secondary_label;
2250 : :
2251 : 0 : hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
2252 : 0 : gtk_box_set_homogeneous (GTK_BOX (hbox), FALSE);
2253 : 0 : if (pack_start)
2254 : 0 : gtk_box_pack_start( GTK_BOX(summarybar), hbox, FALSE, FALSE, 5 );
2255 : : else
2256 : 0 : gtk_box_pack_end( GTK_BOX(summarybar), hbox, FALSE, FALSE, 5 );
2257 : :
2258 : 0 : text_label = gtk_label_new (label_str);
2259 : 0 : gnc_label_set_alignment (text_label, 1.0, 0.5 );
2260 : 0 : gtk_label_set_ellipsize (GTK_LABEL(text_label), PANGO_ELLIPSIZE_END);
2261 : 0 : gtk_box_pack_start (GTK_BOX(hbox), text_label, FALSE, FALSE, 0);
2262 : :
2263 : 0 : secondary_label = gtk_label_new ( "" );
2264 : 0 : g_object_set_data (G_OBJECT(secondary_label), "text_label", text_label);
2265 : 0 : g_object_set_data (G_OBJECT(secondary_label), "text_box", hbox);
2266 : 0 : gnc_label_set_alignment (secondary_label, 1.0, 0.5 );
2267 : 0 : gtk_box_pack_start (GTK_BOX(hbox), secondary_label, FALSE, FALSE, 0);
2268 : :
2269 : 0 : if (extra != NULL)
2270 : 0 : gtk_box_pack_start( GTK_BOX(hbox), extra, FALSE, FALSE, 0 );
2271 : :
2272 : 0 : return secondary_label;
2273 : : }
2274 : :
2275 : : static void
2276 : 0 : gsr_summarybar_set_arrow_draw (GNCSplitReg *gsr)
2277 : : {
2278 : 0 : if (gsr->sort_arrow_handler_id > 0)
2279 : 0 : g_signal_handler_disconnect (G_OBJECT(gsr->sort_arrow), gsr->sort_arrow_handler_id);
2280 : :
2281 : 0 : gsr->sort_arrow_handler_id = g_signal_connect (G_OBJECT (gsr->sort_arrow), "draw",
2282 : : G_CALLBACK (gnc_draw_arrow_cb), GINT_TO_POINTER(gsr->sort_rev));
2283 : :
2284 : 0 : gtk_widget_queue_draw (gsr->sort_arrow);
2285 : 0 : }
2286 : :
2287 : : GtkWidget *
2288 : 0 : gsr_create_summary_bar( GNCSplitReg *gsr )
2289 : : {
2290 : 0 : GtkWidget *summarybar = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
2291 : 0 : gtk_box_set_homogeneous (GTK_BOX (summarybar), FALSE);
2292 : 0 : gtk_widget_set_name (summarybar, "gnc-id-summarybar");
2293 : :
2294 : 0 : gsr->cleared_label = NULL;
2295 : 0 : gsr->balance_label = NULL;
2296 : 0 : gsr->reconciled_label = NULL;
2297 : 0 : gsr->future_label = NULL;
2298 : 0 : gsr->projectedminimum_label = NULL;
2299 : 0 : gsr->sort_label = NULL;
2300 : 0 : gsr->sort_arrow = NULL;
2301 : 0 : gsr->filter_label = NULL;
2302 : 0 : gsr->shares_label = NULL;
2303 : 0 : gsr->value_label = NULL;
2304 : :
2305 : 0 : if (gnc_ledger_display_type(gsr->ledger) == LD_SINGLE)
2306 : : {
2307 : 0 : if (!xaccAccountIsPriced(gnc_ledger_display_leader(gsr->ledger)))
2308 : : {
2309 : 0 : gsr->balance_label = add_summary_label (summarybar, TRUE, _("Present:"), NULL);
2310 : 0 : gsr->future_label = add_summary_label (summarybar, TRUE, _("Future:"), NULL);
2311 : 0 : gsr->cleared_label = add_summary_label (summarybar, TRUE, _("Cleared:"), NULL);
2312 : 0 : gsr->reconciled_label = add_summary_label (summarybar, TRUE, _("Reconciled:"), NULL);
2313 : 0 : gsr->projectedminimum_label = add_summary_label (summarybar, TRUE, _("Projected Minimum:"), NULL);
2314 : : }
2315 : : else
2316 : : {
2317 : 0 : gsr->shares_label = add_summary_label (summarybar, TRUE, _("Shares:"), NULL);
2318 : 0 : gsr->value_label = add_summary_label (summarybar, TRUE, _("Current Value:"), NULL);
2319 : : }
2320 : : }
2321 : :
2322 : 0 : gsr->filter_label = add_summary_label (summarybar, FALSE, "", NULL);
2323 : 0 : gsr->sort_arrow = gtk_image_new_from_icon_name ("image-missing", GTK_ICON_SIZE_SMALL_TOOLBAR);
2324 : 0 : gsr->sort_label = add_summary_label (summarybar, FALSE, _("Sort By:"), gsr->sort_arrow);
2325 : :
2326 : 0 : gnc_widget_style_context_add_class (GTK_WIDGET(gsr->filter_label), "gnc-class-highlight");
2327 : 0 : gnc_widget_style_context_add_class (GTK_WIDGET(gsr->sort_arrow), "gnc-class-highlight");
2328 : :
2329 : 0 : gsr->summarybar = summarybar;
2330 : :
2331 : : /* Force the first update */
2332 : 0 : gsr_redraw_all_cb(NULL, gsr);
2333 : 0 : return gsr->summarybar;
2334 : : }
2335 : :
2336 : : /**
2337 : : * Opens up a register window for a group of Accounts.
2338 : : * @param gsr the register window instance
2339 : : * @return A GNCPlaceholderType indicating presence and type of placeholder
2340 : : * accounts
2341 : : **/
2342 : : static
2343 : : GNCPlaceholderType
2344 : 0 : gnc_split_reg_get_placeholder( GNCSplitReg *gsr )
2345 : : {
2346 : : Account *leader;
2347 : : SplitRegister *reg;
2348 : : gboolean single_account;
2349 : :
2350 : 0 : if (gsr == NULL)
2351 : 0 : return PLACEHOLDER_NONE;
2352 : :
2353 : 0 : reg = gnc_ledger_display_get_split_register( gsr->ledger );
2354 : :
2355 : 0 : switch (reg->type)
2356 : : {
2357 : 0 : case GENERAL_JOURNAL:
2358 : : case INCOME_LEDGER:
2359 : : case PORTFOLIO_LEDGER:
2360 : : case SEARCH_LEDGER:
2361 : 0 : single_account = FALSE;
2362 : 0 : break;
2363 : 0 : default:
2364 : 0 : single_account = TRUE;
2365 : 0 : break;
2366 : : }
2367 : :
2368 : 0 : leader = gnc_ledger_display_leader( gsr->ledger );
2369 : :
2370 : 0 : if (leader == NULL)
2371 : 0 : return PLACEHOLDER_NONE;
2372 : 0 : if (single_account)
2373 : : {
2374 : 0 : if (xaccAccountGetPlaceholder( leader ))
2375 : 0 : return PLACEHOLDER_THIS;
2376 : 0 : return PLACEHOLDER_NONE;
2377 : : }
2378 : 0 : return xaccAccountGetDescendantPlaceholder( leader );
2379 : : }
2380 : :
2381 : : /**
2382 : : * @see gtk_callback_bug_workaround
2383 : : **/
2384 : : typedef struct dialog_args
2385 : : {
2386 : : GNCSplitReg *gsr;
2387 : : gchar *string;
2388 : : } dialog_args;
2389 : :
2390 : : /**
2391 : : * Gtk has occasional problems with performing function as part of a
2392 : : * callback. This routine gets called via a timer callback to get it out of
2393 : : * the data path with the problem.
2394 : : **/
2395 : : static
2396 : : gboolean
2397 : 0 : gtk_callback_bug_workaround (gpointer argp)
2398 : : {
2399 : 0 : dialog_args *args = argp;
2400 : 0 : const gchar *read_only_this = _("This account register is read-only.");
2401 : 0 : const gchar *read_only_acc = _("The '%s' account register is read-only.");
2402 : 0 : gchar *read_only = NULL;
2403 : : GtkWidget *dialog;
2404 : 0 : GNCLedgerDisplayType ledger_type = gnc_ledger_display_type (args->gsr->ledger);
2405 : 0 : Account *acc = gnc_ledger_display_leader (args->gsr->ledger);
2406 : 0 : const gchar *acc_name = NULL;
2407 : :
2408 : 0 : if (acc)
2409 : : {
2410 : 0 : acc_name = xaccAccountGetName (acc);
2411 : :
2412 : 0 : if (ledger_type == LD_SINGLE)
2413 : 0 : read_only = g_strdup_printf (read_only_acc, acc_name);
2414 : : else
2415 : : {
2416 : 0 : gchar *tmp = g_strconcat (acc_name, "+", NULL);
2417 : 0 : read_only = g_strdup_printf (read_only_acc, tmp);
2418 : 0 : g_free (tmp);
2419 : : }
2420 : : }
2421 : : else
2422 : 0 : read_only = g_strdup (read_only_this);
2423 : :
2424 : 0 : dialog = gtk_message_dialog_new(GTK_WINDOW(args->gsr->window),
2425 : : GTK_DIALOG_DESTROY_WITH_PARENT,
2426 : : GTK_MESSAGE_WARNING,
2427 : : GTK_BUTTONS_CLOSE,
2428 : : "%s", read_only);
2429 : 0 : gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
2430 : : "%s", args->string);
2431 : 0 : gnc_dialog_run(GTK_DIALOG(dialog), GNC_PREF_WARN_REG_IS_READ_ONLY);
2432 : 0 : gtk_widget_destroy(dialog);
2433 : 0 : g_free(read_only);
2434 : 0 : g_free(args);
2435 : 0 : return FALSE;
2436 : : }
2437 : :
2438 : : /**
2439 : : * Determines whether this register window should be read-only.
2440 : : **/
2441 : : static
2442 : : void
2443 : 0 : gnc_split_reg_determine_read_only( GNCSplitReg *gsr, gboolean show_dialog )
2444 : : {
2445 : : SplitRegister *reg;
2446 : :
2447 : 0 : if (qof_book_is_readonly(gnc_get_current_book()))
2448 : : {
2449 : : /* Is the book read-only? Then for sure also make this register
2450 : : read-only. */
2451 : 0 : gsr->read_only = TRUE;
2452 : : }
2453 : :
2454 : 0 : if ( !gsr->read_only )
2455 : : {
2456 : 0 : char *string = NULL;
2457 : 0 : reg = gnc_ledger_display_get_split_register( gsr->ledger );
2458 : 0 : if(reg->mismatched_commodities)
2459 : : {
2460 : 0 : string = _("The transactions of this account may not be edited "
2461 : : "because its subaccounts have mismatched commodities "
2462 : : "or currencies.\n"
2463 : : "You need to open each account individually to edit "
2464 : : "transactions.");
2465 : : }
2466 : : else
2467 : : {
2468 : 0 : switch (gnc_split_reg_get_placeholder(gsr))
2469 : : {
2470 : 0 : case PLACEHOLDER_NONE:
2471 : : /* stay as false. */
2472 : 0 : return;
2473 : :
2474 : 0 : case PLACEHOLDER_THIS:
2475 : 0 : string = _("The transactions of this account may not be edited.\n"
2476 : : "If you want to edit transactions in this register, "
2477 : : "please open the account options and turn off the "
2478 : : "placeholder checkbox.");
2479 : 0 : break;
2480 : :
2481 : 0 : default:
2482 : 0 : string = _("The transactions in one of the selected "
2483 : : "sub-accounts may not be edited.\n"
2484 : : "If you want to edit transactions in this register, please open "
2485 : : "the sub-account options and turn off the placeholder checkbox.\n"
2486 : : "You may also open an individual account instead "
2487 : : "of a set of accounts.");
2488 : 0 : break;
2489 : : }
2490 : : }
2491 : 0 : gsr->read_only = TRUE;
2492 : 0 : if (show_dialog)
2493 : : {
2494 : : /* Put up a warning dialog */
2495 : 0 : dialog_args *args = g_malloc(sizeof(dialog_args));
2496 : 0 : args->string = string;
2497 : 0 : args->gsr = gsr;
2498 : :
2499 : 0 : g_timeout_add (250, gtk_callback_bug_workaround, args); /* 0.25 seconds */
2500 : : }
2501 : : }
2502 : :
2503 : : /* Make the contents immutable */
2504 : 0 : reg = gnc_ledger_display_get_split_register( gsr->ledger );
2505 : 0 : gnc_split_register_set_read_only( reg, TRUE );
2506 : :
2507 : : }
2508 : :
2509 : : static
2510 : : GtkWidget *
2511 : 0 : gnc_split_reg_get_parent( GNCLedgerDisplay *ledger )
2512 : : {
2513 : : GNCSplitReg *gsr =
2514 : 0 : GNC_SPLIT_REG(gnc_ledger_display_get_user_data( ledger ));
2515 : :
2516 : 0 : if (gsr == NULL)
2517 : 0 : return NULL;
2518 : :
2519 : 0 : return gsr->window;
2520 : : }
2521 : :
2522 : : static
2523 : : void
2524 : 0 : gsr_emit_help_changed( GnucashRegister *reg, gpointer user_data )
2525 : : {
2526 : 0 : gsr_emit_simple_signal( (GNCSplitReg*)user_data, "help-changed" );
2527 : 0 : }
2528 : :
2529 : : static
2530 : : void
2531 : 0 : gsr_emit_show_popup_menu( GnucashRegister *reg, gpointer user_data )
2532 : : {
2533 : 0 : gsr_emit_simple_signal( (GNCSplitReg*)user_data, "show-popup-menu" );
2534 : 0 : }
2535 : :
2536 : : static
2537 : : void
2538 : 0 : gsr_emit_simple_signal( GNCSplitReg *gsr, const char *sigName )
2539 : : {
2540 : 0 : g_signal_emit_by_name( gsr, sigName, NULL );
2541 : 0 : }
2542 : :
2543 : : GnucashRegister*
2544 : 0 : gnc_split_reg_get_register( GNCSplitReg *gsr )
2545 : : {
2546 : 0 : if ( !gsr )
2547 : 0 : return NULL;
2548 : :
2549 : 0 : return gsr->reg;
2550 : : }
2551 : :
2552 : : SortType
2553 : 0 : gnc_split_reg_get_sort_type( GNCSplitReg *gsr )
2554 : : {
2555 : 0 : g_assert( gsr );
2556 : 0 : return gsr->sort_type;
2557 : : }
2558 : :
2559 : : void
2560 : 0 : gnc_split_reg_set_sort_type( GNCSplitReg *gsr, SortType t )
2561 : : {
2562 : 0 : gnc_split_reg_sort( gsr, t );
2563 : 0 : }
2564 : :
2565 : : void
2566 : 0 : gnc_split_reg_set_sort_type_force( GNCSplitReg *gsr, SortType t, gboolean force )
2567 : : {
2568 : 0 : gnc_split_reg_sort_force( gsr, t, force );
2569 : 0 : }
2570 : :
2571 : :
2572 : : GtkWidget*
2573 : 0 : gnc_split_reg_get_summarybar( GNCSplitReg *gsr )
2574 : : {
2575 : 0 : if ( !gsr ) return NULL;
2576 : 0 : return gsr->summarybar;
2577 : : }
2578 : :
2579 : : gboolean
2580 : 0 : gnc_split_reg_get_read_only( GNCSplitReg *gsr )
2581 : : {
2582 : : SplitRegister *reg;
2583 : :
2584 : 0 : g_assert( gsr );
2585 : :
2586 : : // reset read_only flag
2587 : 0 : gsr->read_only = FALSE;
2588 : 0 : gnc_split_reg_determine_read_only (gsr, FALSE);
2589 : :
2590 : 0 : reg = gnc_ledger_display_get_split_register( gsr->ledger );
2591 : 0 : gnc_split_register_set_read_only( reg, gsr->read_only );
2592 : 0 : return gsr->read_only;
2593 : : }
2594 : :
2595 : : void
2596 : 0 : gnc_split_reg_set_moved_cb( GNCSplitReg *gsr, GFunc cb, gpointer cb_data )
2597 : : {
2598 : 0 : gnucash_register_set_moved_cb (gsr->reg, cb, cb_data);
2599 : 0 : }
|