|
GnuCash 2.4.99
|
00001 /********************************************************************\ 00002 * gnc-split-reg.c -- A widget for the common register look-n-feel. * 00003 * Copyright (C) 1997 Robin D. Clark * 00004 * Copyright (C) 1997-1998 Linas Vepstas <linas@linas.org> * 00005 * Copyright (C) 1998 Rob Browning <rlb@cs.utexas.edu> * 00006 * Copyright (C) 1999-2000 Dave Peticolas <dave@krondo.com> * 00007 * Copyright (C) 2001 Gnumatic, Inc. * 00008 * Copyright (C) 2002,2006 Joshua Sled <jsled@asynchronous.org> * 00009 * * 00010 * This program is free software; you can redistribute it and/or * 00011 * modify it under the terms of the GNU General Public License as * 00012 * published by the Free Software Foundation; either version 2 of * 00013 * the License, or (at your option) any later version. * 00014 * * 00015 * This program is distributed in the hope that it will be useful, * 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00018 * GNU General Public License for more details. * 00019 * * 00020 * You should have received a copy of the GNU General Public License* 00021 * along with this program; if not, contact: * 00022 * * 00023 * Free Software Foundation Voice: +1-617-542-5942 * 00024 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * 00025 * Boston, MA 02110-1301, USA gnu@gnu.org * 00026 \********************************************************************/ 00027 00028 #include "config.h" 00029 00030 #include <gtk/gtk.h> 00031 #include <glib/gi18n.h> 00032 #include <time.h> 00033 00034 #include "gnc-split-reg.h" 00035 00036 #include "Account.h" 00037 #include "qof.h" 00038 #include "SX-book.h" 00039 #include "dialog-account.h" 00040 #include "dialog-sx-editor.h" 00041 #include "dialog-sx-from-trans.h" 00042 #include "gnc-component-manager.h" 00043 #include "gnc-date-edit.h" 00044 #include "gnc-engine.h" 00045 #include "gnc-euro.h" 00046 #include "gnc-gconf-utils.h" 00047 #include "gnc-gui-query.h" 00048 #include "gnc-ledger-display.h" 00049 #include "gnc-pricedb.h" 00050 #include "gnc-ui-util.h" 00051 #include "gnc-ui.h" 00052 #include "gnucash-sheet.h" 00053 #include "table-allgui.h" 00054 00055 #include <libguile.h> 00056 #include "dialog-utils.h" 00057 00058 // static QofLogModule log_module = GNC_MOD_SX; 00059 static QofLogModule log_module = GNC_MOD_GUI; 00060 00061 /***** PROTOTYPES ***************************************************/ 00062 void gnc_split_reg_raise( GNCSplitReg *gsr ); 00063 00064 static GtkWidget* add_summary_label( GtkWidget *summarybar, 00065 const char *label_str ); 00066 00067 static void gnc_split_reg_determine_read_only( GNCSplitReg *gsr ); 00068 00069 static GNCPlaceholderType gnc_split_reg_get_placeholder( GNCSplitReg *gsr ); 00070 static GtkWidget *gnc_split_reg_get_parent( GNCLedgerDisplay *ledger ); 00071 00072 static void gsr_create_table( GNCSplitReg *gsr ); 00073 static void gsr_setup_table( GNCSplitReg *gsr ); 00074 static void gsr_setup_status_widgets( GNCSplitReg *gsr ); 00075 00076 static void gsr_update_summary_label( GtkWidget *label, 00077 xaccGetBalanceFn getter, 00078 Account *leader, 00079 GNCPrintAmountInfo print_info, 00080 gnc_commodity *cmdty, 00081 gboolean reverse, 00082 gboolean euroFlag ); 00083 00084 static void gsr_redraw_all_cb (GnucashRegister *g_reg, gpointer data); 00085 00086 static void gnc_split_reg_refresh_toolbar( GNCSplitReg *gsr ); 00087 00088 static void gnc_split_reg_ld_destroy( GNCLedgerDisplay *ledger ); 00089 00090 static Transaction* create_balancing_transaction(QofBook *book, Account *account, 00091 time_t statement_date, gnc_numeric balancing_amount); 00092 00093 void gsr_default_enter_handler ( GNCSplitReg *w, gpointer ud ); 00094 void gsr_default_cancel_handler ( GNCSplitReg *w, gpointer ud ); 00095 void gsr_default_delete_handler ( GNCSplitReg *w, gpointer ud ); 00096 void gsr_default_reinit_handler ( GNCSplitReg *w, gpointer ud ); 00097 void gsr_default_dup_handler ( GNCSplitReg *w, gpointer ud ); 00098 void gsr_default_schedule_handler ( GNCSplitReg *w, gpointer ud ); 00099 void gsr_default_expand_handler ( GNCSplitReg *w, gpointer ud ); 00100 void gsr_default_blank_handler ( GNCSplitReg *w, gpointer ud ); 00101 void gsr_default_jump_handler ( GNCSplitReg *w, gpointer ud ); 00102 void gsr_default_cut_handler ( GNCSplitReg *w, gpointer ud ); 00103 void gsr_default_cut_txn_handler ( GNCSplitReg *w, gpointer ud ); 00104 void gsr_default_copy_handler ( GNCSplitReg *w, gpointer ud ); 00105 void gsr_default_copy_txn_handler ( GNCSplitReg *w, gpointer ud ); 00106 void gsr_default_paste_handler ( GNCSplitReg *w, gpointer ud ); 00107 void gsr_default_paste_txn_handler( GNCSplitReg *w, gpointer ud ); 00108 void gsr_default_void_txn_handler ( GNCSplitReg *w, gpointer ud ); 00109 void gsr_default_unvoid_txn_handler ( GNCSplitReg *w, gpointer ud ); 00110 void gsr_default_reverse_txn_handler ( GNCSplitReg *w, gpointer ud ); 00111 00112 static void gsr_emit_simple_signal( GNCSplitReg *gsr, const char *sigName ); 00113 static void gsr_emit_help_changed( GnucashRegister *reg, gpointer user_data ); 00114 static void gsr_emit_include_date_signal( GNCSplitReg *gsr, time_t date ); 00115 00116 void gnc_split_reg_cut_cb(GtkWidget *w, gpointer data); 00117 void gnc_split_reg_copy_cb(GtkWidget *w, gpointer data); 00118 void gnc_split_reg_paste_cb(GtkWidget *w, gpointer data); 00119 00120 void gnc_split_reg_cut_trans_cb(GtkWidget *w, gpointer data); 00121 void gnc_split_reg_copy_trans_cb(GtkWidget *w, gpointer data); 00122 void gnc_split_reg_paste_trans_cb(GtkWidget *w, gpointer data); 00123 void gnc_split_reg_void_trans_cb(GtkWidget *w, gpointer data); 00124 void gnc_split_reg_unvoid_trans_cb(GtkWidget *w, gpointer data); 00125 void gnc_split_reg_reverse_trans_cb(GtkWidget *w, gpointer data); 00126 00127 void gnc_split_reg_record_cb (GnucashRegister *reg, gpointer data); 00128 void gnc_split_reg_reinitialize_trans_cb(GtkWidget *w, gpointer data); 00129 void gnc_split_reg_delete_trans_cb(GtkWidget *w, gpointer data); 00130 void gnc_split_reg_duplicate_trans_cb(GtkWidget *w, gpointer data); 00131 void gnc_split_reg_recur_cb(GtkWidget *w, gpointer data); 00132 void gnc_split_reg_record_trans_cb(GtkWidget *w, gpointer data); 00133 void gnc_split_reg_cancel_trans_cb(GtkWidget *w, gpointer data); 00134 00135 void gnc_split_reg_expand_trans_menu_cb(GtkWidget *widget, gpointer data); 00136 void gnc_split_reg_expand_trans_toolbar_cb(GtkWidget *widget, gpointer data); 00137 void gnc_split_reg_new_trans_cb(GtkWidget *widget, gpointer data); 00138 void gnc_split_reg_jump_cb(GtkWidget *widget, gpointer data); 00139 00140 void gnc_split_reg_style_ledger_cb (GtkWidget *w, gpointer data); 00141 void gnc_split_reg_style_auto_ledger_cb (GtkWidget *w, gpointer data); 00142 void gnc_split_reg_style_journal_cb (GtkWidget *w, gpointer data); 00143 void gnc_split_reg_double_line_cb (GtkWidget *w, gpointer data); 00144 00145 void gnc_split_reg_sort_standard_cb (GtkWidget *w, gpointer data); 00146 void gnc_split_reg_sort_date_cb (GtkWidget *w, gpointer data); 00147 void gnc_split_reg_sort_date_entered_cb (GtkWidget *w, gpointer data); 00148 void gnc_split_reg_sort_date_reconciled_cb (GtkWidget *w, gpointer data); 00149 void gnc_split_reg_sort_num_cb (GtkWidget *w, gpointer data); 00150 void gnc_split_reg_sort_amount_cb (GtkWidget *w, gpointer data); 00151 void gnc_split_reg_sort_memo_cb (GtkWidget *w, gpointer data); 00152 void gnc_split_reg_sort_desc_cb (GtkWidget *w, gpointer data); 00153 void gnc_split_reg_sort_action_cb (GtkWidget *w, gpointer data); 00154 void gnc_split_reg_sort_notes_cb (GtkWidget *w, gpointer data); 00155 00156 void gnc_split_reg_destroy_cb(GtkWidget *widget, gpointer data); 00157 void gnc_split_reg_size_allocate( GtkWidget *widget, 00158 GtkAllocation *allocation, 00159 gpointer user_data ); 00160 00161 00162 void gnc_split_reg_handle_exchange_cb (GtkWidget *w, gpointer data); 00163 00164 static void gnc_split_reg_class_init( GNCSplitRegClass *class ); 00165 static void gnc_split_reg_init( GNCSplitReg *gsr ); 00166 static void gnc_split_reg_init2( GNCSplitReg *gsr ); 00167 00168 void gnc_split_register_size_allocate (GtkWidget *widget, 00169 GtkAllocation *allocation, 00170 gpointer user_data); 00171 00172 FROM_STRING_FUNC(SortType, ENUM_LIST_SORTTYPE) 00173 AS_STRING_FUNC(SortType, ENUM_LIST_SORTTYPE) 00174 00175 GType 00176 gnc_split_reg_get_type( void ) 00177 { 00178 static GType gnc_split_reg_type = 0; 00179 00180 if (!gnc_split_reg_type) 00181 { 00182 GTypeInfo type_info = 00183 { 00184 sizeof(GNCSplitRegClass), /* class_size */ 00185 NULL, /* base_init */ 00186 NULL, /* base_finalize */ 00187 (GClassInitFunc)gnc_split_reg_class_init, 00188 NULL, /* class_finalize */ 00189 NULL, /* class_data */ 00190 sizeof(GNCSplitReg), /* */ 00191 0, /* n_preallocs */ 00192 (GInstanceInitFunc)gnc_split_reg_init, 00193 }; 00194 00195 gnc_split_reg_type = g_type_register_static( GTK_TYPE_VBOX, 00196 "GNCSplitReg", 00197 &type_info, 0 ); 00198 } 00199 00200 return gnc_split_reg_type; 00201 } 00202 00203 /* SIGNALS */ 00204 enum gnc_split_reg_signal_enum 00205 { 00206 ENTER_ENT_SIGNAL, 00207 CANCEL_ENT_SIGNAL, 00208 DELETE_ENT_SIGNAL, 00209 REINIT_ENT_SIGNAL, 00210 DUP_ENT_SIGNAL, 00211 SCHEDULE_ENT_SIGNAL, 00212 EXPAND_ENT_SIGNAL, 00213 BLANK_SIGNAL, 00214 JUMP_SIGNAL, 00215 CUT_SIGNAL, 00216 CUT_TXN_SIGNAL, 00217 COPY_SIGNAL, 00218 COPY_TXN_SIGNAL, 00219 PASTE_SIGNAL, 00220 PASTE_TXN_SIGNAL, 00221 VOID_TXN_SIGNAL, 00222 UNVOID_TXN_SIGNAL, 00223 REVERSE_TXN_SIGNAL, 00224 HELP_CHANGED_SIGNAL, 00225 INCLUDE_DATE_SIGNAL, 00226 LAST_SIGNAL 00227 }; 00228 00229 static guint gnc_split_reg_signals[LAST_SIGNAL] = { 0 }; 00230 00231 static void 00232 gnc_split_reg_class_init( GNCSplitRegClass *class ) 00233 { 00234 int i; 00235 GtkObjectClass *object_class; 00236 static struct similar_signal_info 00237 { 00238 enum gnc_split_reg_signal_enum s; 00239 const char *signal_name; 00240 guint defaultOffset; 00241 } signals[] = 00242 { 00243 { ENTER_ENT_SIGNAL, "enter_ent", G_STRUCT_OFFSET( GNCSplitRegClass, enter_ent_cb ) }, 00244 { CANCEL_ENT_SIGNAL, "cancel_ent", G_STRUCT_OFFSET( GNCSplitRegClass, cancel_ent_cb ) }, 00245 { DELETE_ENT_SIGNAL, "delete_ent", G_STRUCT_OFFSET( GNCSplitRegClass, delete_ent_cb ) }, 00246 { REINIT_ENT_SIGNAL, "reinit_ent", G_STRUCT_OFFSET( GNCSplitRegClass, reinit_ent_cb ) }, 00247 { DUP_ENT_SIGNAL, "dup_ent", G_STRUCT_OFFSET( GNCSplitRegClass, dup_ent_cb ) }, 00248 { SCHEDULE_ENT_SIGNAL, "schedule_ent", G_STRUCT_OFFSET( GNCSplitRegClass, schedule_ent_cb ) }, 00249 { EXPAND_ENT_SIGNAL, "expand_ent", G_STRUCT_OFFSET( GNCSplitRegClass, expand_ent_cb ) }, 00250 { BLANK_SIGNAL, "blank", G_STRUCT_OFFSET( GNCSplitRegClass, blank_cb ) }, 00251 { JUMP_SIGNAL, "jump", G_STRUCT_OFFSET( GNCSplitRegClass, jump_cb ) }, 00252 { CUT_SIGNAL, "cut", G_STRUCT_OFFSET( GNCSplitRegClass, cut_cb ) }, 00253 { CUT_TXN_SIGNAL, "cut_txn", G_STRUCT_OFFSET( GNCSplitRegClass, cut_txn_cb ) }, 00254 { COPY_SIGNAL, "copy", G_STRUCT_OFFSET( GNCSplitRegClass, copy_cb ) }, 00255 { COPY_TXN_SIGNAL, "copy_txn", G_STRUCT_OFFSET( GNCSplitRegClass, copy_txn_cb ) }, 00256 { PASTE_SIGNAL, "paste", G_STRUCT_OFFSET( GNCSplitRegClass, paste_cb ) }, 00257 { PASTE_TXN_SIGNAL, "paste_txn", G_STRUCT_OFFSET( GNCSplitRegClass, paste_txn_cb ) }, 00258 { VOID_TXN_SIGNAL, "void_txn", G_STRUCT_OFFSET( GNCSplitRegClass, void_txn_cb ) }, 00259 { UNVOID_TXN_SIGNAL, "unvoid_txn", G_STRUCT_OFFSET( GNCSplitRegClass, unvoid_txn_cb ) }, 00260 { REVERSE_TXN_SIGNAL, "reverse_txn", G_STRUCT_OFFSET( GNCSplitRegClass, reverse_txn_cb ) }, 00261 { HELP_CHANGED_SIGNAL, "help-changed", G_STRUCT_OFFSET( GNCSplitRegClass, help_changed_cb ) }, 00262 { INCLUDE_DATE_SIGNAL, "include-date", G_STRUCT_OFFSET( GNCSplitRegClass, include_date_cb ) }, 00263 { LAST_SIGNAL, NULL, 0 } 00264 }; 00265 00266 object_class = (GtkObjectClass*) class; 00267 00268 for ( i = 0; signals[i].s != INCLUDE_DATE_SIGNAL; i++ ) 00269 { 00270 gnc_split_reg_signals[ signals[i].s ] = 00271 g_signal_new( signals[i].signal_name, 00272 G_TYPE_FROM_CLASS(object_class), 00273 G_SIGNAL_RUN_LAST, 00274 signals[i].defaultOffset, 00275 NULL, NULL, 00276 g_cclosure_marshal_VOID__VOID, 00277 G_TYPE_NONE, 0 ); 00278 } 00279 /* Setup the non-default-marshalled signals; 'i' is still valid, here. */ 00280 /* "include-date" */ 00281 gnc_split_reg_signals[ INCLUDE_DATE_SIGNAL ] = 00282 g_signal_new( "include-date", 00283 G_TYPE_FROM_CLASS(object_class), 00284 G_SIGNAL_RUN_LAST, 00285 signals[i++].defaultOffset, 00286 NULL, NULL, 00287 g_cclosure_marshal_VOID__INT, /* time_t == int */ 00288 G_TYPE_NONE, 1, G_TYPE_INT ); 00289 00290 g_assert( i == LAST_SIGNAL ); 00291 00292 /* Setup the default handlers. */ 00293 class->enter_ent_cb = gsr_default_enter_handler; 00294 class->cancel_ent_cb = gsr_default_cancel_handler; 00295 class->delete_ent_cb = gsr_default_delete_handler; 00296 class->reinit_ent_cb = gsr_default_reinit_handler; 00297 class->dup_ent_cb = gsr_default_dup_handler; 00298 class->schedule_ent_cb = gsr_default_schedule_handler; 00299 class->expand_ent_cb = gsr_default_expand_handler; 00300 class->blank_cb = gsr_default_blank_handler; 00301 class->jump_cb = gsr_default_jump_handler; 00302 class->cut_cb = gsr_default_cut_handler; 00303 class->cut_txn_cb = gsr_default_cut_txn_handler; 00304 class->copy_cb = gsr_default_copy_handler; 00305 class->copy_txn_cb = gsr_default_copy_txn_handler; 00306 class->paste_cb = gsr_default_paste_handler; 00307 class->paste_txn_cb = gsr_default_paste_txn_handler; 00308 class->void_txn_cb = gsr_default_void_txn_handler; 00309 class->unvoid_txn_cb = gsr_default_unvoid_txn_handler; 00310 class->reverse_txn_cb = gsr_default_reverse_txn_handler; 00311 00312 class->help_changed_cb = NULL; 00313 class->include_date_cb = NULL; 00314 } 00315 00316 GtkWidget* 00317 gnc_split_reg_new( GNCLedgerDisplay *ld, 00318 GtkWindow *parent, 00319 gint numberOfLines, 00320 gboolean read_only ) 00321 { 00322 GNCSplitReg *gsrToRet; 00323 00324 ENTER("ld=%p, parent=%p, numberOfLines=%d, read_only=%s", 00325 ld, parent, numberOfLines, read_only ? "TRUE" : "FALSE"); 00326 00327 gsrToRet = g_object_new( gnc_split_reg_get_type(), NULL ); 00328 00329 gsrToRet->numRows = numberOfLines; 00330 gsrToRet->read_only = read_only; 00331 00332 gsrToRet->ledger = ld; 00333 gsrToRet->window = GTK_WIDGET(parent); 00334 00335 gnc_split_reg_init2( gsrToRet ); 00336 00337 LEAVE("%p", gsrToRet); 00338 return GTK_WIDGET( gsrToRet ); 00339 } 00340 00341 static void 00342 gnc_split_reg_init( GNCSplitReg *gsr ) 00343 { 00344 gsr->sort_type = BY_STANDARD; 00345 gsr->width = -1; 00346 gsr->height = -1; 00347 gsr->numRows = 10; 00348 gsr->read_only = FALSE; 00349 00350 g_signal_connect( gsr, "destroy", 00351 G_CALLBACK (gnc_split_reg_destroy_cb), gsr ); 00352 } 00353 00354 static void 00355 gnc_split_reg_init2( GNCSplitReg *gsr ) 00356 { 00357 if ( !gsr ) return; 00358 00359 gnc_split_reg_determine_read_only( gsr ); 00360 00361 gsr_setup_status_widgets( gsr ); 00362 /* ordering is important here... setup_status before create_table */ 00363 gsr_create_table( gsr ); 00364 gsr_setup_table( gsr ); 00365 } 00366 00367 static 00368 void 00369 gsr_setup_table( GNCSplitReg *gsr ) 00370 { 00371 SplitRegister *sr; 00372 00373 ENTER("gsr=%p", gsr); 00374 00375 sr = gnc_ledger_display_get_split_register( gsr->ledger ); 00376 gnc_split_register_show_present_divider( sr, TRUE ); 00377 /* events should be sufficient to redraw this */ 00378 /* gnc_ledger_display_refresh( gsr->ledger ); */ 00379 gnc_split_reg_refresh_toolbar( gsr ); 00380 00381 LEAVE(" "); 00382 } 00383 00384 static 00385 void 00386 gsr_create_table( GNCSplitReg *gsr ) 00387 { 00388 GtkWidget *register_widget; 00389 SplitRegister *sr; 00390 00391 ENTER("gsr=%p", gsr); 00392 00393 gnc_ledger_display_set_user_data( gsr->ledger, (gpointer)gsr ); 00394 gnc_ledger_display_set_handlers( gsr->ledger, 00395 gnc_split_reg_ld_destroy, 00396 gnc_split_reg_get_parent ); 00397 00398 /* FIXME: We'd really rather pass this down... */ 00399 sr = gnc_ledger_display_get_split_register( gsr->ledger ); 00400 register_widget = gnucash_register_new( sr->table ); 00401 gsr->reg = GNUCASH_REGISTER( register_widget ); 00402 gnc_table_init_gui( GTK_WIDGET(gsr->reg), sr ); 00403 00404 gtk_box_pack_start (GTK_BOX (gsr), GTK_WIDGET(gsr->reg), TRUE, TRUE, 0); 00405 GNUCASH_SHEET(gsr->reg->sheet)->window = gsr->window; 00406 gtk_widget_show ( GTK_WIDGET(gsr->reg) ); 00407 g_signal_connect (gsr->reg, "activate_cursor", 00408 G_CALLBACK(gnc_split_reg_record_cb), gsr); 00409 g_signal_connect (gsr->reg, "redraw_all", 00410 G_CALLBACK(gsr_redraw_all_cb), gsr); 00411 g_signal_connect (gsr->reg, "redraw_help", 00412 G_CALLBACK(gsr_emit_help_changed), gsr); 00413 00414 LEAVE(" "); 00415 } 00416 00417 static 00418 void 00419 gsr_setup_status_widgets( GNCSplitReg *gsr ) 00420 { 00421 SplitRegister *sr; 00422 gboolean use_double_line; 00423 00424 sr = gnc_ledger_display_get_split_register( gsr->ledger ); 00425 use_double_line = gnc_ledger_display_default_double_line( gsr->ledger ); 00426 00427 /* be sure to initialize the gui elements associated with the cursor */ 00428 gnc_split_register_config( sr, sr->type, sr->style, use_double_line ); 00429 } 00430 00431 void 00432 gnc_split_reg_destroy_cb(GtkWidget *widget, gpointer data) 00433 { 00434 } 00435 00439 void 00440 gnc_split_reg_raise( GNCSplitReg *gsr ) 00441 { 00442 if (gsr == NULL) 00443 return; 00444 00445 if (gsr->window == NULL) 00446 return; 00447 00448 gtk_window_present( GTK_WINDOW(gsr->window) ); 00449 } 00450 00451 00456 static 00457 void 00458 gsr_update_summary_label( GtkWidget *label, 00459 xaccGetBalanceFn getter, 00460 Account *leader, 00461 GNCPrintAmountInfo print_info, 00462 gnc_commodity *cmdty, 00463 gboolean reverse, 00464 gboolean euroFlag ) 00465 { 00466 gnc_numeric amount; 00467 char string[256]; 00468 00469 if ( label == NULL ) 00470 return; 00471 00472 amount = (*getter)( leader ); 00473 00474 if ( reverse ) 00475 { 00476 amount = gnc_numeric_neg( amount ); 00477 } 00478 00479 xaccSPrintAmount( string, amount, print_info ); 00480 00481 if ( euroFlag ) 00482 { 00483 strcat( string, " / " ); 00484 xaccSPrintAmount( string + strlen( string ), 00485 gnc_convert_to_euro( cmdty, amount ), 00486 gnc_commodity_print_info( gnc_get_euro(), TRUE ) ); 00487 } 00488 00489 gnc_set_label_color( label, amount ); 00490 gtk_label_set_text( GTK_LABEL(label), string ); 00491 } 00492 00493 static GNCPrice * 00494 account_latest_price (Account *account) 00495 { 00496 QofBook *book; 00497 GNCPriceDB *pdb; 00498 gnc_commodity *commodity; 00499 gnc_commodity *currency; 00500 00501 if (!account) return NULL; 00502 commodity = xaccAccountGetCommodity (account); 00503 currency = gnc_default_currency (); 00504 00505 book = gnc_account_get_book (account); 00506 pdb = gnc_pricedb_get_db (book); 00507 00508 return gnc_pricedb_lookup_latest (pdb, commodity, currency); 00509 } 00510 00511 static GNCPrice * 00512 account_latest_price_any_currency (Account *account) 00513 { 00514 QofBook *book; 00515 GNCPriceDB *pdb; 00516 gnc_commodity *commodity; 00517 GList *price_list; 00518 GNCPrice *result; 00519 00520 if (!account) return NULL; 00521 commodity = xaccAccountGetCommodity (account); 00522 00523 book = gnc_account_get_book (account); 00524 pdb = gnc_pricedb_get_db (book); 00525 00526 price_list = gnc_pricedb_lookup_latest_any_currency (pdb, commodity); 00527 if (!price_list) return NULL; 00528 00529 result = gnc_price_clone((GNCPrice *)(price_list->data), book); 00530 00531 gnc_price_list_destroy(price_list); 00532 00533 return result; 00534 } 00535 00536 static 00537 void 00538 gsr_redraw_all_cb (GnucashRegister *g_reg, gpointer data) 00539 { 00540 GNCSplitReg *gsr = data; 00541 gnc_commodity * commodity; 00542 GNCPrintAmountInfo print_info; 00543 gnc_numeric amount; 00544 char string[256]; 00545 Account *leader; 00546 gboolean reverse; 00547 gboolean euro; 00548 00549 if ( gsr->summarybar == NULL ) 00550 return; 00551 00552 leader = gnc_ledger_display_leader( gsr->ledger ); 00553 00554 commodity = xaccAccountGetCommodity( leader ); 00555 00556 /* no EURO converson, if account is already EURO or no EURO currency */ 00557 if (commodity != NULL) 00558 euro = (gnc_is_euro_currency( commodity ) && 00559 (strncasecmp(gnc_commodity_get_mnemonic(commodity), "EUR", 3))); 00560 else 00561 euro = FALSE; 00562 00563 print_info = gnc_account_print_info( leader, TRUE ); 00564 reverse = gnc_reverse_balance( leader ); 00565 00566 gsr_update_summary_label( gsr->balance_label, 00567 xaccAccountGetPresentBalance, 00568 leader, print_info, commodity, reverse, euro ); 00569 gsr_update_summary_label( gsr->cleared_label, 00570 xaccAccountGetClearedBalance, 00571 leader, print_info, commodity, reverse, euro ); 00572 gsr_update_summary_label( gsr->reconciled_label, 00573 xaccAccountGetReconciledBalance, 00574 leader, print_info, commodity, reverse, euro ); 00575 gsr_update_summary_label( gsr->future_label, 00576 xaccAccountGetBalance, 00577 leader, print_info, commodity, reverse, euro ); 00578 gsr_update_summary_label( gsr->projectedminimum_label, 00579 xaccAccountGetProjectedMinimumBalance, 00580 leader, print_info, commodity, reverse, euro ); 00581 00582 /* Print the summary share amount */ 00583 if (gsr->shares_label != NULL) 00584 { 00585 print_info = gnc_account_print_info( leader, TRUE ); 00586 00587 amount = xaccAccountGetBalance( leader ); 00588 if (reverse) 00589 amount = gnc_numeric_neg( amount ); 00590 00591 xaccSPrintAmount( string, amount, print_info ); 00592 00593 gnc_set_label_color( gsr->shares_label, amount ); 00594 gtk_label_set_text( GTK_LABEL(gsr->shares_label), string ); 00595 } 00596 00597 /* Print the summary share value */ 00598 if (gsr->value_label != NULL) 00599 { 00600 GNCPrice *price; 00601 00602 amount = xaccAccountGetBalance (leader); 00603 if (reverse) amount = gnc_numeric_neg (amount); 00604 00605 price = account_latest_price (leader); 00606 if (!price) 00607 { 00608 /* If the balance is zero, then print zero. */ 00609 if (gnc_numeric_equal(amount, gnc_numeric_zero())) 00610 { 00611 gnc_commodity *currency = gnc_default_currency (); 00612 print_info = gnc_commodity_print_info (currency, TRUE); 00613 amount = gnc_numeric_zero (); 00614 00615 xaccSPrintAmount (string, amount, print_info); 00616 00617 gnc_set_label_color (gsr->value_label, amount); 00618 gtk_label_set_text (GTK_LABEL (gsr->value_label), string); 00619 } 00620 else 00621 { 00622 /* else try to do a double-price-conversion :-( */ 00623 price = account_latest_price_any_currency (leader); 00624 if (!price) 00625 { 00626 gnc_set_label_color (gsr->value_label, gnc_numeric_zero ()); 00627 gtk_label_set_text (GTK_LABEL (gsr->value_label), 00628 _("<No information>")); 00629 } 00630 else 00631 { 00632 gnc_commodity *currency = gnc_price_get_currency (price); 00633 gnc_commodity *default_currency = gnc_default_currency (); 00634 gnc_numeric currency_amount; 00635 gnc_numeric default_currency_amount; 00636 00637 print_info = gnc_commodity_print_info (currency, TRUE); 00638 00639 currency_amount = 00640 xaccAccountConvertBalanceToCurrency(leader, amount, 00641 commodity, currency); 00642 xaccSPrintAmount (string, currency_amount, print_info); 00643 00644 default_currency_amount = 00645 xaccAccountConvertBalanceToCurrency(leader, amount, 00646 commodity, 00647 default_currency); 00648 if (!gnc_numeric_zero_p(default_currency_amount)) 00649 { 00650 strcat( string, " / " ); 00651 print_info = gnc_commodity_print_info (default_currency, TRUE); 00652 xaccSPrintAmount( string + strlen( string ), default_currency_amount, 00653 print_info); 00654 } 00655 00656 gnc_set_label_color (gsr->value_label, amount); 00657 gtk_label_set_text (GTK_LABEL (gsr->value_label), string); 00658 00659 gnc_price_unref (price); 00660 } 00661 } 00662 } 00663 else 00664 { 00665 gnc_commodity *currency = gnc_price_get_currency (price); 00666 00667 print_info = gnc_commodity_print_info (currency, TRUE); 00668 00669 amount = gnc_numeric_mul (amount, gnc_price_get_value (price), 00670 gnc_commodity_get_fraction (currency), 00671 GNC_HOW_RND_ROUND_HALF_UP); 00672 00673 xaccSPrintAmount (string, amount, print_info); 00674 00675 gnc_set_label_color (gsr->value_label, amount); 00676 gtk_label_set_text (GTK_LABEL (gsr->value_label), string); 00677 00678 gnc_price_unref (price); 00679 } 00680 } 00681 } 00682 00683 static void 00684 gnc_split_reg_refresh_toolbar( GNCSplitReg *gsr ) 00685 { 00686 GtkToolbarStyle tbstyle; 00687 00688 if ((gsr == NULL) || (gsr->toolbar == NULL)) 00689 return; 00690 00691 tbstyle = gnc_get_toolbar_style (); 00692 gtk_toolbar_set_style( GTK_TOOLBAR(gsr->toolbar), tbstyle ); 00693 } 00694 00695 static void 00696 gnc_split_reg_ld_destroy( GNCLedgerDisplay *ledger ) 00697 { 00698 GNCSplitReg *gsr = gnc_ledger_display_get_user_data( ledger ); 00699 00700 if (gsr) 00701 { 00702 SplitRegister *reg; 00703 00704 reg = gnc_ledger_display_get_split_register (ledger); 00705 00706 if (reg && reg->table) 00707 gnc_table_save_state (reg->table); 00708 00709 /* 00710 * Don't destroy the window here any more. The register no longer 00711 * owns it. 00712 */ 00713 } 00714 gnc_ledger_display_set_user_data (ledger, NULL); 00715 } 00716 00717 void 00718 gsr_default_cut_handler( GNCSplitReg *gsr, gpointer data ) 00719 { 00720 gnucash_register_cut_clipboard( gsr->reg ); 00721 } 00722 00726 void 00727 gnc_split_reg_cut_cb (GtkWidget *w, gpointer data) 00728 { 00729 GNCSplitReg *gsr = data; 00730 gsr_emit_simple_signal( gsr, "cut" ); 00731 } 00732 00733 void 00734 gsr_default_copy_handler( GNCSplitReg *gsr, gpointer data ) 00735 { 00736 gnucash_register_copy_clipboard( gsr->reg ); 00737 } 00738 00742 void 00743 gnc_split_reg_copy_cb (GtkWidget *w, gpointer data) 00744 { 00745 GNCSplitReg *gsr = data; 00746 gsr_emit_simple_signal( gsr, "copy" ); 00747 } 00748 00749 void 00750 gsr_default_paste_handler( GNCSplitReg *gsr, gpointer data ) 00751 { 00752 gnucash_register_paste_clipboard( gsr->reg ); 00753 } 00754 00758 void 00759 gnc_split_reg_paste_cb (GtkWidget *w, gpointer data) 00760 { 00761 GNCSplitReg *gsr = data; 00762 gsr_emit_simple_signal( gsr, "paste" ); 00763 } 00764 00765 void 00766 gsr_default_cut_txn_handler( GNCSplitReg *gsr, gpointer data ) 00767 { 00768 gnc_split_register_cut_current 00769 (gnc_ledger_display_get_split_register( gsr->ledger )); 00770 } 00771 00775 void 00776 gnc_split_reg_cut_trans_cb (GtkWidget *w, gpointer data) 00777 { 00778 GNCSplitReg *gsr = data; 00779 gsr_emit_simple_signal( gsr, "cut_txn" ); 00780 } 00781 00782 void 00783 gsr_default_copy_txn_handler( GNCSplitReg *gsr, gpointer data ) 00784 { 00785 gnc_split_register_copy_current 00786 (gnc_ledger_display_get_split_register( gsr->ledger )); 00787 } 00788 00792 void 00793 gnc_split_reg_copy_trans_cb(GtkWidget *w, gpointer data) 00794 { 00795 GNCSplitReg *gsr = data; 00796 gsr_emit_simple_signal( gsr, "copy_txn" ); 00797 } 00798 00799 void 00800 gsr_default_paste_txn_handler( GNCSplitReg *gsr, gpointer data ) 00801 { 00802 gnc_split_register_paste_current 00803 (gnc_ledger_display_get_split_register( gsr->ledger )); 00804 } 00805 00809 void 00810 gnc_split_reg_paste_trans_cb (GtkWidget *w, gpointer data) 00811 { 00812 GNCSplitReg *gsr = data; 00813 gsr_emit_simple_signal( gsr, "paste_txn" ); 00814 } 00815 00816 /********************************************************************\ 00817 * gnc_split_reg_void_trans_cb * 00818 * * 00819 * Args: widget - the widget that called us * 00820 * data - the data struct for this register * 00821 * Return: none * 00822 \********************************************************************/ 00823 void 00824 gsr_default_void_txn_handler (GNCSplitReg *gsr, gpointer data) 00825 { 00826 // Override this function. 00827 } 00828 00829 void 00830 gnc_split_reg_void_trans_cb (GtkWidget *w, gpointer data) 00831 { 00832 GNCSplitReg *gsr = data; 00833 gsr_emit_simple_signal( gsr, "void_txn" ); 00834 } 00835 00836 /********************************************************************\ 00837 * gnc_split_reg_unvoid_trans_cb * 00838 * * 00839 * Args: widget - the widget that called us * 00840 * data - the data struct for this register * 00841 * Return: none * 00842 \********************************************************************/ 00843 void 00844 gsr_default_unvoid_txn_handler (GNCSplitReg *gsr, gpointer data) 00845 { 00846 // Override this function. 00847 } 00848 00849 void 00850 gnc_split_reg_unvoid_trans_cb (GtkWidget *w, gpointer data) 00851 { 00852 GNCSplitReg *gsr = data; 00853 gsr_emit_simple_signal( gsr, "unvoid_txn" ); 00854 } 00855 00856 /********************************************************************\ 00857 * gnc_split_reg_reverse_trans_cb * 00858 * * 00859 * Args: widget - the widget that called us * 00860 * data - the data struct for this register * 00861 * Return: none * 00862 \********************************************************************/ 00863 void 00864 gsr_default_reverse_txn_handler (GNCSplitReg *gsr, gpointer data) 00865 { 00866 SplitRegister *reg; 00867 Transaction *trans, *new_trans; 00868 00869 reg = gnc_ledger_display_get_split_register( gsr->ledger ); 00870 trans = gnc_split_register_get_current_trans (reg); 00871 if (trans == NULL) 00872 return; 00873 00874 if (xaccTransGetReversedBy(trans)) 00875 { 00876 gnc_error_dialog(gsr->window, "%s", 00877 _("A reversing entry has already been created for this transaction.")); 00878 return; 00879 } 00880 00881 new_trans = xaccTransReverse(trans); 00882 00883 /* Clear transaction level info */ 00884 xaccTransSetDatePostedSecs(new_trans, time(NULL)); 00885 xaccTransSetDateEnteredSecs(new_trans, time(NULL)); 00886 00887 /* Now jump to new trans */ 00888 gnc_split_reg_jump_to_split(gsr, xaccTransGetSplit(new_trans, 0)); 00889 } 00890 00891 void 00892 gnc_split_reg_reverse_trans_cb (GtkWidget *w, gpointer data) 00893 { 00894 GNCSplitReg *gsr = data; 00895 gsr_emit_simple_signal( gsr, "reverse_txn" ); 00896 } 00897 00898 00899 static gboolean 00900 is_trans_readonly_and_warn (const Transaction *trans) 00901 { 00902 GtkWidget *dialog; 00903 const gchar *reason; 00904 const gchar *title = _("Cannot modify or delete this transaction."); 00905 const gchar *message = 00906 _("This transaction is marked read-only with the comment: '%s'"); 00907 00908 if (!trans) return FALSE; 00909 00910 if (xaccTransIsReadonlyByPostedDate (trans)) 00911 { 00912 dialog = gtk_message_dialog_new(NULL, 00913 0, 00914 GTK_MESSAGE_ERROR, 00915 GTK_BUTTONS_OK, 00916 "%s", title); 00917 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), 00918 "%s", _("The date of this transaction is older than the \"Read-Only Threshold\" set for this book. " 00919 "This setting can be changed in File -> Properties -> Accounts.")); 00920 gtk_dialog_run(GTK_DIALOG(dialog)); 00921 gtk_widget_destroy(dialog); 00922 return TRUE; 00923 } 00924 00925 reason = xaccTransGetReadOnly (trans); 00926 if (reason) 00927 { 00928 dialog = gtk_message_dialog_new(NULL, 00929 0, 00930 GTK_MESSAGE_ERROR, 00931 GTK_BUTTONS_OK, 00932 "%s", title); 00933 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), 00934 message, reason); 00935 gtk_dialog_run(GTK_DIALOG(dialog)); 00936 gtk_widget_destroy(dialog); 00937 return TRUE; 00938 } 00939 return FALSE; 00940 } 00941 00942 00943 void 00944 gsr_default_reinit_handler( GNCSplitReg *gsr, gpointer data ) 00945 { 00946 VirtualCellLocation vcell_loc; 00947 SplitRegister *reg; 00948 Transaction *trans; 00949 Split *split; 00950 GtkWidget *dialog; 00951 gint response; 00952 const gchar *warning; 00953 00954 const char *title = _("Remove the splits from this transaction?"); 00955 const char *recn_warn = _("This transaction contains reconciled splits. " 00956 "Modifying it is not a good idea because that will " 00957 "cause your reconciled balance to be off."); 00958 00959 reg = gnc_ledger_display_get_split_register( gsr->ledger ); 00960 00961 trans = gnc_split_register_get_current_trans (reg); 00962 if (is_trans_readonly_and_warn(trans)) 00963 return; 00964 dialog = gtk_message_dialog_new(GTK_WINDOW(gsr->window), 00965 GTK_DIALOG_DESTROY_WITH_PARENT, 00966 GTK_MESSAGE_WARNING, 00967 GTK_BUTTONS_NONE, 00968 "%s", title); 00969 if (xaccTransHasReconciledSplits (trans)) 00970 { 00971 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), 00972 "%s", recn_warn); 00973 warning = "register_remove_all_splits2"; 00974 } 00975 else 00976 { 00977 warning = "register_remove_all_splits"; 00978 } 00979 00980 gtk_dialog_add_button(GTK_DIALOG(dialog), 00981 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); 00982 gnc_gtk_dialog_add_button(dialog, _("_Remove Splits"), 00983 GTK_STOCK_DELETE, GTK_RESPONSE_ACCEPT); 00984 response = gnc_dialog_run(GTK_DIALOG(dialog), warning); 00985 gtk_widget_destroy (dialog); 00986 if (response != GTK_RESPONSE_ACCEPT) 00987 return; 00988 00989 /* 00990 * Find the "transaction" split for the current transaction. This is 00991 * the split that appears at the top of the transaction in the 00992 * register. 00993 */ 00994 split = gnc_split_register_get_current_split (reg); 00995 if (!gnc_split_register_get_split_virt_loc(reg, split, &vcell_loc)) 00996 return; 00997 split = gnc_split_register_get_current_trans_split (reg, &vcell_loc); 00998 gnc_split_register_empty_current_trans_except_split (reg, split); 00999 } 01000 01004 void 01005 gnc_split_reg_reinitialize_trans_cb(GtkWidget *widget, gpointer data) 01006 { 01007 GNCSplitReg *gsr = data; 01008 gsr_emit_simple_signal( gsr, "reinit_ent" ); 01009 } 01010 01011 void 01012 gsr_default_delete_handler( GNCSplitReg *gsr, gpointer data ) 01013 { 01014 SplitRegisterStyle style; 01015 CursorClass cursor_class; 01016 SplitRegister *reg; 01017 Transaction *trans; 01018 Split *split; 01019 GtkWidget *dialog; 01020 gint response; 01021 const gchar *warning; 01022 01023 reg = gnc_ledger_display_get_split_register( gsr->ledger ); 01024 01025 /* get the current split based on cursor position */ 01026 split = gnc_split_register_get_current_split(reg); 01027 if (split == NULL) 01028 { 01029 gnc_split_register_cancel_cursor_split_changes (reg); 01030 return; 01031 } 01032 01033 trans = xaccSplitGetParent(split); 01034 style = reg->style; 01035 cursor_class = gnc_split_register_get_current_cursor_class (reg); 01036 01037 /* Deleting the blank split just cancels */ 01038 { 01039 Split *blank_split = gnc_split_register_get_blank_split (reg); 01040 01041 if (split == blank_split) 01042 { 01043 gnc_split_register_cancel_cursor_trans_changes (reg); 01044 return; 01045 } 01046 } 01047 01048 if (cursor_class == CURSOR_CLASS_NONE) 01049 return; 01050 01051 if (is_trans_readonly_and_warn(trans)) 01052 return; 01053 01054 /* On a split cursor, just delete the one split. */ 01055 if (cursor_class == CURSOR_CLASS_SPLIT) 01056 { 01057 const char *format = _("Delete the split '%s' from the transaction '%s'?"); 01058 const char *recn_warn = _("You would be deleting a reconciled split! " 01059 "This is not a good idea as it will cause your " 01060 "reconciled balance to be off."); 01061 const char *anchor_error = _("You cannot delete this split."); 01062 const char *anchor_split = _("This is the split anchoring this transaction " 01063 "to the register. You may not delete it from " 01064 "this register window. You may delete the " 01065 "entire transaction from this window, or you " 01066 "may navigate to a register that shows " 01067 "another side of this same transaction and " 01068 "delete the split from that register."); 01069 char *buf = NULL; 01070 const char *memo; 01071 const char *desc; 01072 char recn; 01073 01074 if (split == gnc_split_register_get_current_trans_split (reg, NULL)) 01075 { 01076 dialog = gtk_message_dialog_new(GTK_WINDOW(gsr->window), 01077 GTK_DIALOG_MODAL 01078 | GTK_DIALOG_DESTROY_WITH_PARENT, 01079 GTK_MESSAGE_ERROR, 01080 GTK_BUTTONS_OK, 01081 "%s", anchor_error); 01082 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), 01083 "%s", anchor_split); 01084 gtk_dialog_run(GTK_DIALOG(dialog)); 01085 gtk_widget_destroy (dialog); 01086 return; 01087 } 01088 01089 memo = xaccSplitGetMemo (split); 01090 memo = (memo && *memo) ? memo : _("(no memo)"); 01091 01092 desc = xaccTransGetDescription (trans); 01093 desc = (desc && *desc) ? desc : _("(no description)"); 01094 01095 /* ask for user confirmation before performing permanent damage */ 01096 buf = g_strdup_printf (format, memo, desc); 01097 dialog = gtk_message_dialog_new(GTK_WINDOW(gsr->window), 01098 GTK_DIALOG_MODAL 01099 | GTK_DIALOG_DESTROY_WITH_PARENT, 01100 GTK_MESSAGE_QUESTION, 01101 GTK_BUTTONS_NONE, 01102 "%s", buf); 01103 g_free(buf); 01104 recn = xaccSplitGetReconcile (split); 01105 if (recn == YREC || recn == FREC) 01106 { 01107 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), 01108 "%s", recn_warn); 01109 warning = "register_delete_split2"; 01110 } 01111 else 01112 { 01113 warning = "register_delete_split"; 01114 } 01115 01116 gtk_dialog_add_button(GTK_DIALOG(dialog), 01117 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); 01118 gnc_gtk_dialog_add_button(dialog, _("_Delete Split"), 01119 GTK_STOCK_DELETE, GTK_RESPONSE_ACCEPT); 01120 response = gnc_dialog_run(GTK_DIALOG(dialog), warning); 01121 gtk_widget_destroy (dialog); 01122 if (response != GTK_RESPONSE_ACCEPT) 01123 return; 01124 01125 gnc_split_register_delete_current_split (reg); 01126 return; 01127 } 01128 01129 g_return_if_fail(cursor_class == CURSOR_CLASS_TRANS); 01130 01131 /* On a transaction cursor with 2 or fewer splits in single or double 01132 * mode, we just delete the whole transaction, kerblooie */ 01133 { 01134 const char *title = _("Delete the current transaction?"); 01135 const char *recn_warn = _("You would be deleting a transaction " 01136 "with reconciled splits! " 01137 "This is not a good idea as it will cause your " 01138 "reconciled balance to be off."); 01139 01140 dialog = gtk_message_dialog_new(GTK_WINDOW(gsr->window), 01141 GTK_DIALOG_MODAL 01142 | GTK_DIALOG_DESTROY_WITH_PARENT, 01143 GTK_MESSAGE_WARNING, 01144 GTK_BUTTONS_NONE, 01145 "%s", title); 01146 if (xaccTransHasReconciledSplits (trans)) 01147 { 01148 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), 01149 "%s", recn_warn); 01150 warning = "register_delete_trans2"; 01151 } 01152 else 01153 { 01154 warning = "register_delete_trans"; 01155 } 01156 gtk_dialog_add_button(GTK_DIALOG(dialog), 01157 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); 01158 gnc_gtk_dialog_add_button(dialog, _("_Delete Transaction"), 01159 GTK_STOCK_DELETE, GTK_RESPONSE_ACCEPT); 01160 response = gnc_dialog_run(GTK_DIALOG(dialog), warning); 01161 gtk_widget_destroy (dialog); 01162 if (response != GTK_RESPONSE_ACCEPT) 01163 return; 01164 01165 gnc_split_register_delete_current_trans (reg); 01166 return; 01167 } 01168 } 01169 01173 void 01174 gnc_split_reg_delete_trans_cb(GtkWidget *widget, gpointer data) 01175 { 01176 GNCSplitReg *gsr = data; 01177 gsr_emit_simple_signal( gsr, "delete_ent" ); 01178 } 01179 01180 void 01181 gsr_default_dup_handler( GNCSplitReg *gsr, gpointer data ) 01182 { 01183 gnc_split_register_duplicate_current 01184 (gnc_ledger_display_get_split_register( gsr->ledger )); 01185 } 01186 01190 void 01191 gnc_split_reg_duplicate_trans_cb(GtkWidget *w, gpointer data) 01192 { 01193 GNCSplitReg *gsr = data; 01194 gsr_emit_simple_signal( gsr, "dup_ent" ); 01195 } 01196 01202 void 01203 gsr_default_schedule_handler( GNCSplitReg *gsr, gpointer data ) 01204 { 01205 SplitRegister *reg = gnc_ledger_display_get_split_register( gsr->ledger ); 01206 Transaction *pending_trans = gnc_split_register_get_current_trans (reg); 01207 01208 /* If the transaction has a sched-xact KVP frame, then go to the editor 01209 * for the existing SX; otherwise, do the sx-from-trans dialog. */ 01210 { 01211 kvp_frame *txn_frame; 01212 kvp_value *kvp_val; 01213 /* set a kvp-frame element in the transaction indicating and 01214 * pointing-to the SX this was created from. */ 01215 txn_frame = xaccTransGetSlots( pending_trans ); 01216 if ( txn_frame != NULL ) 01217 { 01218 kvp_val = kvp_frame_get_slot( txn_frame, "from-sched-xaction" ); 01219 if ( kvp_val ) 01220 { 01221 GncGUID *fromSXId = kvp_value_get_guid( kvp_val ); 01222 SchedXaction *theSX = NULL; 01223 GList *sxElts; 01224 01225 /* Get the correct SX */ 01226 for ( sxElts = gnc_book_get_schedxactions(gnc_get_current_book())->sx_list; 01227 (!theSX) && sxElts; 01228 sxElts = sxElts->next ) 01229 { 01230 SchedXaction *sx = (SchedXaction*)sxElts->data; 01231 theSX = 01232 ( ( guid_equal( xaccSchedXactionGetGUID( sx ), fromSXId ) ) 01233 ? sx : NULL ); 01234 } 01235 01236 if ( theSX ) 01237 { 01238 gnc_ui_scheduled_xaction_editor_dialog_create(theSX, FALSE); 01239 return; 01240 } 01241 } 01242 } 01243 } 01244 01245 gnc_sx_create_from_trans(pending_trans); 01246 } 01247 01248 void 01249 gnc_split_reg_recur_cb(GtkWidget *w, gpointer data) 01250 { 01251 GNCSplitReg *gsr = data; 01252 gsr_emit_simple_signal( gsr, "schedule_ent" ); 01253 } 01254 01258 void 01259 gnc_split_reg_record_trans_cb (GtkWidget *w, gpointer data) 01260 { 01261 GNCSplitReg *gsr = data; 01262 gsr_emit_simple_signal( gsr, "enter_ent" ); 01263 } 01264 01265 void 01266 gsr_default_cancel_handler( GNCSplitReg *gsr, gpointer data ) 01267 { 01268 gnc_split_register_cancel_cursor_trans_changes 01269 (gnc_ledger_display_get_split_register( gsr->ledger )); 01270 } 01271 01275 void 01276 gnc_split_reg_cancel_trans_cb(GtkWidget *w, gpointer data) 01277 { 01278 GNCSplitReg *gsr = data; 01279 gsr_emit_simple_signal( gsr, "cancel_ent" ); 01280 } 01281 01282 void 01283 gsr_default_expand_handler( GNCSplitReg *gsr, gpointer data ) 01284 { 01285 gint activeCount; 01286 gboolean expand; 01287 SplitRegister *reg; 01288 01289 if (!gsr) 01290 return; 01291 01292 reg = gnc_ledger_display_get_split_register (gsr->ledger); 01293 01294 /* These should all be in agreement. */ 01295 activeCount = 01296 ( ( GTK_CHECK_MENU_ITEM(gsr->split_menu_check)->active ? 1 : -1 ) 01297 + ( GTK_CHECK_MENU_ITEM(gsr->split_popup_check)->active ? 1 : -1 ) 01298 + ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(gsr->split_button) ) 01299 ? 1 : -1 ) ); 01300 01301 /* If activeCount > 0, then there's more active than inactive; otherwise, 01302 * more inactive than active. Both determine which state the user is 01303 * attempting to get to. */ 01304 expand = ( activeCount < 0 ); 01305 01306 /* The ledger's invocation of 'redraw_all' will force the agreement in the 01307 * other split state widgets, so we neglect doing it here. */ 01308 gnc_split_register_expand_current_trans (reg, expand); 01309 } 01310 01311 void 01312 gnc_split_reg_expand_trans_menu_cb (GtkWidget *widget, gpointer data) 01313 { 01314 GNCSplitReg *gsr = data; 01315 gsr_emit_simple_signal( gsr, "expand_ent" ); 01316 } 01317 01318 void 01319 gnc_split_reg_expand_trans_toolbar_cb (GtkWidget *widget, gpointer data) 01320 { 01321 GNCSplitReg *gsr = data; 01322 gsr_emit_simple_signal( gsr, "expand_ent" ); 01323 } 01324 01328 void 01329 gnc_split_reg_jump_to_split(GNCSplitReg *gsr, Split *split) 01330 { 01331 Transaction *trans; 01332 VirtualCellLocation vcell_loc; 01333 SplitRegister *reg; 01334 01335 if (!gsr) return; 01336 01337 trans = xaccSplitGetParent(split); 01338 01339 gsr_emit_include_date_signal( gsr, xaccTransGetDate(trans) ); 01340 01341 reg = gnc_ledger_display_get_split_register( gsr->ledger ); 01342 01343 if (gnc_split_register_get_split_virt_loc(reg, split, &vcell_loc)) 01344 gnucash_register_goto_virt_cell( gsr->reg, vcell_loc ); 01345 01346 gnc_ledger_display_refresh( gsr->ledger ); 01347 } 01348 01349 01353 void 01354 gnc_split_reg_jump_to_split_amount(GNCSplitReg *gsr, Split *split) 01355 { 01356 VirtualLocation virt_loc; 01357 SplitRegister *reg; 01358 Transaction *trans; 01359 01360 if (!gsr) return; 01361 01362 trans = xaccSplitGetParent(split); 01363 gsr_emit_include_date_signal( gsr, xaccTransGetDate(trans) ); 01364 01365 reg = gnc_ledger_display_get_split_register (gsr->ledger); 01366 01367 if (gnc_split_register_get_split_amount_virt_loc (reg, split, &virt_loc)) 01368 gnucash_register_goto_virt_loc (gsr->reg, virt_loc); 01369 01370 gnc_ledger_display_refresh (gsr->ledger); 01371 } 01372 01373 void 01374 gnc_split_reg_jump_to_blank (GNCSplitReg *gsr) 01375 { 01376 SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger); 01377 VirtualCellLocation vcell_loc; 01378 Split *blank; 01379 01380 ENTER("gsr=%p", gsr); 01381 01382 blank = gnc_split_register_get_blank_split (reg); 01383 if (blank == NULL) 01384 { 01385 LEAVE("no blank split"); 01386 return; 01387 } 01388 01389 if (gnc_split_register_get_split_virt_loc (reg, blank, &vcell_loc)) 01390 gnucash_register_goto_virt_cell (gsr->reg, vcell_loc); 01391 01392 gnc_ledger_display_refresh (gsr->ledger); 01393 LEAVE(" "); 01394 } 01395 01396 void 01397 gnc_split_reg_balancing_entry(GNCSplitReg *gsr, Account *account, 01398 time_t statement_date, gnc_numeric balancing_amount) 01399 { 01400 01401 Transaction *transaction; 01402 Split *split; 01403 01404 // create transaction 01405 transaction = create_balancing_transaction(gnc_get_current_book(), 01406 account, statement_date, balancing_amount); 01407 01408 // jump to transaction 01409 split = xaccTransFindSplitByAccount(transaction, account); 01410 if (split == NULL) 01411 { 01412 // default behaviour: jump to blank split 01413 g_warning("create_balancing_transaction failed"); 01414 gnc_split_reg_jump_to_blank(gsr); 01415 } 01416 else 01417 { 01418 // goto balancing transaction 01419 gnc_split_reg_jump_to_split(gsr, split ); 01420 } 01421 } 01422 01423 static Transaction* 01424 create_balancing_transaction(QofBook *book, Account *account, 01425 time_t statement_date, gnc_numeric balancing_amount) 01426 { 01427 01428 Transaction *trans; 01429 Split *split; 01430 01431 if (!account) 01432 return NULL; 01433 if (gnc_numeric_zero_p(balancing_amount)) 01434 return NULL; 01435 01436 xaccAccountBeginEdit(account); 01437 01438 trans = xaccMallocTransaction(book); 01439 01440 xaccTransBeginEdit(trans); 01441 01442 // fill Transaction 01443 xaccTransSetCurrency(trans, xaccAccountGetCommodity(account)); 01444 xaccTransSetDatePostedSecs(trans, statement_date); 01445 xaccTransSetDescription(trans, _("Balancing entry from reconcilation")); 01446 01447 // 1. Split 01448 split = xaccMallocSplit(book); 01449 xaccTransAppendSplit(trans, split); 01450 xaccAccountInsertSplit(account, split); 01451 xaccSplitSetAmount(split, balancing_amount); 01452 xaccSplitSetValue(split, balancing_amount); 01453 01454 // 2. Split (no account is defined: split goes to orphan account) 01455 split = xaccMallocSplit(book); 01456 xaccTransAppendSplit(trans, split); 01457 01458 balancing_amount = gnc_numeric_neg(balancing_amount); 01459 xaccSplitSetAmount(split, balancing_amount); 01460 xaccSplitSetValue(split, balancing_amount); 01461 01462 xaccTransCommitEdit(trans); 01463 xaccAccountCommitEdit(account); 01464 return trans; 01465 } 01466 01467 void 01468 gsr_default_blank_handler( GNCSplitReg *gsr, gpointer data ) 01469 { 01470 SplitRegister *reg; 01471 01472 ENTER("gsr=%p, gpointer=%p", gsr, data); 01473 01474 reg = gnc_ledger_display_get_split_register (gsr->ledger); 01475 01476 if (gnc_split_register_save (reg, TRUE)) 01477 gnc_split_register_redraw (reg); 01478 01479 gnc_split_reg_jump_to_blank (gsr); 01480 LEAVE(" "); 01481 } 01482 01483 void 01484 gnc_split_reg_new_trans_cb (GtkWidget *widget, gpointer data) 01485 { 01486 GNCSplitReg *gsr = data; 01487 gsr_emit_simple_signal( gsr, "blank" ); 01488 } 01489 01490 void 01491 gsr_default_jump_handler( GNCSplitReg *gsr, gpointer data ) 01492 { 01493 g_assert_not_reached(); 01494 } 01495 01496 void 01497 gnc_split_reg_jump_cb( GtkWidget *widget, gpointer data ) 01498 { 01499 GNCSplitReg *gsr = data; 01500 gsr_emit_simple_signal( gsr, "jump" ); 01501 } 01502 01503 void 01504 gnc_split_reg_change_style (GNCSplitReg *gsr, SplitRegisterStyle style) 01505 { 01506 SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger); 01507 01508 if (style == reg->style) 01509 return; 01510 01511 gnc_split_register_config (reg, reg->type, style, reg->use_double_line); 01512 gnc_ledger_display_refresh (gsr->ledger); 01513 } 01514 01515 void 01516 gnc_split_reg_style_ledger_cb (GtkWidget *w, gpointer data) 01517 { 01518 GNCSplitReg *gsr = data; 01519 01520 if (!GTK_CHECK_MENU_ITEM(w)->active) 01521 return; 01522 01523 gnc_split_reg_change_style (gsr, REG_STYLE_LEDGER); 01524 } 01525 01526 void 01527 gnc_split_reg_style_auto_ledger_cb (GtkWidget *w, gpointer data) 01528 { 01529 GNCSplitReg *gsr = data; 01530 01531 if (!GTK_CHECK_MENU_ITEM(w)->active) 01532 return; 01533 01534 gnc_split_reg_change_style (gsr, REG_STYLE_AUTO_LEDGER); 01535 } 01536 01537 void 01538 gnc_split_reg_style_journal_cb (GtkWidget *w, gpointer data) 01539 { 01540 GNCSplitReg *gsr = data; 01541 01542 if (!GTK_CHECK_MENU_ITEM(w)->active) 01543 return; 01544 01545 gnc_split_reg_change_style (gsr, REG_STYLE_JOURNAL); 01546 } 01547 01548 void 01549 gnc_split_reg_double_line_cb (GtkWidget *w, gpointer data) 01550 { 01551 GNCSplitReg *gsr = data; 01552 SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger); 01553 gboolean use_double_line; 01554 01555 use_double_line = GTK_CHECK_MENU_ITEM(w)->active; 01556 if ( use_double_line == reg->use_double_line ) 01557 return; 01558 01559 gnc_split_register_config( reg, reg->type, reg->style, use_double_line ); 01560 gnc_ledger_display_refresh( gsr->ledger ); 01561 } 01562 01563 static void 01564 gnc_split_reg_sort( GNCSplitReg *gsr, SortType sort_code ) 01565 { 01566 Query *query = gnc_ledger_display_get_query( gsr->ledger ); 01567 gboolean show_present_divider = FALSE; 01568 GSList *p1 = NULL, *p2 = NULL, *p3 = NULL, *standard; 01569 SplitRegister *reg; 01570 01571 if (gsr->sort_type == sort_code) 01572 return; 01573 01574 standard = g_slist_prepend( NULL, QUERY_DEFAULT_SORT ); 01575 01576 switch (sort_code) 01577 { 01578 case BY_STANDARD: 01579 p1 = standard; 01580 show_present_divider = TRUE; 01581 break; 01582 case BY_DATE: 01583 p1 = g_slist_prepend (p1, TRANS_DATE_POSTED); 01584 p1 = g_slist_prepend (p1, SPLIT_TRANS); 01585 p2 = standard; 01586 show_present_divider = TRUE; 01587 break; 01588 case BY_DATE_ENTERED: 01589 p1 = g_slist_prepend (p1, TRANS_DATE_ENTERED); 01590 p1 = g_slist_prepend (p1, SPLIT_TRANS); 01591 p2 = standard; 01592 break; 01593 case BY_DATE_RECONCILED: 01594 p1 = g_slist_prepend (p1, SPLIT_RECONCILE); 01595 p2 = g_slist_prepend (p2, SPLIT_DATE_RECONCILED); 01596 p3 = standard; 01597 break; 01598 case BY_NUM: 01599 p1 = g_slist_prepend (p1, TRANS_NUM); 01600 p1 = g_slist_prepend (p1, SPLIT_TRANS); 01601 p2 = standard; 01602 break; 01603 case BY_AMOUNT: 01604 p1 = g_slist_prepend (p1, SPLIT_VALUE); 01605 p2 = standard; 01606 break; 01607 case BY_MEMO: 01608 p1 = g_slist_prepend (p1, SPLIT_MEMO); 01609 p2 = standard; 01610 break; 01611 case BY_DESC: 01612 p1 = g_slist_prepend (p1, TRANS_DESCRIPTION); 01613 p1 = g_slist_prepend (p1, SPLIT_TRANS); 01614 p2 = standard; 01615 break; 01616 case BY_ACTION: 01617 p1 = g_slist_prepend (p1, SPLIT_ACTION); 01618 p2 = standard; 01619 break; 01620 case BY_NOTES: 01621 p1 = g_slist_prepend (p1, TRANS_NOTES); 01622 p1 = g_slist_prepend (p1, SPLIT_TRANS); 01623 p2 = standard; 01624 break; 01625 default: 01626 g_slist_free (standard); 01627 g_return_if_fail (FALSE); 01628 } 01629 01630 qof_query_set_sort_order( query, p1, p2, p3 ); 01631 reg = gnc_ledger_display_get_split_register( gsr->ledger ); 01632 gnc_split_register_show_present_divider( reg, show_present_divider ); 01633 gsr->sort_type = sort_code; 01634 gnc_ledger_display_refresh( gsr->ledger ); 01635 } 01636 01637 void 01638 gnc_split_reg_sort_standard_cb(GtkWidget *w, gpointer data) 01639 { 01640 GNCSplitReg *gsr = data; 01641 gnc_split_reg_sort(gsr, BY_STANDARD); 01642 } 01643 01644 void 01645 gnc_split_reg_sort_date_cb(GtkWidget *w, gpointer data) 01646 { 01647 GNCSplitReg *gsr = data; 01648 gnc_split_reg_sort(gsr, BY_DATE); 01649 } 01650 01651 void 01652 gnc_split_reg_sort_date_entered_cb(GtkWidget *w, gpointer data) 01653 { 01654 GNCSplitReg *gsr = data; 01655 gnc_split_reg_sort(gsr, BY_DATE_ENTERED); 01656 } 01657 01658 void 01659 gnc_split_reg_sort_date_reconciled_cb(GtkWidget *w, gpointer data) 01660 { 01661 GNCSplitReg *gsr = data; 01662 gnc_split_reg_sort(gsr, BY_DATE_RECONCILED); 01663 } 01664 01665 void 01666 gnc_split_reg_sort_num_cb(GtkWidget *w, gpointer data) 01667 { 01668 GNCSplitReg *gsr = data; 01669 gnc_split_reg_sort(gsr, BY_NUM); 01670 } 01671 01672 void 01673 gnc_split_reg_sort_amount_cb(GtkWidget *w, gpointer data) 01674 { 01675 GNCSplitReg *gsr = data; 01676 gnc_split_reg_sort(gsr, BY_AMOUNT); 01677 } 01678 01679 void 01680 gnc_split_reg_sort_memo_cb(GtkWidget *w, gpointer data) 01681 { 01682 GNCSplitReg *gsr = data; 01683 gnc_split_reg_sort(gsr, BY_MEMO); 01684 } 01685 01686 void 01687 gnc_split_reg_sort_desc_cb(GtkWidget *w, gpointer data) 01688 { 01689 GNCSplitReg *gsr = data; 01690 gnc_split_reg_sort(gsr, BY_DESC); 01691 } 01692 01693 void 01694 gnc_split_reg_sort_action_cb(GtkWidget *w, gpointer data) 01695 { 01696 GNCSplitReg *gsr = data; 01697 gnc_split_reg_sort(gsr, BY_ACTION); 01698 } 01699 01700 void 01701 gnc_split_reg_sort_notes_cb(GtkWidget *w, gpointer data) 01702 { 01703 GNCSplitReg *gsr = data; 01704 gnc_split_reg_sort(gsr, BY_NOTES); 01705 } 01706 01707 void 01708 gnc_split_reg_handle_exchange_cb (GtkWidget *w, gpointer data) 01709 { 01710 GNCSplitReg *gsr = data; 01711 SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger); 01712 01713 /* XXX Ignore the return value -- we don't care if this succeeds */ 01714 (void)gnc_split_register_handle_exchange (reg, TRUE); 01715 } 01716 01717 static void 01718 gnc_split_reg_record (GNCSplitReg *gsr) 01719 { 01720 SplitRegister *reg; 01721 Transaction *trans; 01722 01723 ENTER("gsr=%p", gsr); 01724 01725 reg = gnc_ledger_display_get_split_register (gsr->ledger); 01726 trans = gnc_split_register_get_current_trans (reg); 01727 01728 if (!gnc_split_register_save (reg, TRUE)) 01729 { 01730 LEAVE("no save"); 01731 return; 01732 } 01733 01734 gsr_emit_include_date_signal( gsr, xaccTransGetDate(trans) ); 01735 01736 /* Explicit redraw shouldn't be needed, 01737 * since gui_refresh events should handle this. */ 01738 /* gnc_split_register_redraw (reg); */ 01739 LEAVE(" "); 01740 } 01741 01742 static gboolean 01743 gnc_split_reg_match_trans_row( VirtualLocation virt_loc, 01744 gpointer user_data ) 01745 { 01746 GNCSplitReg *gsr = user_data; 01747 CursorClass cursor_class; 01748 SplitRegister *sr; 01749 01750 sr = gnc_ledger_display_get_split_register (gsr->ledger); 01751 cursor_class = gnc_split_register_get_cursor_class (sr, virt_loc.vcell_loc); 01752 01753 return (cursor_class == CURSOR_CLASS_TRANS); 01754 } 01755 01756 static void 01757 gnc_split_reg_goto_next_trans_row (GNCSplitReg *gsr) 01758 { 01759 ENTER("gsr=%p", gsr); 01760 gnucash_register_goto_next_matching_row( gsr->reg, 01761 gnc_split_reg_match_trans_row, 01762 gsr ); 01763 LEAVE(" "); 01764 } 01765 01766 void 01767 gnc_split_reg_enter( GNCSplitReg *gsr, gboolean next_transaction ) 01768 { 01769 SplitRegister *sr = gnc_ledger_display_get_split_register( gsr->ledger ); 01770 gboolean goto_blank; 01771 01772 ENTER("gsr=%p, next_transaction=%s", gsr, next_transaction ? "TRUE" : "FALSE"); 01773 01774 goto_blank = gnc_gconf_get_bool(GCONF_GENERAL_REGISTER, 01775 "enter_moves_to_end", NULL); 01776 01777 /* If we are in single or double line mode and we hit enter 01778 * on the blank split, go to the blank split instead of the 01779 * next row. This prevents the cursor from jumping around 01780 * when you are entering transactions. */ 01781 if ( !goto_blank && !next_transaction ) 01782 { 01783 SplitRegisterStyle style = sr->style; 01784 01785 if (style == REG_STYLE_LEDGER) 01786 { 01787 Split *blank_split; 01788 01789 blank_split = gnc_split_register_get_blank_split(sr); 01790 if (blank_split != NULL) 01791 { 01792 Split *current_split; 01793 01794 current_split = gnc_split_register_get_current_split(sr); 01795 01796 if (blank_split == current_split) 01797 goto_blank = TRUE; 01798 } 01799 } 01800 } 01801 01802 /* First record the transaction. This will perform a refresh. */ 01803 gnc_split_reg_record( gsr ); 01804 01805 if (!goto_blank && next_transaction) 01806 gnc_split_register_expand_current_trans (sr, FALSE); 01807 01808 /* Now move. */ 01809 if (goto_blank) 01810 gnc_split_reg_jump_to_blank( gsr ); 01811 else if (next_transaction) 01812 gnc_split_reg_goto_next_trans_row( gsr ); 01813 else 01814 gnucash_register_goto_next_virt_row( gsr->reg ); 01815 LEAVE(" "); 01816 } 01817 01818 void 01819 gsr_default_enter_handler( GNCSplitReg *gsr, gpointer data ) 01820 { 01821 gnc_split_reg_enter( gsr, FALSE ); 01822 } 01823 01824 void 01825 gnc_split_reg_record_cb (GnucashRegister *reg, gpointer data) 01826 { 01827 gsr_emit_simple_signal( (GNCSplitReg*)data, "enter_ent" ); 01828 } 01829 01830 void 01831 gnc_split_reg_size_allocate (GtkWidget *widget, 01832 GtkAllocation *allocation, 01833 gpointer user_data) 01834 { 01835 GNCSplitReg *gsr = user_data; 01836 gsr->width = allocation->width; 01837 gtk_window_set_default_size( GTK_WINDOW(gsr->window), gsr->width, 0 ); 01838 } 01839 01840 static 01841 GtkWidget* 01842 add_summary_label (GtkWidget *summarybar, const char *label_str) 01843 { 01844 GtkWidget *hbox; 01845 GtkWidget *label; 01846 01847 hbox = gtk_hbox_new(FALSE, 2); 01848 gtk_box_pack_start( GTK_BOX(summarybar), hbox, FALSE, FALSE, 5 ); 01849 01850 label = gtk_label_new( label_str ); 01851 gtk_misc_set_alignment( GTK_MISC(label), 1.0, 0.5 ); 01852 gtk_box_pack_start( GTK_BOX(hbox), label, FALSE, FALSE, 0 ); 01853 01854 label = gtk_label_new( "" ); 01855 gtk_misc_set_alignment( GTK_MISC(label), 1.0, 0.5 ); 01856 gtk_box_pack_start( GTK_BOX(hbox), label, FALSE, FALSE, 0 ); 01857 01858 return label; 01859 } 01860 01861 GtkWidget * 01862 gsr_create_summary_bar( GNCSplitReg *gsr ) 01863 { 01864 GtkWidget *summarybar; 01865 01866 gsr->cleared_label = NULL; 01867 gsr->balance_label = NULL; 01868 gsr->reconciled_label = NULL; 01869 gsr->future_label = NULL; 01870 gsr->projectedminimum_label = NULL; 01871 gsr->shares_label = NULL; 01872 gsr->value_label = NULL; 01873 01874 if ( gnc_ledger_display_type(gsr->ledger) >= LD_SUBACCOUNT ) 01875 { 01876 gsr->summarybar = NULL; 01877 return NULL; 01878 } 01879 01880 summarybar = gtk_hbox_new (FALSE, 4); 01881 01882 if (!xaccAccountIsPriced(gnc_ledger_display_leader(gsr->ledger))) 01883 { 01884 gsr->balance_label = add_summary_label (summarybar, _("Present:")); 01885 gsr->future_label = add_summary_label (summarybar, _("Future:")); 01886 gsr->cleared_label = add_summary_label (summarybar, _("Cleared:")); 01887 gsr->reconciled_label = add_summary_label (summarybar, _("Reconciled:")); 01888 gsr->projectedminimum_label = add_summary_label (summarybar, _("Projected Minimum:")); 01889 } 01890 else 01891 { 01892 gsr->shares_label = add_summary_label (summarybar, _("Shares:")); 01893 gsr->value_label = add_summary_label (summarybar, _("Current Value:")); 01894 } 01895 01896 gsr->summarybar = summarybar; 01897 01898 /* Force the first update */ 01899 gsr_redraw_all_cb(NULL, gsr); 01900 return gsr->summarybar; 01901 } 01902 01909 static 01910 GNCPlaceholderType 01911 gnc_split_reg_get_placeholder( GNCSplitReg *gsr ) 01912 { 01913 Account *leader; 01914 SplitRegister *reg; 01915 gboolean single_account; 01916 01917 if (gsr == NULL) 01918 return PLACEHOLDER_NONE; 01919 01920 reg = gnc_ledger_display_get_split_register( gsr->ledger ); 01921 01922 switch (reg->type) 01923 { 01924 case GENERAL_LEDGER: 01925 case INCOME_LEDGER: 01926 case PORTFOLIO_LEDGER: 01927 case SEARCH_LEDGER: 01928 single_account = FALSE; 01929 break; 01930 default: 01931 single_account = TRUE; 01932 break; 01933 } 01934 01935 leader = gnc_ledger_display_leader( gsr->ledger ); 01936 01937 if (leader == NULL) 01938 return PLACEHOLDER_NONE; 01939 if (single_account) 01940 { 01941 if (xaccAccountGetPlaceholder( leader )) 01942 return PLACEHOLDER_THIS; 01943 return PLACEHOLDER_NONE; 01944 } 01945 return xaccAccountGetDescendantPlaceholder( leader ); 01946 } 01947 01951 typedef struct dialog_args 01952 { 01953 GNCSplitReg *gsr; 01954 gchar *string; 01955 } dialog_args; 01956 01962 static 01963 gboolean 01964 gtk_callback_bug_workaround (gpointer argp) 01965 { 01966 dialog_args *args = argp; 01967 const gchar *read_only = _("This account register is read-only."); 01968 GtkWidget *dialog; 01969 01970 dialog = gtk_message_dialog_new(GTK_WINDOW(args->gsr->window), 01971 GTK_DIALOG_DESTROY_WITH_PARENT, 01972 GTK_MESSAGE_WARNING, 01973 GTK_BUTTONS_CLOSE, 01974 "%s", read_only); 01975 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), 01976 "%s", args->string); 01977 gnc_dialog_run(GTK_DIALOG(dialog), "register_read_only"); 01978 gtk_widget_destroy(dialog); 01979 g_free(args); 01980 return FALSE; 01981 } 01982 01986 static 01987 void 01988 gnc_split_reg_determine_read_only( GNCSplitReg *gsr ) 01989 { 01990 dialog_args *args = g_malloc(sizeof(dialog_args)); 01991 SplitRegister *reg; 01992 01993 if (qof_book_is_readonly(gnc_get_current_book())) 01994 { 01995 /* Is the book read-only? Then for sure also make this register 01996 read-only. */ 01997 gsr->read_only = TRUE; 01998 } 01999 02000 if ( !gsr->read_only ) 02001 { 02002 02003 switch (gnc_split_reg_get_placeholder(gsr)) 02004 { 02005 case PLACEHOLDER_NONE: 02006 /* stay as false. */ 02007 return; 02008 02009 case PLACEHOLDER_THIS: 02010 args->string = _("This account may not be edited. If you want " 02011 "to edit transactions in this register, please " 02012 "open the account options and turn off the " 02013 "placeholder checkbox."); 02014 break; 02015 02016 default: 02017 args->string = _("One of the sub-accounts selected may not be " 02018 "edited. If you want to edit transactions in " 02019 "this register, please open the sub-account " 02020 "options and turn off the placeholder checkbox. " 02021 "You may also open an individual account instead " 02022 "of a set of accounts."); 02023 break; 02024 } 02025 gsr->read_only = TRUE; 02026 /* Put up a warning dialog */ 02027 args->gsr = gsr; 02028 g_timeout_add (250, gtk_callback_bug_workaround, args); /* 0.25 seconds */ 02029 } 02030 02031 /* Make the contents immutable */ 02032 reg = gnc_ledger_display_get_split_register( gsr->ledger ); 02033 gnc_split_register_set_read_only( reg, TRUE ); 02034 02035 } 02036 02037 static 02038 GtkWidget * 02039 gnc_split_reg_get_parent( GNCLedgerDisplay *ledger ) 02040 { 02041 GNCSplitReg *gsr = 02042 GNC_SPLIT_REG(gnc_ledger_display_get_user_data( ledger )); 02043 02044 if (gsr == NULL) 02045 return NULL; 02046 02047 return gsr->window; 02048 } 02049 02050 static 02051 void 02052 gsr_emit_help_changed( GnucashRegister *reg, gpointer user_data ) 02053 { 02054 gsr_emit_simple_signal( (GNCSplitReg*)user_data, "help-changed" ); 02055 } 02056 02057 static 02058 void 02059 gsr_emit_include_date_signal( GNCSplitReg *gsr, time_t date ) 02060 { 02061 g_signal_emit_by_name( gsr, "include-date", date, NULL ); 02062 } 02063 02064 static 02065 void 02066 gsr_emit_simple_signal( GNCSplitReg *gsr, const char *sigName ) 02067 { 02068 g_signal_emit_by_name( gsr, sigName, NULL ); 02069 } 02070 02071 GnucashRegister* 02072 gnc_split_reg_get_register( GNCSplitReg *gsr ) 02073 { 02074 if ( !gsr ) 02075 return NULL; 02076 02077 return gsr->reg; 02078 } 02079 02080 SortType 02081 gnc_split_reg_get_sort_type( GNCSplitReg *gsr ) 02082 { 02083 g_assert( gsr ); 02084 return gsr->sort_type; 02085 } 02086 02087 void 02088 gnc_split_reg_set_sort_type( GNCSplitReg *gsr, SortType t ) 02089 { 02090 gnc_split_reg_sort( gsr, t ); 02091 } 02092 02093 GtkWidget* 02094 gnc_split_reg_get_summarybar( GNCSplitReg *gsr ) 02095 { 02096 if ( !gsr ) return NULL; 02097 return gsr->summarybar; 02098 } 02099 02100 gboolean 02101 gnc_split_reg_get_read_only( GNCSplitReg *gsr ) 02102 { 02103 g_assert( gsr ); 02104 return gsr->read_only; 02105 } 02106 02107 void 02108 gnc_split_reg_set_moved_cb( GNCSplitReg *gsr, GFunc cb, gpointer cb_data ) 02109 { 02110 gnucash_register_set_moved_cb (gsr->reg, cb, cb_data); 02111 }
1.7.4