GnuCash c935c2f+
Loading...
Searching...
No Matches
gnc-split-reg.c
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;
66static QofLogModule log_module = GNC_MOD_GUI;
67
68/***** PROTOTYPES ***************************************************/
69void gnc_split_reg_raise( GNCSplitReg *gsr );
70
71static GtkWidget* add_summary_label( GtkWidget *summarybar, gboolean pack_start,
72 const char *label_str, GtkWidget *extra );
73
74static void gsr_summarybar_set_arrow_draw (GNCSplitReg *gsr);
75
76static void gnc_split_reg_determine_read_only( GNCSplitReg *gsr, gboolean show_dialog );
77static gboolean is_trans_readonly_and_warn (GtkWindow *parent, Transaction *trans);
78
79static GNCPlaceholderType gnc_split_reg_get_placeholder( GNCSplitReg *gsr );
80static GtkWidget *gnc_split_reg_get_parent( GNCLedgerDisplay *ledger );
81
82static void gsr_create_table( GNCSplitReg *gsr );
83static void gsr_setup_table( GNCSplitReg *gsr );
84static void gsr_setup_status_widgets( GNCSplitReg *gsr );
85
86static 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
94static void gsr_redraw_all_cb (GnucashRegister *g_reg, gpointer data);
95
96static void gnc_split_reg_ld_destroy( GNCLedgerDisplay *ledger );
97
98static Transaction* create_balancing_transaction(QofBook *book, Account *account,
99 time64 statement_date, gnc_numeric balancing_amount);
100
101void gsr_default_enter_handler ( GNCSplitReg *w, gpointer ud );
102void gsr_default_cancel_handler ( GNCSplitReg *w, gpointer ud );
103void gsr_default_delete_handler ( GNCSplitReg *w, gpointer ud );
104void gsr_default_reinit_handler ( GNCSplitReg *w, gpointer ud );
105void gsr_default_dup_handler ( GNCSplitReg *w, gpointer ud );
106void gsr_default_schedule_handler ( GNCSplitReg *w, gpointer ud );
107void gsr_default_expand_handler ( GNCSplitReg *w, gpointer ud );
108void gsr_default_blank_handler ( GNCSplitReg *w, gpointer ud );
109void gsr_default_jump_handler ( GNCSplitReg *w, gpointer ud );
110void gsr_default_cut_handler ( GNCSplitReg *w, gpointer ud );
111void gsr_default_cut_txn_handler ( GNCSplitReg *w, gpointer ud );
112void gsr_default_copy_handler ( GNCSplitReg *w, gpointer ud );
113void gsr_default_copy_txn_handler ( GNCSplitReg *w, gpointer ud );
114void gsr_default_paste_handler ( GNCSplitReg *w, gpointer ud );
115void gsr_default_paste_txn_handler( GNCSplitReg *w, gpointer ud );
116void gsr_default_void_txn_handler ( GNCSplitReg *w, gpointer ud );
117void gsr_default_unvoid_txn_handler ( GNCSplitReg *w, gpointer ud );
118void gsr_default_reverse_txn_handler ( GNCSplitReg *w, gpointer ud );
119void gsr_default_doclink_handler ( GNCSplitReg *w );
120void gsr_default_doclink_open_handler ( GNCSplitReg *w );
121void gsr_default_doclink_remove_handler ( GNCSplitReg *w );
122static void gsr_default_doclink_from_sheet_handler ( GNCSplitReg *w );
123
124static void gsr_emit_simple_signal ( GNCSplitReg *gsr, const char *sigName );
125static void gsr_emit_help_changed ( GnucashRegister *reg, gpointer user_data );
126static void gsr_emit_show_popup_menu ( GnucashRegister *reg, gpointer user_data );
127
128void gnc_split_reg_cut_cb(GtkWidget *w, gpointer data);
129void gnc_split_reg_copy_cb(GtkWidget *w, gpointer data);
130void gnc_split_reg_paste_cb(GtkWidget *w, gpointer data);
131
132void gnc_split_reg_cut_trans_cb(GtkWidget *w, gpointer data);
133void gnc_split_reg_copy_trans_cb(GtkWidget *w, gpointer data);
134void gnc_split_reg_paste_trans_cb(GtkWidget *w, gpointer data);
135void gnc_split_reg_void_trans_cb(GtkWidget *w, gpointer data);
136void gnc_split_reg_unvoid_trans_cb(GtkWidget *w, gpointer data);
137void gnc_split_reg_reverse_trans_cb(GtkWidget *w, gpointer data);
138
139void gnc_split_reg_record_cb (GnucashRegister *reg, gpointer data);
140void gnc_split_reg_reinitialize_trans_cb(GtkWidget *w, gpointer data);
141void gnc_split_reg_delete_trans_cb(GtkWidget *w, gpointer data);
142void gnc_split_reg_duplicate_trans_cb(GtkWidget *w, gpointer data);
143void gnc_split_reg_recur_cb(GtkWidget *w, gpointer data);
144void gnc_split_reg_record_trans_cb(GtkWidget *w, gpointer data);
145void gnc_split_reg_cancel_trans_cb(GtkWidget *w, gpointer data);
146
147void gnc_split_reg_expand_trans_menu_cb(GtkWidget *widget, gpointer data);
148void gnc_split_reg_expand_trans_toolbar_cb(GtkWidget *widget, gpointer data);
149void gnc_split_reg_new_trans_cb(GtkWidget *widget, gpointer data);
150void gnc_split_reg_jump_cb(GtkWidget *widget, gpointer data);
151
152void gnc_split_reg_style_ledger_cb (GtkWidget *w, gpointer data);
153void gnc_split_reg_style_auto_ledger_cb (GtkWidget *w, gpointer data);
154void gnc_split_reg_style_journal_cb (GtkWidget *w, gpointer data);
155void gnc_split_reg_double_line_cb (GtkWidget *w, gpointer data);
156
157void gnc_split_reg_sort_standard_cb (GtkWidget *w, gpointer data);
158void gnc_split_reg_sort_date_cb (GtkWidget *w, gpointer data);
159void gnc_split_reg_sort_date_entered_cb (GtkWidget *w, gpointer data);
160void gnc_split_reg_sort_date_reconciled_cb (GtkWidget *w, gpointer data);
161void gnc_split_reg_sort_num_cb (GtkWidget *w, gpointer data);
162void gnc_split_reg_sort_amount_cb (GtkWidget *w, gpointer data);
163void gnc_split_reg_sort_memo_cb (GtkWidget *w, gpointer data);
164void gnc_split_reg_sort_desc_cb (GtkWidget *w, gpointer data);
165void gnc_split_reg_sort_action_cb (GtkWidget *w, gpointer data);
166void gnc_split_reg_sort_notes_cb (GtkWidget *w, gpointer data);
167
168
169void gnc_split_reg_size_allocate( GtkWidget *widget,
170 GtkAllocation *allocation,
171 gpointer user_data );
172
173
174static void gnc_split_reg_init2( GNCSplitReg *gsr );
175void gnc_split_reg_dispose(GObject *obj);
176
177FROM_STRING_FUNC(SortType, ENUM_LIST_SORTTYPE)
178AS_STRING_FUNC(SortType, ENUM_LIST_SORTTYPE)
179
180G_DEFINE_TYPE (GNCSplitReg, gnc_split_reg, GTK_TYPE_BOX)
181
182/* SIGNALS */
183enum 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
209static guint gnc_split_reg_signals[LAST_SIGNAL] = { 0 };
210
211static void
212gnc_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 object_class = (GObjectClass*) klass;
247
248 for ( i = 0; signals[i].s != LAST_SIGNAL; i++ )
249 {
250 gnc_split_reg_signals[ signals[i].s ] =
251 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 klass->enter_ent_cb = gsr_default_enter_handler;
262 klass->cancel_ent_cb = gsr_default_cancel_handler;
263 klass->delete_ent_cb = gsr_default_delete_handler;
264 klass->reinit_ent_cb = gsr_default_reinit_handler;
265 klass->dup_ent_cb = gsr_default_dup_handler;
266 klass->schedule_ent_cb = gsr_default_schedule_handler;
267 klass->expand_ent_cb = gsr_default_expand_handler;
268 klass->blank_cb = gsr_default_blank_handler;
269 klass->jump_cb = gsr_default_jump_handler;
270 klass->cut_cb = gsr_default_cut_handler;
271 klass->cut_txn_cb = gsr_default_cut_txn_handler;
272 klass->copy_cb = gsr_default_copy_handler;
273 klass->copy_txn_cb = gsr_default_copy_txn_handler;
274 klass->paste_cb = gsr_default_paste_handler;
275 klass->paste_txn_cb = gsr_default_paste_txn_handler;
276 klass->void_txn_cb = gsr_default_void_txn_handler;
277 klass->unvoid_txn_cb = gsr_default_unvoid_txn_handler;
278 klass->reverse_txn_cb = gsr_default_reverse_txn_handler;
279
280 klass->help_changed_cb = NULL;
281 klass->show_popup_menu_cb = NULL;
282
283 object_class->dispose = gnc_split_reg_dispose;
284}
285
286GtkWidget*
287gnc_split_reg_new( GNCLedgerDisplay *ld,
288 GtkWindow *parent,
289 gint numberOfLines,
290 gboolean read_only )
291{
292 GNCSplitReg *gsrToRet;
293
294 ENTER("ld=%p, parent=%p, numberOfLines=%d, read_only=%s",
295 ld, parent, numberOfLines, read_only ? "TRUE" : "FALSE");
296
297 gsrToRet = g_object_new( gnc_split_reg_get_type(), NULL );
298
299 gsrToRet->numRows = numberOfLines;
300 gsrToRet->read_only = read_only;
301
302 gsrToRet->ledger = ld;
303 gsrToRet->window = GTK_WIDGET(parent);
304
305 gnc_split_reg_init2( gsrToRet );
306
307 LEAVE("%p", gsrToRet);
308 return GTK_WIDGET( gsrToRet );
309}
310
311static void
312gnc_split_reg_init( GNCSplitReg *gsr )
313{
314 gtk_orientable_set_orientation (GTK_ORIENTABLE(gsr), GTK_ORIENTATION_VERTICAL);
315
316 gsr->sort_type = BY_STANDARD;
317 gsr->sort_rev = FALSE;
318 gsr->sort_arrow_handler_id = 0;
319 gsr->filter_text = NULL;
320 gsr->width = -1;
321 gsr->height = -1;
322 gsr->numRows = 10;
323 gsr->read_only = FALSE;
324}
325
326static void
327gnc_split_reg_pref_acc_labels (gpointer prefs, gchar *pref, gpointer user_data)
328{
329 GNCSplitReg *gsr = user_data;
330 gnucash_register_refresh_from_prefs (gsr->reg);
331}
332
333static void
334gnc_split_reg_init2( GNCSplitReg *gsr )
335{
336 if ( !gsr ) return;
337
338 gnc_split_reg_determine_read_only( gsr, TRUE );
339
340 gsr_setup_status_widgets( gsr );
341 /* ordering is important here... setup_status before create_table */
342 gsr_create_table( gsr );
343 gsr_setup_table( gsr );
344
345 gnc_prefs_register_cb (GNC_PREFS_GROUP_GENERAL,
346 GNC_PREF_ACCOUNTING_LABELS,
347 gnc_split_reg_pref_acc_labels,
348 gsr);
349}
350
351static
352void
353gsr_setup_table( GNCSplitReg *gsr )
354{
355 SplitRegister *sr;
356
357 ENTER("gsr=%p", gsr);
358
359 sr = gnc_ledger_display_get_split_register( gsr->ledger );
361 /* events should be sufficient to redraw this */
362 /* gnc_ledger_display_refresh( gsr->ledger ); */
363
364 LEAVE(" ");
365}
366
367static void
368gsr_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 ledger_type = gnc_ledger_display_type (gsr->ledger);
374
375 // General ledger should already be using .gcm file
376 if ((ledger_type == LD_SINGLE) || (ledger_type == LD_SUBACCOUNT))
377 {
378 Account *leader = gnc_ledger_display_leader (gsr->ledger);
379 const char* kvp_filter = NULL;
380 const char* kvp_sort_order = NULL;
381 gboolean kvp_sort_reversed = FALSE;
382
383 kvp_filter = xaccAccountGetFilter (leader);
384 if (kvp_filter)
385 {
386 gchar *temp_filter_text = g_strdup (kvp_filter);
387 // make it conform to .gcm file list
388 g_strdelimit (temp_filter_text, ",", ';');
389 g_key_file_set_string (state_file, state_section, KEY_PAGE_FILTER,
390 temp_filter_text);
391 g_free (temp_filter_text);
392 xaccAccountSetFilter (leader, NULL);
393 }
394
395 kvp_sort_order = xaccAccountGetSortOrder (leader);
396 if (kvp_sort_order)
397 {
398 g_key_file_set_string (state_file, state_section,
399 KEY_PAGE_SORT, kvp_sort_order);
400 xaccAccountSetSortOrder (leader, NULL);
401 }
402
403 kvp_sort_reversed = xaccAccountGetSortReversed (leader);
404 if (kvp_sort_reversed)
405 {
406 g_key_file_set_boolean (state_file, state_section,
407 KEY_PAGE_SORT_REV, kvp_sort_reversed);
408 xaccAccountSetSortReversed (leader, FALSE);
409 }
410 }
411}
412
413gchar *
414gsr_get_register_state_section (GNCSplitReg *gsr)
415{
416 GNCLedgerDisplayType ledger_type = gnc_ledger_display_type (gsr->ledger);
417 Account *account = gnc_ledger_display_leader (gsr->ledger);
418 const GncGUID *guid = xaccAccountGetGUID (account);
419 gchar guidstr[GUID_ENCODING_LENGTH+1];
420 gchar *register_state_section;
421
422 guid_to_string_buff (guid, guidstr);
423
424 if (ledger_type == LD_SUBACCOUNT)
425 register_state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", guidstr, "+", NULL);
426 else
427 register_state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", guidstr, NULL);
428
429 return register_state_section;
430}
431
432static
433void
434gsr_create_table( GNCSplitReg *gsr )
435{
436 GtkWidget *register_widget = NULL;
437 SplitRegister *sr = NULL;
438 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 register_state_section = gsr_get_register_state_section (gsr);
443
444 ENTER("gsr=%p", gsr);
445
446 sr = gnc_ledger_display_get_split_register (gsr->ledger);
447
448 gnc_ledger_display_set_user_data( gsr->ledger, (gpointer)gsr );
450 gnc_split_reg_ld_destroy,
451 gnc_split_reg_get_parent );
452
453 /* FIXME: We'd really rather pass this down... */
454 sr = gnc_ledger_display_get_split_register( gsr->ledger );
455 register_widget = gnucash_register_new( sr->table, register_state_section );
456 gsr->reg = GNUCASH_REGISTER( register_widget );
457
458 gtk_box_pack_start (GTK_BOX (gsr), GTK_WIDGET(gsr->reg), TRUE, TRUE, 0);
459 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 gnucash_register_set_open_doclink_cb (gsr->reg,
463 (GFunc)gsr_default_doclink_from_sheet_handler, gsr);
464
465 gtk_widget_show ( GTK_WIDGET(gsr->reg) );
466 g_signal_connect (gsr->reg, "activate_cursor",
467 G_CALLBACK(gnc_split_reg_record_cb), gsr);
468 g_signal_connect (gsr->reg, "redraw_all",
469 G_CALLBACK(gsr_redraw_all_cb), gsr);
470 g_signal_connect (gsr->reg, "redraw_help",
471 G_CALLBACK(gsr_emit_help_changed), gsr);
472 g_signal_connect (gsr->reg, "show_popup_menu",
473 G_CALLBACK(gsr_emit_show_popup_menu), gsr);
474
475 gsr_move_sort_and_filter_to_state_file (gsr, state_file, register_state_section);
476
477 g_free (register_state_section);
478 LEAVE(" ");
479}
480
481static
482void
483gsr_setup_status_widgets( GNCSplitReg *gsr )
484{
485 SplitRegister *sr;
486 gboolean use_double_line;
487
488 sr = gnc_ledger_display_get_split_register( gsr->ledger );
489 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 gnc_split_register_config( sr, sr->type, sr->style, use_double_line );
493}
494
495void
496gnc_split_reg_dispose(GObject *obj)
497{
498 GNCSplitReg *gsr = GNC_SPLIT_REG(obj);
499
500 if (gsr->filter_text)
501 g_free (gsr->filter_text);
502 gsr->filter_text = NULL;
503
504 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 if (gsr->reg)
510 {
511 g_signal_handlers_disconnect_by_data (gsr->reg, gsr);
512 gtk_widget_destroy (GTK_WIDGET (gsr->reg));
513 }
514 gsr->reg = NULL;
515}
516
520void
521gnc_split_reg_raise( GNCSplitReg *gsr )
522{
523 if (gsr == NULL)
524 return;
525
526 if (gsr->window == NULL)
527 return;
528
529 gtk_window_present( GTK_WINDOW(gsr->window) );
530}
531
532
537static
538void
539gsr_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 const gchar *label_str = NULL;
550 GtkWidget *text_label, *hbox;
551 gchar *bidi_string;
552
553 if ( label == NULL )
554 return;
555
556 hbox = g_object_get_data (G_OBJECT(label), "text_box");
557 text_label = g_object_get_data (G_OBJECT(label), "text_label");
558 label_str = gtk_label_get_text (GTK_LABEL(text_label));
559
560 amount = (*getter)( leader );
561
562 if ( reverse )
563 {
564 amount = gnc_numeric_neg( amount );
565 }
566
567 xaccSPrintAmount( string, amount, print_info );
568
569 if ( euroFlag )
570 {
571 strcat( string, " / " );
572 xaccSPrintAmount( string + strlen( string ),
573 gnc_convert_to_euro( cmdty, amount ),
574 gnc_commodity_print_info( gnc_get_euro(), TRUE ) );
575 }
576
577 gnc_set_label_color( label, amount );
578 bidi_string = gnc_wrap_text_with_bidi_ltr_isolate (string);
579 gtk_label_set_text( GTK_LABEL(label), bidi_string );
580 g_free (bidi_string);
581
582 if (label_str)
583 {
584 gchar *tooltip = g_strdup_printf ("%s %s", label_str, string);
585 gtk_widget_set_tooltip_text (GTK_WIDGET(hbox), tooltip);
586 g_free (tooltip);
587 }
588}
589
590static
591void
592gsr_redraw_all_cb (GnucashRegister *g_reg, gpointer data)
593{
594 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 if ( gsr->summarybar == NULL )
603 return;
604
605 leader = gnc_ledger_display_leader( gsr->ledger );
606
607 commodity = xaccAccountGetCommodity( leader );
608
609 /* no EURO conversion, if account is already EURO or no EURO currency */
610 if (commodity != NULL)
611 euro = (gnc_is_euro_currency( commodity ) &&
612 (strncasecmp(gnc_commodity_get_mnemonic(commodity), "EUR", 3)));
613 else
614 euro = FALSE;
615
616 print_info = gnc_account_print_info( leader, TRUE );
617 reverse = gnc_reverse_balance( leader );
618
619 if (gsr->balance_label != NULL) // only test the first as they are a group
620 {
621 gsr_update_summary_label( gsr->balance_label,
622 xaccAccountGetPresentBalance,
623 leader, print_info, commodity, reverse, euro );
624 gsr_update_summary_label( gsr->cleared_label,
626 leader, print_info, commodity, reverse, euro );
627 gsr_update_summary_label( gsr->reconciled_label,
629 leader, print_info, commodity, reverse, euro );
630 gsr_update_summary_label( gsr->future_label,
632 leader, print_info, commodity, reverse, euro );
633 gsr_update_summary_label( gsr->projectedminimum_label,
634 xaccAccountGetProjectedMinimumBalance,
635 leader, print_info, commodity, reverse, euro );
636 }
637
638 // Sort label
639 if (gsr->sort_label != NULL)
640 {
641 gchar *old_tt_text = gtk_widget_get_tooltip_text (GTK_WIDGET(gsr->sort_label));
642 gchar *new_tt_text;
643 gchar *text = NULL;
644
645 switch (gsr->sort_type)
646 {
647 case (0):
648 text = _("None");
649 break;
650 case (1):
651 text = _("Standard Order");
652 break;
653 case (2):
654 text = _("Date");
655 break;
656 case (3):
657 text = _("Date of Entry");
658 break;
659 case (4):
660 text = _("Statement Date");
661 break;
662 case (5):
663 text = _("Number");
664 break;
665 case (6):
666 text = _("Amount");
667 break;
668 case (7):
669 text = _("Memo");
670 break;
671 case (8):
672 text = _("Description");
673 break;
674 case (9):
675 text = _("Action");
676 break;
677 case (10):
678 text = _("Notes");
679 break;
680 }
681
682 if (gsr->sort_rev)
683 gtk_widget_set_tooltip_text (GTK_WIDGET(gsr->sort_label), _("Descending"));
684 else
685 gtk_widget_set_tooltip_text (GTK_WIDGET(gsr->sort_label), _("Ascending"));
686
687 new_tt_text = gtk_widget_get_tooltip_text (GTK_WIDGET(gsr->sort_label));
688
689 // does the arrow need changing
690 if (g_strcmp0 (old_tt_text, new_tt_text) != 0)
691 gsr_summarybar_set_arrow_draw (gsr);
692
693 if (old_tt_text)
694 g_free (old_tt_text);
695
696 if (new_tt_text)
697 g_free (new_tt_text);
698
699 gtk_label_set_text (GTK_LABEL(gsr->sort_label), text);
700 }
701
702 // Filter label
703 if (gsr->filter_label != NULL)
704 {
705 gchar *old_tt_text = gtk_widget_get_tooltip_text (GTK_WIDGET(gsr->filter_label));
706
707 // check for a change in text
708 if (g_strcmp0 (old_tt_text, gsr->filter_text) != 0)
709 {
710 if (gsr->filter_text != NULL)
711 gtk_label_set_text (GTK_LABEL(gsr->filter_label), _("Filtered"));
712 else
713 gtk_label_set_text (GTK_LABEL(gsr->filter_label), "");
714
715 gtk_widget_set_tooltip_text (GTK_WIDGET(gsr->filter_label), gsr->filter_text);
716
717 }
718 g_free (old_tt_text);
719 }
720
721 if (gsr->shares_label == NULL && gsr->value_label == NULL)
722 return;
723 amount = xaccAccountGetBalance( leader );
724 if (reverse)
725 amount = gnc_numeric_neg( amount );
726
727 /* Print the summary share amount */
728 if (gsr->shares_label != NULL)
729 {
730 char string[256];
731 print_info = gnc_account_print_info( leader, TRUE );
732 xaccSPrintAmount( string, amount, print_info );
733 gnc_set_label_color( gsr->shares_label, amount );
734 gtk_label_set_text( GTK_LABEL(gsr->shares_label), string );
735 }
736
737 /* Print the summary share value */
738 if (gsr->value_label != NULL)
739 {
740 char string[256];
741 QofBook *book = gnc_account_get_book (leader);
742 GNCPriceDB *pricedb = gnc_pricedb_get_db (book);
743 gnc_commodity *currency = gnc_default_currency ();
744 gnc_numeric value =
746 commodity, currency);
747 print_info = gnc_commodity_print_info (currency, TRUE);
748 xaccSPrintAmount (string, value, print_info);
749 gnc_set_label_color (gsr->value_label, amount);
750 gtk_label_set_text (GTK_LABEL (gsr->value_label), string);
751
752 }
753}
754
755static void
756gnc_split_reg_ld_destroy( GNCLedgerDisplay *ledger )
757{
758 GNCSplitReg *gsr = gnc_ledger_display_get_user_data( ledger );
759
760 if (gsr)
761 {
762 /* register_state_section is used to store per register state: column widths, sort order,... */
763 gchar *register_state_section = gsr_get_register_state_section (gsr);
764 SplitRegister *reg = gnc_ledger_display_get_split_register (ledger);
765
766 if (reg && reg->table)
767 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 g_free (register_state_section);
774 }
775
777 g_object_unref (gsr);
778}
779
780void
781gsr_default_cut_handler( GNCSplitReg *gsr, gpointer data )
782{
783 gnucash_register_cut_clipboard( gsr->reg );
784}
785
789void
790gnc_split_reg_cut_cb (GtkWidget *w, gpointer data)
791{
792 GNCSplitReg *gsr = data;
793 gsr_emit_simple_signal( gsr, "cut" );
794}
795
796void
797gsr_default_copy_handler( GNCSplitReg *gsr, gpointer data )
798{
799 gnucash_register_copy_clipboard( gsr->reg );
800}
801
805void
806gnc_split_reg_copy_cb (GtkWidget *w, gpointer data)
807{
808 GNCSplitReg *gsr = data;
809 gsr_emit_simple_signal( gsr, "copy" );
810}
811
812void
813gsr_default_paste_handler( GNCSplitReg *gsr, gpointer data )
814{
815 gnucash_register_paste_clipboard( gsr->reg );
816}
817
821void
822gnc_split_reg_paste_cb (GtkWidget *w, gpointer data)
823{
824 GNCSplitReg *gsr = data;
825 gsr_emit_simple_signal( gsr, "paste" );
826}
827
828void
829gsr_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 reg = gnc_ledger_display_get_split_register (gsr->ledger);
840
841 /* get the current split based on cursor position */
843 if (split == NULL)
844 {
846 return;
847 }
848
849 trans = xaccSplitGetParent (split);
851
852 /* test for blank_split reference pointing to split */
853 if (gnc_split_register_is_blank_split (reg, split))
855
856 /* Cutting the blank split just cancels */
857 {
858 Split *blank_split = gnc_split_register_get_blank_split (reg);
859
860 if (split == blank_split)
861 {
863 return;
864 }
865 }
866
867 if (cursor_class == CURSOR_CLASS_NONE)
868 return;
869
870 /* this is probably not required but leave as a double check */
871 if (is_trans_readonly_and_warn (GTK_WINDOW(gsr->window), trans))
872 return;
873
874 /* On a split cursor, just delete the one split. */
875 if (cursor_class == CURSOR_CLASS_SPLIT)
876 {
877 const char *format = _("Cut the split '%s' from the transaction '%s'?");
878 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 const char *anchor_error = _("You cannot cut this split.");
882 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 char *buf = NULL;
890 const char *memo;
891 const char *desc;
892 char recn;
893
894 if (reg->type != GENERAL_JOURNAL) // no anchoring split
895 {
896 if (split == gnc_split_register_get_current_trans_split (reg, NULL))
897 {
898 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 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG(dialog),
905 "%s", anchor_split);
906 gtk_dialog_run (GTK_DIALOG(dialog));
907 gtk_widget_destroy (dialog);
908 return;
909 }
910 }
911 memo = xaccSplitGetMemo (split);
912 memo = (memo && *memo) ? memo : _("(no memo)");
913
914 desc = xaccTransGetDescription (trans);
915 desc = (desc && *desc) ? desc : _("(no description)");
916
917 /* ask for user confirmation before performing permanent damage */
918 buf = g_strdup_printf (format, memo, desc);
919 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 g_free (buf);
926 recn = xaccSplitGetReconcile (split);
927 if (recn == YREC || recn == FREC)
928 {
929 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG(dialog),
930 "%s", recn_warn);
931 warning = GNC_PREF_WARN_REG_SPLIT_CUT_RECD;
932 }
933 else
934 {
935 warning = GNC_PREF_WARN_REG_SPLIT_CUT;
936 }
937
938 gtk_dialog_add_button (GTK_DIALOG(dialog),
939 _("_Cancel"), GTK_RESPONSE_CANCEL);
940 gnc_gtk_dialog_add_button (dialog, _("_Cut Split"),
941 "edit-delete", GTK_RESPONSE_ACCEPT);
942 response = gnc_dialog_run (GTK_DIALOG(dialog), warning);
943 gtk_widget_destroy (dialog);
944 if (response != GTK_RESPONSE_ACCEPT)
945 return;
946
948 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 const char *title = _("Cut the current transaction?");
955 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 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);
967 {
968 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG(dialog),
969 "%s", recn_warn);
970 warning = GNC_PREF_WARN_REG_TRANS_CUT_RECD;
971 }
972 else
973 {
974 warning = GNC_PREF_WARN_REG_TRANS_CUT;
975 }
976 gtk_dialog_add_button (GTK_DIALOG(dialog),
977 _("_Cancel"), GTK_RESPONSE_CANCEL);
978 gnc_gtk_dialog_add_button (dialog, _("_Cut Transaction"),
979 "edit-delete", GTK_RESPONSE_ACCEPT);
980 response = gnc_dialog_run (GTK_DIALOG(dialog), warning);
981 gtk_widget_destroy (dialog);
982 if (response != GTK_RESPONSE_ACCEPT)
983 return;
984
986 return;
987 }
988}
989
993void
994gnc_split_reg_cut_trans_cb (GtkWidget *w, gpointer data)
995{
996 GNCSplitReg *gsr = data;
997 gsr_emit_simple_signal( gsr, "cut_txn" );
998}
999
1000void
1001gsr_default_copy_txn_handler( GNCSplitReg *gsr, gpointer data )
1002{
1005}
1006
1010void
1011gnc_split_reg_copy_trans_cb(GtkWidget *w, gpointer data)
1012{
1013 GNCSplitReg *gsr = data;
1014 gsr_emit_simple_signal( gsr, "copy_txn" );
1015}
1016
1017void
1018gsr_default_paste_txn_handler( GNCSplitReg *gsr, gpointer data )
1019{
1022}
1023
1027void
1028gnc_split_reg_paste_trans_cb (GtkWidget *w, gpointer data)
1029{
1030 GNCSplitReg *gsr = data;
1031 gsr_emit_simple_signal( gsr, "paste_txn" );
1032}
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\********************************************************************/
1041void
1042gsr_default_void_txn_handler (GNCSplitReg *gsr, gpointer data)
1043{
1044 // Override this function.
1045}
1046
1047void
1048gnc_split_reg_void_trans_cb (GtkWidget *w, gpointer data)
1049{
1050 GNCSplitReg *gsr = data;
1051 gsr_emit_simple_signal( gsr, "void_txn" );
1052}
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\********************************************************************/
1061void
1062gsr_default_unvoid_txn_handler (GNCSplitReg *gsr, gpointer data)
1063{
1064 // Override this function.
1065}
1066
1067void
1068gnc_split_reg_unvoid_trans_cb (GtkWidget *w, gpointer data)
1069{
1070 GNCSplitReg *gsr = data;
1071 gsr_emit_simple_signal( gsr, "unvoid_txn" );
1072}
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\********************************************************************/
1081void
1082gsr_default_reverse_txn_handler (GNCSplitReg *gsr, gpointer data)
1083{
1084 SplitRegister *reg;
1085 Transaction *trans, *new_trans;
1086
1087 reg = gnc_ledger_display_get_split_register( gsr->ledger );
1089 if (trans == NULL)
1090 return;
1091
1092 if (xaccTransGetReversedBy(trans))
1093 {
1094 gnc_error_dialog (GTK_WINDOW (gsr->window), "%s",
1095 _("A reversing entry has already been created for this transaction."));
1096 return;
1097 }
1098
1099 new_trans = xaccTransReverse(trans);
1100
1101 /* Clear transaction level info */
1103 xaccTransSetDateEnteredSecs(new_trans, gnc_time (NULL));
1104
1105 /* Now jump to new trans */
1106 gnc_split_reg_jump_to_split(gsr, xaccTransGetSplit(new_trans, 0));
1107}
1108
1109void
1110gnc_split_reg_reverse_trans_cb (GtkWidget *w, gpointer data)
1111{
1112 GNCSplitReg *gsr = data;
1113 gsr_emit_simple_signal( gsr, "reverse_txn" );
1114}
1115
1116
1117static gboolean
1118is_trans_readonly_and_warn (GtkWindow *parent, Transaction *trans)
1119{
1120 GtkWidget *dialog;
1121 const gchar *reason;
1122 const gchar *title = _("Cannot modify or delete this transaction.");
1123 const gchar *message =
1124 _("This transaction is marked read-only with the comment: '%s'");
1125
1126 if (!trans) return FALSE;
1127
1129 {
1130 dialog = gtk_message_dialog_new(parent,
1131 0,
1132 GTK_MESSAGE_ERROR,
1133 GTK_BUTTONS_OK,
1134 "%s", title);
1135 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 gtk_dialog_run(GTK_DIALOG(dialog));
1139 gtk_widget_destroy(dialog);
1140 return TRUE;
1141 }
1142
1143 reason = xaccTransGetReadOnly (trans);
1144 if (reason)
1145 {
1146 dialog = gtk_message_dialog_new(parent,
1147 0,
1148 GTK_MESSAGE_ERROR,
1149 GTK_BUTTONS_OK,
1150 "%s", title);
1151 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
1152 message, reason);
1153 gtk_dialog_run(GTK_DIALOG(dialog));
1154 gtk_widget_destroy(dialog);
1155 return TRUE;
1156 }
1157 return FALSE;
1158}
1159
1160
1161void
1162gsr_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 const char *title = _("Remove the splits from this transaction?");
1173 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 reg = gnc_ledger_display_get_split_register( gsr->ledger );
1178
1180 if (is_trans_readonly_and_warn(GTK_WINDOW(gsr->window), trans))
1181 return;
1182 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 if (xaccTransHasReconciledSplits (trans))
1188 {
1189 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
1190 "%s", recn_warn);
1191 warning = GNC_PREF_WARN_REG_SPLIT_DEL_ALL_RECD;
1192 }
1193 else
1194 {
1195 warning = GNC_PREF_WARN_REG_SPLIT_DEL_ALL;
1196 }
1197
1198 gtk_dialog_add_button(GTK_DIALOG(dialog),
1199 _("_Cancel"), GTK_RESPONSE_CANCEL);
1200 gnc_gtk_dialog_add_button(dialog,
1201 /* Translators: This is the confirmation button in a warning dialog */
1202 _("_Remove Splits"),
1203 "edit-delete", GTK_RESPONSE_ACCEPT);
1204 response = gnc_dialog_run(GTK_DIALOG(dialog), warning);
1205 gtk_widget_destroy (dialog);
1206 if (response != GTK_RESPONSE_ACCEPT)
1207 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 */
1215 if (!gnc_split_register_get_split_virt_loc(reg, split, &vcell_loc))
1216 return;
1217 split = gnc_split_register_get_current_trans_split (reg, &vcell_loc);
1219}
1220
1224void
1225gnc_split_reg_reinitialize_trans_cb(GtkWidget *widget, gpointer data)
1226{
1227 GNCSplitReg *gsr = data;
1228 gsr_emit_simple_signal( gsr, "reinit_ent" );
1229}
1230
1231/* Edit the document link for the current transaction. */
1232void
1233gsr_default_doclink_handler (GNCSplitReg *gsr)
1234{
1235 SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger);
1236 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 if (!split)
1244 {
1246 return;
1247 }
1248
1249 trans = xaccSplitGetParent (split);
1251
1252 if (cursor_class == CURSOR_CLASS_NONE)
1253 return;
1254
1255 if (is_trans_readonly_and_warn (GTK_WINDOW(gsr->window), trans))
1256 return;
1257
1258 // fix an earlier error when storing relative paths before version 3.5
1259 uri = gnc_doclink_convert_trans_link_uri (trans, gsr->read_only);
1260
1261 ret_uri =
1262 gnc_doclink_get_uri_dialog (GTK_WINDOW (gsr->window),
1263 _("Change a Transaction Linked Document"),
1264 uri);
1265
1266 if (ret_uri && g_strcmp0 (uri, ret_uri) != 0)
1267 xaccTransSetDocLink (trans, ret_uri);
1268
1269 g_free (ret_uri);
1270 g_free (uri);
1271}
1272
1273/* Opens the document link for the current transaction. */
1274void
1275gsr_default_doclink_open_handler (GNCSplitReg *gsr)
1276{
1277 CursorClass cursor_class;
1278 SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger);
1279 Transaction *trans;
1280 Split *split = gnc_split_register_get_current_split (reg);
1281 gchar *uri;
1282
1283 /* get the current split based on cursor position */
1284 if (!split)
1285 {
1287 return;
1288 }
1289
1290 trans = xaccSplitGetParent (split);
1292
1293 if (cursor_class == CURSOR_CLASS_NONE)
1294 return;
1295
1296 // fix an earlier error when storing relative paths before version 3.5
1297 uri = gnc_doclink_convert_trans_link_uri (trans, gsr->read_only);
1298
1299 gnc_doclink_open_uri (GTK_WINDOW (gsr->window), uri);
1300 g_free (uri);
1301}
1302
1303/* Removes the document link for the current transaction. */
1304void
1305gsr_default_doclink_remove_handler (GNCSplitReg *gsr)
1306{
1307 CursorClass cursor_class;
1308 SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger);
1309 Transaction *trans;
1310 Split *split = gnc_split_register_get_current_split (reg);
1311
1312 /* get the current split based on cursor position */
1313 if (!split)
1314 {
1316 return;
1317 }
1318
1319 trans = xaccSplitGetParent (split);
1321
1322 if (cursor_class == CURSOR_CLASS_NONE)
1323 return;
1324
1325 if (is_trans_readonly_and_warn (GTK_WINDOW(gsr->window), trans))
1326 return;
1327
1328 xaccTransSetDocLink (trans, "");
1329}
1330
1331static void
1332gsr_default_doclink_from_sheet_handler (GNCSplitReg *gsr)
1333{
1334 SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger);
1335 Transaction *trans;
1336 Split *split;
1337 gchar *uri = NULL;
1338
1339 /* get the current split based on cursor position */
1341 if (!split)
1342 return;
1343
1344 trans = xaccSplitGetParent (split);
1345
1346 // fix an earlier error when storing relative paths before version 3.5
1347 uri = gnc_doclink_convert_trans_link_uri (trans, gsr->read_only);
1348
1349 if (uri)
1350 gnc_doclink_open_uri (GTK_WINDOW (gsr->window), uri);
1351
1352 g_free (uri);
1353}
1354
1355void
1356gsr_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 reg = gnc_ledger_display_get_split_register( gsr->ledger );
1367
1368 /* get the current split based on cursor position */
1370 if (split == NULL)
1371 {
1373 return;
1374 }
1375
1376 trans = xaccSplitGetParent(split);
1378
1379 /* test for blank_split reference pointing to split */
1380 if (gnc_split_register_is_blank_split (reg, split))
1382
1383 /* Deleting the blank split just cancels */
1384 {
1385 Split *blank_split = gnc_split_register_get_blank_split (reg);
1386
1387 if (split == blank_split)
1388 {
1390 return;
1391 }
1392 }
1393
1394 if (cursor_class == CURSOR_CLASS_NONE)
1395 return;
1396
1397 if (is_trans_readonly_and_warn(GTK_WINDOW(gsr->window), trans))
1398 return;
1399
1400 /* On a split cursor, just delete the one split. */
1401 if (cursor_class == CURSOR_CLASS_SPLIT)
1402 {
1403 const char *format = _("Delete the split '%s' from the transaction '%s'?");
1404 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 const char *anchor_error = _("You cannot delete this split.");
1408 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 char *buf = NULL;
1416 const char *memo;
1417 const char *desc;
1418 char recn;
1419
1420 if (reg->type != GENERAL_JOURNAL) // no anchoring split
1421 {
1422 if (split == gnc_split_register_get_current_trans_split (reg, NULL))
1423 {
1424 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 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
1431 "%s", anchor_split);
1432 gtk_dialog_run(GTK_DIALOG(dialog));
1433 gtk_widget_destroy (dialog);
1434 return;
1435 }
1436 }
1437
1438 memo = xaccSplitGetMemo (split);
1439 memo = (memo && *memo) ? memo : _("(no memo)");
1440
1441 desc = xaccTransGetDescription (trans);
1442 desc = (desc && *desc) ? desc : _("(no description)");
1443
1444 /* ask for user confirmation before performing permanent damage */
1445 buf = g_strdup_printf (format, memo, desc);
1446 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 g_free(buf);
1453 recn = xaccSplitGetReconcile (split);
1454 if (recn == YREC || recn == FREC)
1455 {
1456 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
1457 "%s", recn_warn);
1458 warning = GNC_PREF_WARN_REG_SPLIT_DEL_RECD;
1459 }
1460 else
1461 {
1462 warning = GNC_PREF_WARN_REG_SPLIT_DEL;
1463 }
1464
1465 gtk_dialog_add_button(GTK_DIALOG(dialog),
1466 _("_Cancel"), GTK_RESPONSE_CANCEL);
1467 gnc_gtk_dialog_add_button(dialog, _("_Delete Split"),
1468 "edit-delete", GTK_RESPONSE_ACCEPT);
1469 response = gnc_dialog_run(GTK_DIALOG(dialog), warning);
1470 gtk_widget_destroy (dialog);
1471 if (response != GTK_RESPONSE_ACCEPT)
1472 return;
1473
1475 return;
1476 }
1477
1478 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 const char *title = _("Delete the current transaction?");
1484 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 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 if (xaccTransHasReconciledSplits (trans))
1496 {
1497 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
1498 "%s", recn_warn);
1499 warning = GNC_PREF_WARN_REG_TRANS_DEL_RECD;
1500 }
1501 else
1502 {
1503 warning = GNC_PREF_WARN_REG_TRANS_DEL;
1504 }
1505 gtk_dialog_add_button(GTK_DIALOG(dialog),
1506 _("_Cancel"), GTK_RESPONSE_CANCEL);
1507 gnc_gtk_dialog_add_button(dialog, _("_Delete Transaction"),
1508 "edit-delete", GTK_RESPONSE_ACCEPT);
1509 response = gnc_dialog_run(GTK_DIALOG(dialog), warning);
1510 gtk_widget_destroy (dialog);
1511 if (response != GTK_RESPONSE_ACCEPT)
1512 return;
1513
1515 return;
1516 }
1517}
1518
1522void
1523gnc_split_reg_delete_trans_cb(GtkWidget *widget, gpointer data)
1524{
1525 GNCSplitReg *gsr = data;
1526 gsr_emit_simple_signal( gsr, "delete_ent" );
1527}
1528
1529void
1530gsr_default_dup_handler( GNCSplitReg *gsr, gpointer data )
1531{
1534}
1535
1539void
1540gnc_split_reg_duplicate_trans_cb(GtkWidget *w, gpointer data)
1541{
1542 GNCSplitReg *gsr = data;
1543 gsr_emit_simple_signal( gsr, "dup_ent" );
1544}
1545
1551void
1552gsr_default_schedule_handler( GNCSplitReg *gsr, gpointer data )
1553{
1554 GncGUID *fromSXId = NULL;
1555 SchedXaction *theSX = NULL;
1556 GList *sxElts;
1557 SplitRegister *reg = gnc_ledger_display_get_split_register( gsr->ledger );
1558 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 qof_instance_get (QOF_INSTANCE (pending_trans),
1564 "from-sched-xaction", &fromSXId,
1565 NULL);
1566
1567 /* Get the correct SX */
1568 for ( sxElts = gnc_book_get_schedxactions (gnc_get_current_book())->sx_list;
1569 (!theSX) && sxElts;
1570 sxElts = sxElts->next )
1571 {
1572 SchedXaction *sx = (SchedXaction*)sxElts->data;
1573 theSX =
1574 ((guid_equal (xaccSchedXactionGetGUID (sx), fromSXId))
1575 ? sx : NULL);
1576 }
1577 guid_free (fromSXId);
1578
1579 if ( theSX )
1580 {
1581 gnc_ui_scheduled_xaction_editor_dialog_create(GTK_WINDOW(data), theSX, FALSE);
1582 return;
1583 }
1584 gnc_sx_create_from_trans(GTK_WINDOW(data), pending_trans);
1585}
1586
1587void
1588gnc_split_reg_recur_cb(GtkWidget *w, gpointer data)
1589{
1590 GNCSplitReg *gsr = data;
1591 gsr_emit_simple_signal( gsr, "schedule_ent" );
1592}
1593
1597void
1598gnc_split_reg_record_trans_cb (GtkWidget *w, gpointer data)
1599{
1600 GNCSplitReg *gsr = data;
1601 gsr_emit_simple_signal( gsr, "enter_ent" );
1602}
1603
1604void
1605gsr_default_cancel_handler( GNCSplitReg *gsr, gpointer data )
1606{
1609}
1610
1614void
1615gnc_split_reg_cancel_trans_cb(GtkWidget *w, gpointer data)
1616{
1617 GNCSplitReg *gsr = data;
1618 gsr_emit_simple_signal( gsr, "cancel_ent" );
1619}
1620
1621void
1622gsr_default_expand_handler( GNCSplitReg *gsr, gpointer data )
1623{
1624 gint activeCount;
1625 gboolean expand;
1626 SplitRegister *reg;
1627
1628 if (!gsr)
1629 return;
1630
1631 reg = gnc_ledger_display_get_split_register (gsr->ledger);
1632
1633 /* These should all be in agreement. */
1634 activeCount =
1635 ( ( gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM(gsr->split_menu_check)) ? 1 : -1 )
1636 + ( gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM(gsr->split_popup_check)) ? 1 : -1 )
1637 + ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(gsr->split_button) )
1638 ? 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 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. */
1648}
1649
1650void
1651gnc_split_reg_expand_trans_menu_cb (GtkWidget *widget, gpointer data)
1652{
1653 GNCSplitReg *gsr = data;
1654 gsr_emit_simple_signal( gsr, "expand_ent" );
1655}
1656
1657void
1658gnc_split_reg_expand_trans_toolbar_cb (GtkWidget *widget, gpointer data)
1659{
1660 GNCSplitReg *gsr = data;
1661 gsr_emit_simple_signal( gsr, "expand_ent" );
1662}
1663
1664gboolean
1665gnc_split_reg_clear_filter_for_split (GNCSplitReg *gsr, Split *split)
1666{
1667 VirtualCellLocation vcell_loc;
1668 SplitRegister *reg;
1669
1670 if (!gsr)
1671 return FALSE;
1672
1673 reg = gnc_ledger_display_get_split_register (gsr->ledger);
1674
1675 if (!gnc_split_register_get_split_virt_loc (reg, split, &vcell_loc))
1676 {
1677 gint response = gnc_ok_cancel_dialog (GTK_WINDOW(gsr->window),
1678 GTK_RESPONSE_CANCEL,
1679 (_("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 if (response == GTK_RESPONSE_OK)
1685 return TRUE;
1686 }
1687 return FALSE;
1688}
1689
1693void
1694gnc_split_reg_jump_to_split(GNCSplitReg *gsr, Split *split)
1695{
1696 if (!gsr) return;
1697
1698 SplitRegister *reg = gnc_ledger_display_get_split_register( gsr->ledger );
1699
1700 VirtualCellLocation vcell_loc;
1701 if (gnc_split_register_get_split_virt_loc(reg, split, &vcell_loc))
1702 gnucash_register_goto_virt_cell( gsr->reg, vcell_loc );
1703
1704 gnc_ledger_display_refresh( gsr->ledger );
1705}
1706
1710void
1711gnc_split_reg_jump_to_split_amount(GNCSplitReg *gsr, Split *split)
1712{
1713 if (!gsr) return;
1714
1715 SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger);
1716
1717 VirtualLocation virt_loc;
1718 if (gnc_split_register_get_split_amount_virt_loc (reg, split, &virt_loc))
1719 gnucash_register_goto_virt_loc (gsr->reg, virt_loc);
1720
1721 gnc_ledger_display_refresh (gsr->ledger);
1722}
1723
1724void
1725gnc_split_reg_jump_to_blank (GNCSplitReg *gsr)
1726{
1727 SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger);
1728 VirtualCellLocation vcell_loc;
1729 Split *blank;
1730
1731 ENTER("gsr=%p", gsr);
1732
1734 if (blank == NULL)
1735 {
1736 LEAVE("no blank split");
1737 return;
1738 }
1739
1740 if (gnc_split_register_get_split_virt_loc (reg, blank, &vcell_loc))
1741 {
1742 if ((vcell_loc.virt_row > 1) && (reg->style == REG_STYLE_JOURNAL))
1743 vcell_loc.virt_row--; // highlight the date field
1744
1745 gnucash_register_goto_virt_cell (gsr->reg, vcell_loc);
1746 }
1747 gnc_ledger_display_refresh (gsr->ledger);
1748 LEAVE(" ");
1749}
1750
1751void
1752gnc_split_reg_focus_on_sheet (GNCSplitReg *gsr)
1753{
1754 GnucashRegister *reg = gsr->reg;
1755 GnucashSheet *sheet = gnucash_register_get_sheet (reg);
1756
1757 // Make sure the sheet is the focus only when it is realized
1758 if (!gtk_widget_has_focus(GTK_WIDGET(sheet)) && gtk_widget_get_realized (GTK_WIDGET(sheet)))
1759 gtk_widget_grab_focus (GTK_WIDGET(sheet));
1760}
1761
1762void
1763gnc_split_reg_set_sheet_focus (GNCSplitReg *gsr, gboolean has_focus)
1764{
1765 GnucashRegister *reg = gsr->reg;
1766 GnucashSheet *sheet = gnucash_register_get_sheet (reg);
1767 gnucash_sheet_set_has_focus (sheet, has_focus);
1768}
1769
1770void
1771gnc_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 transaction = create_balancing_transaction(gnc_get_current_book(),
1780 account, statement_date, balancing_amount);
1781
1782 // jump to transaction
1783 split = xaccTransFindSplitByAccount(transaction, account);
1784 if (split == NULL)
1785 {
1786 // default behaviour: jump to blank split
1787 g_warning("create_balancing_transaction failed");
1788 gnc_split_reg_jump_to_blank(gsr);
1789 }
1790 else
1791 {
1792 // goto balancing transaction
1793 gnc_split_reg_jump_to_split(gsr, split );
1794 }
1795}
1796
1797static Transaction*
1798create_balancing_transaction(QofBook *book, Account *account,
1799 time64 statement_date, gnc_numeric balancing_amount)
1800{
1801
1802 Transaction *trans;
1803 Split *split;
1804
1805 if (!account)
1806 return NULL;
1807 if (gnc_numeric_zero_p(balancing_amount))
1808 return NULL;
1809
1810 xaccAccountBeginEdit(account);
1811
1812 trans = xaccMallocTransaction(book);
1813
1814 xaccTransBeginEdit(trans);
1815
1816 // fill Transaction
1818 xaccTransSetDatePostedSecsNormalized(trans, statement_date);
1819 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 */
1823
1824 // 1. Split
1825 split = xaccMallocSplit(book);
1826 xaccTransAppendSplit(trans, split);
1827 xaccAccountInsertSplit(account, split);
1828 xaccSplitSetAmount(split, balancing_amount);
1829 xaccSplitSetValue(split, balancing_amount);
1830
1831 // 2. Split (no account is defined: split goes to orphan account)
1832 split = xaccMallocSplit(book);
1833 xaccTransAppendSplit(trans, split);
1834
1835 balancing_amount = gnc_numeric_neg(balancing_amount);
1836 xaccSplitSetAmount(split, balancing_amount);
1837 xaccSplitSetValue(split, balancing_amount);
1838
1839 xaccTransCommitEdit(trans);
1840 xaccAccountCommitEdit(account);
1841 return trans;
1842}
1843
1844void
1845gsr_default_blank_handler( GNCSplitReg *gsr, gpointer data )
1846{
1847 SplitRegister *reg;
1848
1849 ENTER("gsr=%p, gpointer=%p", gsr, data);
1850
1851 reg = gnc_ledger_display_get_split_register (gsr->ledger);
1852
1853 if (gnc_split_register_save (reg, TRUE))
1855
1856 gnc_split_reg_jump_to_blank (gsr);
1857 LEAVE(" ");
1858}
1859
1860void
1861gnc_split_reg_new_trans_cb (GtkWidget *widget, gpointer data)
1862{
1863 GNCSplitReg *gsr = data;
1864 gsr_emit_simple_signal( gsr, "blank" );
1865}
1866
1867void
1868gsr_default_jump_handler( GNCSplitReg *gsr, gpointer data )
1869{
1870 g_assert_not_reached();
1871}
1872
1873void
1874gnc_split_reg_jump_cb( GtkWidget *widget, gpointer data )
1875{
1876 GNCSplitReg *gsr = data;
1877 gsr_emit_simple_signal( gsr, "jump" );
1878}
1879
1880void
1881gnc_split_reg_change_style (GNCSplitReg *gsr, SplitRegisterStyle style, gboolean refresh)
1882{
1883 SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger);
1884
1885 if (style == reg->style)
1886 return;
1887
1888 gnc_split_register_config (reg, reg->type, style, reg->use_double_line);
1889 if (refresh)
1890 gnc_ledger_display_refresh (gsr->ledger);
1891}
1892
1893void
1894gnc_split_reg_style_ledger_cb (GtkWidget *w, gpointer data)
1895{
1896 GNCSplitReg *gsr = data;
1897
1898 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM(w)))
1899 return;
1900
1901 gnc_split_reg_change_style (gsr, REG_STYLE_LEDGER, TRUE);
1902}
1903
1904void
1905gnc_split_reg_style_auto_ledger_cb (GtkWidget *w, gpointer data)
1906{
1907 GNCSplitReg *gsr = data;
1908
1909 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM(w)))
1910 return;
1911
1912 gnc_split_reg_change_style (gsr, REG_STYLE_AUTO_LEDGER, TRUE);
1913}
1914
1915void
1916gnc_split_reg_style_journal_cb (GtkWidget *w, gpointer data)
1917{
1918 GNCSplitReg *gsr = data;
1919
1920 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM(w)))
1921 return;
1922
1923 gnc_split_reg_change_style (gsr, REG_STYLE_JOURNAL, TRUE);
1924}
1925
1926void
1927gnc_split_reg_double_line_cb (GtkWidget *w, gpointer data)
1928{
1929 GNCSplitReg *gsr = data;
1930 SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger);
1931 gboolean use_double_line;
1932
1933 use_double_line = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM(w));
1934 if ( use_double_line == reg->use_double_line )
1935 return;
1936
1937 gnc_split_register_config( reg, reg->type, reg->style, use_double_line );
1938 gnc_ledger_display_refresh( gsr->ledger );
1939}
1940
1941void
1942gnc_split_reg_sort (GNCSplitReg *gsr, SortType sort_code, ForceSort fs, Refresh ref)
1943{
1944 Query *query = gnc_ledger_display_get_query( gsr->ledger );
1945 gboolean show_present_divider = FALSE;
1946 GSList *p1 = NULL, *p2 = NULL, *p3 = NULL, *standard;
1947 SplitRegister *reg;
1948
1949 if ((gsr->sort_type == sort_code) && !fs)
1950 return;
1951
1952 standard = g_slist_prepend( NULL, QUERY_DEFAULT_SORT );
1953
1954 switch (sort_code)
1955 {
1956 case BY_STANDARD:
1957 p1 = standard;
1958 show_present_divider = TRUE;
1959 break;
1960 case BY_DATE:
1961 p1 = g_slist_prepend (p1, TRANS_DATE_POSTED);
1962 p1 = g_slist_prepend (p1, SPLIT_TRANS);
1963 p2 = standard;
1964 show_present_divider = TRUE;
1965 break;
1966 case BY_DATE_ENTERED:
1967 p1 = g_slist_prepend (p1, TRANS_DATE_ENTERED);
1968 p1 = g_slist_prepend (p1, SPLIT_TRANS);
1969 p2 = standard;
1970 break;
1971 case BY_DATE_RECONCILED:
1972 p1 = g_slist_prepend (p1, SPLIT_RECONCILE);
1973 p2 = g_slist_prepend (p2, SPLIT_DATE_RECONCILED);
1974 p3 = standard;
1975 break;
1976 case BY_NUM:
1977 p1 = g_slist_prepend (p1, TRANS_NUM);
1978 p1 = g_slist_prepend (p1, SPLIT_TRANS);
1979 p2 = standard;
1980 break;
1981 case BY_AMOUNT:
1982 p1 = g_slist_prepend (p1, SPLIT_VALUE);
1983 p2 = standard;
1984 break;
1985 case BY_MEMO:
1986 p1 = g_slist_prepend (p1, SPLIT_MEMO);
1987 p2 = standard;
1988 break;
1989 case BY_DESC:
1990 p1 = g_slist_prepend (p1, TRANS_DESCRIPTION);
1991 p1 = g_slist_prepend (p1, SPLIT_TRANS);
1992 p2 = standard;
1993 break;
1994 case BY_ACTION:
1995 p1 = g_slist_prepend (p1, SPLIT_ACTION);
1996 p2 = standard;
1997 break;
1998 case BY_NOTES:
1999 p1 = g_slist_prepend (p1, TRANS_NOTES);
2000 p1 = g_slist_prepend (p1, SPLIT_TRANS);
2001 p2 = standard;
2002 break;
2003 default:
2004 g_slist_free (standard);
2005 g_return_if_fail (FALSE);
2006 break;
2007 }
2008
2009 qof_query_set_sort_order( query, p1, p2, p3 );
2010 reg = gnc_ledger_display_get_split_register( gsr->ledger );
2011 gnc_split_register_show_present_divider( reg, show_present_divider );
2012 gsr->sort_type = sort_code;
2013 if (ref)
2014 gnc_ledger_display_refresh( gsr->ledger );
2015}
2016
2017void
2018gnc_split_reg_sort_standard_cb(GtkWidget *w, gpointer data)
2019{
2020 GNCSplitReg *gsr = data;
2021 gnc_split_reg_sort(gsr, BY_STANDARD, no_force, refresh);
2022}
2023
2024void
2025gnc_split_reg_sort_date_cb(GtkWidget *w, gpointer data)
2026{
2027 GNCSplitReg *gsr = data;
2028 gnc_split_reg_sort(gsr, BY_DATE, no_force, refresh);
2029}
2030
2031void
2032gnc_split_reg_sort_date_entered_cb(GtkWidget *w, gpointer data)
2033{
2034 GNCSplitReg *gsr = data;
2035 gnc_split_reg_sort(gsr, BY_DATE_ENTERED, no_force, refresh);
2036}
2037
2038void
2039gnc_split_reg_sort_date_reconciled_cb(GtkWidget *w, gpointer data)
2040{
2041 GNCSplitReg *gsr = data;
2042 gnc_split_reg_sort(gsr, BY_DATE_RECONCILED, no_force, refresh);
2043}
2044
2045void
2046gnc_split_reg_sort_num_cb(GtkWidget *w, gpointer data)
2047{
2048 GNCSplitReg *gsr = data;
2049 gnc_split_reg_sort(gsr, BY_NUM, no_force, refresh);
2050}
2051
2052void
2053gnc_split_reg_sort_amount_cb(GtkWidget *w, gpointer data)
2054{
2055 GNCSplitReg *gsr = data;
2056 gnc_split_reg_sort(gsr, BY_AMOUNT, no_force, refresh);
2057}
2058
2059void
2060gnc_split_reg_sort_memo_cb(GtkWidget *w, gpointer data)
2061{
2062 GNCSplitReg *gsr = data;
2063 gnc_split_reg_sort(gsr, BY_MEMO, no_force, refresh);
2064}
2065
2066void
2067gnc_split_reg_sort_desc_cb(GtkWidget *w, gpointer data)
2068{
2069 GNCSplitReg *gsr = data;
2070 gnc_split_reg_sort(gsr, BY_DESC, no_force, refresh);
2071}
2072
2073void
2074gnc_split_reg_sort_action_cb(GtkWidget *w, gpointer data)
2075{
2076 GNCSplitReg *gsr = data;
2077 gnc_split_reg_sort(gsr, BY_ACTION, no_force, refresh);
2078}
2079
2080void
2081gnc_split_reg_sort_notes_cb(GtkWidget *w, gpointer data)
2082{
2083 GNCSplitReg *gsr = data;
2084 gnc_split_reg_sort(gsr, BY_NOTES, no_force, refresh);
2085}
2086
2087void
2088gnc_split_reg_set_sort_reversed(GNCSplitReg *gsr, gboolean rev, Refresh ref)
2089{
2090 /* Note: sort_reversed is the boolean opposite of sort_increasing
2091 * so when rev == true, we're sorting decreasing
2092 * In other words, qof_query_set_sort_increasing should
2093 * always use the inverse of rev.
2094 */
2095 SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger);
2096 Query *query = gnc_ledger_display_get_query( gsr->ledger );
2097
2099
2100 qof_query_set_sort_increasing (query, !rev, !rev, !rev);
2101 gsr->sort_rev = rev;
2102
2103 if (ref)
2104 gnc_ledger_display_refresh( gsr->ledger );
2105}
2106
2107static gboolean
2108gnc_split_reg_record (GNCSplitReg *gsr)
2109{
2110 ENTER("gsr=%p", gsr);
2111
2112 SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger);
2113
2114 if (!gnc_split_register_save (reg, TRUE))
2115 {
2116 LEAVE("no save");
2117 return FALSE;
2118 }
2119
2120 /* Explicit redraw shouldn't be needed,
2121 * since gui_refresh events should handle this. */
2122 /* gnc_split_register_redraw (reg); */
2123 LEAVE(" ");
2124 return TRUE;
2125}
2126
2127static gboolean
2128gnc_split_reg_match_trans_row( VirtualLocation virt_loc,
2129 gpointer user_data )
2130{
2131 GNCSplitReg *gsr = user_data;
2132 CursorClass cursor_class;
2133 SplitRegister *sr;
2134
2135 sr = gnc_ledger_display_get_split_register (gsr->ledger);
2136 cursor_class = gnc_split_register_get_cursor_class (sr, virt_loc.vcell_loc);
2137
2138 return (cursor_class == CURSOR_CLASS_TRANS);
2139}
2140
2141static void
2142gnc_split_reg_goto_next_trans_row (GNCSplitReg *gsr)
2143{
2144 ENTER("gsr=%p", gsr);
2145 gnucash_register_goto_next_matching_row( gsr->reg,
2146 gnc_split_reg_match_trans_row,
2147 gsr );
2148 LEAVE(" ");
2149}
2150
2151void
2152gnc_split_reg_enter( GNCSplitReg *gsr, gboolean next_transaction )
2153{
2154 SplitRegister *sr = gnc_ledger_display_get_split_register( gsr->ledger );
2155 gboolean goto_blank;
2156
2157 ENTER("gsr=%p, next_transaction=%s", gsr, next_transaction ? "TRUE" : "FALSE");
2158
2159 goto_blank = gnc_prefs_get_bool(GNC_PREFS_GROUP_GENERAL_REGISTER,
2160 GNC_PREF_ENTER_MOVES_TO_END);
2161
2162 /* If we are in single or double line view and we hit enter
2163 * on the blank split, go to the blank split instead of the
2164 * next row. This prevents the cursor from jumping around
2165 * when you are entering transactions. */
2166 if ( !goto_blank && !next_transaction )
2167 {
2168 SplitRegisterStyle style = sr->style;
2169
2170 if (style == REG_STYLE_LEDGER)
2171 {
2172 Split *blank_split;
2173
2174 blank_split = gnc_split_register_get_blank_split(sr);
2175 if (blank_split != NULL)
2176 {
2177 Split *current_split;
2178
2179 current_split = gnc_split_register_get_current_split(sr);
2180
2181 if (blank_split == current_split)
2182 goto_blank = TRUE;
2183 }
2184 }
2185 }
2186 /* First record the transaction. This will perform a refresh. */
2187 if (!gnc_split_reg_record (gsr))
2188 {
2189 /* we may come here from the transfer cell if we decline to create a
2190 * new account, make sure the sheet has the focus if the record is FALSE
2191 * which results in no cursor movement. */
2192 gnc_split_reg_focus_on_sheet (gsr);
2193
2194 /* if there are no changes, just enter was pressed, proceed to move
2195 * other wise lets not move. */
2196 if (gnc_table_current_cursor_changed (sr->table, FALSE))
2197 {
2198 LEAVE(" ");
2199 return;
2200 }
2201 }
2202
2203 if (!goto_blank && next_transaction)
2205
2206 /* Now move. */
2207 if (goto_blank)
2208 gnc_split_reg_jump_to_blank( gsr );
2209 else if (next_transaction)
2210 gnc_split_reg_goto_next_trans_row( gsr );
2211 else
2212 gnucash_register_goto_next_virt_row( gsr->reg );
2213 LEAVE(" ");
2214}
2215
2216void
2217gsr_default_enter_handler( GNCSplitReg *gsr, gpointer data )
2218{
2219 gnc_split_reg_enter( gsr, FALSE );
2220}
2221
2222void
2223gnc_split_reg_record_cb (GnucashRegister *reg, gpointer data)
2224{
2225 gsr_emit_simple_signal( (GNCSplitReg*)data, "enter_ent" );
2226}
2227
2228void
2229gnc_split_reg_size_allocate (GtkWidget *widget,
2230 GtkAllocation *allocation,
2231 gpointer user_data)
2232{
2233 GNCSplitReg *gsr = user_data;
2234 gsr->width = allocation->width;
2235 gtk_window_set_default_size( GTK_WINDOW(gsr->window), gsr->width, 0 );
2236}
2237
2238static
2239GtkWidget*
2240add_summary_label (GtkWidget *summarybar, gboolean pack_start, const char *label_str, GtkWidget *extra)
2241{
2242 GtkWidget *hbox;
2243 GtkWidget *text_label, *secondary_label;
2244
2245 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
2246 gtk_box_set_homogeneous (GTK_BOX (hbox), FALSE);
2247 if (pack_start)
2248 gtk_box_pack_start( GTK_BOX(summarybar), hbox, FALSE, FALSE, 5 );
2249 else
2250 gtk_box_pack_end( GTK_BOX(summarybar), hbox, FALSE, FALSE, 5 );
2251
2252 text_label = gtk_label_new (label_str);
2253 gnc_label_set_alignment (text_label, 1.0, 0.5 );
2254 gtk_label_set_ellipsize (GTK_LABEL(text_label), PANGO_ELLIPSIZE_END);
2255 gtk_box_pack_start (GTK_BOX(hbox), text_label, FALSE, FALSE, 0);
2256
2257 secondary_label = gtk_label_new ( "" );
2258 g_object_set_data (G_OBJECT(secondary_label), "text_label", text_label);
2259 g_object_set_data (G_OBJECT(secondary_label), "text_box", hbox);
2260 gnc_label_set_alignment (secondary_label, 1.0, 0.5 );
2261 gtk_box_pack_start (GTK_BOX(hbox), secondary_label, FALSE, FALSE, 0);
2262
2263 if (extra != NULL)
2264 gtk_box_pack_start( GTK_BOX(hbox), extra, FALSE, FALSE, 0 );
2265
2266 return secondary_label;
2267}
2268
2269static void
2270gsr_summarybar_set_arrow_draw (GNCSplitReg *gsr)
2271{
2272 if (gsr->sort_arrow_handler_id > 0)
2273 g_signal_handler_disconnect (G_OBJECT(gsr->sort_arrow), gsr->sort_arrow_handler_id);
2274
2275 gsr->sort_arrow_handler_id = g_signal_connect (G_OBJECT (gsr->sort_arrow), "draw",
2276 G_CALLBACK (gnc_draw_arrow_cb), GINT_TO_POINTER(gsr->sort_rev));
2277
2278 gtk_widget_queue_draw (gsr->sort_arrow);
2279}
2280
2281GtkWidget *
2282gsr_create_summary_bar( GNCSplitReg *gsr )
2283{
2284 GtkWidget *summarybar = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
2285 gtk_box_set_homogeneous (GTK_BOX (summarybar), FALSE);
2286 gtk_widget_set_name (summarybar, "gnc-id-summarybar");
2287
2288 gsr->cleared_label = NULL;
2289 gsr->balance_label = NULL;
2290 gsr->reconciled_label = NULL;
2291 gsr->future_label = NULL;
2292 gsr->projectedminimum_label = NULL;
2293 gsr->sort_label = NULL;
2294 gsr->sort_arrow = NULL;
2295 gsr->filter_label = NULL;
2296 gsr->shares_label = NULL;
2297 gsr->value_label = NULL;
2298
2299 if (gnc_ledger_display_type(gsr->ledger) == LD_SINGLE)
2300 {
2302 {
2303 gsr->balance_label = add_summary_label (summarybar, TRUE, _("Present:"), NULL);
2304 gsr->future_label = add_summary_label (summarybar, TRUE, _("Future:"), NULL);
2305 gsr->cleared_label = add_summary_label (summarybar, TRUE, _("Cleared:"), NULL);
2306 gsr->reconciled_label = add_summary_label (summarybar, TRUE, _("Reconciled:"), NULL);
2307 gsr->projectedminimum_label = add_summary_label (summarybar, TRUE, _("Projected Minimum:"), NULL);
2308 }
2309 else
2310 {
2311 gsr->shares_label = add_summary_label (summarybar, TRUE, _("Shares:"), NULL);
2312 gsr->value_label = add_summary_label (summarybar, TRUE, _("Current Value:"), NULL);
2313 }
2314 }
2315
2316 gsr->filter_label = add_summary_label (summarybar, FALSE, "", NULL);
2317 gsr->sort_arrow = gtk_image_new_from_icon_name ("image-missing", GTK_ICON_SIZE_SMALL_TOOLBAR);
2318 gsr->sort_label = add_summary_label (summarybar, FALSE, _("Sort By:"), gsr->sort_arrow);
2319
2320 gnc_widget_style_context_add_class (GTK_WIDGET(gsr->filter_label), "gnc-class-highlight");
2321 gnc_widget_style_context_add_class (GTK_WIDGET(gsr->sort_arrow), "gnc-class-highlight");
2322
2323 gsr->summarybar = summarybar;
2324
2325 /* Force the first update */
2326 gsr_redraw_all_cb(NULL, gsr);
2327 return gsr->summarybar;
2328}
2329
2336static
2338gnc_split_reg_get_placeholder( GNCSplitReg *gsr )
2339{
2340 Account *leader;
2341 SplitRegister *reg;
2342 gboolean single_account;
2343
2344 if (gsr == NULL)
2345 return PLACEHOLDER_NONE;
2346
2347 reg = gnc_ledger_display_get_split_register( gsr->ledger );
2348
2349 switch (reg->type)
2350 {
2351 case GENERAL_JOURNAL:
2352 case INCOME_LEDGER:
2353 case PORTFOLIO_LEDGER:
2354 case SEARCH_LEDGER:
2355 single_account = FALSE;
2356 break;
2357 default:
2358 single_account = TRUE;
2359 break;
2360 }
2361
2362 leader = gnc_ledger_display_leader( gsr->ledger );
2363
2364 if (leader == NULL)
2365 return PLACEHOLDER_NONE;
2366 if (single_account)
2367 {
2368 if (xaccAccountGetPlaceholder( leader ))
2369 return PLACEHOLDER_THIS;
2370 return PLACEHOLDER_NONE;
2371 }
2372 return xaccAccountGetDescendantPlaceholder( leader );
2373}
2374
2378typedef struct dialog_args
2379{
2380 GNCSplitReg *gsr;
2381 gchar *string;
2382} dialog_args;
2383
2389static
2390gboolean
2391gtk_callback_bug_workaround (gpointer argp)
2392{
2393 dialog_args *args = argp;
2394 const gchar *read_only_this = _("This account register is read-only.");
2395 const gchar *read_only_acc = _("The '%s' account register is read-only.");
2396 gchar *read_only = NULL;
2397 GtkWidget *dialog;
2398 GNCLedgerDisplayType ledger_type = gnc_ledger_display_type (args->gsr->ledger);
2399 Account *acc = gnc_ledger_display_leader (args->gsr->ledger);
2400 const gchar *acc_name = NULL;
2401
2402 if (acc)
2403 {
2404 acc_name = xaccAccountGetName (acc);
2405
2406 if (ledger_type == LD_SINGLE)
2407 read_only = g_strdup_printf (read_only_acc, acc_name);
2408 else
2409 {
2410 gchar *tmp = g_strconcat (acc_name, "+", NULL);
2411 read_only = g_strdup_printf (read_only_acc, tmp);
2412 g_free (tmp);
2413 }
2414 }
2415 else
2416 read_only = g_strdup (read_only_this);
2417
2418 dialog = gtk_message_dialog_new(GTK_WINDOW(args->gsr->window),
2419 GTK_DIALOG_DESTROY_WITH_PARENT,
2420 GTK_MESSAGE_WARNING,
2421 GTK_BUTTONS_CLOSE,
2422 "%s", read_only);
2423 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
2424 "%s", args->string);
2425 gnc_dialog_run(GTK_DIALOG(dialog), GNC_PREF_WARN_REG_IS_READ_ONLY);
2426 gtk_widget_destroy(dialog);
2427 g_free(read_only);
2428 g_free(args);
2429 return FALSE;
2430}
2431
2435static
2436void
2437gnc_split_reg_determine_read_only( GNCSplitReg *gsr, gboolean show_dialog )
2438{
2439 SplitRegister *reg;
2440
2441 if (qof_book_is_readonly(gnc_get_current_book()))
2442 {
2443 /* Is the book read-only? Then for sure also make this register
2444 read-only. */
2445 gsr->read_only = TRUE;
2446 }
2447
2448 if ( !gsr->read_only )
2449 {
2450 char *string = NULL;
2451 reg = gnc_ledger_display_get_split_register( gsr->ledger );
2452 if(reg->mismatched_commodities)
2453 {
2454 string = _("The transactions of this account may not be edited "
2455 "because its subaccounts have mismatched commodities "
2456 "or currencies.\n"
2457 "You need to open each account individually to edit "
2458 "transactions.");
2459 }
2460 else
2461 {
2462 switch (gnc_split_reg_get_placeholder(gsr))
2463 {
2464 case PLACEHOLDER_NONE:
2465 /* stay as false. */
2466 return;
2467
2468 case PLACEHOLDER_THIS:
2469 string = _("The transactions of this account may not be edited.\n"
2470 "If you want to edit transactions in this register, "
2471 "please open the account options and turn off the "
2472 "placeholder checkbox.");
2473 break;
2474
2475 default:
2476 string = _("The transactions in one of the selected "
2477 "sub-accounts may not be edited.\n"
2478 "If you want to edit transactions in this register, please open "
2479 "the sub-account options and turn off the placeholder checkbox.\n"
2480 "You may also open an individual account instead "
2481 "of a set of accounts.");
2482 break;
2483 }
2484 }
2485 gsr->read_only = TRUE;
2486 if (show_dialog)
2487 {
2488 /* Put up a warning dialog */
2489 dialog_args *args = g_malloc(sizeof(dialog_args));
2490 args->string = string;
2491 args->gsr = gsr;
2492
2493 g_timeout_add (250, gtk_callback_bug_workaround, args); /* 0.25 seconds */
2494 }
2495 }
2496
2497 /* Make the contents immutable */
2498 reg = gnc_ledger_display_get_split_register( gsr->ledger );
2500
2501}
2502
2503static
2504GtkWidget *
2505gnc_split_reg_get_parent( GNCLedgerDisplay *ledger )
2506{
2507 GNCSplitReg *gsr =
2508 GNC_SPLIT_REG(gnc_ledger_display_get_user_data( ledger ));
2509
2510 if (gsr == NULL)
2511 return NULL;
2512
2513 return gsr->window;
2514}
2515
2516static
2517void
2518gsr_emit_help_changed( GnucashRegister *reg, gpointer user_data )
2519{
2520 gsr_emit_simple_signal( (GNCSplitReg*)user_data, "help-changed" );
2521}
2522
2523static
2524void
2525gsr_emit_show_popup_menu( GnucashRegister *reg, gpointer user_data )
2526{
2527 gsr_emit_simple_signal( (GNCSplitReg*)user_data, "show-popup-menu" );
2528}
2529
2530static
2531void
2532gsr_emit_simple_signal( GNCSplitReg *gsr, const char *sigName )
2533{
2534 g_signal_emit_by_name( gsr, sigName, NULL );
2535}
2536
2537GnucashRegister*
2538gnc_split_reg_get_register( GNCSplitReg *gsr )
2539{
2540 if ( !gsr )
2541 return NULL;
2542
2543 return gsr->reg;
2544}
2545
2546SortType
2547gnc_split_reg_get_sort_type( GNCSplitReg *gsr )
2548{
2549 g_assert( gsr );
2550 return gsr->sort_type;
2551}
2552
2553GtkWidget*
2554gnc_split_reg_get_summarybar( GNCSplitReg *gsr )
2555{
2556 if ( !gsr ) return NULL;
2557 return gsr->summarybar;
2558}
2559
2560gboolean
2561gnc_split_reg_get_read_only( GNCSplitReg *gsr )
2562{
2563 SplitRegister *reg;
2564
2565 g_assert( gsr );
2566
2567 // reset read_only flag
2568 gsr->read_only = FALSE;
2569 gnc_split_reg_determine_read_only (gsr, FALSE);
2570
2571 reg = gnc_ledger_display_get_split_register( gsr->ledger );
2572 gnc_split_register_set_read_only( reg, gsr->read_only );
2573 return gsr->read_only;
2574}
2575
2576void
2577gnc_split_reg_set_moved_cb( GNCSplitReg *gsr, GFunc cb, gpointer cb_data )
2578{
2579 gnucash_register_set_moved_cb (gsr->reg, cb, cb_data);
2580}
Account handling public routines.
Anchor Scheduled Transaction info in a book.
This file contains the functions to present a gui to the user for creating a new account or editing a...
All type declarations for the whole Gnucash engine.
File path resolution utility functions.
Gnome specific utility functions.
Public declarations for GncLedgerDisplay class.
Generic api to store and retrieve preferences.
a simple price database for gnucash
Functions to load, save and get gui state.
utility functions for the GnuCash UI
Utility functions for convert uri in separate components and back.
Public declarations of GnucashRegister class.
const char * xaccAccountGetName(const Account *acc)
Get the account's name.
Definition Account.cpp:3289
void xaccAccountCommitEdit(Account *acc)
ThexaccAccountCommitEdit() subroutine is the second phase of a two-phase-commit wrapper for account u...
Definition Account.cpp:1516
void xaccAccountBeginEdit(Account *acc)
The xaccAccountBeginEdit() subroutine is the first phase of a two-phase-commit wrapper for account up...
Definition Account.cpp:1475
void xaccAccountSetFilter(Account *acc, const char *str)
Set the account's Filter.
Definition Account.cpp:2619
const char * xaccAccountGetSortOrder(const Account *acc)
Get the account's Sort Order.
Definition Account.cpp:3362
#define xaccAccountGetGUID(X)
Definition Account.h:252
gboolean xaccAccountIsPriced(const Account *acc)
Returns true if the account is a stock, mutual fund or currency, otherwise false.
Definition Account.cpp:4551
void xaccAccountSetSortReversed(Account *acc, gboolean sortreversed)
Set the account's Sort Order direction.
Definition Account.cpp:2631
gnc_numeric xaccAccountGetBalance(const Account *acc)
Get the current balance of the account, which may include future splits.
Definition Account.cpp:3467
const char * xaccAccountGetFilter(const Account *acc)
Get the account's filter.
Definition Account.cpp:3356
void xaccAccountSetSortOrder(Account *acc, const char *str)
Set the account's Sort Order.
Definition Account.cpp:2625
gnc_numeric xaccAccountGetClearedBalance(const Account *acc)
Get the current balance of the account, only including cleared transactions.
Definition Account.cpp:3474
gnc_numeric xaccAccountGetReconciledBalance(const Account *acc)
Get the current balance of the account, only including reconciled transactions.
Definition Account.cpp:3481
gboolean xaccAccountGetSortReversed(const Account *acc)
Get the account's Sort Order direction.
Definition Account.cpp:3368
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Get the account's commodity
Definition Account.cpp:3408
gboolean qof_book_is_readonly(const QofBook *book)
Return whether the book is read only.
Definition qofbook.cpp:497
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
Retrieve the mnemonic for the specified commodity.
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Definition gnc-date.h:87
time64 gnc_time(time64 *tbuf)
get the current time
Definition gnc-date.cpp:262
Transaction * xaccTransReverse(Transaction *orig)
xaccTransReverse creates a Transaction that reverses the given transaction by inverting all the numer...
gboolean xaccAccountGetPlaceholder(const Account *acc)
Get the "placeholder" flag for an account.
Definition Account.cpp:4119
GNCPlaceholderType xaccAccountGetDescendantPlaceholder(const Account *acc)
Returns PLACEHOLDER_NONE if account is NULL or neither account nor any descendant of account is a pla...
Definition Account.cpp:4162
void xaccTransSetDescription(Transaction *trans, const char *desc)
Sets the transaction Description.
Transaction * xaccTransGetReversedBy(const Transaction *trans)
Returns the transaction that reversed the given transaction.
#define xaccTransAppendSplit(t, s)
Add a split to the transaction.
void xaccTransCommitEdit(Transaction *trans)
The xaccTransCommitEdit() method indicates that the changes to the transaction and its splits are com...
const char * xaccTransGetDescription(const Transaction *trans)
Gets the transaction Description.
GNCPlaceholderType
DOCUMENT ME!
Definition Account.h:1283
gboolean xaccTransHasReconciledSplits(const Transaction *trans)
FIXME: document me.
Split * xaccTransGetSplit(const Transaction *trans, int i)
Return a pointer to the indexed split in this transaction's split list.
void xaccTransSetDateEnteredSecs(Transaction *trans, time64 secs)
Modify the date of when the transaction was entered.
void xaccTransSetDocLink(Transaction *trans, const char *doclink)
Sets the transaction Document Link.
Transaction * xaccMallocTransaction(QofBook *book)
The xaccMallocTransaction() will malloc memory and initialize it.
void xaccTransSetDatePostedSecsNormalized(Transaction *trans, time64 time)
This function sets the posted date of the transaction, specified by a time64 (see ctime(3)).
void xaccTransSetCurrency(Transaction *trans, gnc_commodity *curr)
Set a new currency on a transaction.
#define xaccAccountInsertSplit(acc, s)
The xaccAccountInsertSplit() method will insert the indicated split into the indicated account.
Definition Account.h:1069
gboolean xaccTransIsReadonlyByPostedDate(const Transaction *trans)
Returns TRUE if this Transaction is read-only because its posted-date is older than the "auto-readonl...
void xaccTransBeginEdit(Transaction *trans)
The xaccTransBeginEdit() method must be called before any changes are made to a transaction or any of...
const char * xaccTransGetReadOnly(Transaction *trans)
Returns a non-NULL value if this Transaction was marked as read-only with some specific "reason" text...
#define GUID_ENCODING_LENGTH
Number of characters needed to encode a guid as a string not including the null terminator.
Definition guid.h:84
gboolean guid_equal(const GncGUID *guid_1, const GncGUID *guid_2)
Given two GUIDs, return TRUE if they are non-NULL and equal.
Definition guid.cpp:237
gchar * guid_to_string_buff(const GncGUID *guid, gchar *str)
The guid_to_string_buff() routine puts a null-terminated string encoding of the id into the memory po...
Definition guid.cpp:208
GKeyFile * gnc_state_get_current(void)
Returns a pointer to the most recently loaded state.
Definition gnc-state.c:248
void gnc_ledger_display_set_handlers(GNCLedgerDisplay *ld, GNCLedgerDisplayDestroy destroy, GNCLedgerDisplayGetParent get_parent)
set the handlers used by the ledger display
gboolean gnc_ledger_display_default_double_line(GNCLedgerDisplay *gld)
Returns a boolean of whether this display should be single or double lined mode by default.
Query * gnc_ledger_display_get_query(GNCLedgerDisplay *ld)
return the query associated with a ledger
void gnc_ledger_display_refresh(GNCLedgerDisplay *ld)
redisplay/redraw only the indicated window.
Account * gnc_ledger_display_leader(GNCLedgerDisplay *ld)
Implementations.
void gnc_ledger_display_set_user_data(GNCLedgerDisplay *ld, gpointer user_data)
get and set the user data associated with the ledger
GtkWidget * gnucash_register_new(Table *table, const gchar *state_section)
this already has scrollbars attached
SplitRegister * gnc_ledger_display_get_split_register(GNCLedgerDisplay *ld)
return the split register associated with a ledger display
int xaccSPrintAmount(char *bufp, gnc_numeric val, GNCPrintAmountInfo info)
Make a string representation of a gnc_numeric.
char * gnc_wrap_text_with_bidi_ltr_isolate(const char *text)
This function helps with GTK's use of 'Unicode Bidirectional Text Algorithm'.
gnc_commodity * gnc_account_or_default_currency(const Account *account, gboolean *currency_from_account_found)
Returns a gnc_commodity that is a currency, suitable for being a Transaction's currency.
gnc_commodity * gnc_default_currency(void)
Return the default currency set by the user.
void qof_instance_get(const QofInstance *inst, const gchar *first_prop,...)
Wrapper for g_object_get.
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition qoflog.h:282
#define ENTER(format, args...)
Print a function entry debugging message.
Definition qoflog.h:272
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
gnc_numeric gnc_numeric_neg(gnc_numeric a)
Returns a newly created gnc_numeric that is the negative of the given gnc_numeric value.
void gnc_prefs_remove_cb_by_func(const gchar *group, const gchar *pref_name, gpointer func, gpointer user_data)
Remove a function that was registered for a callback when the given preference changed.
gulong gnc_prefs_register_cb(const char *group, const gchar *pref_name, gpointer func, gpointer user_data)
Register a callback that gets triggered when the given preference changes.
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Get a boolean value from the preferences backend.
gnc_numeric gnc_pricedb_convert_balance_latest_price(GNCPriceDB *pdb, gnc_numeric balance, const gnc_commodity *balance_currency, const gnc_commodity *new_currency)
Convert a balance from one currency to another using the most recent price between the two.
GNCPriceDB * gnc_pricedb_get_db(QofBook *book)
Return the pricedb associated with the book.
#define QUERY_DEFAULT_SORT
Default sort object type.
Definition qofquery.h:105
void qof_query_set_sort_increasing(QofQuery *q, gboolean prim_inc, gboolean sec_inc, gboolean tert_inc)
When a query is run, the results are sorted before being returned.
void qof_query_set_sort_order(QofQuery *q, QofQueryParamList *params1, QofQueryParamList *params2, QofQueryParamList *params3)
When a query is run, the results are sorted before being returned.
#define xaccSchedXactionGetGUID(X)
CursorClass gnc_split_register_get_cursor_class(SplitRegister *reg, VirtualCellLocation vcell_loc)
Returns the class of the cursor at the given virtual cell location.
SplitRegisterStyle
Register styles.
gboolean gnc_split_register_get_split_amount_virt_loc(SplitRegister *reg, Split *split, VirtualLocation *virt_loc)
Searches the split register for the given split and determines the location of either its credit (if ...
void gnc_split_register_set_read_only(SplitRegister *reg, gboolean read_only)
Sets whether a register window is "read only".
void gnc_split_register_change_blank_split_ref(SplitRegister *reg, Split *split)
Change the blank_split reference from pointing to split to another split of the transaction.
void gnc_split_register_show_present_divider(SplitRegister *reg, gboolean show_present)
If TRUE, visually indicate the demarcation between splits with post dates prior to the present,...
gboolean gnc_split_register_save(SplitRegister *reg, gboolean do_commit)
Copy the contents of the current cursor to a split.
Split * gnc_split_register_get_current_split(SplitRegister *reg)
Returns the split at which the cursor is currently located.
Split * gnc_split_register_get_current_trans_split(SplitRegister *reg, VirtualCellLocation *trans_split_loc)
Gets the anchoring split of the transaction at the current cursor location, which may be on the trans...
Transaction * gnc_split_register_get_current_trans(SplitRegister *reg)
Gets the transaction at the current cursor location, which may be on the transaction itself or on any...
void gnc_split_register_delete_current_split(SplitRegister *reg)
Deletes the split associated with the current cursor, if both are non-NULL.
void gnc_split_register_cancel_cursor_trans_changes(SplitRegister *reg)
Cancels any changes made to the current pending transaction, reloads the table from the engine,...
gboolean gnc_split_register_get_split_virt_loc(SplitRegister *reg, Split *split, VirtualCellLocation *vcell_loc)
Searches the split register for a given split.
void gnc_split_register_paste_current(SplitRegister *reg)
Pastes a previous copied entity onto the current entity, but only if the copied and current entity ha...
void gnc_split_register_cut_current(SplitRegister *reg)
Equivalent to copying the current entity and the deleting it with the appropriate delete method.
void gnc_split_register_redraw(SplitRegister *reg)
Causes a redraw of the register window associated with reg.
void gnc_split_register_expand_current_trans(SplitRegister *reg, gboolean expand)
Expand the current transaction if it is collapsed.
void gnc_split_register_copy_current(SplitRegister *reg)
Makes a copy of the current entity, either a split or a transaction, so that it can be pasted later.
void gnc_split_register_cancel_cursor_split_changes(SplitRegister *reg)
Cancels any changes made to the current cursor, reloads the cursor from the engine,...
Split * gnc_split_register_get_blank_split(SplitRegister *reg)
Gets the blank split for a register.
void gnc_split_register_set_reverse_sort(SplitRegister *reg, gboolean reverse_sort)
Sets a split register's reverse sort order based on register.
gboolean gnc_split_register_is_blank_split(SplitRegister *reg, Split *split)
Return TRUE if split is the blank_split.
void gnc_split_register_config(SplitRegister *reg, SplitRegisterType newtype, SplitRegisterStyle newstyle, gboolean use_double_line)
Sets a split register's type, style or line use.
CursorClass
Types of cursors.
CursorClass gnc_split_register_get_current_cursor_class(SplitRegister *reg)
Returns the class of a register's current cursor.
void gnc_split_register_empty_current_trans_except_split(SplitRegister *reg, Split *split)
Deletes the non-transaction splits associated with the current cursor, if both are non-NULL.
Split * gnc_split_register_duplicate_current(SplitRegister *reg)
Duplicates either the current transaction or the current split depending on the register mode and cur...
void gnc_split_register_delete_current_trans(SplitRegister *reg)
Deletes the transaction associated with the current cursor, if both are non-NULL.
void gnc_table_save_state(Table *table, const gchar *state_section)
Implementation.
Definition table-gnome.c:71
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
char xaccSplitGetReconcile(const Split *split)
Returns the value of the reconcile flag.
void xaccSplitSetValue(Split *split, gnc_numeric val)
The xaccSplitSetValue() method sets the value of this split in the transaction's commodity.
Split * xaccMallocSplit(QofBook *book)
Constructor.
void xaccSplitSetAmount(Split *split, gnc_numeric amt)
The xaccSplitSetAmount() method sets the amount in the account's commodity that the split should have...
const char * xaccSplitGetMemo(const Split *split)
Returns the memo string.
#define FREC
frozen into accounting period
Definition Split.h:75
#define YREC
The Split has been reconciled.
Definition Split.h:74
STRUCTS.
The type used to store guids in C.
Definition guid.h:75
QofBook reference.
Definition qofbook-p.hpp:47
A Query.
Definition qofquery.cpp:75
Declarations for the Table object.