GnuCash  4.11-11-ge9df8d41d2+
gnc-plugin-page-register.c
Go to the documentation of this file.
1 /**********************************************************************
2  * gnc-plugin-page-register.c -- register page functions *
3  * *
4  * Copyright (C) 2003 Jan Arne Petersen <jpetersen@uni-bonn.de> *
5  * Copyright (C) 2003,2005,2006 David Hampton <hampton@employees.org> *
6  * Copyright (C) 2011, Robert Fewell *
7  * *
8  * This program is free software; you can redistribute it and/or *
9  * modify it under the terms of the GNU General Public License as *
10  * published by the Free Software Foundation; either version 2 of *
11  * the License, or (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, contact: *
20  * *
21  * Free Software Foundation Voice: +1-617-542-5942 *
22  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
23  * Boston, MA 02110-1301, USA gnu@gnu.org *
24  **********************************************************************/
25 
36 #include <config.h>
37 
38 #include <libguile.h>
39 #include <gtk/gtk.h>
40 #include <glib/gi18n.h>
41 #include "swig-runtime.h"
42 #include "guile-mappings.h"
43 
45 /*################## Added for Reg2 #################*/
47 /*################## Added for Reg2 #################*/
48 #include "gnc-plugin-register.h"
50 #include "gnc-plugin-page-report.h"
51 #include "gnc-plugin-business.h"
52 
53 #include "dialog-account.h"
54 #include "dialog-dup-trans.h"
55 #include "dialog-find-account.h"
56 #include "dialog-find-transactions.h"
57 #include "dialog-print-check.h"
58 #include "dialog-invoice.h"
59 #include "dialog-transfer.h"
60 #include "dialog-utils.h"
61 #include "assistant-stock-split.h"
62 #include "assistant-stock-transaction.h"
63 #include "gnc-component-manager.h"
64 #include "gnc-date.h"
65 #include "gnc-date-edit.h"
66 #include "gnc-engine.h"
67 #include "gnc-event.h"
68 #include "gnc-features.h"
69 #include "gnc-glib-utils.h"
70 #include "gnc-gnome-utils.h"
71 #include "gnc-gobject-utils.h"
72 #include "gnc-gui-query.h"
73 #include "gnc-icons.h"
74 #include "gnc-split-reg.h"
75 #include "gnc-state.h"
76 #include "gnc-prefs.h"
77 #include "gnc-ui-util.h"
78 #include "gnc-window.h"
79 #include "gnc-main-window.h"
80 #include "gnc-session.h"
81 #include "gnc-ui.h"
82 #include "gnc-warnings.h"
83 #include "gnucash-sheet.h"
84 #include "dialog-lot-viewer.h"
85 #include "Scrub.h"
86 #include "ScrubBusiness.h"
87 #include "qof.h"
88 #include "window-reconcile.h"
89 #include "window-autoclear.h"
90 #include "window-report.h"
91 #include "engine-helpers.h"
92 #include "qofbookslots.h"
93 
94 /* This static indicates the debugging module that this .o belongs to. */
95 static QofLogModule log_module = GNC_MOD_GUI;
96 
97 #define DEFAULT_LINES_AMOUNT 50
98 #define DEFAULT_FILTER_NUM_DAYS_GL "30"
99 
100 static void gnc_plugin_page_register_class_init (GncPluginPageRegisterClass*
101  klass);
102 static void gnc_plugin_page_register_init (GncPluginPageRegister* plugin_page);
103 static void gnc_plugin_page_register_finalize (GObject* object);
104 
105 /* static Account *gnc_plugin_page_register_get_current_account (GncPluginPageRegister *page); */
106 
107 static GtkWidget* gnc_plugin_page_register_create_widget (
108  GncPluginPage* plugin_page);
109 static void gnc_plugin_page_register_destroy_widget (GncPluginPage*
110  plugin_page);
111 static void gnc_plugin_page_register_window_changed (GncPluginPage*
112  plugin_page, GtkWidget* window);
113 static gboolean gnc_plugin_page_register_focus_widget (GncPluginPage*
114  plugin_page);
115 static void gnc_plugin_page_register_focus (GncPluginPage* plugin_page,
116  gboolean current_page);
117 static void gnc_plugin_page_register_save_page (GncPluginPage* plugin_page,
118  GKeyFile* file, const gchar* group);
119 static GncPluginPage* gnc_plugin_page_register_recreate_page (
120  GtkWidget* window, GKeyFile* file, const gchar* group);
121 static void gnc_plugin_page_register_update_edit_menu (GncPluginPage* page,
122  gboolean hide);
123 static gboolean gnc_plugin_page_register_finish_pending (GncPluginPage* page);
124 
125 static gchar* gnc_plugin_page_register_get_tab_name (GncPluginPage*
126  plugin_page);
127 static gchar* gnc_plugin_page_register_get_tab_color (GncPluginPage*
128  plugin_page);
129 static gchar* gnc_plugin_page_register_get_long_name (GncPluginPage*
130  plugin_page);
131 
132 static void gnc_plugin_page_register_summarybar_position_changed (
133  gpointer prefs, gchar* pref, gpointer user_data);
134 
135 /* Callbacks for the "Sort By" dialog */
136 void gnc_plugin_page_register_sort_button_cb (GtkToggleButton* button,
137  GncPluginPageRegister* page);
138 void gnc_plugin_page_register_sort_response_cb (GtkDialog* dialog,
139  gint response, GncPluginPageRegister* plugin_page);
140 void gnc_plugin_page_register_sort_order_save_cb (GtkToggleButton* button,
141  GncPluginPageRegister* page);
142 void gnc_plugin_page_register_sort_order_reverse_cb (GtkToggleButton* button,
143  GncPluginPageRegister* page);
144 
145 static gchar* gnc_plugin_page_register_get_sort_order (GncPluginPage*
146  plugin_page);
147 void gnc_plugin_page_register_set_sort_order (GncPluginPage* plugin_page,
148  const gchar* sort_order);
149 static gboolean gnc_plugin_page_register_get_sort_reversed (
150  GncPluginPage* plugin_page);
151 void gnc_plugin_page_register_set_sort_reversed (GncPluginPage* plugin_page,
152  gboolean reverse_order);
153 
154 /* Callbacks for the "Filter By" dialog */
155 void gnc_plugin_page_register_filter_select_range_cb (GtkRadioButton* button,
156  GncPluginPageRegister* page);
157 void gnc_plugin_page_register_filter_start_cb (GtkWidget* radio,
158  GncPluginPageRegister* page);
159 void gnc_plugin_page_register_filter_end_cb (GtkWidget* radio,
160  GncPluginPageRegister* page);
161 void gnc_plugin_page_register_filter_response_cb (GtkDialog* dialog,
162  gint response, GncPluginPageRegister* plugin_page);
163 void gnc_plugin_page_register_filter_status_all_cb (GtkButton* button,
164  GncPluginPageRegister* plugin_page);
165 void gnc_plugin_page_register_filter_status_one_cb (GtkToggleButton* button,
166  GncPluginPageRegister* page);
167 void gnc_plugin_page_register_filter_save_cb (GtkToggleButton* button,
168  GncPluginPageRegister* page);
169 void gnc_plugin_page_register_filter_days_changed_cb (GtkSpinButton* button,
170  GncPluginPageRegister* page);
171 
172 static time64 gnc_plugin_page_register_filter_dmy2time (char* date_string);
173 static gchar* gnc_plugin_page_register_filter_time2dmy (time64 raw_time);
174 static gchar* gnc_plugin_page_register_get_filter (GncPluginPage* plugin_page);
175 void gnc_plugin_page_register_set_filter (GncPluginPage* plugin_page,
176  const gchar* filter);
177 static void gnc_plugin_page_register_set_filter_tooltip (
178  GncPluginPageRegister* page);
179 
180 static void gnc_ppr_update_status_query (GncPluginPageRegister* page);
181 static void gnc_ppr_update_date_query (GncPluginPageRegister* page);
182 
183 /* Command callbacks */
184 static void gnc_plugin_page_register_cmd_print_check (GtkAction* action,
185  GncPluginPageRegister* plugin_page);
186 static void gnc_plugin_page_register_cmd_cut (GtkAction* action,
187  GncPluginPageRegister* plugin_page);
188 static void gnc_plugin_page_register_cmd_copy (GtkAction* action,
189  GncPluginPageRegister* plugin_page);
190 static void gnc_plugin_page_register_cmd_paste (GtkAction* action,
191  GncPluginPageRegister* plugin_page);
192 static void gnc_plugin_page_register_cmd_edit_account (GtkAction* action,
193  GncPluginPageRegister* plugin_page);
194 static void gnc_plugin_page_register_cmd_find_account (GtkAction* action,
195  GncPluginPageRegister* plugin_page);
196 static void gnc_plugin_page_register_cmd_find_transactions (GtkAction* action,
197  GncPluginPageRegister* plugin_page);
198 static void gnc_plugin_page_register_cmd_edit_tax_options (GtkAction* action,
199  GncPluginPageRegister* plugin_page);
200 static void gnc_plugin_page_register_cmd_cut_transaction (GtkAction* action,
201  GncPluginPageRegister* plugin_page);
202 static void gnc_plugin_page_register_cmd_copy_transaction (GtkAction* action,
203  GncPluginPageRegister* plugin_page);
204 static void gnc_plugin_page_register_cmd_paste_transaction (GtkAction* action,
205  GncPluginPageRegister* plugin_page);
206 static void gnc_plugin_page_register_cmd_void_transaction (GtkAction* action,
207  GncPluginPageRegister* plugin_page);
208 static void gnc_plugin_page_register_cmd_unvoid_transaction (GtkAction* action,
209  GncPluginPageRegister* plugin_page);
210 static void gnc_plugin_page_register_cmd_reverse_transaction (
211  GtkAction* action, GncPluginPageRegister* plugin_page);
212 static void gnc_plugin_page_register_cmd_view_sort_by (GtkAction* action,
213  GncPluginPageRegister* plugin_page);
214 static void gnc_plugin_page_register_cmd_view_filter_by (GtkAction* action,
215  GncPluginPageRegister* plugin_page);
216 static void gnc_plugin_page_register_cmd_style_changed (GtkAction* action,
217  GtkRadioAction* current, GncPluginPageRegister* plugin_page);
218 static void gnc_plugin_page_register_cmd_style_double_line (
219  GtkToggleAction* action, GncPluginPageRegister* plugin_page);
220 
221 static void gnc_plugin_page_register_cmd_reconcile (GtkAction* action,
222  GncPluginPageRegister* plugin_page);
223 static void gnc_plugin_page_register_cmd_stock_assistant (GtkAction* action,
224  GncPluginPageRegister* page);
225 
226 static void gnc_plugin_page_register_cmd_autoclear (GtkAction* action,
227  GncPluginPageRegister* plugin_page);
228 static void gnc_plugin_page_register_cmd_transfer (GtkAction* action,
229  GncPluginPageRegister* plugin_page);
230 static void gnc_plugin_page_register_cmd_stock_split (GtkAction* action,
231  GncPluginPageRegister* plugin_page);
232 static void gnc_plugin_page_register_cmd_lots (GtkAction* action,
233  GncPluginPageRegister* plugin_page);
234 static void gnc_plugin_page_register_cmd_enter_transaction (GtkAction* action,
235  GncPluginPageRegister* plugin_page);
236 static void gnc_plugin_page_register_cmd_cancel_transaction (GtkAction* action,
237  GncPluginPageRegister* plugin_page);
238 static void gnc_plugin_page_register_cmd_delete_transaction (GtkAction* action,
239  GncPluginPageRegister* plugin_page);
240 static void gnc_plugin_page_register_cmd_blank_transaction (GtkAction* action,
241  GncPluginPageRegister* plugin_page);
242 static void gnc_plugin_page_register_cmd_goto_date (GtkAction* action,
243  GncPluginPageRegister* page);
244 static void gnc_plugin_page_register_cmd_duplicate_transaction (
245  GtkAction* action, GncPluginPageRegister* plugin_page);
246 static void gnc_plugin_page_register_cmd_reinitialize_transaction (
247  GtkAction* action, GncPluginPageRegister* plugin_page);
248 static void gnc_plugin_page_register_cmd_expand_transaction (
249  GtkToggleAction* action, GncPluginPageRegister* plugin_page);
250 static void gnc_plugin_page_register_cmd_exchange_rate (GtkAction* action,
251  GncPluginPageRegister* plugin_page);
252 static void gnc_plugin_page_register_cmd_jump (GtkAction* action,
253  GncPluginPageRegister* plugin_page);
254 static void gnc_plugin_page_register_cmd_reload (GtkAction* action,
255  GncPluginPageRegister* plugin_page);
256 static void gnc_plugin_page_register_cmd_schedule (GtkAction* action,
257  GncPluginPageRegister* plugin_page);
258 static void gnc_plugin_page_register_cmd_scrub_all (GtkAction* action,
259  GncPluginPageRegister* plugin_page);
260 static void gnc_plugin_page_register_cmd_scrub_current (GtkAction* action,
261  GncPluginPageRegister* plugin_page);
262 static void gnc_plugin_page_register_cmd_account_report (GtkAction* action,
263  GncPluginPageRegister* plugin_page);
264 static void gnc_plugin_page_register_cmd_transaction_report (GtkAction* action,
265  GncPluginPageRegister* plugin_page);
266 static void gnc_plugin_page_register_cmd_linked_transaction (GtkAction *action,
267  GncPluginPageRegister *plugin_page);
268 static void gnc_plugin_page_register_cmd_linked_transaction_open (GtkAction *action,
269  GncPluginPageRegister *plugin_page);
270 static void gnc_plugin_page_register_cmd_linked_transaction_remove (GtkAction *action,
271  GncPluginPageRegister *plugin_page);
272 static void gnc_plugin_page_register_cmd_jump_linked_invoice (GtkAction* action,
273  GncPluginPageRegister* plugin_page);
274 static void gnc_plugin_page_help_changed_cb (GNCSplitReg* gsr,
275  GncPluginPageRegister* register_page);
276 static void gnc_plugin_page_popup_menu_cb (GNCSplitReg* gsr,
277  GncPluginPageRegister* register_page);
278 static void gnc_plugin_page_register_refresh_cb (GHashTable* changes,
279  gpointer user_data);
280 static void gnc_plugin_page_register_close_cb (gpointer user_data);
281 
282 static void gnc_plugin_page_register_ui_update (gpointer various,
283  GncPluginPageRegister* page);
284 static void gppr_account_destroy_cb (Account* account);
285 static void gnc_plugin_page_register_event_handler (QofInstance* entity,
286  QofEventId event_type,
287  GncPluginPageRegister* page,
288  GncEventData* ed);
289 
290 static GncInvoice* invoice_from_split (Split* split);
291 static GList* invoices_from_transaction (Transaction* trans);
292 
293 /************************************************************/
294 /* Actions */
295 /************************************************************/
296 
297 #define CUT_TRANSACTION_LABEL N_("Cu_t Transaction")
298 #define COPY_TRANSACTION_LABEL N_("_Copy Transaction")
299 #define PASTE_TRANSACTION_LABEL N_("_Paste Transaction")
300 #define DUPLICATE_TRANSACTION_LABEL N_("Dup_licate Transaction")
301 #define DELETE_TRANSACTION_LABEL N_("_Delete Transaction")
302 /* Translators: This is a menu item that opens a dialog for linking an
303  external file or URL with the bill, invoice, transaction, or voucher or
304  removing such an link. */
305 #define LINK_TRANSACTION_LABEL N_("_Manage Document Link...")
306 /* Translators: This is a menu item that opens an external file or URI that may
307  be linked to the current bill, invoice, transaction, or voucher using
308  the operating system's default application for the file or URI mime type. */
309 #define LINK_TRANSACTION_OPEN_LABEL N_("_Open Linked Document")
310 /* Translators: This is a menu item that will open the bill, invoice, or voucher
311  that is posted to the current transaction if there is one. */
312 #define JUMP_LINKED_INVOICE_LABEL N_("Jump to Invoice")
313 #define CUT_SPLIT_LABEL N_("Cu_t Split")
314 #define COPY_SPLIT_LABEL N_("_Copy Split")
315 #define PASTE_SPLIT_LABEL N_("_Paste Split")
316 #define DUPLICATE_SPLIT_LABEL N_("Dup_licate Split")
317 #define DELETE_SPLIT_LABEL N_("_Delete Split")
318 #define CUT_TRANSACTION_TIP N_("Cut the selected transaction into clipboard")
319 #define COPY_TRANSACTION_TIP N_("Copy the selected transaction into clipboard")
320 #define PASTE_TRANSACTION_TIP N_("Paste the transaction from the clipboard")
321 #define DUPLICATE_TRANSACTION_TIP N_("Make a copy of the current transaction")
322 #define DELETE_TRANSACTION_TIP N_("Delete the current transaction")
323 #define LINK_TRANSACTION_TIP N_("Add, change, or unlink the document linked with the current transaction")
324 #define LINK_TRANSACTION_OPEN_TIP N_("Open the linked document for the current transaction")
325 #define JUMP_LINKED_INVOICE_TIP N_("Jump to the linked bill, invoice, or voucher")
326 #define CUT_SPLIT_TIP N_("Cut the selected split into clipboard")
327 #define COPY_SPLIT_TIP N_("Copy the selected split into clipboard")
328 #define PASTE_SPLIT_TIP N_("Paste the split from the clipboard")
329 #define DUPLICATE_SPLIT_TIP N_("Make a copy of the current split")
330 #define DELETE_SPLIT_TIP N_("Delete the current split")
331 
332 static GtkActionEntry gnc_plugin_page_register_actions [] =
333 {
334  /* File menu */
335 
336  {
337  "FilePrintAction", "document-print", N_ ("_Print Checks..."), "<primary>p", NULL,
338  G_CALLBACK (gnc_plugin_page_register_cmd_print_check)
339  },
340 
341  /* Edit menu */
342 
343  {
344  "EditCutAction", "edit-cut", N_ ("Cu_t"), "<primary>X",
345  N_ ("Cut the current selection and copy it to clipboard"),
346  G_CALLBACK (gnc_plugin_page_register_cmd_cut)
347  },
348  {
349  "EditCopyAction", "edit-copy", N_ ("_Copy"), "<primary>C",
350  N_ ("Copy the current selection to clipboard"),
351  G_CALLBACK (gnc_plugin_page_register_cmd_copy)
352  },
353  {
354  "EditPasteAction", "edit-paste", N_ ("_Paste"), "<primary>V",
355  N_ ("Paste the clipboard content at the cursor position"),
356  G_CALLBACK (gnc_plugin_page_register_cmd_paste)
357  },
358  {
359  "EditEditAccountAction", GNC_ICON_EDIT_ACCOUNT, N_ ("Edit _Account"), "<primary>e",
360  N_ ("Edit the selected account"),
361  G_CALLBACK (gnc_plugin_page_register_cmd_edit_account)
362  },
363  {
364  "EditFindAccountAction", "edit-find", N_ ("F_ind Account"), "<primary>i",
365  N_ ("Find an account"),
366  G_CALLBACK (gnc_plugin_page_register_cmd_find_account)
367  },
368  {
369  "EditFindTransactionsAction", "edit-find", N_ ("_Find..."), "<primary>f",
370  N_ ("Find transactions with a search"),
371  G_CALLBACK (gnc_plugin_page_register_cmd_find_transactions)
372  },
373  {
374  "EditTaxOptionsAction", NULL,
375  /* Translators: remember to reuse this
376  translation in dialog-account.glade */
377  N_("Ta_x Report Options"), NULL,
378  /* Translators: currently implemented are
379  US: income tax and
380  DE: VAT
381  So adjust this string */
382  N_("Setup relevant accounts for tax reports, e.g. US income tax"),
383  G_CALLBACK (gnc_plugin_page_register_cmd_edit_tax_options)
384  },
385 
386  /* Transaction menu */
387 
388  {
389  "CutTransactionAction", "edit-cut", CUT_TRANSACTION_LABEL, "",
390  CUT_TRANSACTION_TIP,
391  G_CALLBACK (gnc_plugin_page_register_cmd_cut_transaction)
392  },
393  {
394  "CopyTransactionAction", "edit-copy", COPY_TRANSACTION_LABEL, "",
395  COPY_TRANSACTION_TIP,
396  G_CALLBACK (gnc_plugin_page_register_cmd_copy_transaction)
397  },
398  {
399  "PasteTransactionAction", "edit-paste", PASTE_TRANSACTION_LABEL, "",
400  PASTE_TRANSACTION_TIP,
401  G_CALLBACK (gnc_plugin_page_register_cmd_paste_transaction)
402  },
403  {
404  "DuplicateTransactionAction", "edit-copy", DUPLICATE_TRANSACTION_LABEL, "",
405  DUPLICATE_TRANSACTION_TIP,
406  G_CALLBACK (gnc_plugin_page_register_cmd_duplicate_transaction)
407  },
408  {
409  "DeleteTransactionAction", "edit-delete", DELETE_TRANSACTION_LABEL, NULL,
410  DELETE_TRANSACTION_TIP,
411  G_CALLBACK (gnc_plugin_page_register_cmd_delete_transaction)
412  },
413  {
414  "RemoveTransactionSplitsAction", "edit-clear", N_ ("Remo_ve Other Splits"), NULL,
415  N_ ("Remove all splits in the current transaction"),
416  G_CALLBACK (gnc_plugin_page_register_cmd_reinitialize_transaction)
417  },
418  {
419  "RecordTransactionAction", "list-add", N_ ("_Enter Transaction"), NULL,
420  N_ ("Record the current transaction"),
421  G_CALLBACK (gnc_plugin_page_register_cmd_enter_transaction)
422  },
423  {
424  "CancelTransactionAction", "process-stop", N_ ("Ca_ncel Transaction"), NULL,
425  N_ ("Cancel the current transaction"),
426  G_CALLBACK (gnc_plugin_page_register_cmd_cancel_transaction)
427  },
428  {
429  "VoidTransactionAction", NULL, N_ ("_Void Transaction"), NULL, NULL,
430  G_CALLBACK (gnc_plugin_page_register_cmd_void_transaction)
431  },
432  {
433  "UnvoidTransactionAction", NULL, N_ ("_Unvoid Transaction"), NULL, NULL,
434  G_CALLBACK (gnc_plugin_page_register_cmd_unvoid_transaction)
435  },
436  {
437  "ReverseTransactionAction", NULL, N_ ("Add _Reversing Transaction"), NULL, NULL,
438  G_CALLBACK (gnc_plugin_page_register_cmd_reverse_transaction)
439  },
440  {
441  "LinkTransactionAction", NULL, LINK_TRANSACTION_LABEL, NULL,
442  LINK_TRANSACTION_TIP,
443  G_CALLBACK (gnc_plugin_page_register_cmd_linked_transaction)
444  },
445  {
446  "LinkedTransactionOpenAction", NULL, LINK_TRANSACTION_OPEN_LABEL, NULL,
447  LINK_TRANSACTION_OPEN_TIP,
448  G_CALLBACK (gnc_plugin_page_register_cmd_linked_transaction_open)
449  },
450  {
451  "JumpLinkedInvoiceAction", NULL, JUMP_LINKED_INVOICE_LABEL, NULL,
452  JUMP_LINKED_INVOICE_TIP,
453  G_CALLBACK (gnc_plugin_page_register_cmd_jump_linked_invoice)
454  },
455 
456  /* View menu */
457 
458  {
459  "ViewSortByAction", NULL, N_ ("_Sort By..."), NULL, NULL,
460  G_CALLBACK (gnc_plugin_page_register_cmd_view_sort_by)
461  },
462  {
463  "ViewFilterByAction", NULL, N_ ("_Filter By..."), NULL, NULL,
464  G_CALLBACK (gnc_plugin_page_register_cmd_view_filter_by)
465  },
466  {
467  "ViewRefreshAction", "view-refresh", N_ ("_Refresh"), "<primary>r",
468  N_ ("Refresh this window"),
469  G_CALLBACK (gnc_plugin_page_register_cmd_reload)
470  },
471 
472  /* Actions menu */
473 
474  {
475  "ActionsTransferAction", GNC_ICON_TRANSFER, N_ ("_Transfer..."), "<primary>t",
476  N_ ("Transfer funds from one account to another"),
477  G_CALLBACK (gnc_plugin_page_register_cmd_transfer)
478  },
479  {
480  "ActionsReconcileAction", "edit-select-all", N_ ("_Reconcile..."), NULL,
481  N_ ("Reconcile the selected account"),
482  G_CALLBACK (gnc_plugin_page_register_cmd_reconcile)
483  },
484  {
485  "ActionsAutoClearAction", "edit-select-all", N_ ("_Auto-clear..."), NULL,
486  N_ ("Automatically clear individual transactions, so as to reach a certain cleared amount"),
487  G_CALLBACK (gnc_plugin_page_register_cmd_autoclear)
488  },
489  {
490  "ActionsStockAssistantAction", NULL, N_ ("Stock Ass_istant"), NULL,
491  N_ ("Stock Assistant"),
492  G_CALLBACK (gnc_plugin_page_register_cmd_stock_assistant)
493  },
494  {
495  "ActionsStockSplitAction", NULL, N_ ("Stoc_k Split..."), NULL,
496  N_ ("Record a stock split or a stock merger"),
497  G_CALLBACK (gnc_plugin_page_register_cmd_stock_split)
498  },
499  {
500  "ActionsLotsAction", NULL, N_ ("View _Lots..."), NULL,
501  N_ ("Bring up the lot viewer/editor window"),
502  G_CALLBACK (gnc_plugin_page_register_cmd_lots)
503  },
504  {
505  "BlankTransactionAction", "go-bottom", N_ ("_Blank Transaction"), "<primary>Page_Down",
506  N_ ("Move to the blank transaction at the bottom of the register"),
507  G_CALLBACK (gnc_plugin_page_register_cmd_blank_transaction)
508  },
509  {
510  "GotoDateAction", "x-office-calendar", N_ ("_Go to Date"), "<primary>G",
511  N_ ("Move to the split at the specified date"),
512  G_CALLBACK (gnc_plugin_page_register_cmd_goto_date)
513  },
514  {
515  "EditExchangeRateAction", NULL, N_ ("Edit E_xchange Rate"), NULL,
516  N_ ("Edit the exchange rate for the current transaction"),
517  G_CALLBACK (gnc_plugin_page_register_cmd_exchange_rate)
518  },
519  {
520 /* Translators: This is a menu item that will open a register tab for the
521  account of the first other account in the current transaction's split list
522  with focus on the current transaction's entry in that register. */
523  "JumpTransactionAction", GNC_ICON_JUMP_TO, N_ ("_Jump to the other account"), NULL,
524  N_ ("Open a new register tab for the other account with focus on this transaction."),
525  G_CALLBACK (gnc_plugin_page_register_cmd_jump)
526  },
527  {
528  "ScheduleTransactionAction", GNC_ICON_SCHEDULE, N_ ("Sche_dule..."), NULL,
529  N_ ("Create a Scheduled Transaction with the current transaction as a template"),
530  G_CALLBACK (gnc_plugin_page_register_cmd_schedule)
531  },
532  {
533  "ScrubAllAction", NULL,
534  /* Translators: The following 2 are Scrub actions in register view */
535  N_ ("_All transactions"), NULL, NULL,
536  G_CALLBACK (gnc_plugin_page_register_cmd_scrub_all)
537  },
538  {
539  "ScrubCurrentAction", NULL, N_ ("_This transaction"), NULL, NULL,
540  G_CALLBACK (gnc_plugin_page_register_cmd_scrub_current)
541  },
542 
543  /* Reports menu */
544 
545  {
546  "ReportsAccountReportAction", NULL, N_ ("Account Report"), NULL,
547  N_ ("Open a register report for this Account"),
548  G_CALLBACK (gnc_plugin_page_register_cmd_account_report)
549  },
550  {
551  "ReportsAcctTransReportAction", NULL, N_ ("Account Report - Single Transaction"), NULL,
552  N_ ("Open a register report for the selected Transaction"),
553  G_CALLBACK (gnc_plugin_page_register_cmd_transaction_report)
554  },
555 };
556 
557 static guint gnc_plugin_page_register_n_actions = G_N_ELEMENTS (
558  gnc_plugin_page_register_actions);
559 
560 static GtkToggleActionEntry toggle_entries[] =
561 {
562  {
563  "ViewStyleDoubleLineAction", NULL, N_ ("_Double Line"), NULL,
564  N_ ("Show a second line with \"Action\", \"Notes\", and \"Linked Document\" for each transaction."),
565  G_CALLBACK (gnc_plugin_page_register_cmd_style_double_line), FALSE
566  },
567 
568  {
569  "SplitTransactionAction", GNC_ICON_SPLIT_TRANS, N_ ("S_plit Transaction"), NULL,
570  N_ ("Show all splits in the current transaction"),
571  G_CALLBACK (gnc_plugin_page_register_cmd_expand_transaction), FALSE
572  },
573 };
574 
575 static guint n_toggle_entries = G_N_ELEMENTS (toggle_entries);
576 
577 static GtkRadioActionEntry radio_entries_2 [] =
578 {
579  /* Translators: This is a menu item in the View menu */
580  {
581  "ViewStyleBasicAction", NULL, N_ ("_Basic Ledger"), NULL,
582  N_ ("Show transactions on one or two lines"), REG_STYLE_LEDGER
583  },
584  /* Translators: This is a menu item in the View menu */
585  {
586  "ViewStyleAutoSplitAction", NULL, N_ ("_Auto-Split Ledger"), NULL,
587  N_ ("Show transactions on one or two lines and expand the current transaction"), REG_STYLE_AUTO_LEDGER
588  },
589  /* Translators: This is a menu item in the View menu */
590  {
591  "ViewStyleJournalAction", NULL, N_ ("Transaction _Journal"), NULL,
592  N_ ("Show expanded transactions with all splits"), REG_STYLE_JOURNAL
593  }
594 };
595 
596 static guint n_radio_entries_2 = G_N_ELEMENTS (radio_entries_2);
597 
601 static const gchar* important_actions[] =
602 {
603  "SplitTransactionAction",
604  NULL,
605 };
606 
609 static const gchar* actions_requiring_account[] =
610 {
611  "EditEditAccountAction",
612  "ActionsReconcileAction",
613  "ActionsAutoClearAction",
614  "ActionsLotsAction",
615  NULL
616 };
617 
619 static const gchar* view_style_actions[] =
620 {
621  "ViewStyleBasicAction",
622  "ViewStyleAutoSplitAction",
623  "ViewStyleJournalAction",
624  NULL
625 };
626 
627 static const gchar* actions_requiring_extra[] =
628 {
629  "ActionsStockAssistantAction",
630  NULL
631 };
632 
633 static const gchar* actions_requiring_priced_account[] =
634 {
635  "ActionsStockAssistantAction",
636  NULL
637 };
638 
640 static action_toolbar_labels toolbar_labels[] =
641 {
642  { "ActionsTransferAction", N_ ("Transfer") },
643  { "RecordTransactionAction", N_ ("Enter") },
644  { "CancelTransactionAction", N_ ("Cancel") },
645  { "DeleteTransactionAction", N_ ("Delete") },
646  { "DuplicateTransactionAction", N_ ("Duplicate") },
647  { "SplitTransactionAction", N_ ("Split") },
648  { "JumpTransactionAction", N_ ("Jump") },
649  { "ScheduleTransactionAction", N_ ("Schedule") },
650  { "BlankTransactionAction", N_ ("Blank") },
651  { "ActionsReconcileAction", N_ ("Reconcile") },
652  { "ActionsAutoClearAction", N_ ("Auto-clear") },
653  { "LinkTransactionAction", N_ ("Manage Document Link") },
654  { "LinkedTransactionOpenAction", N_ ("Open Linked Document") },
655  { "JumpLinkedInvoiceAction", N_ ("Invoice") },
656  { NULL, NULL },
657 };
658 
660 {
661  const char* action_name;
662  int value;
663  GtkWidget* widget;
664 };
665 
666 static struct status_action status_actions[] =
667 {
668  { "filter_status_reconciled", CLEARED_RECONCILED, NULL },
669  { "filter_status_cleared", CLEARED_CLEARED, NULL },
670  { "filter_status_voided", CLEARED_VOIDED, NULL },
671  { "filter_status_frozen", CLEARED_FROZEN, NULL },
672  { "filter_status_unreconciled", CLEARED_NO, NULL },
673  { NULL, 0, NULL },
674 };
675 
676 #define CLEARED_VALUE "cleared_value"
677 #define DEFAULT_FILTER "0x001f"
678 #define DEFAULT_SORT_ORDER "BY_STANDARD"
679 
680 /************************************************************/
681 /* Data Structures */
682 /************************************************************/
683 
685 {
686  GNCLedgerDisplay* ledger;
687  GNCSplitReg* gsr;
688 
689  GtkWidget* widget;
690 
691  gint event_handler_id;
692  gint component_manager_id;
693  GncGUID key; /* The guid of the Account we're watching */
694 
695  gint lines_default;
696  gboolean read_only;
697  gboolean page_focus;
698  gboolean enable_refresh; // used to reduce ledger display refreshes
699  Query* search_query; // saved search query for comparison
700  Query* filter_query; // saved filter query for comparison
701 
702  struct
703  {
704  GtkWidget* dialog;
705  GtkWidget* num_radio;
706  GtkWidget* act_radio;
707  SortType original_sort_type;
708  gboolean original_save_order;
709  gboolean save_order;
710  gboolean reverse_order;
711  gboolean original_reverse_order;
712  } sd;
713 
714  struct
715  {
716  GtkWidget* dialog;
717  GtkWidget* table;
718  GtkWidget* start_date_choose;
719  GtkWidget* start_date_today;
720  GtkWidget* start_date;
721  GtkWidget* end_date_choose;
722  GtkWidget* end_date_today;
723  GtkWidget* end_date;
724  GtkWidget* num_days;
725  cleared_match_t original_cleared_match;
726  cleared_match_t cleared_match;
727  time64 original_start_time;
728  time64 original_end_time;
729  time64 start_time;
730  time64 end_time;
731  gint days;
732  gint original_days;
733  gboolean original_save_filter;
734  gboolean save_filter;
735  } fd;
737 
738 G_DEFINE_TYPE_WITH_PRIVATE (GncPluginPageRegister, gnc_plugin_page_register,
739  GNC_TYPE_PLUGIN_PAGE)
740 
741 #define GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE(o) \
742  ((GncPluginPageRegisterPrivate*)g_type_instance_get_private((GTypeInstance*)o, GNC_TYPE_PLUGIN_PAGE_REGISTER))
743 
744 static GObjectClass* parent_class = NULL;
745 
746 /************************************************************/
747 /* Implementation */
748 /************************************************************/
749 
750 static GncPluginPage*
751 gnc_plugin_page_register_new_common (GNCLedgerDisplay* ledger)
752 {
753  GncPluginPageRegister* register_page;
755  GncPluginPage* plugin_page;
756  GNCSplitReg* gsr;
757  const GList* item;
758  GList* book_list;
759  gchar* label;
760  gchar* label_color;
761  QofQuery* q;
762 
763  // added for version 4.0 onwards
764  if (!gnc_features_check_used (gnc_get_current_book(), GNC_FEATURE_REG_SORT_FILTER))
765  gnc_features_set_used (gnc_get_current_book(), GNC_FEATURE_REG_SORT_FILTER);
766 
767  /* Is there an existing page? */
768  gsr = gnc_ledger_display_get_user_data (ledger);
769  if (gsr)
770  {
771  item = gnc_gobject_tracking_get_list (GNC_PLUGIN_PAGE_REGISTER_NAME);
772  for (; item; item = g_list_next (item))
773  {
774  register_page = (GncPluginPageRegister*)item->data;
775  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (register_page);
776  if (priv->gsr == gsr)
777  return GNC_PLUGIN_PAGE (register_page);
778  }
779  }
780 
781  register_page = g_object_new (GNC_TYPE_PLUGIN_PAGE_REGISTER, NULL);
782  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (register_page);
783  priv->ledger = ledger;
784  priv->key = *guid_null();
785 
786  plugin_page = GNC_PLUGIN_PAGE (register_page);
787  label = gnc_plugin_page_register_get_tab_name (plugin_page);
788  gnc_plugin_page_set_page_name (plugin_page, label);
789  g_free (label);
790 
791  label_color = gnc_plugin_page_register_get_tab_color (plugin_page);
792  gnc_plugin_page_set_page_color (plugin_page, label_color);
793  g_free (label_color);
794 
795  label = gnc_plugin_page_register_get_long_name (plugin_page);
796  gnc_plugin_page_set_page_long_name (plugin_page, label);
797  g_free (label);
798 
799  q = gnc_ledger_display_get_query (ledger);
800  book_list = qof_query_get_books (q);
801  for (item = book_list; item; item = g_list_next (item))
802  gnc_plugin_page_add_book (plugin_page, (QofBook*)item->data);
803  // Do not free the list. It is owned by the query.
804 
805  priv->component_manager_id = 0;
806  return plugin_page;
807 }
808 
809 static gpointer
810 gnc_plug_page_register_check_commodity (Account* account, void* usr_data)
811 {
812  // Check that account's commodity matches the commodity in usr_data
813  gnc_commodity* com0 = (gnc_commodity*) usr_data;
814  gnc_commodity* com1 = xaccAccountGetCommodity (account);
815  return gnc_commodity_equal (com1, com0) ? NULL : com1;
816 }
817 
819 gnc_plugin_page_register_new (Account* account, gboolean subaccounts)
820 {
821  GNCLedgerDisplay* ledger;
822  GncPluginPage* page;
824  gnc_commodity* com0;
825  gnc_commodity* com1;
826 
827  /*################## Added for Reg2 #################*/
828  const GList* item;
829  GncPluginPageRegister2* new_register_page;
830  /*################## Added for Reg2 #################*/
831 
832  ENTER ("account=%p, subaccounts=%s", account,
833  subaccounts ? "TRUE" : "FALSE");
834 
835  /*################## Added for Reg2 #################*/
836  // We test for the new register being open here, ie matching account guids
837  item = gnc_gobject_tracking_get_list (GNC_PLUGIN_PAGE_REGISTER2_NAME);
838  for (; item; item = g_list_next (item))
839  {
840  Account* new_account;
841  new_register_page = (GncPluginPageRegister2*)item->data;
842  new_account = gnc_plugin_page_register2_get_account (new_register_page);
843 
844  if (guid_equal (xaccAccountGetGUID (account),
845  xaccAccountGetGUID (new_account)))
846  {
847  GtkWindow* window = GTK_WINDOW (gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (
848  new_register_page)));
849  gnc_error_dialog (window, "%s",
850  _ ("You have tried to open an account in the old register while it is open in the new register."));
851  return NULL;
852  }
853  }
854  /*################## Added for Reg2 #################*/
855  com0 = gnc_account_get_currency_or_parent (account);
856  com1 = gnc_account_foreach_descendant_until (account,
857  gnc_plug_page_register_check_commodity, com0);
858 
859  if (subaccounts)
860  ledger = gnc_ledger_display_subaccounts (account, com1 != NULL);
861  else
862  ledger = gnc_ledger_display_simple (account);
863 
864  page = gnc_plugin_page_register_new_common (ledger);
865  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
866  priv->key = *xaccAccountGetGUID (account);
867 
868  LEAVE ("%p", page);
869  return page;
870 }
871 
874 {
875  GNCLedgerDisplay* ledger;
876 
877  ledger = gnc_ledger_display_gl();
878  return gnc_plugin_page_register_new_common (ledger);
879 }
880 
882 gnc_plugin_page_register_new_ledger (GNCLedgerDisplay* ledger)
883 {
884  return gnc_plugin_page_register_new_common (ledger);
885 }
886 
887 static void
888 gnc_plugin_page_register_class_init (GncPluginPageRegisterClass* klass)
889 {
890  GObjectClass* object_class = G_OBJECT_CLASS (klass);
891  GncPluginPageClass* gnc_plugin_class = GNC_PLUGIN_PAGE_CLASS (klass);
892 
893  parent_class = g_type_class_peek_parent (klass);
894 
895  object_class->finalize = gnc_plugin_page_register_finalize;
896 
897  gnc_plugin_class->tab_icon = GNC_ICON_ACCOUNT;
898  gnc_plugin_class->plugin_name = GNC_PLUGIN_PAGE_REGISTER_NAME;
899  gnc_plugin_class->create_widget = gnc_plugin_page_register_create_widget;
900  gnc_plugin_class->destroy_widget = gnc_plugin_page_register_destroy_widget;
901  gnc_plugin_class->window_changed = gnc_plugin_page_register_window_changed;
902  gnc_plugin_class->focus_page = gnc_plugin_page_register_focus;
903  gnc_plugin_class->save_page = gnc_plugin_page_register_save_page;
904  gnc_plugin_class->recreate_page = gnc_plugin_page_register_recreate_page;
905  gnc_plugin_class->update_edit_menu_actions =
906  gnc_plugin_page_register_update_edit_menu;
907  gnc_plugin_class->finish_pending = gnc_plugin_page_register_finish_pending;
908  gnc_plugin_class->focus_page_function = gnc_plugin_page_register_focus_widget;
909 
910  gnc_ui_register_account_destroy_callback (gppr_account_destroy_cb);
911 }
912 
913 static void
914 gnc_plugin_page_register_init (GncPluginPageRegister* plugin_page)
915 {
917  GncPluginPage* parent;
918  GtkActionGroup* action_group;
919  gboolean use_new;
920 
921  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
922 
923  /* Init parent declared variables */
924  parent = GNC_PLUGIN_PAGE (plugin_page);
925  use_new = gnc_prefs_get_bool (GNC_PREFS_GROUP_GENERAL_REGISTER,
926  GNC_PREF_USE_NEW);
927  g_object_set (G_OBJECT (plugin_page),
928  "page-name", _ ("General Journal"),
929  "page-uri", "default:",
930  "ui-description", "gnc-plugin-page-register-ui.xml",
931  "use-new-window", use_new,
932  NULL);
933 
934  /* Create menu and toolbar information */
935  action_group =
937  "GncPluginPageRegisterActions");
938  gtk_action_group_add_actions (action_group, gnc_plugin_page_register_actions,
939  gnc_plugin_page_register_n_actions, plugin_page);
940  gtk_action_group_add_toggle_actions (action_group,
941  toggle_entries, n_toggle_entries,
942  plugin_page);
943  gtk_action_group_add_radio_actions (action_group,
944  radio_entries_2, n_radio_entries_2,
945  REG_STYLE_LEDGER,
946  G_CALLBACK (gnc_plugin_page_register_cmd_style_changed),
947  plugin_page);
948 
949  gnc_plugin_init_short_names (action_group, toolbar_labels);
950  gnc_plugin_set_important_actions (action_group, important_actions);
951 
952  priv->lines_default = DEFAULT_LINES_AMOUNT;
953  priv->read_only = FALSE;
954  priv->fd.cleared_match = CLEARED_ALL;
955  priv->fd.days = 0;
956  priv->enable_refresh = TRUE;
957  priv->search_query = NULL;
958  priv->filter_query = NULL;
959 }
960 
961 static void
962 gnc_plugin_page_register_finalize (GObject* object)
963 {
964  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (object));
965 
966  ENTER ("object %p", object);
967 
968  G_OBJECT_CLASS (parent_class)->finalize (object);
969  LEAVE (" ");
970 }
971 
972 Account*
974 {
976  GNCLedgerDisplayType ledger_type;
977  Account* leader;
978 
979  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
980  ledger_type = gnc_ledger_display_type (priv->ledger);
981  leader = gnc_ledger_display_leader (priv->ledger);
982 
983  if ((ledger_type == LD_SINGLE) || (ledger_type == LD_SUBACCOUNT))
984  return leader;
985  return NULL;
986 }
987 
988 Transaction*
990 {
992  SplitRegister* reg;
993 
994  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
995  reg = gnc_ledger_display_get_split_register (priv->ledger);
997 }
998 
1003 static gboolean
1004 gnc_plugin_page_register_focus_widget (GncPluginPage* register_plugin_page)
1005 {
1006  if (GNC_IS_PLUGIN_PAGE_REGISTER (register_plugin_page))
1007  {
1008  GNCSplitReg *gsr = gnc_plugin_page_register_get_gsr (GNC_PLUGIN_PAGE(register_plugin_page));
1009 
1010  gnc_plugin_page_register_ui_update (NULL, GNC_PLUGIN_PAGE_REGISTER(register_plugin_page));
1011 
1012  gnc_split_reg_focus_on_sheet (gsr);
1013  }
1014  return FALSE;
1015 }
1016 
1017 /* This is the list of actions which are switched inactive in a read-only book. */
1018 static const char* readonly_inactive_actions[] =
1019 {
1020  "EditCutAction",
1021  "EditPasteAction",
1022  "CutTransactionAction",
1023  "PasteTransactionAction",
1024  "DuplicateTransactionAction",
1025  "DeleteTransactionAction",
1026  "RemoveTransactionSplitsAction",
1027  "RecordTransactionAction",
1028  "CancelTransactionAction",
1029  "UnvoidTransactionAction",
1030  "VoidTransactionAction",
1031  "ReverseTransactionAction",
1032  "ActionsTransferAction",
1033  "ActionsReconcileAction",
1034  "ActionsStockSplitAction",
1035  "ScheduleTransactionAction",
1036  "ScrubAllAction",
1037  "ScrubCurrentAction",
1038  "LinkTransactionAction",
1039  NULL
1040 };
1041 
1042 /* This is the list of actions whose text needs to be changed based on whether */
1043 /* the current cursor class is transaction or split. */
1044 static const char* tran_vs_split_actions[] =
1045 {
1046  "CutTransactionAction",
1047  "CopyTransactionAction",
1048  "PasteTransactionAction",
1049  "DuplicateTransactionAction",
1050  "DeleteTransactionAction",
1051  NULL
1052 };
1053 
1054 /* This is the list of labels for when the current cursor class is transaction. */
1055 static const char* tran_action_labels[] =
1056 {
1057  CUT_TRANSACTION_LABEL,
1058  COPY_TRANSACTION_LABEL,
1059  PASTE_TRANSACTION_LABEL,
1060  DUPLICATE_TRANSACTION_LABEL,
1061  DELETE_TRANSACTION_LABEL,
1062  LINK_TRANSACTION_LABEL,
1063  LINK_TRANSACTION_OPEN_LABEL,
1064  JUMP_LINKED_INVOICE_LABEL,
1065  NULL
1066 };
1067 
1068 /* This is the list of tooltips for when the current cursor class is transaction. */
1069 static const char* tran_action_tips[] =
1070 {
1071  CUT_TRANSACTION_TIP,
1072  COPY_TRANSACTION_TIP,
1073  PASTE_TRANSACTION_TIP,
1074  DUPLICATE_TRANSACTION_TIP,
1075  DELETE_TRANSACTION_TIP,
1076  LINK_TRANSACTION_TIP,
1077  LINK_TRANSACTION_OPEN_TIP,
1078  JUMP_LINKED_INVOICE_TIP,
1079  NULL
1080 };
1081 
1082 /* This is the list of labels for when the current cursor class is split. */
1083 static const char* split_action_labels[] =
1084 {
1085  CUT_SPLIT_LABEL,
1086  COPY_SPLIT_LABEL,
1087  PASTE_SPLIT_LABEL,
1088  DUPLICATE_SPLIT_LABEL,
1089  DELETE_SPLIT_LABEL,
1090  NULL
1091 };
1092 
1093 /* This is the list of tooltips for when the current cursor class is split. */
1094 static const char* split_action_tips[] =
1095 {
1096  CUT_SPLIT_TIP,
1097  COPY_SPLIT_TIP,
1098  PASTE_SPLIT_TIP,
1099  DUPLICATE_SPLIT_TIP,
1100  DELETE_SPLIT_TIP,
1101  NULL
1102 };
1103 
1104 static void
1105 gnc_plugin_page_register_ui_update (gpointer various,
1106  GncPluginPageRegister* page)
1107 {
1109  SplitRegister* reg;
1110  GtkAction* action;
1111  gboolean expanded, voided, read_only = FALSE, read_only_reg = FALSE;
1112  Transaction* trans;
1113  GList* invoices;
1114  CursorClass cursor_class;
1115  const char* uri;
1116 
1117  /* Set 'Split Transaction' */
1118  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
1119  reg = gnc_ledger_display_get_split_register (priv->ledger);
1120  cursor_class = gnc_split_register_get_current_cursor_class (reg);
1122  action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page),
1123  "SplitTransactionAction");
1124  gtk_action_set_sensitive (action, reg->style == REG_STYLE_LEDGER);
1125  g_signal_handlers_block_by_func
1126  (action, gnc_plugin_page_register_cmd_expand_transaction, page);
1127  gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), expanded);
1128  g_signal_handlers_unblock_by_func
1129  (action, gnc_plugin_page_register_cmd_expand_transaction, page);
1130 
1131  /* If we are in a readonly book, or possibly a place holder
1132  * account register make any modifying action inactive */
1133  if (qof_book_is_readonly (gnc_get_current_book()) ||
1134  gnc_split_reg_get_read_only (priv->gsr))
1135  read_only_reg = TRUE;
1136 
1137  /* Set available actions based on read only */
1139 
1140  /* If the register is not read only, make any modifying action active
1141  * to start with */
1142  if (!read_only_reg)
1143  {
1144  const char** iter;
1145  for (iter = readonly_inactive_actions; *iter; ++iter)
1146  {
1147  /* Set the action's sensitivity */
1148  GtkAction* action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page), *iter);
1149  gtk_action_set_sensitive (action, TRUE);
1150  }
1151  main_window_update_page_set_read_only_icon (GNC_PLUGIN_PAGE(page), FALSE);
1152 
1153  if (trans)
1154  read_only = xaccTransIsReadonlyByPostedDate (trans);
1155 
1156  voided = xaccTransHasSplitsInState (trans, VREC);
1157 
1158  action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page),
1159  "CutTransactionAction");
1160  gtk_action_set_sensitive (GTK_ACTION (action), !read_only & !voided);
1161 
1162  action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page),
1163  "PasteTransactionAction");
1164  gtk_action_set_sensitive (GTK_ACTION (action), !read_only & !voided);
1165 
1166  action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page),
1167  "DeleteTransactionAction");
1168  gtk_action_set_sensitive (GTK_ACTION (action), !read_only & !voided);
1169 
1170  if (cursor_class == CURSOR_CLASS_SPLIT)
1171  {
1172  action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page),
1173  "DuplicateTransactionAction");
1174  gtk_action_set_sensitive (GTK_ACTION (action), !read_only & !voided);
1175  }
1176 
1177  action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page),
1178  "RemoveTransactionSplitsAction");
1179  gtk_action_set_sensitive (GTK_ACTION (action), !read_only & !voided);
1180 
1181  /* Set 'Void' and 'Unvoid' */
1182  if (read_only)
1183  voided = TRUE;
1184 
1185  action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page),
1186  "VoidTransactionAction");
1187  gtk_action_set_sensitive (GTK_ACTION (action), !voided);
1188 
1189  if (read_only)
1190  voided = FALSE;
1191 
1192  action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page),
1193  "UnvoidTransactionAction");
1194  gtk_action_set_sensitive (GTK_ACTION (action), voided);
1195  }
1196 
1197  /* Set 'Open and Remove Linked Documents' */
1198  action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page),
1199  "LinkedTransactionOpenAction");
1200  if (trans)
1201  {
1202  uri = xaccTransGetDocLink (trans);
1203  gtk_action_set_sensitive (GTK_ACTION(action), (uri ? TRUE:FALSE));
1204  }
1205  /* Set 'ExecAssociatedInvoice'
1206  We can determine an invoice from a txn if either
1207  - it is an invoice transaction
1208  - it has splits with an invoice associated with it
1209  */
1210  action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page),
1211  "JumpLinkedInvoiceAction");
1212  if (trans)
1213  {
1214  invoices = invoices_from_transaction (trans);
1215  gtk_action_set_sensitive (GTK_ACTION (action), (invoices != NULL));
1216  g_list_free (invoices);
1217  }
1218 
1219  gnc_plugin_business_split_reg_ui_update (GNC_PLUGIN_PAGE (page));
1220 
1221  /* If we are read only, make any modifying action inactive */
1222  if (read_only_reg)
1223  {
1224  const char** iter;
1225  for (iter = readonly_inactive_actions; *iter; ++iter)
1226  {
1227  /* Set the action's sensitivity */
1228  GtkAction* action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page), *iter);
1229  gtk_action_set_sensitive (action, FALSE);
1230  }
1231  main_window_update_page_set_read_only_icon (GNC_PLUGIN_PAGE(page), TRUE);
1232  }
1233 
1234  /* Modifying action descriptions based on cursor class */
1235  {
1236  const char** iter, **label_iter, **tooltip_iter;
1237  gboolean curr_label_trans = FALSE;
1238  iter = tran_vs_split_actions;
1239  action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page), *iter);
1240  label_iter = tran_action_labels;
1241  if (g_strcmp0 (gtk_action_get_label (action), _ (*label_iter)) == 0)
1242  curr_label_trans = TRUE;
1243  if ((cursor_class == CURSOR_CLASS_SPLIT) && curr_label_trans)
1244  {
1245  label_iter = split_action_labels;
1246  tooltip_iter = split_action_tips;
1247  for (iter = tran_vs_split_actions; *iter; ++iter)
1248  {
1249  /* Adjust the action's label and tooltip */
1250  action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page), *iter);
1251  gtk_action_set_label (action, _ (*label_iter));
1252  gtk_action_set_tooltip (action, _ (*tooltip_iter));
1253  ++label_iter;
1254  ++tooltip_iter;
1255  }
1256  }
1257  else if ((cursor_class == CURSOR_CLASS_TRANS) && !curr_label_trans)
1258  {
1259  label_iter = tran_action_labels;
1260  tooltip_iter = tran_action_tips;
1261  for (iter = tran_vs_split_actions; *iter; ++iter)
1262  {
1263  /* Adjust the action's label and tooltip */
1264  action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page), *iter);
1265  gtk_action_set_label (action, _ (*label_iter));
1266  gtk_action_set_tooltip (action, _ (*tooltip_iter));
1267  ++label_iter;
1268  ++tooltip_iter;
1269  }
1270  }
1271  }
1272 }
1273 
1274 static void
1275 gnc_plugin_page_register_ui_initial_state (GncPluginPageRegister* page)
1276 {
1278  GtkActionGroup* action_group;
1279  GtkAction* action;
1280  Account* account;
1281  SplitRegister* reg;
1282  GNCLedgerDisplayType ledger_type;
1283  int i;
1284  gboolean is_readwrite = !qof_book_is_readonly (gnc_get_current_book());
1285 
1286  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
1287  account = gnc_plugin_page_register_get_account (page);
1288  action_group = gnc_plugin_page_get_action_group (GNC_PLUGIN_PAGE (page));
1289  gnc_plugin_update_actions (action_group, actions_requiring_account,
1290  "sensitive", is_readwrite && account != NULL);
1291 
1292  gnc_plugin_update_actions (action_group, actions_requiring_extra,
1293  "visible", gnc_prefs_is_extra_enabled ());
1294 
1295  gnc_plugin_update_actions (action_group, actions_requiring_priced_account,
1296  "sensitive", account && xaccAccountIsPriced (account));
1297 
1298  /* Set "style" radio button */
1299  ledger_type = gnc_ledger_display_type (priv->ledger);
1300  gnc_plugin_update_actions (action_group, view_style_actions,
1301  "sensitive", ledger_type == LD_SINGLE);
1302 
1303  reg = gnc_ledger_display_get_split_register (priv->ledger);
1304  for (i = n_radio_entries_2 - 1; i > 0; i--)
1305  {
1306  DEBUG (" index %d: comparing %x to %x", i, radio_entries_2[i].value,
1307  reg->style);
1308  if (radio_entries_2[i].value == reg->style)
1309  {
1310  DEBUG ("match");
1311  break;
1312  }
1313  }
1314 
1315  /* Either a match was found, or fell out with i = 0 */
1316  action = gtk_action_group_get_action (action_group, radio_entries_2[i].name);
1317  g_signal_handlers_block_by_func (action,
1318  gnc_plugin_page_register_cmd_style_changed, page);
1319  gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1320  g_signal_handlers_unblock_by_func (action,
1321  gnc_plugin_page_register_cmd_style_changed, page);
1322 
1323  /* Set "double line" toggle button */
1324  action = gtk_action_group_get_action (action_group,
1325  "ViewStyleDoubleLineAction");
1326  g_signal_handlers_block_by_func (action,
1327  gnc_plugin_page_register_cmd_style_double_line, page);
1328  gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1329  reg->use_double_line);
1330  g_signal_handlers_unblock_by_func (action,
1331  gnc_plugin_page_register_cmd_style_double_line, page);
1332 }
1333 
1334 /* Virtual Functions */
1335 
1336 static const gchar*
1337 get_filter_default_num_of_days (GNCLedgerDisplayType ledger_type)
1338 {
1339  if (ledger_type == LD_GL)
1340  return DEFAULT_FILTER_NUM_DAYS_GL;
1341  else
1342  return "0";
1343 }
1344 
1345 /* For setting the focus on a register page, the default gnc_plugin
1346  * function for 'focus_page' is overridden so that the page focus
1347  * can be conditionally set. This is to allow for enabling the setting
1348  * of the sheet focus only when the page is the current one.
1349  */
1350 static void
1351 gnc_plugin_page_register_focus (GncPluginPage* plugin_page,
1352  gboolean on_current_page)
1353 {
1354  GncPluginPageRegister* page;
1356  GNCSplitReg* gsr;
1357 
1358  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
1359 
1360  page = GNC_PLUGIN_PAGE_REGISTER (plugin_page);
1361  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
1362 
1363  gsr = gnc_plugin_page_register_get_gsr (GNC_PLUGIN_PAGE (plugin_page));
1364 
1365  if (on_current_page)
1366  {
1367  priv->page_focus = TRUE;
1368 
1369  // Chain up to use parent version of 'focus_page' which will
1370  // use an idle_add as the page changed signal is emitted multiple times.
1371  GNC_PLUGIN_PAGE_CLASS (parent_class)->focus_page (plugin_page, TRUE);
1372  }
1373  else
1374  priv->page_focus = FALSE;
1375 
1376  // set the sheet focus setting
1377  gnc_split_reg_set_sheet_focus (gsr, priv->page_focus);
1378 }
1379 
1380 static GtkWidget*
1381 gnc_plugin_page_register_create_widget (GncPluginPage* plugin_page)
1382 {
1383  GncPluginPageRegister* page;
1385  GNCLedgerDisplayType ledger_type;
1386  GncWindow* gnc_window;
1387  guint numRows;
1388  GtkWidget* gsr;
1389  SplitRegister* reg;
1390  Account* acct;
1391  gchar* order;
1392  int filter_changed = 0;
1393  gboolean create_new_page = FALSE;
1394 
1395  ENTER ("page %p", plugin_page);
1396  page = GNC_PLUGIN_PAGE_REGISTER (plugin_page);
1397  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
1398 
1399  if (priv->widget != NULL)
1400  {
1401  LEAVE ("existing widget %p", priv->widget);
1402  return priv->widget;
1403  }
1404  // on create, the page will be the current page so set the focus flag
1405  priv->page_focus = TRUE;
1406 
1407  priv->widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
1408  gtk_box_set_homogeneous (GTK_BOX (priv->widget), FALSE);
1409  gtk_widget_show (priv->widget);
1410 
1411  // Set the name for this widget so it can be easily manipulated with css
1412  gtk_widget_set_name (GTK_WIDGET(priv->widget), "gnc-id-register-page");
1413 
1414  numRows = priv->lines_default;
1415  numRows = MIN (numRows, DEFAULT_LINES_AMOUNT);
1416 
1417  gnc_window = GNC_WINDOW(GNC_PLUGIN_PAGE(page)->window);
1418  gsr = gnc_split_reg_new (priv->ledger,
1419  gnc_window_get_gtk_window (gnc_window),
1420  numRows, priv->read_only);
1421  priv->gsr = (GNCSplitReg *)gsr;
1422 
1423  gtk_widget_show (gsr);
1424  gtk_box_pack_start (GTK_BOX (priv->widget), gsr, TRUE, TRUE, 0);
1425 
1426  g_signal_connect (G_OBJECT (gsr), "help-changed",
1427  G_CALLBACK (gnc_plugin_page_help_changed_cb),
1428  page);
1429 
1430  g_signal_connect (G_OBJECT (gsr), "show-popup-menu",
1431  G_CALLBACK (gnc_plugin_page_popup_menu_cb),
1432  page);
1433 
1434  reg = gnc_ledger_display_get_split_register (priv->ledger);
1435  gnc_split_register_config (reg, reg->type, reg->style,
1436  reg->use_double_line);
1437 
1438  gnc_plugin_page_register_ui_initial_state (page);
1439  gnc_plugin_page_register_ui_update (NULL, page);
1440 
1441  ledger_type = gnc_ledger_display_type (priv->ledger);
1442 
1443  {
1444  gchar** filter;
1445  gchar* filter_str;
1446  guint filtersize = 0;
1447  /* Set the sort order for the split register and status of save order button */
1448  priv->sd.save_order = FALSE;
1449  order = gnc_plugin_page_register_get_sort_order (plugin_page);
1450 
1451  PINFO ("Loaded Sort order is %s", order);
1452 
1453  gnc_split_reg_set_sort_type (priv->gsr, SortTypefromString (order));
1454 
1455  if (order && (g_strcmp0 (order, DEFAULT_SORT_ORDER) != 0))
1456  priv->sd.save_order = TRUE;
1457 
1458  priv->sd.original_save_order = priv->sd.save_order;
1459  g_free (order);
1460 
1461  priv->sd.reverse_order = gnc_plugin_page_register_get_sort_reversed (
1462  plugin_page);
1463  gnc_split_reg_set_sort_reversed (priv->gsr, priv->sd.reverse_order, FALSE);
1464  if (priv->sd.reverse_order)
1465  priv->sd.save_order = TRUE;
1466 
1467  priv->sd.original_reverse_order = priv->sd.reverse_order;
1468 
1469  /* Set the filter for the split register and status of save filter button */
1470  priv->fd.save_filter = FALSE;
1471 
1472  filter_str = gnc_plugin_page_register_get_filter (plugin_page);
1473  filter = g_strsplit (filter_str, ",", -1);
1474  filtersize = g_strv_length (filter);
1475  g_free (filter_str);
1476 
1477  PINFO ("Loaded Filter Status is %s", filter[0]);
1478 
1479  priv->fd.cleared_match = (gint)g_ascii_strtoll (filter[0], NULL, 16);
1480 
1481  if (filtersize > 0 && (g_strcmp0 (filter[0], DEFAULT_FILTER) != 0))
1482  filter_changed = filter_changed + 1;
1483 
1484  if (filtersize > 1 && (g_strcmp0 (filter[1], "0") != 0))
1485  {
1486  PINFO ("Loaded Filter Start Date is %s", filter[1]);
1487 
1488  priv->fd.start_time = gnc_plugin_page_register_filter_dmy2time (filter[1]);
1489  priv->fd.start_time = gnc_time64_get_day_start (priv->fd.start_time);
1490  filter_changed = filter_changed + 1;
1491  }
1492 
1493  if (filtersize > 2 && (g_strcmp0 (filter[2], "0") != 0))
1494  {
1495  PINFO ("Loaded Filter End Date is %s", filter[2]);
1496 
1497  priv->fd.end_time = gnc_plugin_page_register_filter_dmy2time (filter[2]);
1498  priv->fd.end_time = gnc_time64_get_day_end (priv->fd.end_time);
1499  filter_changed = filter_changed + 1;
1500  }
1501 
1502  // set the default for the number of days
1503  priv->fd.days = (gint)g_ascii_strtoll (
1504  get_filter_default_num_of_days (ledger_type), NULL, 10);
1505 
1506  if (filtersize > 3 &&
1507  (g_strcmp0 (filter[3], get_filter_default_num_of_days (ledger_type)) != 0))
1508  {
1509  PINFO ("Loaded Filter Days is %s", filter[3]);
1510 
1511  priv->fd.days = (gint)g_ascii_strtoll (filter[3], NULL, 10);
1512  filter_changed = filter_changed + 1;
1513  }
1514 
1515  if (filter_changed != 0)
1516  priv->fd.save_filter = TRUE;
1517 
1518  priv->fd.original_save_filter = priv->fd.save_filter;
1519  g_strfreev (filter);
1520  }
1521 
1522  if (ledger_type == LD_GL)
1523  {
1524  time64 start_time = 0, end_time = 0;
1525 
1526  if (reg->type == GENERAL_JOURNAL)
1527  {
1528  start_time = priv->fd.start_time;
1529  end_time = priv->fd.end_time;
1530  }
1531  else // search ledger and the like
1532  {
1533  priv->fd.days = 0;
1534  priv->fd.cleared_match = (gint)g_ascii_strtoll (DEFAULT_FILTER, NULL, 16);
1535  gnc_split_reg_set_sort_type (priv->gsr,
1536  SortTypefromString (DEFAULT_SORT_ORDER));
1537  priv->sd.reverse_order = FALSE;
1538  priv->fd.save_filter = FALSE;
1539  priv->sd.save_order = FALSE;
1540  }
1541 
1542  priv->fd.original_days = priv->fd.days;
1543 
1544  priv->fd.original_start_time = start_time;
1545  priv->fd.start_time = start_time;
1546  priv->fd.original_end_time = end_time;
1547  priv->fd.end_time = end_time;
1548  }
1549 
1550  // if enable_refresh is TRUE, default, come from creating
1551  // new page instead of restoring
1552  if (priv->enable_refresh == TRUE)
1553  {
1554  create_new_page = TRUE;
1555  priv->enable_refresh = FALSE; // disable refresh
1556  }
1557 
1558  /* Update Query with Filter Status and Dates */
1559  gnc_ppr_update_status_query (page);
1560  gnc_ppr_update_date_query (page);
1561 
1562  /* Now do the refresh if this is a new page instead of restore */
1563  if (create_new_page)
1564  {
1565  priv->enable_refresh = TRUE;
1566  gnc_ledger_display_refresh (priv->ledger);
1567  }
1568 
1569  // Set filter tooltip for summary bar
1570  gnc_plugin_page_register_set_filter_tooltip (page);
1571 
1572  plugin_page->summarybar = gsr_create_summary_bar (priv->gsr);
1573  if (plugin_page->summarybar)
1574  {
1575  gtk_widget_show_all (plugin_page->summarybar);
1576  gtk_box_pack_start (GTK_BOX (priv->widget), plugin_page->summarybar,
1577  FALSE, FALSE, 0);
1578 
1579  gnc_plugin_page_register_summarybar_position_changed (NULL, NULL, page);
1580  gnc_prefs_register_cb (GNC_PREFS_GROUP_GENERAL,
1581  GNC_PREF_SUMMARYBAR_POSITION_TOP,
1582  gnc_plugin_page_register_summarybar_position_changed,
1583  page);
1584  gnc_prefs_register_cb (GNC_PREFS_GROUP_GENERAL,
1585  GNC_PREF_SUMMARYBAR_POSITION_BOTTOM,
1586  gnc_plugin_page_register_summarybar_position_changed,
1587  page);
1588  }
1589 
1590  priv->event_handler_id = qof_event_register_handler
1591  ((QofEventHandler)gnc_plugin_page_register_event_handler, page);
1592  priv->component_manager_id =
1593  gnc_register_gui_component (GNC_PLUGIN_PAGE_REGISTER_NAME,
1594  gnc_plugin_page_register_refresh_cb,
1595  gnc_plugin_page_register_close_cb,
1596  page);
1597  gnc_gui_component_set_session (priv->component_manager_id,
1598  gnc_get_current_session());
1600  if (acct)
1601  gnc_gui_component_watch_entity (
1602  priv->component_manager_id, xaccAccountGetGUID (acct),
1603  QOF_EVENT_DESTROY | QOF_EVENT_MODIFY);
1604 
1605  gnc_split_reg_set_moved_cb
1606  (priv->gsr, (GFunc)gnc_plugin_page_register_ui_update, page);
1607 
1608  g_signal_connect (G_OBJECT (plugin_page), "inserted",
1609  G_CALLBACK (gnc_plugin_page_inserted_cb),
1610  NULL);
1611 
1612  /* DRH - Probably lots of other stuff from regWindowLedger should end up here. */
1613  LEAVE (" ");
1614  return priv->widget;
1615 }
1616 
1617 static void
1618 gnc_plugin_page_register_destroy_widget (GncPluginPage* plugin_page)
1619 {
1620  GncPluginPageRegister* page;
1622 
1623  ENTER ("page %p", plugin_page);
1624  page = GNC_PLUGIN_PAGE_REGISTER (plugin_page);
1625  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
1626 
1627  gnc_prefs_remove_cb_by_func (GNC_PREFS_GROUP_GENERAL,
1628  GNC_PREF_SUMMARYBAR_POSITION_TOP,
1629  gnc_plugin_page_register_summarybar_position_changed,
1630  page);
1631  gnc_prefs_remove_cb_by_func (GNC_PREFS_GROUP_GENERAL,
1632  GNC_PREF_SUMMARYBAR_POSITION_BOTTOM,
1633  gnc_plugin_page_register_summarybar_position_changed,
1634  page);
1635 
1636  // Remove the page_changed signal callback
1637  gnc_plugin_page_disconnect_page_changed (GNC_PLUGIN_PAGE (plugin_page));
1638 
1639  // Remove the page focus idle function if present
1640  g_idle_remove_by_data (GNC_PLUGIN_PAGE_REGISTER (plugin_page));
1641 
1642  if (priv->widget == NULL)
1643  return;
1644 
1645  if (priv->component_manager_id)
1646  {
1647  gnc_unregister_gui_component (priv->component_manager_id);
1648  priv->component_manager_id = 0;
1649  }
1650 
1651  if (priv->event_handler_id)
1652  {
1653  qof_event_unregister_handler (priv->event_handler_id);
1654  priv->event_handler_id = 0;
1655  }
1656 
1657  if (priv->sd.dialog)
1658  {
1659  gtk_widget_destroy (priv->sd.dialog);
1660  memset (&priv->sd, 0, sizeof (priv->sd));
1661  }
1662 
1663  if (priv->fd.dialog)
1664  {
1665  gtk_widget_destroy (priv->fd.dialog);
1666  memset (&priv->fd, 0, sizeof (priv->fd));
1667  }
1668 
1669  qof_query_destroy (priv->search_query);
1670  qof_query_destroy (priv->filter_query);
1671 
1672  gtk_widget_hide (priv->widget);
1673  gnc_ledger_display_close (priv->ledger);
1674  priv->ledger = NULL;
1675  LEAVE (" ");
1676 }
1677 
1678 static void
1679 gnc_plugin_page_register_window_changed (GncPluginPage* plugin_page,
1680  GtkWidget* window)
1681 {
1682  GncPluginPageRegister* page;
1684 
1685  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
1686 
1687  page = GNC_PLUGIN_PAGE_REGISTER (plugin_page);
1688  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
1689  priv->gsr->window =
1690  GTK_WIDGET (gnc_window_get_gtk_window (GNC_WINDOW (window)));
1691 }
1692 
1693 static const gchar* style_names[] =
1694 {
1695  "Ledger",
1696  "Auto Ledger",
1697  "Journal",
1698  NULL
1699 };
1700 
1701 #define KEY_REGISTER_TYPE "RegisterType"
1702 #define KEY_ACCOUNT_NAME "AccountName"
1703 #define KEY_ACCOUNT_GUID "AccountGuid"
1704 #define KEY_REGISTER_STYLE "RegisterStyle"
1705 #define KEY_DOUBLE_LINE "DoubleLineMode"
1706 
1707 #define LABEL_ACCOUNT "Account"
1708 #define LABEL_SUBACCOUNT "SubAccount"
1709 #define LABEL_GL "GL"
1710 #define LABEL_SEARCH "Search"
1711 
1712 
1722 static void
1723 gnc_plugin_page_register_save_page (GncPluginPage* plugin_page,
1724  GKeyFile* key_file,
1725  const gchar* group_name)
1726 {
1727  GncPluginPageRegister* page;
1729  GNCLedgerDisplayType ledger_type;
1730  SplitRegister* reg;
1731  Account* leader;
1732 
1733  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
1734  g_return_if_fail (key_file != NULL);
1735  g_return_if_fail (group_name != NULL);
1736 
1737  ENTER ("page %p, key_file %p, group_name %s", plugin_page, key_file,
1738  group_name);
1739 
1740  page = GNC_PLUGIN_PAGE_REGISTER (plugin_page);
1741  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
1742 
1743  reg = gnc_ledger_display_get_split_register (priv->ledger);
1744  ledger_type = gnc_ledger_display_type (priv->ledger);
1745  if (ledger_type > LD_GL)
1746  {
1747  LEAVE ("Unsupported ledger type");
1748  return;
1749  }
1750  if ((ledger_type == LD_SINGLE) || (ledger_type == LD_SUBACCOUNT))
1751  {
1752  const gchar* label;
1753  gchar* name;
1754  gchar acct_guid[GUID_ENCODING_LENGTH + 1];
1755  label = (ledger_type == LD_SINGLE) ? LABEL_ACCOUNT : LABEL_SUBACCOUNT;
1756  leader = gnc_ledger_display_leader (priv->ledger);
1757  g_key_file_set_string (key_file, group_name, KEY_REGISTER_TYPE, label);
1758  name = gnc_account_get_full_name (leader);
1759  g_key_file_set_string (key_file, group_name, KEY_ACCOUNT_NAME, name);
1760  g_free (name);
1761  guid_to_string_buff (xaccAccountGetGUID (leader), acct_guid);
1762  g_key_file_set_string (key_file, group_name, KEY_ACCOUNT_GUID, acct_guid);
1763  }
1764  else if (reg->type == GENERAL_JOURNAL)
1765  {
1766  g_key_file_set_string (key_file, group_name, KEY_REGISTER_TYPE,
1767  LABEL_GL);
1768  }
1769  else if (reg->type == SEARCH_LEDGER)
1770  {
1771  g_key_file_set_string (key_file, group_name, KEY_REGISTER_TYPE,
1772  LABEL_SEARCH);
1773  }
1774  else
1775  {
1776  LEAVE ("Unsupported register type");
1777  return;
1778  }
1779 
1780  g_key_file_set_string (key_file, group_name, KEY_REGISTER_STYLE,
1781  style_names[reg->style]);
1782  g_key_file_set_boolean (key_file, group_name, KEY_DOUBLE_LINE,
1783  reg->use_double_line);
1784 
1785  LEAVE(" ");
1786 }
1787 
1788 
1801 static void
1802 gnc_plugin_page_register_restore_edit_menu (GncPluginPage* page,
1803  GKeyFile* key_file,
1804  const gchar* group_name)
1805 {
1806  GtkAction* action;
1807  GError* error = NULL;
1808  gchar* style_name;
1809  gint i;
1810  gboolean use_double_line;
1811 
1812  ENTER (" ");
1813 
1814  /* Convert the style name to an index */
1815  style_name = g_key_file_get_string (key_file, group_name,
1816  KEY_REGISTER_STYLE, &error);
1817  for (i = 0 ; style_names[i]; i++)
1818  {
1819  if (g_ascii_strcasecmp (style_name, style_names[i]) == 0)
1820  {
1821  DEBUG ("Found match for style name: %s", style_name);
1822  break;
1823  }
1824  }
1825  g_free (style_name);
1826 
1827  /* Update the style menu action for this page */
1828  if (i <= REG_STYLE_JOURNAL)
1829  {
1830  DEBUG ("Setting style: %d", i);
1831  action = gnc_plugin_page_get_action (page, radio_entries_2[i].name);
1832  gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1833  }
1834 
1835  /* Update the double line action on this page */
1836  use_double_line =
1837  g_key_file_get_boolean (key_file, group_name, KEY_DOUBLE_LINE, &error);
1838  DEBUG ("Setting double_line_mode: %d", use_double_line);
1839  action = gnc_plugin_page_get_action (page, "ViewStyleDoubleLineAction");
1840  gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), use_double_line);
1841 
1842  LEAVE (" ");
1843 }
1844 
1845 
1855 static GncPluginPage*
1856 gnc_plugin_page_register_recreate_page (GtkWidget* window,
1857  GKeyFile* key_file,
1858  const gchar* group_name)
1859 {
1861  GncPluginPage* page;
1862  GError* error = NULL;
1863  gchar* reg_type, *acct_guid;
1864  GncGUID guid;
1865  Account* account = NULL;
1866  QofBook* book;
1867  gboolean include_subs;
1868 
1869  g_return_val_if_fail (key_file, NULL);
1870  g_return_val_if_fail (group_name, NULL);
1871  ENTER ("key_file %p, group_name %s", key_file, group_name);
1872 
1873  /* Create the new page. */
1874  reg_type = g_key_file_get_string (key_file, group_name,
1875  KEY_REGISTER_TYPE, &error);
1876  DEBUG ("Page type: %s", reg_type);
1877  if ((g_ascii_strcasecmp (reg_type, LABEL_ACCOUNT) == 0) ||
1878  (g_ascii_strcasecmp (reg_type, LABEL_SUBACCOUNT) == 0))
1879  {
1880  include_subs = (g_ascii_strcasecmp (reg_type, LABEL_SUBACCOUNT) == 0);
1881  DEBUG ("Include subs: %d", include_subs);
1882  book = qof_session_get_book (gnc_get_current_session());
1883  if (!book)
1884  {
1885  LEAVE("Session has no book");
1886  return NULL;
1887  }
1888  acct_guid = g_key_file_get_string (key_file, group_name,
1889  KEY_ACCOUNT_GUID, &error);
1890  if (string_to_guid (acct_guid, &guid)) //find account by guid
1891  {
1892  account = xaccAccountLookup (&guid, book);
1893  g_free (acct_guid);
1894  }
1895  if (account == NULL) //find account by full name
1896  {
1897  gchar* acct_name = g_key_file_get_string (key_file, group_name,
1898  KEY_ACCOUNT_NAME, &error);
1899  account = gnc_account_lookup_by_full_name (gnc_book_get_root_account (book),
1900  acct_name);
1901  g_free (acct_name);
1902  }
1903  if (account == NULL)
1904  {
1905  LEAVE ("Bad account name");
1906  g_free (reg_type);
1907  return NULL;
1908  }
1909  page = gnc_plugin_page_register_new (account, include_subs);
1910  }
1911  else if (g_ascii_strcasecmp (reg_type, LABEL_GL) == 0)
1912  {
1914  }
1915  else
1916  {
1917  LEAVE ("Bad ledger type");
1918  g_free (reg_type);
1919  return NULL;
1920  }
1921  g_free (reg_type);
1922 
1923  /* disable the refresh of the display ledger, this is for
1924  * sort/filter updates and double line/style changes */
1925  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
1926  priv->enable_refresh = FALSE;
1927 
1928  /* Recreate page in given window */
1929  gnc_plugin_page_set_use_new_window (page, FALSE);
1930 
1931  /* Install it now so we can them manipulate the created widget */
1932  gnc_main_window_open_page (GNC_MAIN_WINDOW (window), page);
1933 
1934  /* Now update the page to the last state it was in */
1935  gnc_plugin_page_register_restore_edit_menu (page, key_file, group_name);
1936 
1937  /* enable the refresh */
1938  priv->enable_refresh = TRUE;
1939  gnc_ledger_display_refresh (priv->ledger);
1940  LEAVE (" ");
1941  return page;
1942 }
1943 
1944 
1945 /*
1946  * Based on code from Epiphany (src/ephy-window.c)
1947  */
1948 static void
1949 gnc_plugin_page_register_update_edit_menu (GncPluginPage* page, gboolean hide)
1950 {
1952  GncPluginPageRegister* reg_page;
1953  GtkAction* action;
1954  gboolean can_copy = FALSE, can_cut = FALSE, can_paste = FALSE;
1955  gboolean has_selection;
1956  gboolean is_readwrite = !qof_book_is_readonly (gnc_get_current_book());
1957 
1958  reg_page = GNC_PLUGIN_PAGE_REGISTER (page);
1959  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (reg_page);
1960  has_selection = gnucash_register_has_selection (priv->gsr->reg);
1961 
1962  can_copy = has_selection;
1963  can_cut = is_readwrite && has_selection;
1964  can_paste = is_readwrite;
1965 
1966  action = gnc_plugin_page_get_action (page, "EditCopyAction");
1967  gtk_action_set_sensitive (action, can_copy);
1968  gtk_action_set_visible (action, !hide || can_copy);
1969  action = gnc_plugin_page_get_action (page, "EditCutAction");
1970  gtk_action_set_sensitive (action, can_cut);
1971  gtk_action_set_visible (action, !hide || can_cut);
1972  action = gnc_plugin_page_get_action (page, "EditPasteAction");
1973  gtk_action_set_sensitive (action, can_paste);
1974  gtk_action_set_visible (action, !hide || can_paste);
1975 }
1976 
1977 static gboolean is_scrubbing = FALSE;
1978 static gboolean show_abort_verify = TRUE;
1979 
1980 static gboolean
1981 finish_scrub (GncPluginPage* page)
1982 {
1983  gboolean ret = FALSE;
1984 
1985  if (is_scrubbing)
1986  {
1987  ret = gnc_verify_dialog (GTK_WINDOW(gnc_plugin_page_get_window
1988  (GNC_PLUGIN_PAGE(page))),
1989  FALSE,
1990  _("'Check & Repair' is currently running, do you want to abort it?"));
1991 
1992  show_abort_verify = FALSE;
1993 
1994  if (ret)
1995  gnc_set_abort_scrub (TRUE);
1996  }
1997  return ret;
1998 }
1999 
2000 static gboolean
2001 gnc_plugin_page_register_finish_pending (GncPluginPage* page)
2002 {
2004  GncPluginPageRegister* reg_page;
2005  SplitRegister* reg;
2006  GtkWidget* dialog, *window;
2007  gchar* name;
2008  gint response;
2009 
2010  if (is_scrubbing && show_abort_verify)
2011  {
2012  if (!finish_scrub (page))
2013  return FALSE;
2014  }
2015 
2016  reg_page = GNC_PLUGIN_PAGE_REGISTER (page);
2017  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (reg_page);
2018  reg = gnc_ledger_display_get_split_register (priv->ledger);
2019 
2020  if (!reg || !gnc_split_register_changed (reg))
2021  return TRUE;
2022 
2023  name = gnc_plugin_page_register_get_tab_name (page);
2024  window = gnc_plugin_page_get_window (page);
2025  dialog = gtk_message_dialog_new (GTK_WINDOW (window),
2026  GTK_DIALOG_DESTROY_WITH_PARENT,
2027  GTK_MESSAGE_WARNING,
2028  GTK_BUTTONS_NONE,
2029  /* Translators: %s is the name
2030  of the tab page */
2031  _ ("Save changes to %s?"), name);
2032  g_free (name);
2033  gtk_message_dialog_format_secondary_text
2034  (GTK_MESSAGE_DIALOG (dialog),
2035  "%s",
2036  _ ("This register has pending changes to a transaction. "
2037  "Would you like to save the changes to this transaction, "
2038  "discard the transaction, or cancel the operation?"));
2039  gnc_gtk_dialog_add_button (dialog, _ ("_Discard Transaction"),
2040  "edit-delete", GTK_RESPONSE_REJECT);
2041  gtk_dialog_add_button (GTK_DIALOG (dialog),
2042  _ ("_Cancel"), GTK_RESPONSE_CANCEL);
2043  gnc_gtk_dialog_add_button (dialog, _ ("_Save Transaction"),
2044  "document-save", GTK_RESPONSE_ACCEPT);
2045 
2046  response = gtk_dialog_run (GTK_DIALOG (dialog));
2047  gtk_widget_destroy (dialog);
2048 
2049  switch (response)
2050  {
2051  case GTK_RESPONSE_ACCEPT:
2052  gnc_split_register_save (reg, TRUE);
2053  return TRUE;
2054 
2055  case GTK_RESPONSE_REJECT:
2057  gnc_split_register_save (reg, TRUE);
2058  return TRUE;
2059 
2060  default:
2061  return FALSE;
2062  }
2063 }
2064 
2065 
2066 static gchar*
2067 gnc_plugin_page_register_get_tab_name (GncPluginPage* plugin_page)
2068 {
2070  GNCLedgerDisplayType ledger_type;
2071  GNCLedgerDisplay* ld;
2072  SplitRegister* reg;
2073  Account* leader;
2074 
2075  g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page),
2076  g_strdup (_("unknown")));
2077 
2078  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
2079  ld = priv->ledger;
2081  ledger_type = gnc_ledger_display_type (ld);
2082  leader = gnc_ledger_display_leader (ld);
2083 
2084  switch (ledger_type)
2085  {
2086  case LD_SINGLE:
2087  return g_strdup (xaccAccountGetName (leader));
2088 
2089  case LD_SUBACCOUNT:
2090  return g_strdup_printf ("%s+", xaccAccountGetName (leader));
2091 
2092  case LD_GL:
2093  switch (reg->type)
2094  {
2095  case GENERAL_JOURNAL:
2096  case INCOME_LEDGER:
2097  return g_strdup (_ ("General Journal"));
2098  case PORTFOLIO_LEDGER:
2099  return g_strdup (_ ("Portfolio"));
2100  case SEARCH_LEDGER:
2101  return g_strdup (_ ("Search Results"));
2102  default:
2103  break;
2104  }
2105  break;
2106 
2107  default:
2108  break;
2109  }
2110 
2111  return g_strdup (_ ("unknown"));
2112 }
2113 
2114 static gchar*
2115 gnc_plugin_page_register_get_tab_color (GncPluginPage* plugin_page)
2116 {
2118  GNCLedgerDisplayType ledger_type;
2119  GNCLedgerDisplay* ld;
2120  Account* leader;
2121  const char* color;
2122 
2123  g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page),
2124  g_strdup (_("unknown")));
2125 
2126  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
2127  ld = priv->ledger;
2128  ledger_type = gnc_ledger_display_type (ld);
2129  leader = gnc_ledger_display_leader (ld);
2130  color = NULL;
2131 
2132  if ((ledger_type == LD_SINGLE) || (ledger_type == LD_SUBACCOUNT))
2133  color = xaccAccountGetColor (leader);
2134 
2135  return g_strdup (color ? color : "Not Set");
2136 }
2137 
2138 static void
2139 gnc_plugin_page_register_check_for_empty_group (GKeyFile *state_file, const gchar *state_section)
2140 {
2141  gsize num_keys;
2142  gchar **keys = g_key_file_get_keys (state_file, state_section, &num_keys, NULL);
2143 
2144  if (num_keys == 0)
2145  gnc_state_drop_sections_for (state_section);
2146 
2147  g_strfreev (keys);
2148 }
2149 
2150 static gchar*
2151 gnc_plugin_page_register_get_filter_gcm (Account* leader)
2152 {
2153  GKeyFile* state_file = gnc_state_get_current();
2154  gchar* state_section;
2155  gchar acct_guid[GUID_ENCODING_LENGTH + 1];
2156  GError* error = NULL;
2157  char* filter = NULL;
2158 
2159  // get the filter from the .gcm file
2160  guid_to_string_buff (xaccAccountGetGUID (leader), acct_guid);
2161  state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", acct_guid, NULL);
2162  filter = g_key_file_get_string (state_file, state_section,
2163  KEY_PAGE_FILTER, &error);
2164 
2165  if (error)
2166  g_clear_error (&error);
2167  else
2168  g_strdelimit (filter, ";", ',');
2169 
2170  g_free (state_section);
2171  return filter;
2172 }
2173 
2174 static gchar*
2175 gnc_plugin_page_register_get_filter (GncPluginPage* plugin_page)
2176 {
2178  GNCLedgerDisplayType ledger_type;
2179  Account* leader;
2180  char* filter = NULL;
2181 
2182  g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page),
2183  g_strdup (_("unknown")));
2184 
2185  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
2186 
2187  ledger_type = gnc_ledger_display_type (priv->ledger);
2188  leader = gnc_ledger_display_leader (priv->ledger);
2189 
2190  // load from gcm file
2191  filter = gnc_plugin_page_register_get_filter_gcm (leader);
2192 
2193  if (filter)
2194  return filter;
2195 
2196  return g_strdup_printf ("%s,%s,%s,%s", DEFAULT_FILTER,
2197  "0", "0", get_filter_default_num_of_days (ledger_type));
2198 }
2199 
2200 static void
2201 gnc_plugin_page_register_set_filter_gcm (Account* leader, const gchar* filter,
2202  gchar* default_filter)
2203 {
2204  GKeyFile* state_file = gnc_state_get_current();
2205  gchar* state_section;
2206  gchar* filter_text;
2207  gchar acct_guid[GUID_ENCODING_LENGTH + 1];
2208 
2209  // save the filter to the .gcm file also
2210  guid_to_string_buff (xaccAccountGetGUID (leader), acct_guid);
2211  state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", acct_guid, NULL);
2212  if (!filter || (g_strcmp0 (filter, default_filter) == 0))
2213  {
2214  if (g_key_file_has_key (state_file, state_section, KEY_PAGE_FILTER, NULL))
2215  g_key_file_remove_key (state_file, state_section, KEY_PAGE_FILTER, NULL);
2216 
2217  gnc_plugin_page_register_check_for_empty_group (state_file, state_section);
2218  }
2219  else
2220  {
2221  filter_text = g_strdup (filter);
2222  g_strdelimit (filter_text, ",", ';'); // make it conform to .gcm file list
2223  g_key_file_set_string (state_file, state_section, KEY_PAGE_FILTER,
2224  filter_text);
2225  g_free (filter_text);
2226  }
2227  g_free (state_section);
2228 }
2229 
2230 void
2231 gnc_plugin_page_register_set_filter (GncPluginPage* plugin_page,
2232  const gchar* filter)
2233 {
2235  GNCLedgerDisplayType ledger_type;
2236  Account* leader;
2237  gchar* default_filter;
2238 
2239  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
2240 
2241  ledger_type = gnc_ledger_display_type (priv->ledger);
2242  leader = gnc_ledger_display_leader (priv->ledger);
2243 
2244  default_filter = g_strdup_printf ("%s,%s,%s,%s", DEFAULT_FILTER,
2245  "0", "0", get_filter_default_num_of_days (ledger_type));
2246 
2247  // save to gcm file
2248  gnc_plugin_page_register_set_filter_gcm (leader, filter, default_filter);
2249 
2250  g_free (default_filter);
2251  return;
2252 }
2253 
2254 static gchar*
2255 gnc_plugin_page_register_get_sort_order_gcm (Account* leader)
2256 {
2257  GKeyFile* state_file = gnc_state_get_current();
2258  gchar* state_section;
2259  gchar* sort_text;
2260  gchar acct_guid[GUID_ENCODING_LENGTH + 1];
2261  GError* error = NULL;
2262  char* sort_order = NULL;
2263 
2264  // get the sort_order from the .gcm file
2265  guid_to_string_buff (xaccAccountGetGUID (leader), acct_guid);
2266  state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", acct_guid, NULL);
2267  sort_text = g_key_file_get_string (state_file, state_section, KEY_PAGE_SORT,
2268  &error);
2269 
2270  if (error)
2271  g_clear_error (&error);
2272  else
2273  {
2274  sort_order = g_strdup (sort_text);
2275  g_free (sort_text);
2276  }
2277  g_free (state_section);
2278  return sort_order;
2279 }
2280 
2281 static gchar*
2282 gnc_plugin_page_register_get_sort_order (GncPluginPage* plugin_page)
2283 {
2285  Account* leader;
2286  char* sort_order = NULL;
2287 
2288  g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page),
2289  _ ("unknown"));
2290 
2291  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
2292 
2293  leader = gnc_ledger_display_leader (priv->ledger);
2294 
2295  // load from gcm file
2296  sort_order = gnc_plugin_page_register_get_sort_order_gcm (leader);
2297 
2298 
2299  return sort_order ? sort_order : g_strdup (DEFAULT_SORT_ORDER);
2300 }
2301 
2302 static void
2303 gnc_plugin_page_register_set_sort_order_gcm (Account* leader,
2304  const gchar* sort_order)
2305 {
2306  GKeyFile* state_file = gnc_state_get_current();
2307  gchar* state_section;
2308  gchar acct_guid[GUID_ENCODING_LENGTH + 1];
2309 
2310  // save sort_order to the .gcm file also
2311  guid_to_string_buff (xaccAccountGetGUID (leader), acct_guid);
2312  state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", acct_guid, NULL);
2313  if (!sort_order || (g_strcmp0 (sort_order, DEFAULT_SORT_ORDER) == 0))
2314  {
2315  if (g_key_file_has_key (state_file, state_section, KEY_PAGE_SORT, NULL))
2316  g_key_file_remove_key (state_file, state_section, KEY_PAGE_SORT, NULL);
2317 
2318  gnc_plugin_page_register_check_for_empty_group (state_file, state_section);
2319  }
2320  else
2321  g_key_file_set_string (state_file, state_section, KEY_PAGE_SORT, sort_order);
2322 
2323  g_free (state_section);
2324 }
2325 void
2326 gnc_plugin_page_register_set_sort_order (GncPluginPage* plugin_page,
2327  const gchar* sort_order)
2328 {
2330  Account* leader;
2331 
2332  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
2333 
2334  leader = gnc_ledger_display_leader (priv->ledger);
2335 
2336  // save to gcm file
2337  gnc_plugin_page_register_set_sort_order_gcm (leader, sort_order);
2338 }
2339 
2340 static gboolean
2341 gnc_plugin_page_register_get_sort_reversed_gcm (Account* leader)
2342 {
2343  GKeyFile* state_file = gnc_state_get_current();
2344  gchar* state_section;
2345  gchar acct_guid[GUID_ENCODING_LENGTH + 1];
2346  GError* error = NULL;
2347  gboolean sort_reversed = FALSE;
2348 
2349  // get the sort_reversed from the .gcm file
2350  guid_to_string_buff (xaccAccountGetGUID (leader), acct_guid);
2351  state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", acct_guid, NULL);
2352  sort_reversed = g_key_file_get_boolean (state_file, state_section,
2353  KEY_PAGE_SORT_REV, &error);
2354 
2355  if (error)
2356  g_clear_error (&error);
2357 
2358  g_free (state_section);
2359  return sort_reversed;
2360 }
2361 
2362 static gboolean
2363 gnc_plugin_page_register_get_sort_reversed (GncPluginPage* plugin_page)
2364 {
2366  Account* leader;
2367  gboolean sort_reversed = FALSE;
2368 
2369  g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page), FALSE);
2370 
2371  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
2372 
2373  leader = gnc_ledger_display_leader (priv->ledger);
2374 
2375  // load from gcm file
2376  sort_reversed = gnc_plugin_page_register_get_sort_reversed_gcm (leader);
2377  return sort_reversed;
2378 }
2379 
2380 static void
2381 gnc_plugin_page_register_set_sort_reversed_gcm (Account* leader,
2382  gboolean reverse_order)
2383 {
2384  GKeyFile* state_file = gnc_state_get_current();
2385  gchar* state_section;
2386  gchar acct_guid[GUID_ENCODING_LENGTH + 1];
2387 
2388  // save reverse_order to the .gcm file also
2389  guid_to_string_buff (xaccAccountGetGUID (leader), acct_guid);
2390  state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", acct_guid, NULL);
2391  if (!reverse_order)
2392  {
2393  if (g_key_file_has_key (state_file, state_section, KEY_PAGE_SORT_REV, NULL))
2394  g_key_file_remove_key (state_file, state_section, KEY_PAGE_SORT_REV, NULL);
2395 
2396  gnc_plugin_page_register_check_for_empty_group (state_file, state_section);
2397  }
2398  else
2399  g_key_file_set_boolean (state_file, state_section, KEY_PAGE_SORT_REV,
2400  reverse_order);
2401 
2402  g_free (state_section);
2403 }
2404 
2405 void
2406 gnc_plugin_page_register_set_sort_reversed (GncPluginPage* plugin_page,
2407  gboolean reverse_order)
2408 {
2410  Account* leader;
2411 
2412  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
2413  leader = gnc_ledger_display_leader (priv->ledger);
2414 
2415  // save to gcm file
2416  gnc_plugin_page_register_set_sort_reversed_gcm (leader, reverse_order);
2417 }
2418 
2419 static gchar*
2420 gnc_plugin_page_register_get_long_name (GncPluginPage* plugin_page)
2421 {
2423  GNCLedgerDisplayType ledger_type;
2424  GNCLedgerDisplay* ld;
2425  Account* leader;
2426 
2427  g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page),
2428  _ ("unknown"));
2429 
2430  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
2431  ld = priv->ledger;
2432  ledger_type = gnc_ledger_display_type (ld);
2433  leader = gnc_ledger_display_leader (ld);
2434 
2435  switch (ledger_type)
2436  {
2437  case LD_SINGLE:
2438  return gnc_account_get_full_name (leader);
2439 
2440  case LD_SUBACCOUNT:
2441  {
2442  gchar* account_full_name = gnc_account_get_full_name (leader);
2443  gchar* return_string = g_strdup_printf ("%s+", account_full_name);
2444  g_free ((gpointer*) account_full_name);
2445  return return_string;
2446  }
2447 
2448  default:
2449  break;
2450  }
2451 
2452  return NULL;
2453 }
2454 
2455 static void
2456 gnc_plugin_page_register_summarybar_position_changed (gpointer prefs,
2457  gchar* pref, gpointer user_data)
2458 {
2459  GncPluginPage* plugin_page;
2460  GncPluginPageRegister* page;
2462  GtkPositionType position = GTK_POS_BOTTOM;
2463 
2464  g_return_if_fail (user_data != NULL);
2465 
2466  if (!GNC_IS_PLUGIN_PAGE (user_data))
2467  return;
2468 
2469  plugin_page = GNC_PLUGIN_PAGE (user_data);
2470  page = GNC_PLUGIN_PAGE_REGISTER (user_data);
2471  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2472 
2473  if (priv == NULL)
2474  return;
2475 
2476  if (gnc_prefs_get_bool (GNC_PREFS_GROUP_GENERAL,
2477  GNC_PREF_SUMMARYBAR_POSITION_TOP))
2478  position = GTK_POS_TOP;
2479 
2480  gtk_box_reorder_child (GTK_BOX (priv->widget),
2481  plugin_page->summarybar,
2482  (position == GTK_POS_TOP ? 0 : -1));
2483 }
2484 
2490 Query*
2492 {
2493  GncPluginPageRegister* page;
2495 
2496  g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page), NULL);
2497 
2498  page = GNC_PLUGIN_PAGE_REGISTER (plugin_page);
2499  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2500  return gnc_ledger_display_get_query (priv->ledger);
2501 }
2502 
2503 /************************************************************/
2504 /* "Sort By" Dialog */
2505 /************************************************************/
2506 
2517 static void
2518 gnc_plugin_page_register_sort_book_option_changed (gpointer new_val,
2519  gpointer user_data)
2520 {
2522  GncPluginPageRegister* page = user_data;
2523  gboolean* new_data = (gboolean*)new_val;
2524 
2525  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2526 
2527  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2528  if (*new_data)
2529  {
2530  gtk_button_set_label (GTK_BUTTON (priv->sd.num_radio),
2531  _ ("Transaction Number"));
2532  gtk_button_set_label (GTK_BUTTON (priv->sd.act_radio), _ ("Number/Action"));
2533  }
2534  else
2535  {
2536  gtk_button_set_label (GTK_BUTTON (priv->sd.num_radio), _ ("Number"));
2537  gtk_button_set_label (GTK_BUTTON (priv->sd.act_radio), _ ("Action"));
2538  }
2539  gnc_split_reg_set_sort_type_force (priv->gsr, priv->gsr->sort_type, TRUE);
2540 }
2541 
2553 void
2555  gint response,
2556  GncPluginPageRegister* page)
2557 {
2559  GncPluginPage* plugin_page;
2560  SortType type;
2561  const gchar* order;
2562 
2563  g_return_if_fail (GTK_IS_DIALOG (dialog));
2564  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2565 
2566  ENTER (" ");
2567  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2568  plugin_page = GNC_PLUGIN_PAGE (page);
2569 
2570  if (response != GTK_RESPONSE_OK)
2571  {
2572  /* Restore the original sort order */
2573  gnc_split_reg_set_sort_reversed (priv->gsr, priv->sd.original_reverse_order,
2574  TRUE);
2575  priv->sd.reverse_order = priv->sd.original_reverse_order;
2576  gnc_split_reg_set_sort_type (priv->gsr, priv->sd.original_sort_type);
2577  priv->sd.save_order = priv->sd.original_save_order;
2578  }
2579  else
2580  {
2581  // clear the sort when unticking the save option
2582  if ((!priv->sd.save_order) && ((priv->sd.original_save_order) || (priv->sd.original_reverse_order)))
2583  {
2584  gnc_plugin_page_register_set_sort_order (plugin_page, DEFAULT_SORT_ORDER);
2585  gnc_plugin_page_register_set_sort_reversed (plugin_page, FALSE);
2586  }
2587  priv->sd.original_save_order = priv->sd.save_order;
2588 
2589  if (priv->sd.save_order)
2590  {
2591  type = gnc_split_reg_get_sort_type (priv->gsr);
2592  order = SortTypeasString (type);
2593  gnc_plugin_page_register_set_sort_order (plugin_page, order);
2594  gnc_plugin_page_register_set_sort_reversed (plugin_page,
2595  priv->sd.reverse_order);
2596  }
2597  }
2598  gnc_book_option_remove_cb (OPTION_NAME_NUM_FIELD_SOURCE,
2599  gnc_plugin_page_register_sort_book_option_changed,
2600  page);
2601  priv->sd.dialog = NULL;
2602  priv->sd.num_radio = NULL;
2603  priv->sd.act_radio = NULL;
2604  gtk_widget_destroy (GTK_WIDGET (dialog));
2605  LEAVE (" ");
2606 }
2607 
2608 
2617 void
2619  GncPluginPageRegister* page)
2620 {
2622  const gchar* name;
2623  SortType type;
2624 
2625  g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
2626  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2627 
2628  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2629  name = gtk_buildable_get_name (GTK_BUILDABLE (button));
2630  ENTER ("button %s(%p), page %p", name, button, page);
2631  type = SortTypefromString (name);
2632  gnc_split_reg_set_sort_type (priv->gsr, type);
2633  LEAVE (" ");
2634 }
2635 
2636 
2645 void
2647  GncPluginPageRegister* page)
2648 {
2650 
2651  g_return_if_fail (GTK_IS_CHECK_BUTTON (button));
2652  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2653 
2654  ENTER ("Save toggle button (%p), plugin_page %p", button, page);
2655 
2656  /* Compute the new save sort order */
2657  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2658 
2659  if (gtk_toggle_button_get_active (button))
2660  priv->sd.save_order = TRUE;
2661  else
2662  priv->sd.save_order = FALSE;
2663  LEAVE (" ");
2664 }
2665 
2674 void
2676  GncPluginPageRegister* page)
2677 
2678 {
2680 
2681  g_return_if_fail (GTK_IS_CHECK_BUTTON (button));
2682  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2683 
2684  ENTER ("Reverse toggle button (%p), plugin_page %p", button, page);
2685 
2686  /* Compute the new save sort order */
2687  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2688 
2689  priv->sd.reverse_order = gtk_toggle_button_get_active (button);
2690  gnc_split_reg_set_sort_reversed (priv->gsr, priv->sd.reverse_order, TRUE);
2691  LEAVE (" ");
2692 }
2693 
2694 /************************************************************/
2695 /* "Filter By" Dialog */
2696 /************************************************************/
2697 
2698 static void
2699 gnc_ppr_update_for_search_query (GncPluginPageRegister* page)
2700 {
2702  SplitRegister* reg;
2703 
2704  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2705  reg = gnc_ledger_display_get_split_register (priv->ledger);
2706 
2707  if (reg->type == SEARCH_LEDGER)
2708  {
2709  Query* query_tmp = gnc_ledger_display_get_query (priv->ledger);
2710 
2711  // if filter_query is NULL, then the dialogue find has been run
2712  // before coming here. if query_tmp does not equal filter_query
2713  // then the dialogue find has been run again before coming here
2714  if ((priv->filter_query == NULL) ||
2715  (!qof_query_equal (query_tmp, priv->filter_query)))
2716  {
2717  qof_query_destroy (priv->search_query);
2718  priv->search_query = qof_query_copy (query_tmp);
2719  }
2720  gnc_ledger_display_set_query (priv->ledger, priv->search_query);
2721  }
2722 }
2723 
2724 
2737 static void
2738 gnc_ppr_update_status_query (GncPluginPageRegister* page)
2739 {
2741  GSList* param_list;
2742  Query* query;
2743  SplitRegister* reg;
2744 
2745  ENTER (" ");
2746  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2747  if (!priv->ledger)
2748  {
2749  LEAVE ("no ledger");
2750  return;
2751  }
2752  // check if this a search register and save query
2753  gnc_ppr_update_for_search_query (page);
2754 
2755  query = gnc_ledger_display_get_query (priv->ledger);
2756  if (!query)
2757  {
2758  LEAVE ("no query found");
2759  return;
2760  }
2761 
2762  reg = gnc_ledger_display_get_split_register (priv->ledger);
2763 
2764  /* Remove the old status match */
2765  param_list = qof_query_build_param_list (SPLIT_RECONCILE, NULL);
2766  if (param_list && (reg->type != SEARCH_LEDGER))
2767  {
2768  qof_query_purge_terms (query, param_list);
2769  g_slist_free (param_list);
2770  }
2771 
2772  /* Install the new status match */
2773  if (priv->fd.cleared_match != CLEARED_ALL)
2774  xaccQueryAddClearedMatch (query, priv->fd.cleared_match, QOF_QUERY_AND);
2775 
2776  // Set filter tooltip for summary bar
2777  gnc_plugin_page_register_set_filter_tooltip (page);
2778 
2779  // clear previous filter query and save current
2780  qof_query_destroy (priv->filter_query);
2781  priv->filter_query = qof_query_copy (query);
2782 
2783  if (priv->enable_refresh)
2784  gnc_ledger_display_refresh (priv->ledger);
2785  LEAVE (" ");
2786 }
2787 
2788 
2801 static void
2802 gnc_ppr_update_date_query (GncPluginPageRegister* page)
2803 {
2805  GSList* param_list;
2806  Query* query;
2807  SplitRegister* reg;
2808 
2809  ENTER (" ");
2810  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2811  if (!priv->ledger)
2812  {
2813  LEAVE ("no ledger");
2814  return;
2815  }
2816  // check if this a search register and save query
2817  gnc_ppr_update_for_search_query (page);
2818 
2819  query = gnc_ledger_display_get_query (priv->ledger);
2820 
2821  if (!query)
2822  {
2823  LEAVE ("no query");
2824  return;
2825  }
2826 
2827  reg = gnc_ledger_display_get_split_register (priv->ledger);
2828 
2829  /* Delete any existing old date spec. */
2830  param_list = qof_query_build_param_list (SPLIT_TRANS, TRANS_DATE_POSTED, NULL);
2831  if (param_list && (reg->type != SEARCH_LEDGER))
2832  {
2833  qof_query_purge_terms (query, param_list);
2834  g_slist_free (param_list);
2835  }
2836 
2837  if (priv->fd.start_time || priv->fd.end_time)
2838  {
2839  /* Build a new spec */
2840  xaccQueryAddDateMatchTT (query,
2841  priv->fd.start_time != 0, priv->fd.start_time,
2842  priv->fd.end_time != 0, priv->fd.end_time,
2843  QOF_QUERY_AND);
2844  }
2845 
2846  if (priv->fd.days > 0)
2847  {
2848  time64 start;
2849  struct tm tm;
2850 
2851  gnc_tm_get_today_start (&tm);
2852 
2853  tm.tm_mday = tm.tm_mday - priv->fd.days;
2854  start = gnc_mktime (&tm);
2855  xaccQueryAddDateMatchTT (query, TRUE, start, FALSE, 0, QOF_QUERY_AND);
2856  }
2857 
2858  // Set filter tooltip for summary bar
2859  gnc_plugin_page_register_set_filter_tooltip (page);
2860 
2861  // clear previous filter query and save current
2862  qof_query_destroy (priv->filter_query);
2863  priv->filter_query = qof_query_copy (query);
2864 
2865  if (priv->enable_refresh)
2866  gnc_ledger_display_refresh (priv->ledger);
2867  LEAVE (" ");
2868 }
2869 
2870 
2871 /* This function converts a time64 value date to a string */
2872 static gchar*
2873 gnc_plugin_page_register_filter_time2dmy (time64 raw_time)
2874 {
2875  struct tm* timeinfo;
2876  gchar date_string[11];
2877 
2878  timeinfo = gnc_localtime (&raw_time);
2879  strftime (date_string, 11, "%d-%m-%Y", timeinfo);
2880  PINFO ("Date string is %s", date_string);
2881  gnc_tm_free (timeinfo);
2882 
2883  return g_strdup (date_string);
2884 }
2885 
2886 
2887 /* This function converts a string date to a time64 value */
2888 static time64
2889 gnc_plugin_page_register_filter_dmy2time (char* date_string)
2890 {
2891  struct tm when;
2892 
2893  PINFO ("Date string is %s", date_string);
2894  memset (&when, 0, sizeof (when));
2895 
2896  sscanf (date_string, "%d-%d-%d", &when.tm_mday,
2897  &when.tm_mon, &when.tm_year);
2898 
2899  when.tm_mon -= 1;
2900  when.tm_year -= 1900;
2901 
2902  return gnc_mktime (&when);
2903 }
2904 
2905 
2916 void
2918  GncPluginPageRegister* page)
2919 {
2921  const gchar* name;
2922  gint i, value;
2923 
2924  g_return_if_fail (GTK_IS_CHECK_BUTTON (button));
2925  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2926 
2927  name = gtk_buildable_get_name (GTK_BUILDABLE (button));
2928  ENTER ("toggle button %s (%p), plugin_page %p", name, button, page);
2929 
2930  /* Determine what status bit to change */
2931  value = CLEARED_NONE;
2932  for (i = 0; status_actions[i].action_name; i++)
2933  {
2934  if (g_strcmp0 (name, status_actions[i].action_name) == 0)
2935  {
2936  value = status_actions[i].value;
2937  break;
2938  }
2939  }
2940 
2941  /* Compute the new match status */
2942  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2943  if (gtk_toggle_button_get_active (button))
2944  priv->fd.cleared_match |= value;
2945  else
2946  priv->fd.cleared_match &= ~value;
2947  gnc_ppr_update_status_query (page);
2948  LEAVE (" ");
2949 }
2950 
2951 
2961 void
2963  GncPluginPageRegister* page)
2964 {
2966  GtkWidget* widget;
2967  gint i;
2968 
2969  g_return_if_fail (GTK_IS_BUTTON (button));
2970  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2971 
2972  ENTER ("(button %p, page %p)", button, page);
2973 
2974  /* Turn on all the check menu items */
2975  for (i = 0; status_actions[i].action_name; i++)
2976  {
2977  widget = status_actions[i].widget;
2978  g_signal_handlers_block_by_func (widget,
2980  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
2981  g_signal_handlers_unblock_by_func (widget,
2983  }
2984 
2985  /* Set the requested status */
2986  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2987  priv->fd.cleared_match = CLEARED_ALL;
2988  gnc_ppr_update_status_query (page);
2989  LEAVE (" ");
2990 }
2991 
2992 
3004 static void
3005 get_filter_times (GncPluginPageRegister* page)
3006 {
3008  time64 time_val;
3009 
3010  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3011  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (
3012  priv->fd.start_date_choose)))
3013  {
3014  time_val = gnc_date_edit_get_date (GNC_DATE_EDIT (priv->fd.start_date));
3015  time_val = gnc_time64_get_day_start (time_val);
3016  priv->fd.start_time = time_val;
3017  }
3018  else
3019  {
3020  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (
3021  priv->fd.start_date_today)))
3022  {
3023  priv->fd.start_time = gnc_time64_get_today_start();
3024  }
3025  else
3026  {
3027  priv->fd.start_time = 0;
3028  }
3029  }
3030 
3031  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (
3032  priv->fd.end_date_choose)))
3033  {
3034  time_val = gnc_date_edit_get_date (GNC_DATE_EDIT (priv->fd.end_date));
3035  time_val = gnc_time64_get_day_end (time_val);
3036  priv->fd.end_time = time_val;
3037  }
3038  else
3039  {
3040  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (
3041  priv->fd.start_date_today)))
3042  {
3043  priv->fd.end_time = gnc_time64_get_today_end();
3044  }
3045  else
3046  {
3047  priv->fd.end_time = 0;
3048  }
3049  }
3050 }
3051 
3052 
3064 void
3066  GncPluginPageRegister* page)
3067 {
3069  gboolean active;
3070  const gchar* name;
3071 
3072  g_return_if_fail (GTK_IS_RADIO_BUTTON (button));
3073  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3074 
3075  ENTER ("(button %p, page %p)", button, page);
3076  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3077  name = gtk_buildable_get_name (GTK_BUILDABLE (button));
3078  active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
3079 
3080  if (active && g_strcmp0 (name, "filter_show_range") == 0)
3081  {
3082  gtk_widget_set_sensitive (priv->fd.table, active);
3083  gtk_widget_set_sensitive (priv->fd.num_days, !active);
3084  get_filter_times (page);
3085  }
3086  else if (active && g_strcmp0 (name, "filter_show_days") == 0)
3087  {
3088  gtk_widget_set_sensitive (priv->fd.table, !active);
3089  gtk_widget_set_sensitive (priv->fd.num_days, active);
3090  gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->fd.num_days), priv->fd.days);
3091  }
3092  else
3093  {
3094  gtk_widget_set_sensitive (priv->fd.table, FALSE);
3095  gtk_widget_set_sensitive (priv->fd.num_days, FALSE);
3096  priv->fd.days = 0;
3097  priv->fd.start_time = 0;
3098  priv->fd.end_time = 0;
3099  }
3100  gnc_ppr_update_date_query (page);
3101  LEAVE (" ");
3102 }
3103 
3104 void
3106 {
3108 
3109  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
3110 
3111  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
3112 
3113  priv->fd.days = 0;
3114  priv->fd.start_time = 0;
3115  priv->fd.end_time = 0;
3116  priv->fd.cleared_match = (gint)g_ascii_strtoll (DEFAULT_FILTER, NULL, 16);
3117 
3118  gnc_ppr_update_date_query (GNC_PLUGIN_PAGE_REGISTER(plugin_page));
3119 }
3120 
3131 void
3133  GncPluginPageRegister* page)
3134 {
3136 
3137  g_return_if_fail (GTK_IS_SPIN_BUTTON (button));
3138  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3139 
3140  ENTER ("(button %p, page %p)", button, page);
3141  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3142 
3143  priv->fd.days = gtk_spin_button_get_value (GTK_SPIN_BUTTON (button));
3144  gnc_ppr_update_date_query (page);
3145  LEAVE (" ");
3146 }
3147 
3148 
3159 static void
3160 gnc_plugin_page_register_filter_gde_changed_cb (GtkWidget* unused,
3161  GncPluginPageRegister* page)
3162 {
3163  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3164 
3165  ENTER ("(widget %s(%p), page %p)",
3166  gtk_buildable_get_name (GTK_BUILDABLE (unused)), unused, page);
3167  get_filter_times (page);
3168  gnc_ppr_update_date_query (page);
3169  LEAVE (" ");
3170 }
3171 
3172 
3192 void
3194  GncPluginPageRegister* page)
3195 {
3197  const gchar* name;
3198  gboolean active;
3199 
3200  g_return_if_fail (GTK_IS_RADIO_BUTTON (radio));
3201  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3202 
3203  ENTER ("(radio %s(%p), page %p)",
3204  gtk_buildable_get_name (GTK_BUILDABLE (radio)), radio, page);
3205  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3206  if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio)))
3207  {
3208  LEAVE ("1st callback of pair. Defer to 2nd callback.");
3209  return;
3210  }
3211 
3212  name = gtk_buildable_get_name (GTK_BUILDABLE (radio));
3213  active = !g_strcmp0 (name, "start_date_choose");
3214  gtk_widget_set_sensitive (priv->fd.start_date, active);
3215  get_filter_times (page);
3216  gnc_ppr_update_date_query (page);
3217  LEAVE (" ");
3218 }
3219 
3220 
3240 void
3242  GncPluginPageRegister* page)
3243 {
3245  const gchar* name;
3246  gboolean active;
3247 
3248  g_return_if_fail (GTK_IS_RADIO_BUTTON (radio));
3249  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3250 
3251  ENTER ("(radio %s(%p), page %p)",
3252  gtk_buildable_get_name (GTK_BUILDABLE (radio)), radio, page);
3253  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3254  if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio)))
3255  {
3256  LEAVE ("1st callback of pair. Defer to 2nd callback.");
3257  return;
3258  }
3259 
3260  name = gtk_buildable_get_name (GTK_BUILDABLE (radio));
3261  active = !g_strcmp0 (name, "end_date_choose");
3262  gtk_widget_set_sensitive (priv->fd.end_date, active);
3263  get_filter_times (page);
3264  gnc_ppr_update_date_query (page);
3265  LEAVE (" ");
3266 }
3267 
3268 
3277 void
3279  GncPluginPageRegister* page)
3280 {
3282 
3283  g_return_if_fail (GTK_IS_CHECK_BUTTON (button));
3284  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3285 
3286  ENTER ("Save toggle button (%p), plugin_page %p", button, page);
3287 
3288  /* Compute the new save filter status */
3289  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3290  if (gtk_toggle_button_get_active (button))
3291  priv->fd.save_filter = TRUE;
3292  else
3293  priv->fd.save_filter = FALSE;
3294  LEAVE (" ");
3295 }
3296 
3297 
3309 void
3311  gint response,
3312  GncPluginPageRegister* page)
3313 {
3315  GncPluginPage* plugin_page;
3316 
3317  g_return_if_fail (GTK_IS_DIALOG (dialog));
3318  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3319 
3320  ENTER (" ");
3321  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3322  plugin_page = GNC_PLUGIN_PAGE (page);
3323 
3324  if (response != GTK_RESPONSE_OK)
3325  {
3326  /* Remove the old status match */
3327  priv->fd.cleared_match = priv->fd.original_cleared_match;
3328  priv->enable_refresh = FALSE;
3329  gnc_ppr_update_status_query (page);
3330  priv->enable_refresh = TRUE;
3331  priv->fd.start_time = priv->fd.original_start_time;
3332  priv->fd.end_time = priv->fd.original_end_time;
3333  priv->fd.days = priv->fd.original_days;
3334  priv->fd.save_filter = priv->fd.original_save_filter;
3335  gnc_ppr_update_date_query (page);
3336  }
3337  else
3338  {
3339  // clear the filter when unticking the save option
3340  if ((priv->fd.save_filter == FALSE) && (priv->fd.original_save_filter == TRUE))
3341  gnc_plugin_page_register_set_filter (plugin_page, NULL);
3342 
3343  priv->fd.original_save_filter = priv->fd.save_filter;
3344 
3345  if (priv->fd.save_filter)
3346  {
3347  gchar *filter;
3348  GList *flist = NULL;
3349 
3350  // cleared match
3351  flist = g_list_prepend
3352  (flist, g_strdup_printf ("0x%04x", priv->fd.cleared_match));
3353 
3354  // start time
3355  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->fd.start_date_choose)) && priv->fd.start_time != 0)
3356  flist = g_list_prepend (flist, gnc_plugin_page_register_filter_time2dmy (priv->fd.start_time));
3357  else
3358  flist = g_list_prepend (flist, g_strdup ("0"));
3359 
3360  // end time
3361  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->fd.end_date_choose))
3362  && priv->fd.end_time != 0)
3363  flist = g_list_prepend (flist, gnc_plugin_page_register_filter_time2dmy (priv->fd.end_time));
3364  else
3365  flist = g_list_prepend (flist, g_strdup ("0"));
3366 
3367  // number of days
3368  if (priv->fd.days > 0)
3369  flist = g_list_prepend (flist, g_strdup_printf ("%d", priv->fd.days));
3370  else
3371  flist = g_list_prepend (flist, g_strdup ("0"));
3372 
3373  flist = g_list_reverse (flist);
3374  filter = gnc_g_list_stringjoin (flist, ",");
3375  PINFO ("The filter to save is %s", filter);
3376  gnc_plugin_page_register_set_filter (plugin_page, filter);
3377  g_free (filter);
3378  g_list_free_full (flist, g_free);
3379  }
3380  }
3381  priv->fd.dialog = NULL;
3382  gtk_widget_destroy (GTK_WIDGET (dialog));
3383  LEAVE (" ");
3384 }
3385 
3386 static void
3387 gpp_update_match_filter_text (cleared_match_t match, const guint mask,
3388  const gchar* filter_name, GList **show, GList **hide)
3389 {
3390  if ((match & mask) == mask)
3391  *show = g_list_prepend (*show, g_strdup (filter_name));
3392  else
3393  *hide = g_list_prepend (*hide, g_strdup (filter_name));
3394 }
3395 
3396 static void
3397 gnc_plugin_page_register_set_filter_tooltip (GncPluginPageRegister* page)
3398 {
3400  GList *t_list = NULL;
3401 
3402  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3403 
3404  ENTER (" ");
3405  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3406 
3407  // filtered start time
3408  if (priv->fd.start_time != 0)
3409  {
3410  gchar* sdate = qof_print_date (priv->fd.start_time);
3411  t_list = g_list_prepend
3412  (t_list, g_strdup_printf ("%s %s", _("Start Date:"), sdate));
3413  g_free (sdate);
3414  }
3415 
3416  // filtered number of days
3417  if (priv->fd.days > 0)
3418  t_list = g_list_prepend
3419  (t_list, g_strdup_printf ("%s %d", _("Show previous number of days:"),
3420  priv->fd.days));
3421 
3422  // filtered end time
3423  if (priv->fd.end_time != 0)
3424  {
3425  gchar* edate = qof_print_date (priv->fd.end_time);
3426  t_list = g_list_prepend
3427  (t_list, g_strdup_printf ("%s %s", _("End Date:"), edate));
3428  g_free (edate);
3429  }
3430 
3431  // filtered match items
3432  if (priv->fd.cleared_match != CLEARED_ALL)
3433  {
3434  GList *show = NULL;
3435  GList *hide = NULL;
3436 
3437  gpp_update_match_filter_text (priv->fd.cleared_match, 0x01, _ ("Unreconciled"),
3438  &show, &hide);
3439  gpp_update_match_filter_text (priv->fd.cleared_match, 0x02, _ ("Cleared"),
3440  &show, &hide);
3441  gpp_update_match_filter_text (priv->fd.cleared_match, 0x04, _ ("Reconciled"),
3442  &show, &hide);
3443  gpp_update_match_filter_text (priv->fd.cleared_match, 0x08, _ ("Frozen"),
3444  &show, &hide);
3445  gpp_update_match_filter_text (priv->fd.cleared_match, 0x10, _ ("Voided"),
3446  &show, &hide);
3447 
3448  show = g_list_reverse (show);
3449  hide = g_list_reverse (hide);
3450 
3451  if (show)
3452  {
3453  char *str = gnc_g_list_stringjoin (show, ", ");
3454  t_list = g_list_prepend
3455  (t_list, g_strdup_printf ("%s %s", _("Show:"), str));
3456  g_free (str);
3457  }
3458 
3459  if (hide)
3460  {
3461  char *str = gnc_g_list_stringjoin (hide, ", ");
3462  t_list = g_list_prepend
3463  (t_list, g_strdup_printf ("%s %s", _("Hide:"), str));
3464  g_free (str);
3465  }
3466 
3467  g_list_free_full (show, g_free);
3468  g_list_free_full (hide, g_free);
3469  }
3470 
3471  t_list = g_list_reverse (t_list);
3472 
3473  if (t_list)
3474  t_list = g_list_prepend (t_list, g_strdup (_("Filter By:")));
3475 
3476  // free the existing text if present
3477  if (priv->gsr->filter_text != NULL)
3478  g_free (priv->gsr->filter_text);
3479 
3480  // set the tooltip text variable in the gsr
3481  priv->gsr->filter_text = gnc_g_list_stringjoin (t_list, "\n");
3482 
3483  g_list_free_full (t_list, g_free);
3484 
3485  LEAVE (" ");
3486 }
3487 
3488 
3489 static void
3490 gnc_plugin_page_register_update_page_icon (GncPluginPage* plugin_page)
3491 {
3493  gboolean read_only;
3494 
3495  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
3496 
3497  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
3498 
3499  if (qof_book_is_readonly (gnc_get_current_book()) ||
3500  gnc_split_reg_get_read_only (priv->gsr))
3501  read_only = TRUE;
3502  else
3503  read_only = FALSE;
3504 
3505  main_window_update_page_set_read_only_icon (GNC_PLUGIN_PAGE(plugin_page),
3506  read_only);
3507 }
3508 
3509 /************************************************************/
3510 /* Report Helper Functions */
3511 /************************************************************/
3512 
3513 static char*
3514 gnc_reg_get_name (GNCLedgerDisplay* ledger, gboolean for_window)
3515 {
3516  Account* leader;
3517  SplitRegister* reg;
3518  gchar* account_name;
3519  gchar* reg_name;
3520  gchar* name;
3521  GNCLedgerDisplayType ledger_type;
3522 
3523  if (ledger == NULL)
3524  return NULL;
3525 
3527  ledger_type = gnc_ledger_display_type (ledger);
3528 
3529  switch (reg->type)
3530  {
3531  case GENERAL_JOURNAL:
3532  case INCOME_LEDGER:
3533  if (for_window)
3534  reg_name = _ ("General Journal");
3535  else
3536  reg_name = _ ("Transaction Report");
3537  break;
3538  case PORTFOLIO_LEDGER:
3539  if (for_window)
3540  reg_name = _ ("Portfolio");
3541  else
3542  reg_name = _ ("Portfolio Report");
3543  break;
3544  case SEARCH_LEDGER:
3545  if (for_window)
3546  reg_name = _ ("Search Results");
3547  else
3548  reg_name = _ ("Search Results Report");
3549  break;
3550  default:
3551  if (for_window)
3552  reg_name = _ ("Register");
3553  else
3554  reg_name = _ ("Transaction Report");
3555  break;
3556  }
3557 
3558  leader = gnc_ledger_display_leader (ledger);
3559 
3560  if ((leader != NULL) && (ledger_type != LD_GL))
3561  {
3562  account_name = gnc_account_get_full_name (leader);
3563 
3564  if (ledger_type == LD_SINGLE)
3565  {
3566  name = g_strconcat (account_name, " - ", reg_name, NULL);
3567  }
3568  else
3569  {
3570  name = g_strconcat (account_name, " ", _ ("and subaccounts"), " - ", reg_name,
3571  NULL);
3572  }
3573  g_free (account_name);
3574  }
3575  else
3576  name = g_strdup (reg_name);
3577 
3578  return name;
3579 }
3580 
3581 static int
3582 report_helper (GNCLedgerDisplay* ledger, Split* split, Query* query)
3583 {
3584  SplitRegister* reg = gnc_ledger_display_get_split_register (ledger);
3585  Account* account;
3586  char* str;
3587  const char* tmp;
3588  swig_type_info* qtype;
3589  SCM args;
3590  SCM func;
3591  SCM arg;
3592 
3593  args = SCM_EOL;
3594 
3595  func = scm_c_eval_string ("gnc:register-report-create");
3596  g_return_val_if_fail (scm_is_procedure (func), -1);
3597 
3599  arg = scm_from_utf8_string (tmp ? tmp : _ ("Credit"));
3600  args = scm_cons (arg, args);
3601 
3603  arg = scm_from_utf8_string (tmp ? tmp : _ ("Debit"));
3604  args = scm_cons (arg, args);
3605 
3606  str = gnc_reg_get_name (ledger, FALSE);
3607  arg = scm_from_utf8_string (str ? str : "");
3608  args = scm_cons (arg, args);
3609  g_free (str);
3610 
3611  arg = SCM_BOOL (reg->use_double_line);
3612  args = scm_cons (arg, args);
3613 
3614  arg = SCM_BOOL (reg->type == GENERAL_JOURNAL || reg->type == INCOME_LEDGER
3615  || reg->type == SEARCH_LEDGER);
3616  args = scm_cons (arg, args);
3617 
3618  arg = SCM_BOOL (reg->style == REG_STYLE_JOURNAL);
3619  args = scm_cons (arg, args);
3620 
3621  if (!query)
3622  {
3623  query = gnc_ledger_display_get_query (ledger);
3624  g_return_val_if_fail (query != NULL, -1);
3625  }
3626 
3627  qtype = SWIG_TypeQuery ("_p__QofQuery");
3628  g_return_val_if_fail (qtype, -1);
3629 
3630  arg = SWIG_NewPointerObj (query, qtype, 0);
3631  args = scm_cons (arg, args);
3632  g_return_val_if_fail (arg != SCM_UNDEFINED, -1);
3633 
3634 
3635  if (split)
3636  {
3637  qtype = SWIG_TypeQuery ("_p_Split");
3638  g_return_val_if_fail (qtype, -1);
3639  arg = SWIG_NewPointerObj (split, qtype, 0);
3640  }
3641  else
3642  {
3643  arg = SCM_BOOL_F;
3644  }
3645  args = scm_cons (arg, args);
3646  g_return_val_if_fail (arg != SCM_UNDEFINED, -1);
3647 
3648 
3649  qtype = SWIG_TypeQuery ("_p_Account");
3650  g_return_val_if_fail (qtype, -1);
3651 
3652  account = gnc_ledger_display_leader (ledger);
3653  arg = SWIG_NewPointerObj (account, qtype, 0);
3654  args = scm_cons (arg, args);
3655  g_return_val_if_fail (arg != SCM_UNDEFINED, -1);
3656 
3657 
3658  /* Apply the function to the args */
3659  arg = scm_apply (func, args, SCM_EOL);
3660  g_return_val_if_fail (scm_is_exact (arg), -1);
3661 
3662  return scm_to_int (arg);
3663 }
3664 
3665 /************************************************************/
3666 /* Command callbacks */
3667 /************************************************************/
3668 
3669 static void
3670 gnc_plugin_page_register_cmd_print_check (GtkAction* action,
3671  GncPluginPageRegister* plugin_page)
3672 {
3674  SplitRegister* reg;
3675  Split* split;
3676  Transaction* trans;
3677  GList* splits = NULL, *item;
3678  GNCLedgerDisplayType ledger_type;
3679  Account* account;
3680  GtkWidget* window;
3681 
3682  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
3683 
3684  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
3685 
3686  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
3687  reg = gnc_ledger_display_get_split_register (priv->ledger);
3688  ledger_type = gnc_ledger_display_type (priv->ledger);
3689  window = gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (plugin_page));
3690  if (ledger_type == LD_SINGLE || ledger_type == LD_SUBACCOUNT)
3691  {
3692  account = gnc_plugin_page_register_get_account (plugin_page);
3694  trans = xaccSplitGetParent (split);
3695 
3696  if (split && trans)
3697  {
3698  if (xaccSplitGetAccount (split) == account)
3699  {
3700  splits = g_list_prepend (splits, split);
3701  gnc_ui_print_check_dialog_create (window, splits);
3702  g_list_free (splits);
3703  }
3704  else
3705  {
3706  /* This split is not for the account shown in this register. Get the
3707  split that anchors the transaction to the registor */
3708  split = gnc_split_register_get_current_trans_split (reg, NULL);
3709  if (split)
3710  {
3711  splits = g_list_prepend (splits, split);
3712  gnc_ui_print_check_dialog_create (window, splits);
3713  g_list_free (splits);
3714  }
3715  }
3716  }
3717  }
3718  else if (ledger_type == LD_GL && reg->type == SEARCH_LEDGER)
3719  {
3720  Account* common_acct = NULL;
3721 
3722  /* the following GList* splits must not be freed */
3723  splits = qof_query_run (gnc_ledger_display_get_query (priv->ledger));
3724 
3725  /* Make sure each split is from the same account */
3726  for (item = splits; item; item = g_list_next (item))
3727  {
3728  split = (Split*) item->data;
3729  if (common_acct == NULL)
3730  {
3731  common_acct = xaccSplitGetAccount (split);
3732  }
3733  else
3734  {
3735  if (xaccSplitGetAccount (split) != common_acct)
3736  {
3737  GtkWidget* dialog;
3738  gint response;
3739  const gchar* title = _ ("Print checks from multiple accounts?");
3740  const gchar* message =
3741  _ ("This search result contains splits from more than one account. "
3742  "Do you want to print the checks even though they are not all "
3743  "from the same account?");
3744  dialog = gtk_message_dialog_new (GTK_WINDOW (window),
3745  GTK_DIALOG_DESTROY_WITH_PARENT,
3746  GTK_MESSAGE_WARNING,
3747  GTK_BUTTONS_CANCEL,
3748  "%s", title);
3749  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
3750  "%s", message);
3751  gtk_dialog_add_button (GTK_DIALOG (dialog), _ ("_Print checks"),
3752  GTK_RESPONSE_YES);
3753  response = gnc_dialog_run (GTK_DIALOG (dialog),
3754  GNC_PREF_WARN_CHECKPRINTING_MULTI_ACCT);
3755  gtk_widget_destroy (dialog);
3756  if (response != GTK_RESPONSE_YES)
3757  {
3758  LEAVE ("Multiple accounts");
3759  return;
3760  }
3761  break;
3762  }
3763  }
3764  }
3765  gnc_ui_print_check_dialog_create (window, splits);
3766  }
3767  else
3768  {
3769  gnc_error_dialog (GTK_WINDOW (window), "%s",
3770  _ ("You can only print checks from a bank account register or search results."));
3771  LEAVE ("Unsupported ledger type");
3772  return;
3773  }
3774  LEAVE (" ");
3775 }
3776 
3777 
3778 static void
3779 gnc_plugin_page_register_cmd_cut (GtkAction* action,
3780  GncPluginPageRegister* page)
3781 {
3783 
3784  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3785 
3786  ENTER ("(action %p, page %p)", action, page);
3787  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3788  gnucash_register_cut_clipboard (priv->gsr->reg);
3789  LEAVE ("");
3790 }
3791 
3792 
3793 static void
3794 gnc_plugin_page_register_cmd_copy (GtkAction* action,
3795  GncPluginPageRegister* page)
3796 {
3798 
3799  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3800 
3801  ENTER ("(action %p, page %p)", action, page);
3802  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3803  gnucash_register_copy_clipboard (priv->gsr->reg);
3804  LEAVE ("");
3805 }
3806 
3807 
3808 static void
3809 gnc_plugin_page_register_cmd_paste (GtkAction* action,
3810  GncPluginPageRegister* page)
3811 {
3813 
3814  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3815 
3816  ENTER ("(action %p, page %p)", action, page);
3817  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3818  gnucash_register_paste_clipboard (priv->gsr->reg);
3819  LEAVE ("");
3820 }
3821 
3822 
3823 static void
3824 gnc_plugin_page_register_cmd_edit_account (GtkAction* action,
3825  GncPluginPageRegister* page)
3826 {
3827  Account* account;
3828  GtkWindow* parent = GTK_WINDOW (gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (
3829  page)));
3830  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3831 
3832  ENTER ("(action %p, page %p)", action, page);
3833  account = gnc_plugin_page_register_get_account (page);
3834  if (account)
3835  gnc_ui_edit_account_window (parent, account);
3836  LEAVE (" ");
3837 }
3838 
3839 
3840 static void
3841 gnc_plugin_page_register_cmd_find_account (GtkAction* action,
3842  GncPluginPageRegister* page)
3843 {
3844  GtkWidget* window;
3845 
3846  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3847 
3848  window = gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page));
3849  gnc_find_account_dialog (window, NULL);
3850 }
3851 
3852 
3853 static void
3854 gnc_plugin_page_register_cmd_find_transactions (GtkAction* action,
3855  GncPluginPageRegister* page)
3856 {
3858  GtkWindow* window;
3859 
3860  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3861 
3862  ENTER ("(action %p, page %p)", action, page);
3863  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3864  window = GTK_WINDOW (gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page)));
3865  gnc_ui_find_transactions_dialog_create (window, priv->ledger);
3866  LEAVE (" ");
3867 }
3868 
3869 
3870 static void
3871 gnc_plugin_page_register_cmd_edit_tax_options (GtkAction* action,
3872  GncPluginPageRegister* page)
3873 {
3875  GtkWidget *window;
3876  Account* account;
3877 
3878  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3879 
3880  ENTER ("(action %p, page %p)", action, page);
3881  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3882  window = gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page));
3883  account = gnc_plugin_page_register_get_account (page);
3884  gnc_tax_info_dialog (window, account);
3885  LEAVE (" ");
3886 }
3887 
3888 static void
3889 gnc_plugin_page_register_cmd_cut_transaction (GtkAction* action,
3890  GncPluginPageRegister* plugin_page)
3891 {
3893 
3894  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
3895 
3896  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
3897 
3898  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
3899  gsr_default_cut_txn_handler (priv->gsr, NULL);
3900  LEAVE (" ");
3901 }
3902 
3903 
3904 static void
3905 gnc_plugin_page_register_cmd_copy_transaction (GtkAction* action,
3906  GncPluginPageRegister* page)
3907 {
3909  SplitRegister* reg;
3910 
3911  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3912 
3913  ENTER ("(action %p, page %p)", action, page);
3914  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3915  reg = gnc_ledger_display_get_split_register (priv->ledger);
3917  LEAVE (" ");
3918 }
3919 
3920 
3921 static void
3922 gnc_plugin_page_register_cmd_paste_transaction (GtkAction* action,
3923  GncPluginPageRegister* page)
3924 {
3926  SplitRegister* reg;
3927 
3928  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3929 
3930  ENTER ("(action %p, page %p)", action, page);
3931  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3932  reg = gnc_ledger_display_get_split_register (priv->ledger);
3934  LEAVE (" ");
3935 }
3936 
3937 
3938 static void
3939 gnc_plugin_page_register_cmd_void_transaction (GtkAction* action,
3940  GncPluginPageRegister* page)
3941 {
3943  GtkWidget* dialog, *entry;
3944  SplitRegister* reg;
3945  Transaction* trans;
3946  GtkBuilder* builder;
3947  const char* reason;
3948  gint result;
3949  GtkWindow* window;
3950 
3951  ENTER ("(action %p, page %p)", action, page);
3952 
3953  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3954 
3955  window = GTK_WINDOW (gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page)));
3956  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3957  reg = gnc_ledger_display_get_split_register (priv->ledger);
3959  if (trans == NULL)
3960  return;
3961  if (xaccTransHasSplitsInState (trans, VREC))
3962  return;
3963  if (xaccTransHasReconciledSplits (trans) ||
3965  {
3966  gnc_error_dialog (window, "%s",
3967  _ ("You cannot void a transaction with reconciled or cleared splits."));
3968  return;
3969  }
3970  reason = xaccTransGetReadOnly (trans);
3971  if (reason)
3972  {
3973  gnc_error_dialog (window,
3974  _ ("This transaction is marked read-only with the comment: '%s'"), reason);
3975  return;
3976  }
3977 
3978  if (!gnc_plugin_page_register_finish_pending (GNC_PLUGIN_PAGE (page)))
3979  return;
3980 
3981  builder = gtk_builder_new();
3982  gnc_builder_add_from_file (builder, "gnc-plugin-page-register.glade",
3983  "void_transaction_dialog");
3984  dialog = GTK_WIDGET (gtk_builder_get_object (builder,
3985  "void_transaction_dialog"));
3986  entry = GTK_WIDGET (gtk_builder_get_object (builder, "reason"));
3987 
3988  gtk_window_set_transient_for (GTK_WINDOW (dialog), window);
3989 
3990  result = gtk_dialog_run (GTK_DIALOG (dialog));
3991  if (result == GTK_RESPONSE_OK)
3992  {
3993  reason = gtk_entry_get_text (GTK_ENTRY (entry));
3994  if (reason == NULL)
3995  reason = "";
3997  }
3998 
3999  /* All done. Get rid of it. */
4000  gtk_widget_destroy (dialog);
4001  g_object_unref (G_OBJECT (builder));
4002 }
4003 
4004 
4005 static void
4006 gnc_plugin_page_register_cmd_unvoid_transaction (GtkAction* action,
4007  GncPluginPageRegister* page)
4008 {
4010  SplitRegister* reg;
4011  Transaction* trans;
4012 
4013  ENTER ("(action %p, page %p)", action, page);
4014 
4015  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
4016 
4017  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
4018  reg = gnc_ledger_display_get_split_register (priv->ledger);
4020  if (!xaccTransHasSplitsInState (trans, VREC))
4021  return;
4023  LEAVE (" ");
4024 }
4025 
4026 
4027 static void
4028 gnc_plugin_page_register_cmd_reverse_transaction (GtkAction* action,
4029  GncPluginPageRegister* page)
4030 {
4032  SplitRegister* reg;
4033  GNCSplitReg* gsr;
4034  Transaction* trans, *new_trans;
4035  time64 date = gnc_time (NULL);
4036  GtkWidget *window;
4037  Account *account;
4038  Split *split;
4039 
4040  ENTER ("(action %p, page %p)", action, page);
4041 
4042  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
4043 
4044  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
4045  reg = gnc_ledger_display_get_split_register (priv->ledger);
4046  window = gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page));
4048  if (trans == NULL)
4049  return;
4050 
4052  account = xaccSplitGetAccount (split);
4053 
4054  if (!account)
4055  {
4056  LEAVE ("shouldn't try to reverse the blank transaction...");
4057  return;
4058  }
4059 
4060  new_trans = xaccTransGetReversedBy (trans);
4061  if (new_trans)
4062  {
4063  const char *rev = _("A reversing entry has already been created for this transaction.");
4064  const char *jump = _("Jump to the transaction?");
4065  if (gnc_verify_dialog (GTK_WINDOW (window), TRUE, "%s\n\n%s", rev, jump))
4066  goto jump_to_trans;
4067  else
4068  return;
4069  }
4070 
4071  if (!gnc_dup_time64_dialog (window, _("Reverse Transaction"),
4072  _("New Transaction Information"), &date))
4073  {
4074  LEAVE ("reverse cancelled");
4075  return;
4076  }
4077 
4078  gnc_suspend_gui_refresh();
4079  new_trans = xaccTransReverse (trans);
4080 
4081  /* Clear transaction level info */
4082  xaccTransSetDatePostedSecsNormalized (new_trans, date);
4083  xaccTransSetDateEnteredSecs (new_trans, gnc_time (NULL));
4084 
4085  gnc_resume_gui_refresh();
4086 
4087  jump_to_trans:
4088  /* Now jump to new trans */
4089  gsr = gnc_plugin_page_register_get_gsr (GNC_PLUGIN_PAGE (page));
4090  split = xaccTransFindSplitByAccount(new_trans, account);
4091 
4092  /* Test for visibility of split */
4093  if (gnc_split_reg_clear_filter_for_split (gsr, split))
4094  gnc_plugin_page_register_clear_current_filter (GNC_PLUGIN_PAGE(page));
4095 
4096  gnc_split_reg_jump_to_split (gsr, split);
4097  LEAVE (" ");
4098 }
4099 
4100 static gboolean
4101 gnc_plugin_page_register_show_fs_save (GncPluginPageRegister* page)
4102 {
4103  GncPluginPageRegisterPrivate* priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (
4104  page);
4105  GNCLedgerDisplayType ledger_type = gnc_ledger_display_type (priv->ledger);
4106  SplitRegister* reg = gnc_ledger_display_get_split_register (priv->ledger);
4107 
4108  if (ledger_type == LD_SINGLE || ledger_type == LD_SUBACCOUNT)
4109  return TRUE;
4110  else
4111  {
4112  switch (reg->type)
4113  {
4114  case GENERAL_JOURNAL:
4115  return TRUE;
4116  break;
4117 
4118  case INCOME_LEDGER:
4119  case PORTFOLIO_LEDGER:
4120  case SEARCH_LEDGER:
4121  default:
4122  return FALSE;
4123  break;
4124  }
4125  }
4126 }
4127 
4128 static void
4129 gnc_plugin_page_register_cmd_view_sort_by (GtkAction* action,
4130  GncPluginPageRegister* page)
4131 {
4133  SplitRegister* reg;
4134  GtkWidget* dialog, *button;
4135  GtkBuilder* builder;
4136  SortType sort;
4137  const gchar* name;
4138  gchar* title;
4139 
4140  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
4141  ENTER ("(action %p, page %p)", action, page);
4142 
4143  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
4144  if (priv->sd.dialog)
4145  {
4146  gtk_window_present (GTK_WINDOW (priv->sd.dialog));
4147  LEAVE ("existing dialog");
4148  return;
4149  }
4150 
4151  /* Create the dialog */
4152 
4153  builder = gtk_builder_new();
4154  gnc_builder_add_from_file (builder, "gnc-plugin-page-register.glade",
4155  "sort_by_dialog");
4156  dialog = GTK_WIDGET (gtk_builder_get_object (builder, "sort_by_dialog"));
4157  priv->sd.dialog = dialog;
4158  gtk_window_set_transient_for (GTK_WINDOW (dialog),
4159  gnc_window_get_gtk_window (GNC_WINDOW (GNC_PLUGIN_PAGE (page)->window)));
4160  /* Translators: The %s is the name of the plugin page */
4161  title = g_strdup_printf (_ ("Sort %s by..."),
4162  gnc_plugin_page_get_page_name (GNC_PLUGIN_PAGE (page)));
4163  gtk_window_set_title (GTK_WINDOW (dialog), title);
4164  g_free (title);
4165 
4166  /* Set the button for the current sort order */
4167  sort = gnc_split_reg_get_sort_type (priv->gsr);
4168  name = SortTypeasString (sort);
4169  button = GTK_WIDGET (gtk_builder_get_object (builder, name));
4170  DEBUG ("current sort %d, button %s(%p)", sort, name, button);
4171  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
4172  priv->sd.original_sort_type = sort;
4173 
4174  button = GTK_WIDGET (gtk_builder_get_object (builder, "sort_save"));
4175  if (priv->sd.save_order == TRUE)
4176  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
4177 
4178  // hide the save button if appropriate
4179  gtk_widget_set_visible (GTK_WIDGET (button),
4180  gnc_plugin_page_register_show_fs_save (page));
4181 
4182  /* Set the button for the current reverse_order order */
4183  button = GTK_WIDGET (gtk_builder_get_object (builder, "sort_reverse"));
4184  if (priv->sd.reverse_order == TRUE)
4185  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
4186  priv->sd.original_reverse_order = priv->sd.reverse_order;
4187 
4188  priv->sd.num_radio = GTK_WIDGET (gtk_builder_get_object (builder, "BY_NUM"));
4189  priv->sd.act_radio = GTK_WIDGET (gtk_builder_get_object (builder,
4190  "BY_ACTION"));
4191  /* Adjust labels related to Num/Action radio buttons based on book option */
4192  reg = gnc_ledger_display_get_split_register (priv->ledger);
4193  if (reg && !reg->use_tran_num_for_num_field)
4194  {
4195  gtk_button_set_label (GTK_BUTTON (priv->sd.num_radio),
4196  _ ("Transaction Number"));
4197  gtk_button_set_label (GTK_BUTTON (priv->sd.act_radio), _ ("Number/Action"));
4198  }
4199  gnc_book_option_register_cb (OPTION_NAME_NUM_FIELD_SOURCE,
4200  gnc_plugin_page_register_sort_book_option_changed,
4201  page);
4202 
4203  /* Wire it up */
4204  gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func,
4205  page);
4206 
4207  /* Show it */
4208  gtk_widget_show (dialog);
4209  g_object_unref (G_OBJECT (builder));
4210  LEAVE (" ");
4211 }
4212 
4213 static void
4214 gnc_plugin_page_register_cmd_view_filter_by (GtkAction* action,
4215  GncPluginPageRegister* page)
4216 {
4218  GtkWidget* dialog, *toggle, *button, *table, *hbox;
4219  time64 start_time, end_time, time_val;
4220  GtkBuilder* builder;
4221  gboolean sensitive, value;
4222  Query* query;
4223  gchar* title;
4224  int i;
4225 
4226  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
4227  ENTER ("(action %p, page %p)", action, page);
4228 
4229  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
4230  if (priv->fd.dialog)
4231  {
4232  gtk_window_present (GTK_WINDOW (priv->fd.dialog));
4233  LEAVE ("existing dialog");
4234  return;
4235  }
4236 
4237  /* Create the dialog */
4238  builder = gtk_builder_new();
4239  gnc_builder_add_from_file (builder, "gnc-plugin-page-register.glade",
4240  "days_adjustment");
4241  gnc_builder_add_from_file (builder, "gnc-plugin-page-register.glade",
4242  "filter_by_dialog");
4243  dialog = GTK_WIDGET (gtk_builder_get_object (builder, "filter_by_dialog"));
4244  priv->fd.dialog = dialog;
4245  gtk_window_set_transient_for (GTK_WINDOW (dialog),
4246  gnc_window_get_gtk_window (GNC_WINDOW (GNC_PLUGIN_PAGE (page)->window)));
4247 
4248  /* Translators: The %s is the name of the plugin page */
4249  title = g_strdup_printf (_ ("Filter %s by..."),
4250  gnc_plugin_page_get_page_name (GNC_PLUGIN_PAGE (page)));
4251  gtk_window_set_title (GTK_WINDOW (dialog), title);
4252  g_free (title);
4253 
4254  /* Set the check buttons for the current status */
4255  for (i = 0; status_actions[i].action_name; i++)
4256  {
4257  toggle = GTK_WIDGET (gtk_builder_get_object (builder,
4258  status_actions[i].action_name));
4259  value = priv->fd.cleared_match & status_actions[i].value;
4260  status_actions[i].widget = toggle;
4261  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), value);
4262  }
4263  priv->fd.original_cleared_match = priv->fd.cleared_match;
4264 
4265  button = GTK_WIDGET (gtk_builder_get_object (builder, "filter_save"));
4266  if (priv->fd.save_filter == TRUE)
4267  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
4268 
4269  // hide the save button if appropriate
4270  gtk_widget_set_visible (GTK_WIDGET (button),
4271  gnc_plugin_page_register_show_fs_save (page));
4272 
4273  /* Set up number of days */
4274  priv->fd.num_days = GTK_WIDGET (gtk_builder_get_object (builder,
4275  "filter_show_num_days"));
4276  button = GTK_WIDGET (gtk_builder_get_object (builder, "filter_show_days"));
4277 
4278  query = gnc_ledger_display_get_query (priv->ledger);
4279 
4280  if (priv->fd.days > 0) // using number of days
4281  {
4282  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
4283  gtk_widget_set_sensitive (GTK_WIDGET (priv->fd.num_days), TRUE);
4284  gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->fd.num_days), priv->fd.days);
4285  priv->fd.original_days = priv->fd.days;
4286 
4287  /* Set the start_time and end_time to 0 */
4288  start_time = 0;
4289  end_time = 0;
4290  }
4291  else
4292  {
4293  gtk_widget_set_sensitive (GTK_WIDGET (priv->fd.num_days), FALSE);
4294  priv->fd.original_days = 0;
4295  priv->fd.days = 0;
4296 
4297  /* Get the start and end times */
4298  xaccQueryGetDateMatchTT (query, &start_time, &end_time);
4299  }
4300 
4301  /* Set the date info */
4302  priv->fd.original_start_time = start_time;
4303  priv->fd.start_time = start_time;
4304  priv->fd.original_end_time = end_time;
4305  priv->fd.end_time = end_time;
4306 
4307  button = GTK_WIDGET (gtk_builder_get_object (builder, "filter_show_range"));
4308  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), start_time ||
4309  end_time);
4310  table = GTK_WIDGET (gtk_builder_get_object (builder, "select_range_table"));
4311  priv->fd.table = table;
4312  gtk_widget_set_sensitive (GTK_WIDGET (table), start_time || end_time);
4313 
4314  priv->fd.start_date_choose = GTK_WIDGET (gtk_builder_get_object (builder,
4315  "start_date_choose"));
4316  priv->fd.start_date_today = GTK_WIDGET (gtk_builder_get_object (builder,
4317  "start_date_today"));
4318  priv->fd.end_date_choose = GTK_WIDGET (gtk_builder_get_object (builder,
4319  "end_date_choose"));
4320  priv->fd.end_date_today = GTK_WIDGET (gtk_builder_get_object (builder,
4321  "end_date_today"));
4322 
4323  {
4324  /* Start date info */
4325  if (start_time == 0)
4326  {
4327  button = GTK_WIDGET (gtk_builder_get_object (builder, "start_date_earliest"));
4328  time_val = xaccQueryGetEarliestDateFound (query);
4329  sensitive = FALSE;
4330  }
4331  else
4332  {
4333  time_val = start_time;
4334  if ((start_time >= gnc_time64_get_today_start()) &&
4335  (start_time <= gnc_time64_get_today_end()))
4336  {
4337  button = priv->fd.start_date_today;
4338  sensitive = FALSE;
4339  }
4340  else
4341  {
4342  button = priv->fd.start_date_choose;
4343  sensitive = TRUE;
4344  }
4345  }
4346  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
4347  priv->fd.start_date = gnc_date_edit_new (gnc_time (NULL), FALSE, FALSE);
4348  hbox = GTK_WIDGET (gtk_builder_get_object (builder, "start_date_hbox"));
4349  gtk_box_pack_start (GTK_BOX (hbox), priv->fd.start_date, TRUE, TRUE, 0);
4350  gtk_widget_show (priv->fd.start_date);
4351  gtk_widget_set_sensitive (GTK_WIDGET (priv->fd.start_date), sensitive);
4352  gnc_date_edit_set_time (GNC_DATE_EDIT (priv->fd.start_date), time_val);
4353  g_signal_connect (G_OBJECT (priv->fd.start_date), "date-changed",
4354  G_CALLBACK (gnc_plugin_page_register_filter_gde_changed_cb),
4355  page);
4356  }
4357 
4358  {
4359  /* End date info */
4360  if (end_time == 0)
4361  {
4362  button = GTK_WIDGET (gtk_builder_get_object (builder, "end_date_latest"));
4363  time_val = xaccQueryGetLatestDateFound (query);
4364  sensitive = FALSE;
4365  }
4366  else
4367  {
4368  time_val = end_time;
4369  if ((end_time >= gnc_time64_get_today_start()) &&
4370  (end_time <= gnc_time64_get_today_end()))
4371  {
4372  button = priv->fd.end_date_today;
4373  sensitive = FALSE;
4374  }
4375  else
4376  {
4377  button = priv->fd.end_date_choose;
4378  sensitive = TRUE;
4379  }
4380  }
4381  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
4382  priv->fd.end_date = gnc_date_edit_new (gnc_time (NULL), FALSE, FALSE);
4383  hbox = GTK_WIDGET (gtk_builder_get_object (builder, "end_date_hbox"));
4384  gtk_box_pack_start (GTK_BOX (hbox), priv->fd.end_date, TRUE, TRUE, 0);
4385  gtk_widget_show (priv->fd.end_date);
4386  gtk_widget_set_sensitive (GTK_WIDGET (priv->fd.end_date), sensitive);
4387  gnc_date_edit_set_time (GNC_DATE_EDIT (priv->fd.end_date), time_val);
4388  g_signal_connect (G_OBJECT (priv->fd.end_date), "date-changed",
4389  G_CALLBACK (gnc_plugin_page_register_filter_gde_changed_cb),
4390  page);
4391  }
4392 
4393  /* Wire it up */
4394  gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func,
4395  page);
4396 
4397  /* Show it */
4398  gtk_widget_show (dialog);
4399  g_object_unref (G_OBJECT (builder));
4400  LEAVE (" ");
4401 }
4402 
4403 static void
4404 gnc_plugin_page_register_cmd_reload (GtkAction* action,
4405  GncPluginPageRegister* plugin_page)
4406 {
4408  SplitRegister* reg;
4409 
4410  ENTER ("(action %p, page %p)", action, plugin_page);
4411 
4412  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4413 
4414  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4415  reg = gnc_ledger_display_get_split_register (priv->ledger);
4416 
4417  /* Check for trans being edited */
4418  if (gnc_split_register_changed (reg))
4419  {
4420  LEAVE ("register has pending edits");
4421  return;
4422  }
4423  gnc_ledger_display_refresh (priv->ledger);
4424  LEAVE (" ");
4425 }
4426 
4427 static void
4428 gnc_plugin_page_register_cmd_style_changed (GtkAction* action,
4429  GtkRadioAction* current,
4430  GncPluginPageRegister* plugin_page)
4431 {
4433  SplitRegisterStyle value;
4434 
4435  ENTER ("(action %p, radio action %p, plugin_page %p)",
4436  action, current, plugin_page);
4437 
4438  g_return_if_fail (GTK_IS_ACTION (action));
4439  g_return_if_fail (GTK_IS_RADIO_ACTION (current));
4440  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4441 
4442  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4443  value = gtk_radio_action_get_current_value (current);
4444  gnc_split_reg_change_style (priv->gsr, value, priv->enable_refresh);
4445 
4446  gnc_plugin_page_register_ui_update (NULL, plugin_page);
4447  LEAVE (" ");
4448 }
4449 
4450 static void
4451 gnc_plugin_page_register_cmd_style_double_line (GtkToggleAction* action,
4452  GncPluginPageRegister* plugin_page)
4453 {
4455  SplitRegister* reg;
4456  gboolean use_double_line;
4457 
4458  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4459 
4460  g_return_if_fail (GTK_IS_ACTION (action));
4461  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4462 
4463  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4464  reg = gnc_ledger_display_get_split_register (priv->ledger);
4465 
4466  use_double_line = gtk_toggle_action_get_active (action);
4467  if (use_double_line != reg->use_double_line)
4468  {
4469  gnc_split_register_config (reg, reg->type, reg->style, use_double_line);
4470  if (priv->enable_refresh)
4471  gnc_ledger_display_refresh (priv->ledger);
4472  }
4473  LEAVE (" ");
4474 }
4475 
4476 static void
4477 gnc_plugin_page_register_cmd_transfer (GtkAction* action,
4478  GncPluginPageRegister* page)
4479 {
4480  Account* account;
4481  GncWindow* gnc_window;
4482  GtkWidget* window;
4483 
4484  ENTER ("(action %p, plugin_page %p)", action, page);
4485 
4486  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
4487 
4488  account = gnc_plugin_page_register_get_account (page);
4489  gnc_window = GNC_WINDOW (GNC_PLUGIN_PAGE (page)->window);
4490  window = GTK_WIDGET (gnc_window_get_gtk_window (gnc_window));
4491  gnc_xfer_dialog (window, account);
4492  LEAVE (" ");
4493 }
4494 
4495 static void
4496 gnc_plugin_page_register_cmd_reconcile (GtkAction* action,
4497  GncPluginPageRegister* page)
4498 {
4499  Account* account;
4500  GtkWindow* window;
4501  RecnWindow* recnData;
4502 
4503  ENTER ("(action %p, plugin_page %p)", action, page);
4504 
4505  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
4506 
4507  account = gnc_plugin_page_register_get_account (page);
4508 
4509  window = gnc_window_get_gtk_window (GNC_WINDOW (GNC_PLUGIN_PAGE (
4510  page)->window));
4511  recnData = recnWindow (GTK_WIDGET (window), account);
4512  gnc_ui_reconcile_window_raise (recnData);
4513  LEAVE (" ");
4514 }
4515 
4516 static void
4517 gnc_plugin_page_register_cmd_stock_assistant (GtkAction* action,
4518  GncPluginPageRegister* page)
4519 {
4520  Account *account;
4521  GtkWindow *window;
4522 
4523  ENTER ("(action %p, plugin_page %p)", action, page);
4524 
4525  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
4526  window = gnc_window_get_gtk_window (GNC_WINDOW (GNC_PLUGIN_PAGE (page)->window));
4527  account = gnc_plugin_page_register_get_account (page);
4528  gnc_stock_transaction_assistant (GTK_WIDGET (window), account);
4529 
4530  LEAVE (" ");
4531 }
4532 
4533 static void
4534 gnc_plugin_page_register_cmd_autoclear (GtkAction* action,
4535  GncPluginPageRegister* page)
4536 {
4537  Account* account;
4538  GtkWindow* window;
4539  AutoClearWindow* autoClearData;
4540 
4541  ENTER ("(action %p, plugin_page %p)", action, page);
4542 
4543  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
4544 
4545  account = gnc_plugin_page_register_get_account (page);
4546 
4547  window = gnc_window_get_gtk_window (GNC_WINDOW (GNC_PLUGIN_PAGE (
4548  page)->window));
4549  autoClearData = autoClearWindow (GTK_WIDGET (window), account);
4550  gnc_ui_autoclear_window_raise (autoClearData);
4551  LEAVE (" ");
4552 }
4553 
4554 static void
4555 gnc_plugin_page_register_cmd_stock_split (GtkAction* action,
4556  GncPluginPageRegister* page)
4557 {
4558  Account* account;
4559  GtkWindow* window;
4560 
4561  ENTER ("(action %p, plugin_page %p)", action, page);
4562 
4563  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
4564 
4565  account = gnc_plugin_page_register_get_account (page);
4566  window = gnc_window_get_gtk_window (GNC_WINDOW (GNC_PLUGIN_PAGE (page)->window));
4567  gnc_stock_split_dialog (GTK_WIDGET (window), account);
4568  LEAVE (" ");
4569 }
4570 
4571 static void
4572 gnc_plugin_page_register_cmd_lots (GtkAction* action,
4573  GncPluginPageRegister* page)
4574 {
4575  GtkWindow* window;
4576  Account* account;
4577 
4578  ENTER ("(action %p, plugin_page %p)", action, page);
4579 
4580  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
4581 
4582  window = gnc_window_get_gtk_window (GNC_WINDOW (GNC_PLUGIN_PAGE (
4583  page)->window));
4584  account = gnc_plugin_page_register_get_account (page);
4585  gnc_lot_viewer_dialog (window, account);
4586  LEAVE (" ");
4587 }
4588 
4589 static void
4590 gnc_plugin_page_register_cmd_enter_transaction (GtkAction* action,
4591  GncPluginPageRegister* plugin_page)
4592 {
4594 
4595  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4596 
4597  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4598 
4599  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4600  gnc_split_reg_enter (priv->gsr, FALSE);
4601  LEAVE (" ");
4602 }
4603 
4604 static void
4605 gnc_plugin_page_register_cmd_cancel_transaction (GtkAction* action,
4606  GncPluginPageRegister* plugin_page)
4607 {
4609 
4610  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4611 
4612  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4613 
4614  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4616  (gnc_ledger_display_get_split_register (priv->ledger));
4617  LEAVE (" ");
4618 }
4619 
4620 static void
4621 gnc_plugin_page_register_cmd_delete_transaction (GtkAction* action,
4622  GncPluginPageRegister* plugin_page)
4623 {
4625 
4626  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4627 
4628  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4629 
4630  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4631  gsr_default_delete_handler (priv->gsr, NULL);
4632  LEAVE (" ");
4633 
4634 }
4635 
4636 static void
4637 gnc_plugin_page_register_cmd_linked_transaction (GtkAction *action,
4638  GncPluginPageRegister* plugin_page)
4639 {
4641 
4642  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4643 
4644  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4645 
4646  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4647  gsr_default_doclink_handler (priv->gsr);
4648  gnc_plugin_page_register_ui_update (NULL, plugin_page);
4649  LEAVE (" ");
4650 }
4651 
4652 static void
4653 gnc_plugin_page_register_cmd_linked_transaction_open (GtkAction *action,
4654  GncPluginPageRegister* plugin_page)
4655 {
4657 
4658  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4659 
4660  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4661 
4662  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4663  gsr_default_doclink_open_handler (priv->gsr);
4664  LEAVE (" ");
4665 }
4666 
4667 static void
4668 gnc_plugin_page_register_cmd_linked_transaction_remove (GtkAction *action,
4669  GncPluginPageRegister* plugin_page)
4670 {
4672 
4673  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4674 
4675  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4676 
4677  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4678  gsr_default_doclink_remove_handler (priv->gsr);
4679  gnc_plugin_page_register_ui_update (NULL, plugin_page);
4680  LEAVE (" ");
4681 
4682 }
4683 
4684 static GncInvoice* invoice_from_split (Split* split)
4685 {
4686  GncInvoice* invoice;
4687  GNCLot* lot;
4688 
4689  if (!split)
4690  return NULL;
4691 
4692  lot = xaccSplitGetLot (split);
4693  if (!lot)
4694  return NULL;
4695 
4696  invoice = gncInvoiceGetInvoiceFromLot (lot);
4697  if (!invoice)
4698  return NULL;
4699 
4700  return invoice;
4701 }
4702 
4703 GList* invoices_from_transaction (Transaction* trans)
4704 {
4705  GList *invoices = NULL;
4706  GList *apar_splits;
4707  if (!trans) return NULL;
4708 
4709  apar_splits = xaccTransGetAPARAcctSplitList (trans, TRUE);
4710  if (!apar_splits) return NULL;
4711 
4712  for (GList *node = apar_splits; node; node = node->next)
4713  {
4714  GncInvoice* inv = invoice_from_split ((Split*) node->data);
4715  if (inv) invoices = g_list_prepend (invoices, inv);
4716  }
4717  g_list_free (apar_splits);
4718  return invoices;
4719 }
4720 
4721 static void
4722 gnc_plugin_page_register_cmd_jump_linked_invoice (GtkAction* action,
4723  GncPluginPageRegister* plugin_page)
4724 {
4726  SplitRegister* reg;
4727  GncInvoice* invoice;
4728  Transaction *txn;
4729  GtkWidget *window;
4730 
4731  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4732 
4733  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4734  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4735  reg = gnc_ledger_display_get_split_register (priv->gsr->ledger);
4737  invoice = invoice_from_split (gnc_split_register_get_current_split (reg));
4738  window = GNC_PLUGIN_PAGE(plugin_page)->window;
4739 
4740  if (!invoice)
4741  {
4742  GList *invoices = invoices_from_transaction (txn);
4743  if (!invoices)
4744  PERR ("shouldn't happen: if no invoices, function is never called");
4745  else if (!invoices->next)
4746  invoice = (GncInvoice*) invoices->data;
4747  else
4748  {
4749  GList *details = NULL;
4750  gint choice;
4751  const gchar *amt;
4752  for (GList *node = invoices; node; node = node->next)
4753  {
4754  GncInvoice* inv = node->data;
4755  gchar *date = qof_print_date (gncInvoiceGetDatePosted (inv));
4756  amt = xaccPrintAmount
4757  (gncInvoiceGetTotal (inv),
4758  gnc_account_print_info (gncInvoiceGetPostedAcc (inv), TRUE));
4759  details = g_list_prepend
4760  (details,
4761  /* Translators: %s refer to the following in
4762  order: invoice type, invoice ID, owner name,
4763  posted date, amount */
4764  g_strdup_printf (_("%s %s from %s, posted %s, amount %s"),
4765  gncInvoiceGetTypeString (inv),
4766  gncInvoiceGetID (inv),
4767  gncOwnerGetName (gncInvoiceGetOwner (inv)),
4768  date, amt));
4769  g_free (date);
4770  }
4771  details = g_list_reverse (details);
4772  choice = gnc_choose_radio_option_dialog
4773  (window, _("Select document"),
4774  _("Several documents are linked with this transaction. \
4775 Please choose one:"), _("Select"), 0, details);
4776  if (choice >= 0)
4777  invoice = (GncInvoice *)(g_list_nth (invoices, choice))->data;
4778  g_list_free_full (details, g_free);
4779  }
4780  g_list_free (invoices);
4781  }
4782 
4783  if (invoice)
4784  {
4785  GtkWindow *gtk_window = gnc_window_get_gtk_window (GNC_WINDOW (window));
4786  gnc_ui_invoice_edit (gtk_window, invoice);
4787  }
4788 
4789  LEAVE (" ");
4790 }
4791 
4792 static void
4793 gnc_plugin_page_register_cmd_blank_transaction (GtkAction* action,
4794  GncPluginPageRegister* plugin_page)
4795 {
4797  SplitRegister* reg;
4798 
4799  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4800 
4801  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4802 
4803  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4804  reg = gnc_ledger_display_get_split_register (priv->ledger);
4805 
4806  if (gnc_split_register_save (reg, TRUE))
4808 
4809  gnc_split_reg_jump_to_blank (priv->gsr);
4810  LEAVE (" ");
4811 }
4812 
4813 static void
4814 gnc_plugin_page_register_cmd_goto_date (GtkAction* action,
4815  GncPluginPageRegister* page)
4816 {
4817  GNCSplitReg* gsr;
4818  Query* query;
4819  time64 date = gnc_time (NULL);
4820  GList *splits;
4821 
4822  ENTER ("(action %p, plugin_page %p)", action, page);
4823  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
4824 
4825  if (!gnc_dup_time64_dialog (gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page)),
4826  _("Go to Date"), _("Go to Date"), &date))
4827  {
4828  LEAVE ("goto_date cancelled");
4829  return;
4830  }
4831 
4832  gsr = gnc_plugin_page_register_get_gsr (GNC_PLUGIN_PAGE (page));
4833  query = gnc_plugin_page_register_get_query (GNC_PLUGIN_PAGE (page));
4834  splits = g_list_copy (qof_query_run (query));
4835  splits = g_list_sort (splits, (GCompareFunc)xaccSplitOrder);
4836 
4837  for (GList *lp = splits; lp; lp = lp->next)
4838  {
4839  if (xaccTransGetDate (xaccSplitGetParent (lp->data)) >= date)
4840  {
4841  gnc_split_reg_jump_to_split (gsr, lp->data);
4842  break;
4843  }
4844  }
4845 
4846  g_list_free (splits);
4847  LEAVE (" ");
4848 }
4849 
4850 static void
4851 gnc_plugin_page_register_cmd_duplicate_transaction (GtkAction* action,
4852  GncPluginPageRegister* plugin_page)
4853 {
4855 
4856  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4857 
4858  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4859 
4860  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4862  (gnc_ledger_display_get_split_register (priv->ledger));
4863  LEAVE (" ");
4864 }
4865 
4866 static void
4867 gnc_plugin_page_register_cmd_reinitialize_transaction (GtkAction* action,
4868  GncPluginPageRegister* plugin_page)
4869 {
4871 
4872  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4873 
4874  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4875 
4876  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4877  gsr_default_reinit_handler (priv->gsr, NULL);
4878  LEAVE (" ");
4879 }
4880 
4881 static void
4882 gnc_plugin_page_register_cmd_expand_transaction (GtkToggleAction* action,
4883  GncPluginPageRegister* plugin_page)
4884 {
4886  SplitRegister* reg;
4887  gboolean expand;
4888 
4889  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4890 
4891  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4892 
4893  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4894  reg = gnc_ledger_display_get_split_register (priv->ledger);
4895  expand = gtk_toggle_action_get_active (action);
4897  LEAVE (" ");
4898 }
4899 
4902 static void
4903 gnc_plugin_page_register_cmd_exchange_rate (GtkAction* action,
4904  GncPluginPageRegister* plugin_page)
4905 {
4907  SplitRegister* reg;
4908 
4909  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4910 
4911  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4912 
4913  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4914  reg = gnc_ledger_display_get_split_register (priv->ledger);
4915 
4916  /* XXX Ignore the return value -- we don't care if this succeeds */
4917  (void)gnc_split_register_handle_exchange (reg, TRUE);
4918  LEAVE (" ");
4919 }
4920 
4921 static void
4922 gnc_plugin_page_register_cmd_jump (GtkAction* action,
4923  GncPluginPageRegister* plugin_page)
4924 {
4926  GncPluginPage* new_page;
4927  GtkWidget* window;
4928  GNCSplitReg* gsr;
4929  SplitRegister* reg;
4930  Account* account;
4931  Account* leader;
4932  Split* split;
4933 
4934  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4935 
4936  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4937 
4938  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4939  window = GNC_PLUGIN_PAGE (plugin_page)->window;
4940  if (window == NULL)
4941  {
4942  LEAVE ("no window");
4943  return;
4944  }
4945 
4946  reg = gnc_ledger_display_get_split_register (priv->ledger);
4948  if (split == NULL)
4949  {
4950  LEAVE ("no split (1)");
4951  return;
4952  }
4953 
4954  account = xaccSplitGetAccount (split);
4955  if (account == NULL)
4956  {
4957  LEAVE ("no account");
4958  return;
4959  }
4960 
4961  leader = gnc_ledger_display_leader (priv->ledger);
4962  if (account == leader)
4963  {
4964  split = xaccSplitGetOtherSplit (split);
4965  if (split == NULL)
4966  {
4967  LEAVE ("no split (2)");
4968  return;
4969  }
4970 
4971  account = xaccSplitGetAccount (split);
4972  if (account == NULL)
4973  {
4974  LEAVE ("no account (2)");
4975  return;
4976  }
4977 
4978  if (account == leader)
4979  {
4980  LEAVE ("register open for account");
4981  return;
4982  }
4983  }
4984 
4985  new_page = gnc_plugin_page_register_new (account, FALSE);
4986  if (new_page == NULL)
4987  {
4988  LEAVE ("couldn't create new page");
4989  return;
4990  }
4991 
4992  gnc_main_window_open_page (GNC_MAIN_WINDOW (window), new_page);
4993  gsr = gnc_plugin_page_register_get_gsr (new_page);
4994 
4995  /* Test for visibility of split */
4996  if (gnc_split_reg_clear_filter_for_split (gsr, split))
4997  gnc_plugin_page_register_clear_current_filter (GNC_PLUGIN_PAGE(new_page));
4998 
4999  gnc_split_reg_jump_to_split (gsr, split);
5000  LEAVE (" ");
5001 }
5002 
5003 static void
5004 gnc_plugin_page_register_cmd_schedule (GtkAction* action,
5005  GncPluginPageRegister* plugin_page)
5006 {
5008  GtkWindow* window;
5009 
5010  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
5011 
5012  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
5013 
5014  window = GTK_WINDOW (gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (
5015  plugin_page)));
5016  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
5017  gsr_default_schedule_handler (priv->gsr, window);
5018  LEAVE (" ");
5019 }
5020 
5021 static void scrub_split (Split *split)
5022 {
5023  Account *acct;
5024  Transaction *trans;
5025  GNCLot *lot;
5026 
5027  g_return_if_fail (split);
5028  acct = xaccSplitGetAccount (split);
5029  trans = xaccSplitGetParent (split);
5030  lot = xaccSplitGetLot (split);
5031  g_return_if_fail (trans);
5032 
5033  xaccTransScrubOrphans (trans);
5034  xaccTransScrubImbalance (trans, gnc_get_current_root_account(), NULL);
5035  if (lot && xaccAccountIsAPARType (xaccAccountGetType (acct)))
5036  {
5037  gncScrubBusinessLot (lot);
5038  gncScrubBusinessSplit (split);
5039  }
5040 }
5041 
5042 static void
5043 gnc_plugin_page_register_cmd_scrub_current (GtkAction* action,
5044  GncPluginPageRegister* plugin_page)
5045 {
5047  Query* query;
5048  Split* split;
5049  SplitRegister* reg;
5050 
5051  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
5052 
5053  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
5054 
5055  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
5056  query = gnc_ledger_display_get_query (priv->ledger);
5057  if (query == NULL)
5058  {
5059  LEAVE ("no query found");
5060  return;
5061  }
5062 
5063  reg = gnc_ledger_display_get_split_register (priv->ledger);
5064 
5065  gnc_suspend_gui_refresh();
5066  scrub_split (gnc_split_register_get_current_split (reg));
5067  gnc_resume_gui_refresh();
5068  LEAVE (" ");
5069 }
5070 
5071 static gboolean
5072 scrub_kp_handler (GtkWidget *widget, GdkEventKey *event, gpointer data)
5073 {
5074  if (event->length == 0) return FALSE;
5075 
5076  switch (event->keyval)
5077  {
5078  case GDK_KEY_Escape:
5079  {
5080  gboolean abort_scrub = gnc_verify_dialog (GTK_WINDOW(widget), FALSE,
5081  _("'Check & Repair' is currently running, do you want to abort it?"));
5082 
5083  if (abort_scrub)
5084  gnc_set_abort_scrub (TRUE);
5085 
5086  return TRUE;
5087  }
5088  default:
5089  break;
5090  }
5091  return FALSE;
5092 }
5093 
5094 static void
5095 gnc_plugin_page_register_cmd_scrub_all (GtkAction* action,
5096  GncPluginPageRegister* plugin_page)
5097 {
5099  Query* query;
5100  GncWindow* window;
5101  GList* node, *splits;
5102  gint split_count = 0, curr_split_no = 0;
5103  gulong scrub_kp_handler_ID;
5104  const char* message = _ ("Checking splits in current register: %u of %u");
5105 
5106  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
5107 
5108  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
5109 
5110  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
5111  query = gnc_ledger_display_get_query (priv->ledger);
5112  if (!query)
5113  {
5114  LEAVE ("no query found");
5115  return;
5116  }
5117 
5118  gnc_suspend_gui_refresh();
5119  is_scrubbing = TRUE;
5120  gnc_set_abort_scrub (FALSE);
5121  window = GNC_WINDOW (GNC_PLUGIN_PAGE (plugin_page)->window);
5122  scrub_kp_handler_ID = g_signal_connect (G_OBJECT (window), "key-press-event",
5123  G_CALLBACK (scrub_kp_handler), NULL);
5124  gnc_window_set_progressbar_window (window);
5125 
5126  splits = qof_query_run (query);
5127  split_count = g_list_length (splits);
5128  for (node = splits; node && !gnc_get_abort_scrub (); node = node->next, curr_split_no++)
5129  {
5130  Split* split = node->data;
5131 
5132  if (!split) continue;
5133 
5134  PINFO ("Start processing split %d of %d",
5135  curr_split_no + 1, split_count);
5136 
5137  scrub_split (split);
5138 
5139  PINFO ("Finished processing split %d of %d",
5140  curr_split_no + 1, split_count);
5141 
5142  if (curr_split_no % 10 == 0)
5143  {
5144  char* progress_msg = g_strdup_printf (message, curr_split_no, split_count);
5145  gnc_window_show_progress (progress_msg, (100 * curr_split_no) / split_count);
5146  g_free (progress_msg);
5147  }
5148  }
5149 
5150  g_signal_handler_disconnect (G_OBJECT(window), scrub_kp_handler_ID);
5151  gnc_window_show_progress (NULL, -1.0);
5152  is_scrubbing = FALSE;
5153  show_abort_verify = TRUE;
5154  gnc_set_abort_scrub (FALSE);
5155 
5156  gnc_resume_gui_refresh();
5157  LEAVE (" ");
5158 }
5159 
5160 static void
5161 gnc_plugin_page_register_cmd_account_report (GtkAction* action,
5162  GncPluginPageRegister* plugin_page)
5163 {
5165  GncMainWindow* window;
5166  int id;
5167 
5168  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
5169 
5170  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
5171 
5172  window = GNC_MAIN_WINDOW (GNC_PLUGIN_PAGE (plugin_page)->window);
5173  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
5174  id = report_helper (priv->ledger, NULL, NULL);
5175  if (id >= 0)
5176  gnc_main_window_open_report (id, window);
5177  LEAVE (" ");
5178 }
5179 
5180 static void
5181 gnc_plugin_page_register_cmd_transaction_report (GtkAction* action,
5182  GncPluginPageRegister* plugin_page)
5183 {
5185  GncMainWindow* window;
5186  SplitRegister* reg;
5187  Split* split;
5188  Query* query;
5189  int id;
5190 
5191 
5192  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
5193 
5194  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
5195 
5196  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
5197  reg = gnc_ledger_display_get_split_register (priv->ledger);
5198 
5200  if (!split)
5201  return;
5202 
5203  query = qof_query_create_for (GNC_ID_SPLIT);
5204 
5205  qof_query_set_book (query, gnc_get_current_book());
5206 
5207  xaccQueryAddGUIDMatch (query, xaccSplitGetGUID (split),
5208  GNC_ID_SPLIT, QOF_QUERY_AND);
5209 
5210  window = GNC_MAIN_WINDOW (GNC_PLUGIN_PAGE (plugin_page)->window);
5211  id = report_helper (priv->ledger, split, query);
5212  if (id >= 0)
5213  gnc_main_window_open_report (id, window);
5214  LEAVE (" ");
5215 }
5216 
5217 /************************************************************/
5218 /* Auxiliary functions */
5219 /************************************************************/
5220 
5221 void
5223  gint lines_default,
5224  gboolean read_only)
5225 {
5226  GncPluginPageRegister* page;
5228 
5229  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
5230 
5231  page = GNC_PLUGIN_PAGE_REGISTER (plugin_page);
5232  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
5233  priv->lines_default = lines_default;
5234  priv->read_only = read_only;
5235 }
5236 
5237 GNCSplitReg*
5239 {
5240  GncPluginPageRegister* page;
5242 
5243  g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page), NULL);
5244 
5245  page = GNC_PLUGIN_PAGE_REGISTER (plugin_page);
5246  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
5247 
5248  return priv->gsr;
5249 }
5250 
5251 static void
5252 gnc_plugin_page_help_changed_cb (GNCSplitReg* gsr,
5253  GncPluginPageRegister* register_page)
5254 {
5256  SplitRegister* reg;
5257  GncWindow* window;
5258  char* help;
5259 
5260  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (register_page));
5261 
5262  window = GNC_WINDOW (GNC_PLUGIN_PAGE (register_page)->window);
5263  if (!window)
5264  {
5265  // This routine can be called before the page is added to a
5266  // window.
5267  return;
5268  }
5269 
5270  /* Get the text from the ledger */
5271  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (register_page);
5272  reg = gnc_ledger_display_get_split_register (priv->ledger);
5273  help = gnc_table_get_help (reg->table);
5274  gnc_window_set_status (window, GNC_PLUGIN_PAGE (register_page), help);
5275  g_free (help);
5276 }
5277 
5278 static void
5279 gnc_plugin_page_popup_menu_cb (GNCSplitReg* gsr,
5280  GncPluginPageRegister* register_page)
5281 {
5282  GncWindow* window;
5283 
5284  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (register_page));
5285 
5286  window = GNC_WINDOW (GNC_PLUGIN_PAGE (register_page)->window);
5287  if (!window)
5288  {
5289  // This routine can be called before the page is added to a
5290  // window.
5291  return;
5292  }
5293  gnc_main_window_popup_menu_cb (GTK_WIDGET (window),
5294  GNC_PLUGIN_PAGE (register_page));
5295 }
5296 
5297 static void
5298 gnc_plugin_page_register_refresh_cb (GHashTable* changes, gpointer user_data)
5299 {
5300  GncPluginPageRegister* page = user_data;
5302 
5303  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
5304  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
5305 
5306  if (changes)
5307  {
5308  const EventInfo* ei;
5309  ei = gnc_gui_get_entity_events (changes, &priv->key);
5310  if (ei)
5311  {
5312  if (ei->event_mask & QOF_EVENT_DESTROY)
5313  {
5314  gnc_main_window_close_page (GNC_PLUGIN_PAGE (page));
5315  return;
5316  }
5317  if (ei->event_mask & QOF_EVENT_MODIFY)
5318  {
5319  }
5320  }
5321  }
5322  else
5323  {
5324  /* forced updates */
5325  gnucash_register_refresh_from_prefs (priv->gsr->reg);
5326  gtk_widget_queue_draw (priv->widget);
5327  }
5328 
5329  gnc_plugin_page_register_ui_update (NULL, page);
5330 }
5331 
5332 static void
5333 gnc_plugin_page_register_close_cb (gpointer user_data)
5334 {
5335  GncPluginPage* plugin_page = GNC_PLUGIN_PAGE (user_data);
5336  gnc_main_window_close_page (plugin_page);
5337 }
5338 
5347 static void
5348 gppr_account_destroy_cb (Account* account)
5349 {
5350  GncPluginPageRegister* page;
5352  GNCLedgerDisplayType ledger_type;
5353  const GncGUID* acct_guid;
5354  const GList* citem;
5355  GList* item, *kill = NULL;
5356 
5357  acct_guid = xaccAccountGetGUID (account);
5358 
5359  /* Find all windows that need to be killed. Don't kill them yet, as
5360  * that would affect the list being walked.*/
5361  citem = gnc_gobject_tracking_get_list (GNC_PLUGIN_PAGE_REGISTER_NAME);
5362  for (; citem; citem = g_list_next (citem))
5363  {
5364  page = (GncPluginPageRegister*)citem->data;
5365  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
5366  ledger_type = gnc_ledger_display_type (priv->ledger);
5367  if (ledger_type == LD_GL)
5368  {
5369  kill = g_list_prepend (kill, page);
5370  /* kill it */
5371  }
5372  else if ((ledger_type == LD_SINGLE) || (ledger_type == LD_SUBACCOUNT))
5373  {
5374  if (guid_compare (acct_guid, &priv->key) == 0)
5375  {
5376  kill = g_list_prepend (kill, page);
5377  }
5378  }
5379  }
5380 
5381  kill = g_list_reverse (kill);
5382  /* Now kill them. */
5383  for (item = kill; item; item = g_list_next (item))
5384  {
5385  page = (GncPluginPageRegister*)item->data;
5386  gnc_main_window_close_page (GNC_PLUGIN_PAGE (page));
5387  }
5388  g_list_free (kill);
5389 }
5390 
5405 static void
5406 gnc_plugin_page_register_event_handler (QofInstance* entity,
5407  QofEventId event_type,
5408  GncPluginPageRegister* page,
5409  GncEventData* ed)
5410 {
5411  Transaction* trans;
5412  QofBook* book;
5413  GncPluginPage* visible_page;
5414  GtkWidget* window;
5415  gchar* label, *color;
5416 
5417  g_return_if_fail (page); /* Required */
5418  if (!GNC_IS_TRANS (entity) && !GNC_IS_ACCOUNT (entity))
5419  return;
5420 
5421  ENTER ("entity %p of type %d, page %p, event data %p",
5422  entity, event_type, page, ed);
5423 
5424  window = gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page));
5425 
5426  if (GNC_IS_ACCOUNT (entity))
5427  {
5428  if (GNC_IS_MAIN_WINDOW (window))
5429  {
5430  label = gnc_plugin_page_register_get_tab_name (GNC_PLUGIN_PAGE (page));
5431  main_window_update_page_name (GNC_PLUGIN_PAGE (page), label);
5432  color = gnc_plugin_page_register_get_tab_color (GNC_PLUGIN_PAGE (page));
5433  main_window_update_page_color (GNC_PLUGIN_PAGE (page), color);
5434  // update page icon if read only registers
5435  gnc_plugin_page_register_update_page_icon (GNC_PLUGIN_PAGE (page));
5436 
5437  g_free (color);
5438  g_free (label);
5439  }
5440  LEAVE ("tab name updated");
5441  return;
5442  }
5443 
5444  if (! (event_type & (QOF_EVENT_MODIFY | QOF_EVENT_DESTROY)))
5445  {
5446  LEAVE ("not a modify");
5447  return;
5448  }
5449  trans = GNC_TRANS (entity);
5450  book = qof_instance_get_book (QOF_INSTANCE (trans));
5451  if (!gnc_plugin_page_has_book (GNC_PLUGIN_PAGE (page), book))
5452  {
5453  LEAVE ("not in this book");
5454  return;
5455  }
5456 
5457  if (GNC_IS_MAIN_WINDOW (window))
5458  {
5459  visible_page = gnc_main_window_get_current_page (GNC_MAIN_WINDOW (window));
5460  if (visible_page != GNC_PLUGIN_PAGE (page))
5461  {
5462  LEAVE ("page not visible");
5463  return;
5464  }
5465  }
5466 
5467  gnc_plugin_page_register_ui_update (NULL, page);
5468  LEAVE (" ");
5469  return;
5470 }
5471 
5472 
CursorClass gnc_split_register_get_current_cursor_class(SplitRegister *reg)
Returns the class of a register&#39;s current cursor.
Split * gnc_split_register_get_current_trans_split(SplitRegister *reg, VirtualCellLocation *trans_split_loc)
Gets the anchoring split of the transaction at the current cursor location, which may be on the trans...
void gnc_ledger_display_close(GNCLedgerDisplay *ld)
close the window
GncPluginPage * gnc_plugin_page_register_new(Account *account, gboolean subaccounts)
Create a new "register" plugin page, given a pointer to an account.
Functions to load, save and get gui state.
gint xaccSplitOrder(const Split *sa, const Split *sb)
The xaccSplitOrder(sa,sb) method is useful for sorting.
Definition: Split.c:1504
GtkWidget * gnc_plugin_page_get_window(GncPluginPage *page)
Retrieve a pointer to the GncMainWindow (GtkWindow) containing this page.
gboolean xaccTransHasReconciledSplits(const Transaction *trans)
FIXME: document me.
Definition: Transaction.c:2694
void gnc_ledger_display_refresh(GNCLedgerDisplay *ld)
redisplay/redraw only the indicated window.
const gchar * tab_icon
The relative name of the icon that should be shown on the tab for this page.
const char * gnc_split_register_get_credit_string(SplitRegister *reg)
Return the credit string used in the register.
gboolean(* focus_page_function)(GncPluginPage *plugin_page)
This function performs specific actions to set the focus on a specific widget.
void xaccTransSetDatePostedSecsNormalized(Transaction *trans, time64 time)
This function sets the posted date of the transaction, specified by a time64 (see ctime(3))...
void(* focus_page)(GncPluginPage *plugin_page, gboolean on_current_page)
Perform plugin specific actions to set the focus.
void gnc_plugin_page_register_filter_save_cb(GtkToggleButton *button, GncPluginPageRegister *page)
This function is called whenever the save status is checked or unchecked.
time64 xaccTransGetDate(const Transaction *trans)
Retrieve the posted date of the transaction.
The instance data structure for a content plugin.
const GList * gnc_gobject_tracking_get_list(const gchar *name)
Get a list of all known objects of a specified type.
void gnc_plugin_page_register_filter_days_changed_cb(GtkSpinButton *button, GncPluginPageRegister *page)
This function is called when the "number of days" spin button is changed which is then saved and upda...
gboolean xaccTransIsReadonlyByPostedDate(const Transaction *trans)
Returns TRUE if this Transaction is read-only because its posted-date is older than the "auto-readonl...
Definition: Transaction.c:2606
Date and Time handling routines.
gulong gnc_prefs_register_cb(const char *group, const gchar *pref_name, gpointer func, gpointer user_data)
Register a callback that gets triggered when the given preference changes.
Definition: gnc-prefs.c:128
gboolean gnc_split_register_save(SplitRegister *reg, gboolean do_commit)
Copy the contents of the current cursor to a split.
This file contains the functions to present a gui to the user for creating a new account or editing a...
gchar * gnc_g_list_stringjoin(GList *list_of_strings, const gchar *sep)
Return a string joining a GList whose elements are gchar* strings.
void gnc_split_register_unvoid_current_trans(SplitRegister *reg)
Unvoids the transaction associated with the current cursor, if non-NULL.
QofBook * qof_instance_get_book(gconstpointer inst)
Return the book pointer.
gboolean xaccAccountIsPriced(const Account *acc)
Returns true if the account is a stock, mutual fund or currency, otherwise false. ...
Definition: Account.cpp:4712
void(* QofEventHandler)(QofInstance *ent, QofEventId event_type, gpointer handler_data, gpointer event_data)
Handler invoked when an event is generated.
Definition: qofevent.h:89
void gnc_split_register_expand_current_trans(SplitRegister *reg, gboolean expand)
Expand the current transaction if it is collapsed.
utility functions for the GnuCash UI
#define PINFO(format, args...)
Print an informational note.
Definition: qoflog.h:256
void qof_query_purge_terms(QofQuery *q, QofQueryParamList *param_list)
Remove query terms of a particular type from q.
Definition: qofquery.cpp:689
GNCAccountType xaccAccountGetType(const Account *acc)
Returns the account&#39;s account type.
Definition: Account.cpp:3279
Transaction * gnc_split_register_get_current_trans(SplitRegister *reg)
Gets the transaction at the current cursor location, which may be on the transaction itself or on any...
GncPluginPage *(* recreate_page)(GtkWidget *window, GKeyFile *file, const gchar *group)
Create a new page based on the information saved during a previous instantiation of gnucash...
gint gnc_state_drop_sections_for(const gchar *partial_name)
Drop all sections from the state file whose name contains partial_name.
Definition: gnc-state.c:260
const char * xaccTransGetReadOnly(Transaction *trans)
Returns a non-NULL value if this Transaction was marked as read-only with some specific "reason" text...
Definition: Transaction.c:2567
#define DEBUG(format, args...)
Print a debugging message.
Definition: qoflog.h:264
const gchar * gnc_plugin_page_get_page_name(GncPluginPage *page)
Retrieve the name of this page.
gboolean string_to_guid(const gchar *string, GncGUID *guid)
Given a string, replace the given guid with the parsed one unless the given value is null...
Functions that are supported by all types of windows.
void gnc_features_set_used(QofBook *book, const gchar *feature)
Indicate that the current book uses the given feature.
Definition: gnc-features.c:135
gboolean gnc_commodity_equal(const gnc_commodity *a, const gnc_commodity *b)
This routine returns TRUE if the two commodities are equal.
gpointer gnc_account_foreach_descendant_until(const Account *acc, AccountCb2 thunk, gpointer user_data)
This method will traverse all children of this accounts and their descendants, calling &#39;func&#39; on each...
Definition: Account.cpp:3253
const char * xaccPrintAmount(gnc_numeric val, GNCPrintAmountInfo info)
Make a string representation of a gnc_numeric.
Definition: gnc-ui-util.c:1859
A structure for defining alternate action names for use in the toolbar.
Definition: gnc-plugin.h:228
void gnc_plugin_page_register_sort_response_cb(GtkDialog *dialog, gint response, GncPluginPageRegister *plugin_page)
This function is called when the "Sort By..." dialog is closed.
QofQuery * qof_query_copy(QofQuery *q)
Make a copy of the indicated query.
Definition: qofquery.cpp:1002
gboolean qof_query_equal(const QofQuery *q1, const QofQuery *q2)
Compare two queries for equality.
Definition: qofquery.cpp:1455
void gnc_plugin_page_register_filter_status_all_cb(GtkButton *button, GncPluginPageRegister *plugin_page)
This function is called whenever the "select all" status button is clicked.
Account * gnc_ledger_display_leader(GNCLedgerDisplay *ld)
Implementations.
void gnc_plugin_page_set_page_long_name(GncPluginPage *page, const char *name)
Set the long name of this page.
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
void gnc_tm_get_today_start(struct tm *tm)
The gnc_tm_get_today_start() routine takes a pointer to a struct tm and fills it in with the first se...
Definition: gnc-date.cpp:1332
gchar * guid_to_string_buff(const GncGUID *guid, gchar *str)
The guid_to_string_buff() routine puts a null-terminated string encoding of the id into the memory po...
Definition: guid.cpp:174
void gnc_ledger_display_set_query(GNCLedgerDisplay *ledger_display, Query *q)
Set the query used for a register.
#define PERR(format, args...)
Log a serious error.
Definition: qoflog.h:244
GtkActionGroup * gnc_plugin_page_get_action_group(GncPluginPage *page)
Retrieve the GtkActionGroup object associated with this page.
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
Cleanup functions for business objects.
gnc_numeric gncInvoiceGetTotal(GncInvoice *invoice)
Return the "total" amount of the invoice as seen on the document (and shown to the user in the report...
Definition: gncInvoice.c:1026
GKeyFile * gnc_state_get_current(void)
Returns a pointer to the most recently loaded state.
Definition: gnc-state.c:248
void gnc_ui_edit_account_window(GtkWindow *parent, Account *account)
Display a window for editing the attributes of an existing account.
gboolean gnc_split_register_current_trans_expanded(SplitRegister *reg)
Return TRUE if current trans is expanded and style is REG_STYLE_LEDGER.
GncPluginPage * gnc_main_window_get_current_page(GncMainWindow *window)
Retrieve a pointer to the page that is currently at the front of the specified window.
const char * xaccTransGetDocLink(const Transaction *trans)
Gets the transaction Document Link.
Definition: Transaction.c:2417
void gnc_main_window_open_page(GncMainWindow *window, GncPluginPage *page)
Display a data plugin page in a window.
Query * gnc_ledger_display_get_query(GNCLedgerDisplay *ld)
return the query associated with a ledger
Functions for adding content to a window.
GncPluginPage * gnc_plugin_page_register_new_ledger(GNCLedgerDisplay *ledger)
Create a new "register" plugin page, given a pointer to an already created ledger.
void(* update_edit_menu_actions)(GncPluginPage *plugin_page, gboolean hide)
This function vector allows page specific actions to override the generic code for setting the sensit...
#define VREC
split is void
Definition: Split.h:75
void(* destroy_widget)(GncPluginPage *plugin_page)
Function called to destroy the display widget for a particular type of plugin.
gint qof_event_register_handler(QofEventHandler handler, gpointer user_data)
Register a handler for events.
Definition: qofevent.cpp:73
void gnc_tm_free(struct tm *time)
free a struct tm* created with gnc_localtime() or gnc_gmtime()
Definition: gnc-date.cpp:99
const char * xaccAccountGetColor(const Account *acc)
Get the account&#39;s color.
Definition: Account.cpp:3370
void gnc_plugin_page_register_filter_select_range_cb(GtkRadioButton *button, GncPluginPageRegister *page)
This function is called when the radio buttons changes state.
GNCLedgerDisplay * gnc_ledger_display_subaccounts(Account *account, gboolean mismatched_commodities)
opens up a register window to display the parent account and all of its children. ...
#define xaccAccountGetGUID(X)
Definition: Account.h:248
void gnc_set_abort_scrub(gboolean abort)
The gnc_set_abort_scrub () method causes a currently running scrub operation to stop, if abort is TRUE; gnc_set_abort_scrub(FALSE) must be called before any scrubbing operation.
Definition: Scrub.c:72
void gnc_plugin_page_register_sort_button_cb(GtkToggleButton *button, GncPluginPageRegister *page)
This function is called when a radio button in the "Sort By..." dialog is clicked.
convert single-entry accounts to clean double-entry
char * qof_print_date(time64 secs)
Convenience; calls through to qof_print_date_dmy_buff().
Definition: gnc-date.cpp:617
gboolean xaccTransHasSplitsInState(const Transaction *trans, const char state)
FIXME: document me.
Definition: Transaction.c:2724
QofBook * qof_session_get_book(const QofSession *session)
Returns the QofBook of this session.
Definition: qofsession.cpp:578
gchar * gnc_account_get_full_name(const Account *account)
The gnc_account_get_full_name routine returns the fully qualified name of the account using the given...
Definition: Account.cpp:3308
void gnc_split_register_redraw(SplitRegister *reg)
Causes a redraw of the register window associated with reg.
Functions providing a register page for the GnuCash UI.
const char * gnc_split_register_get_debit_string(SplitRegister *reg)
Return the debit string used in the register.
void main_window_update_page_color(GncPluginPage *page, const gchar *color_in)
Update the color on the page tabs in the main window.
The class data structure for a content plugin.
void qof_query_destroy(QofQuery *query)
Frees the resources associate with a Query object.
gint QofEventId
Define the type of events allowed.
Definition: qofevent.h:45
Gobject helper routines.
void gnc_plugin_page_register_filter_end_cb(GtkWidget *radio, GncPluginPageRegister *page)
This function is called when one of the end date radio buttons is selected.
void gnc_plugin_page_set_use_new_window(GncPluginPage *page, gboolean use_new)
Set the "use new window" setting associated with this page.
CursorClass
Types of cursors.
gboolean guid_equal(const GncGUID *guid_1, const GncGUID *guid_2)
Given two GUIDs, return TRUE if they are non-NULL and equal.
Definition: guid.cpp:204
#define GUID_ENCODING_LENGTH
Number of characters needed to encode a guid as a string not including the null terminator.
Definition: guid.h:84
Transaction * gnc_plugin_page_register_get_current_txn(GncPluginPageRegister *page)
Get the currently selected transaction in this register page.
Account * gnc_plugin_page_register2_get_account(GncPluginPageRegister2 *page)
Get the Account associated with this register page.
gboolean gnc_split_register_changed(SplitRegister *reg)
Returns TRUE if the register has changed cells.
void xaccTransScrubImbalance(Transaction *trans, Account *root, Account *account)
Correct transaction imbalances.
Definition: Scrub.c:794
void gnc_plugin_page_disconnect_page_changed(GncPluginPage *page)
Disconnect the page_changed_id signal callback.
void gnc_plugin_init_short_names(GtkActionGroup *action_group, action_toolbar_labels *toolbar_labels)
Add "short" labels to existing actions.
Definition: gnc-plugin.c:234
gboolean gncScrubBusinessSplit(Split *split)
The gncScrubBusinessSplit() function will fix all issues found with the given split.
void gnc_plugin_page_register_filter_start_cb(GtkWidget *radio, GncPluginPageRegister *page)
This function is called when one of the start date radio buttons is selected.
Functions providing menu items from scheme code.
void qof_query_set_book(QofQuery *query, QofBook *book)
Set the book to be searched.
gboolean gnc_plugin_page_has_book(GncPluginPage *page, QofBook *book)
Query a page to see if it has a reference to a given book.
void(* window_changed)(GncPluginPage *plugin_page, GtkWidget *window)
Perform plugin specific actions when a page is added to a window (or has been removed from one window...
gboolean gnc_main_window_popup_menu_cb(GtkWidget *widget, GncPluginPage *page)
Callback function invoked when the user requests that Gnucash popup the contextual menu via the keybo...
time64 gnc_time64_get_day_start(time64 time_val)
The gnc_time64_get_day_start() routine will take the given time in seconds and adjust it to the first...
Definition: gnc-date.cpp:1299
void gnc_plugin_page_register_filter_response_cb(GtkDialog *dialog, gint response, GncPluginPageRegister *plugin_page)
This function is called when the "Filter By..." dialog is closed.
const gchar * plugin_name
The textual name of this plugin.
void gnc_split_register_config(SplitRegister *reg, SplitRegisterType newtype, SplitRegisterStyle newstyle, gboolean use_double_line)
Sets a split register&#39;s type, style or line use.
void qof_event_unregister_handler(gint handler_id)
Unregister an event handler.
Definition: qofevent.cpp:103
GtkWidget *(* create_widget)(GncPluginPage *plugin_page)
Function called to create the display widget for a particular type of plugin.
time64 gnc_time64_get_today_start(void)
The gnc_time64_get_today_start() routine returns a time64 value corresponding to the first second of ...
Definition: gnc-date.cpp:1344
Account * gnc_account_lookup_by_full_name(const Account *any_acc, const gchar *name)
The gnc_account_lookup_full_name() subroutine works like gnc_account_lookup_by_name, but uses fully-qualified names using the given separator.
Definition: Account.cpp:3163
void gnc_split_register_void_current_trans(SplitRegister *reg, const char *reason)
Voids the transaction associated with the current cursor, if non-NULL.
time64 gnc_mktime(struct tm *time)
calculate seconds from the epoch given a time struct
Definition: gnc-date.cpp:230
void xaccTransScrubOrphans(Transaction *trans)
The xaccTransScrubOrphans() method scrubs only the splits in the given transaction.
Definition: Scrub.c:178
Gnome specific utility functions.
Public declarations of GnucashRegister class.
gboolean xaccAccountIsAPARType(GNCAccountType t)
Convenience function to check if the account is a valid business account type (meaning an Accounts Pa...
Definition: Account.cpp:4688
Additional event handling code.
#define xaccSplitGetGUID(X)
Definition: Split.h:554
struct tm * gnc_localtime(const time64 *secs)
fill out a time struct from a 64-bit time value.
Definition: gnc-date.cpp:105
gboolean(* finish_pending)(GncPluginPage *plugin_page)
This function vector is called to finish any outstanding activities.
SplitList * xaccTransGetAPARAcctSplitList(const Transaction *trans, gboolean strict)
The xaccTransGetAPARSplitList() method returns a GList of the splits in a transaction that belong to ...
Definition: Transaction.c:2333
All type declarations for the whole Gnucash engine.
#define CREC
The Split has been cleared.
Definition: Split.h:71
void(* save_page)(GncPluginPage *page, GKeyFile *file, const gchar *group)
Save enough information about this page so that it can be recreated next time the user starts gnucash...
gnc_commodity * gnc_account_get_currency_or_parent(const Account *account)
Returns a gnc_commodity that is a currency, suitable for being a Transaction&#39;s currency.
Definition: Account.cpp:3455
void gnc_plugin_page_register_filter_status_one_cb(GtkToggleButton *button, GncPluginPageRegister *page)
This function is called whenever one of the status entries is checked or unchecked.
GLib helper routines.
Generic api to store and retrieve preferences.
Split * gnc_split_register_duplicate_current(SplitRegister *reg)
Duplicates either the current transaction or the current split depending on the register mode and cur...
Query * gnc_plugin_page_register_get_query(GncPluginPage *plugin_page)
This function is called to get the query associated with this plugin page.
void gnc_split_register_cancel_cursor_trans_changes(SplitRegister *reg)
Cancels any changes made to the current pending transaction, reloads the table from the engine...
GncInvoice * gncInvoiceGetInvoiceFromLot(GNCLot *lot)
Given a LOT, find and return the Invoice attached to the lot.
Definition: gncInvoice.c:1307
void gnc_split_register_paste_current(SplitRegister *reg)
Pastes a previous copied entity onto the current entity, but only if the copied and current entity ha...
Transaction * xaccTransReverse(Transaction *orig)
xaccTransReverse creates a Transaction that reverses the given transaction by inverting all the numer...
Definition: Transaction.c:2868
GList * qof_query_run(QofQuery *query)
Perform the query, return the results.
void main_window_update_page_set_read_only_icon(GncPluginPage *page, gboolean read_only)
Update the icon on the page tabs in the main window.
gboolean qof_book_is_readonly(const QofBook *book)
Return whether the book is read only.
Definition: qofbook.cpp:580
GtkAction * gnc_plugin_page_get_action(GncPluginPage *page, const gchar *name)
Retrieve a GtkAction object associated with this page.
void gnc_plugin_page_set_page_color(GncPluginPage *page, const char *color)
Set the color of this page.
GncPluginPage * gnc_plugin_page_register_new_gl(void)
Create a new "register" plugin page containing a general journal.
void gnc_plugin_update_actions(GtkActionGroup *action_group, const gchar **action_names, const gchar *property_name, gboolean value)
Update a property on a set of existing GtkActions.
Definition: gnc-plugin.c:280
GNCLedgerDisplay * gnc_ledger_display_simple(Account *account)
opens up a register window to display a single account
gboolean gncScrubBusinessLot(GNCLot *lot)
The gncScrubBusinessLot() function makes sure that the indicated lot has all the correct properties r...
Account * xaccSplitGetAccount(const Split *split)
Returns the account of this split, which was set through xaccAccountInsertSplit().
Definition: gmock-Split.cpp:53
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Get the account&#39;s commodity.
Definition: Account.cpp:3448
const GncGUID * guid_null(void)
Returns a GncGUID which is guaranteed to never reference any entity.
Definition: guid.cpp:131
time64 gnc_time64_get_today_end(void)
The gnc_time64_get_today_end() routine returns a time64 value corresponding to the last second of tod...
Definition: gnc-date.cpp:1353
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Get a boolean value from the preferences backend.
void gnc_plugin_page_inserted_cb(GncPluginPage *page, gpointer user_data)
Set up the page_changed callback for when the current page is changed.
void gnc_main_window_close_page(GncPluginPage *page)
Remove a data plugin page from a window and display the previous page.
Transaction * xaccTransGetReversedBy(const Transaction *trans)
Returns the transaction that reversed the given transaction.
Definition: Transaction.c:2908
Split * xaccSplitGetOtherSplit(const Split *split)
The xaccSplitGetOtherSplit() is a convenience routine that returns the other of a pair of splits...
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
void gnc_plugin_page_set_page_name(GncPluginPage *page, const char *name)
Set the name of this page.
time64 gnc_time(time64 *tbuf)
get the current local time
Definition: gnc-date.cpp:273
Account * gnc_plugin_page_register_get_account(GncPluginPageRegister *page)
Get the Account associated with this register page.
void gnc_plugin_page_add_book(GncPluginPage *page, QofBook *book)
Add a book reference to the specified page.
gint64 time64
Many systems, including Microsoft Windows and BSD-derived Unixes like Darwin, are retaining the int-3...
Definition: gnc-date.h:93
GtkActionGroup * gnc_plugin_page_create_action_group(GncPluginPage *page, const gchar *group_name)
Create the GtkActionGroup object associated with this page.
void gnc_plugin_page_register_sort_order_save_cb(GtkToggleButton *button, GncPluginPageRegister *page)
This function is called whenever the save sort order is checked or unchecked which allows saving of t...
The instance data structure for a main window object.
gboolean gnc_split_register_handle_exchange(SplitRegister *reg, gboolean force_dialog)
If needed display the transfer dialog to get a price/exchange rate and adjust the price cell accordin...
void gnc_plugin_page_register_clear_current_filter(GncPluginPage *plugin_page)
This function clears the registers current filter.
void xaccTransSetDateEnteredSecs(Transaction *trans, time64 secs)
Modify the date of when the transaction was entered.
Definition: Transaction.c:2052
GNCLedgerDisplay * gnc_ledger_display_gl(void)
opens up a general ledger window
time64 gnc_time64_get_day_end(time64 time_val)
The gnc_time64_get_day_end() routine will take the given time in seconds and adjust it to the last se...
Definition: gnc-date.cpp:1319
SplitRegister * gnc_ledger_display_get_split_register(GNCLedgerDisplay *ld)
return the split register associated with a ledger display
const char * xaccAccountGetName(const Account *acc)
Get the account&#39;s name.
Definition: Account.cpp:3301
void gnc_plugin_set_important_actions(GtkActionGroup *action_group, const gchar **name)
Mark certain actions as "important".
Definition: gnc-plugin.c:256
The type used to store guids in C.
Definition: guid.h:75
GNCSplitReg * gnc_plugin_page_register_get_gsr(GncPluginPage *plugin_page)
Get the GNCSplitReg data structure associated with this register page.
void gnc_plugin_page_register_sort_order_reverse_cb(GtkToggleButton *button, GncPluginPageRegister *page)
This function is called whenever the reverse sort order is checked or unchecked which allows reversin...
void main_window_update_page_name(GncPluginPage *page, const gchar *name_in)
Update the name of the page in the main window.
Split * gnc_split_register_get_current_split(SplitRegister *reg)
Returns the split at which the cursor is currently located.
void gnc_plugin_page_register_set_options(GncPluginPage *plugin_page, gint lines_default, gboolean read_only)
Set various register options on a newly created "register" plugin page.
GtkWidget * summarybar
The summary bar widget (if any) that is associated with this plugin.
SplitRegisterStyle
Register styles.
GNCLot * xaccSplitGetLot(const Split *split)
Returns the pointer to the debited/credited Lot where this split belongs to, or NULL if it doesn&#39;t be...
Definition: Split.c:1885
GList * qof_query_get_books(QofQuery *q)
Return the list of books we&#39;re using.
Definition: qofquery.cpp:1324
void gnc_prefs_remove_cb_by_func(const gchar *group, const gchar *pref_name, gpointer func, gpointer user_data)
Remove a function that was registered for a callback when the given preference changed.
Definition: gnc-prefs.c:143
void gnc_split_register_copy_current(SplitRegister *reg)
Makes a copy of the current entity, either a split or a transaction, so that it can be pasted later...
Utility functions for file access.
Account * xaccAccountLookup(const GncGUID *guid, QofBook *book)
The xaccAccountLookup() subroutine will return the account associated with the given id...
Definition: Account.cpp:2050