LCOV - code coverage report
Current view: top level - gnucash/gnome - gnc-split-reg.c (source / functions) Hit Total Coverage
Test: gnucash.info Lines: 0 1101 0.0 %
Date: 2024-10-31 11:06:40 Functions: 0 111 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           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 : }

Generated by: LCOV version 1.14