GnuCash  4.12-68-g5dc52459a1+
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", "applications-utilities",
491  N_ ("Stock Ass_istant"), NULL, 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_priced_account[] =
628 {
629  "ActionsStockAssistantAction",
630  NULL
631 };
632 
634 static action_toolbar_labels toolbar_labels[] =
635 {
636  { "ActionsTransferAction", N_ ("Transfer") },
637  { "RecordTransactionAction", N_ ("Enter") },
638  { "CancelTransactionAction", N_ ("Cancel") },
639  { "DeleteTransactionAction", N_ ("Delete") },
640  { "DuplicateTransactionAction", N_ ("Duplicate") },
641  { "SplitTransactionAction", N_ ("Split") },
642  { "JumpTransactionAction", N_ ("Jump") },
643  { "ScheduleTransactionAction", N_ ("Schedule") },
644  { "BlankTransactionAction", N_ ("Blank") },
645  { "ActionsReconcileAction", N_ ("Reconcile") },
646  { "ActionsAutoClearAction", N_ ("Auto-clear") },
647  { "LinkTransactionAction", N_ ("Manage Document Link") },
648  { "LinkedTransactionOpenAction", N_ ("Open Linked Document") },
649  { "JumpLinkedInvoiceAction", N_ ("Invoice") },
650  { NULL, NULL },
651 };
652 
654 {
655  const char* action_name;
656  int value;
657  GtkWidget* widget;
658 };
659 
660 static struct status_action status_actions[] =
661 {
662  { "filter_status_reconciled", CLEARED_RECONCILED, NULL },
663  { "filter_status_cleared", CLEARED_CLEARED, NULL },
664  { "filter_status_voided", CLEARED_VOIDED, NULL },
665  { "filter_status_frozen", CLEARED_FROZEN, NULL },
666  { "filter_status_unreconciled", CLEARED_NO, NULL },
667  { NULL, 0, NULL },
668 };
669 
670 #define CLEARED_VALUE "cleared_value"
671 #define DEFAULT_FILTER "0x001f"
672 #define DEFAULT_SORT_ORDER "BY_STANDARD"
673 
674 /************************************************************/
675 /* Data Structures */
676 /************************************************************/
677 
679 {
680  GNCLedgerDisplay* ledger;
681  GNCSplitReg* gsr;
682 
683  GtkWidget* widget;
684 
685  gint event_handler_id;
686  gint component_manager_id;
687  GncGUID key; /* The guid of the Account we're watching */
688 
689  gint lines_default;
690  gboolean read_only;
691  gboolean page_focus;
692  gboolean enable_refresh; // used to reduce ledger display refreshes
693  Query* search_query; // saved search query for comparison
694  Query* filter_query; // saved filter query for comparison
695 
696  struct
697  {
698  GtkWidget* dialog;
699  GtkWidget* num_radio;
700  GtkWidget* act_radio;
701  SortType original_sort_type;
702  gboolean original_save_order;
703  gboolean save_order;
704  gboolean reverse_order;
705  gboolean original_reverse_order;
706  } sd;
707 
708  struct
709  {
710  GtkWidget* dialog;
711  GtkWidget* table;
712  GtkWidget* start_date_choose;
713  GtkWidget* start_date_today;
714  GtkWidget* start_date;
715  GtkWidget* end_date_choose;
716  GtkWidget* end_date_today;
717  GtkWidget* end_date;
718  GtkWidget* num_days;
719  cleared_match_t original_cleared_match;
720  cleared_match_t cleared_match;
721  time64 original_start_time;
722  time64 original_end_time;
723  time64 start_time;
724  time64 end_time;
725  gint days;
726  gint original_days;
727  gboolean original_save_filter;
728  gboolean save_filter;
729  } fd;
731 
732 G_DEFINE_TYPE_WITH_PRIVATE (GncPluginPageRegister, gnc_plugin_page_register,
733  GNC_TYPE_PLUGIN_PAGE)
734 
735 #define GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE(o) \
736  ((GncPluginPageRegisterPrivate*)gnc_plugin_page_register_get_instance_private((GncPluginPageRegister*)o))
737 
738 static GObjectClass* parent_class = NULL;
739 
740 /************************************************************/
741 /* Implementation */
742 /************************************************************/
743 
744 static GncPluginPage*
745 gnc_plugin_page_register_new_common (GNCLedgerDisplay* ledger)
746 {
747  GncPluginPageRegister* register_page;
749  GncPluginPage* plugin_page;
750  GNCSplitReg* gsr;
751  const GList* item;
752  GList* book_list;
753  gchar* label;
754  gchar* label_color;
755  QofQuery* q;
756 
757  // added for version 4.0 onwards
758  if (!gnc_features_check_used (gnc_get_current_book(), GNC_FEATURE_REG_SORT_FILTER))
759  gnc_features_set_used (gnc_get_current_book(), GNC_FEATURE_REG_SORT_FILTER);
760 
761  /* Is there an existing page? */
762  gsr = gnc_ledger_display_get_user_data (ledger);
763  if (gsr)
764  {
765  item = gnc_gobject_tracking_get_list (GNC_PLUGIN_PAGE_REGISTER_NAME);
766  for (; item; item = g_list_next (item))
767  {
768  register_page = (GncPluginPageRegister*)item->data;
769  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (register_page);
770  if (priv->gsr == gsr)
771  return GNC_PLUGIN_PAGE (register_page);
772  }
773  }
774 
775  register_page = g_object_new (GNC_TYPE_PLUGIN_PAGE_REGISTER, NULL);
776  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (register_page);
777  priv->ledger = ledger;
778  priv->key = *guid_null();
779 
780  plugin_page = GNC_PLUGIN_PAGE (register_page);
781  label = gnc_plugin_page_register_get_tab_name (plugin_page);
782  gnc_plugin_page_set_page_name (plugin_page, label);
783  g_free (label);
784 
785  label_color = gnc_plugin_page_register_get_tab_color (plugin_page);
786  gnc_plugin_page_set_page_color (plugin_page, label_color);
787  g_free (label_color);
788 
789  label = gnc_plugin_page_register_get_long_name (plugin_page);
790  gnc_plugin_page_set_page_long_name (plugin_page, label);
791  g_free (label);
792 
793  q = gnc_ledger_display_get_query (ledger);
794  book_list = qof_query_get_books (q);
795  for (item = book_list; item; item = g_list_next (item))
796  gnc_plugin_page_add_book (plugin_page, (QofBook*)item->data);
797  // Do not free the list. It is owned by the query.
798 
799  priv->component_manager_id = 0;
800  return plugin_page;
801 }
802 
803 static gpointer
804 gnc_plug_page_register_check_commodity (Account* account, void* usr_data)
805 {
806  // Check that account's commodity matches the commodity in usr_data
807  gnc_commodity* com0 = (gnc_commodity*) usr_data;
808  gnc_commodity* com1 = xaccAccountGetCommodity (account);
809  return gnc_commodity_equal (com1, com0) ? NULL : com1;
810 }
811 
813 gnc_plugin_page_register_new (Account* account, gboolean subaccounts)
814 {
815  GNCLedgerDisplay* ledger;
816  GncPluginPage* page;
818  gnc_commodity* com0;
819  gnc_commodity* com1;
820 
821  /*################## Added for Reg2 #################*/
822  const GList* item;
823  GncPluginPageRegister2* new_register_page;
824  /*################## Added for Reg2 #################*/
825 
826  ENTER ("account=%p, subaccounts=%s", account,
827  subaccounts ? "TRUE" : "FALSE");
828 
829  /*################## Added for Reg2 #################*/
830  // We test for the new register being open here, ie matching account guids
831  item = gnc_gobject_tracking_get_list (GNC_PLUGIN_PAGE_REGISTER2_NAME);
832  for (; item; item = g_list_next (item))
833  {
834  Account* new_account;
835  new_register_page = (GncPluginPageRegister2*)item->data;
836  new_account = gnc_plugin_page_register2_get_account (new_register_page);
837 
838  if (guid_equal (xaccAccountGetGUID (account),
839  xaccAccountGetGUID (new_account)))
840  {
841  GtkWindow* window = GTK_WINDOW (gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (
842  new_register_page)));
843  gnc_error_dialog (window, "%s",
844  _ ("You have tried to open an account in the old register while it is open in the new register."));
845  return NULL;
846  }
847  }
848  /*################## Added for Reg2 #################*/
849  com0 = gnc_account_get_currency_or_parent (account);
850  com1 = gnc_account_foreach_descendant_until (account,
851  gnc_plug_page_register_check_commodity, com0);
852 
853  if (subaccounts)
854  ledger = gnc_ledger_display_subaccounts (account, com1 != NULL);
855  else
856  ledger = gnc_ledger_display_simple (account);
857 
858  page = gnc_plugin_page_register_new_common (ledger);
859  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
860  priv->key = *xaccAccountGetGUID (account);
861 
862  LEAVE ("%p", page);
863  return page;
864 }
865 
868 {
869  GNCLedgerDisplay* ledger;
870 
871  ledger = gnc_ledger_display_gl();
872  return gnc_plugin_page_register_new_common (ledger);
873 }
874 
876 gnc_plugin_page_register_new_ledger (GNCLedgerDisplay* ledger)
877 {
878  return gnc_plugin_page_register_new_common (ledger);
879 }
880 
881 static void
882 gnc_plugin_page_register_class_init (GncPluginPageRegisterClass* klass)
883 {
884  GObjectClass* object_class = G_OBJECT_CLASS (klass);
885  GncPluginPageClass* gnc_plugin_class = GNC_PLUGIN_PAGE_CLASS (klass);
886 
887  parent_class = g_type_class_peek_parent (klass);
888 
889  object_class->finalize = gnc_plugin_page_register_finalize;
890 
891  gnc_plugin_class->tab_icon = GNC_ICON_ACCOUNT;
892  gnc_plugin_class->plugin_name = GNC_PLUGIN_PAGE_REGISTER_NAME;
893  gnc_plugin_class->create_widget = gnc_plugin_page_register_create_widget;
894  gnc_plugin_class->destroy_widget = gnc_plugin_page_register_destroy_widget;
895  gnc_plugin_class->window_changed = gnc_plugin_page_register_window_changed;
896  gnc_plugin_class->focus_page = gnc_plugin_page_register_focus;
897  gnc_plugin_class->save_page = gnc_plugin_page_register_save_page;
898  gnc_plugin_class->recreate_page = gnc_plugin_page_register_recreate_page;
899  gnc_plugin_class->update_edit_menu_actions =
900  gnc_plugin_page_register_update_edit_menu;
901  gnc_plugin_class->finish_pending = gnc_plugin_page_register_finish_pending;
902  gnc_plugin_class->focus_page_function = gnc_plugin_page_register_focus_widget;
903 
904  gnc_ui_register_account_destroy_callback (gppr_account_destroy_cb);
905 }
906 
907 static void
908 gnc_plugin_page_register_init (GncPluginPageRegister* plugin_page)
909 {
911  GncPluginPage* parent;
912  GtkActionGroup* action_group;
913  gboolean use_new;
914 
915  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
916 
917  /* Init parent declared variables */
918  parent = GNC_PLUGIN_PAGE (plugin_page);
919  use_new = gnc_prefs_get_bool (GNC_PREFS_GROUP_GENERAL_REGISTER,
920  GNC_PREF_USE_NEW);
921  g_object_set (G_OBJECT (plugin_page),
922  "page-name", _ ("General Journal"),
923  "page-uri", "default:",
924  "ui-description", "gnc-plugin-page-register-ui.xml",
925  "use-new-window", use_new,
926  NULL);
927 
928  /* Create menu and toolbar information */
929  action_group =
931  "GncPluginPageRegisterActions");
932  gtk_action_group_add_actions (action_group, gnc_plugin_page_register_actions,
933  gnc_plugin_page_register_n_actions, plugin_page);
934  gtk_action_group_add_toggle_actions (action_group,
935  toggle_entries, n_toggle_entries,
936  plugin_page);
937  gtk_action_group_add_radio_actions (action_group,
938  radio_entries_2, n_radio_entries_2,
939  REG_STYLE_LEDGER,
940  G_CALLBACK (gnc_plugin_page_register_cmd_style_changed),
941  plugin_page);
942 
943  gnc_plugin_init_short_names (action_group, toolbar_labels);
944  gnc_plugin_set_important_actions (action_group, important_actions);
945 
946  priv->lines_default = DEFAULT_LINES_AMOUNT;
947  priv->read_only = FALSE;
948  priv->fd.cleared_match = CLEARED_ALL;
949  priv->fd.days = 0;
950  priv->enable_refresh = TRUE;
951  priv->search_query = NULL;
952  priv->filter_query = NULL;
953 }
954 
955 static void
956 gnc_plugin_page_register_finalize (GObject* object)
957 {
958  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (object));
959 
960  ENTER ("object %p", object);
961 
962  G_OBJECT_CLASS (parent_class)->finalize (object);
963  LEAVE (" ");
964 }
965 
966 Account*
968 {
970  GNCLedgerDisplayType ledger_type;
971  Account* leader;
972 
973  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
974  ledger_type = gnc_ledger_display_type (priv->ledger);
975  leader = gnc_ledger_display_leader (priv->ledger);
976 
977  if ((ledger_type == LD_SINGLE) || (ledger_type == LD_SUBACCOUNT))
978  return leader;
979  return NULL;
980 }
981 
982 Transaction*
984 {
986  SplitRegister* reg;
987 
988  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
989  reg = gnc_ledger_display_get_split_register (priv->ledger);
991 }
992 
997 static gboolean
998 gnc_plugin_page_register_focus_widget (GncPluginPage* register_plugin_page)
999 {
1000  if (GNC_IS_PLUGIN_PAGE_REGISTER (register_plugin_page))
1001  {
1002  GNCSplitReg *gsr = gnc_plugin_page_register_get_gsr (GNC_PLUGIN_PAGE(register_plugin_page));
1003 
1004  gnc_plugin_page_register_ui_update (NULL, GNC_PLUGIN_PAGE_REGISTER(register_plugin_page));
1005 
1006  gnc_split_reg_focus_on_sheet (gsr);
1007  }
1008  return FALSE;
1009 }
1010 
1011 /* This is the list of actions which are switched inactive in a read-only book. */
1012 static const char* readonly_inactive_actions[] =
1013 {
1014  "EditCutAction",
1015  "EditPasteAction",
1016  "CutTransactionAction",
1017  "PasteTransactionAction",
1018  "DuplicateTransactionAction",
1019  "DeleteTransactionAction",
1020  "RemoveTransactionSplitsAction",
1021  "RecordTransactionAction",
1022  "CancelTransactionAction",
1023  "UnvoidTransactionAction",
1024  "VoidTransactionAction",
1025  "ReverseTransactionAction",
1026  "ActionsTransferAction",
1027  "ActionsReconcileAction",
1028  "ActionsStockSplitAction",
1029  "ScheduleTransactionAction",
1030  "ScrubAllAction",
1031  "ScrubCurrentAction",
1032  "LinkTransactionAction",
1033  NULL
1034 };
1035 
1036 /* This is the list of actions whose text needs to be changed based on whether */
1037 /* the current cursor class is transaction or split. */
1038 static const char* tran_vs_split_actions[] =
1039 {
1040  "CutTransactionAction",
1041  "CopyTransactionAction",
1042  "PasteTransactionAction",
1043  "DuplicateTransactionAction",
1044  "DeleteTransactionAction",
1045  NULL
1046 };
1047 
1048 /* This is the list of labels for when the current cursor class is transaction. */
1049 static const char* tran_action_labels[] =
1050 {
1051  CUT_TRANSACTION_LABEL,
1052  COPY_TRANSACTION_LABEL,
1053  PASTE_TRANSACTION_LABEL,
1054  DUPLICATE_TRANSACTION_LABEL,
1055  DELETE_TRANSACTION_LABEL,
1056  LINK_TRANSACTION_LABEL,
1057  LINK_TRANSACTION_OPEN_LABEL,
1058  JUMP_LINKED_INVOICE_LABEL,
1059  NULL
1060 };
1061 
1062 /* This is the list of tooltips for when the current cursor class is transaction. */
1063 static const char* tran_action_tips[] =
1064 {
1065  CUT_TRANSACTION_TIP,
1066  COPY_TRANSACTION_TIP,
1067  PASTE_TRANSACTION_TIP,
1068  DUPLICATE_TRANSACTION_TIP,
1069  DELETE_TRANSACTION_TIP,
1070  LINK_TRANSACTION_TIP,
1071  LINK_TRANSACTION_OPEN_TIP,
1072  JUMP_LINKED_INVOICE_TIP,
1073  NULL
1074 };
1075 
1076 /* This is the list of labels for when the current cursor class is split. */
1077 static const char* split_action_labels[] =
1078 {
1079  CUT_SPLIT_LABEL,
1080  COPY_SPLIT_LABEL,
1081  PASTE_SPLIT_LABEL,
1082  DUPLICATE_SPLIT_LABEL,
1083  DELETE_SPLIT_LABEL,
1084  NULL
1085 };
1086 
1087 /* This is the list of tooltips for when the current cursor class is split. */
1088 static const char* split_action_tips[] =
1089 {
1090  CUT_SPLIT_TIP,
1091  COPY_SPLIT_TIP,
1092  PASTE_SPLIT_TIP,
1093  DUPLICATE_SPLIT_TIP,
1094  DELETE_SPLIT_TIP,
1095  NULL
1096 };
1097 
1098 static void
1099 gnc_plugin_page_register_ui_update (gpointer various,
1100  GncPluginPageRegister* page)
1101 {
1103  SplitRegister* reg;
1104  GtkAction* action;
1105  gboolean expanded, voided, read_only = FALSE, read_only_reg = FALSE;
1106  Transaction* trans;
1107  GList* invoices;
1108  CursorClass cursor_class;
1109  const char* uri;
1110 
1111  /* Set 'Split Transaction' */
1112  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
1113  reg = gnc_ledger_display_get_split_register (priv->ledger);
1114  cursor_class = gnc_split_register_get_current_cursor_class (reg);
1116  action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page),
1117  "SplitTransactionAction");
1118  gtk_action_set_sensitive (action, reg->style == REG_STYLE_LEDGER);
1119  g_signal_handlers_block_by_func
1120  (action, gnc_plugin_page_register_cmd_expand_transaction, page);
1121  gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), expanded);
1122  g_signal_handlers_unblock_by_func
1123  (action, gnc_plugin_page_register_cmd_expand_transaction, page);
1124 
1125  /* If we are in a readonly book, or possibly a place holder
1126  * account register make any modifying action inactive */
1127  if (qof_book_is_readonly (gnc_get_current_book()) ||
1128  gnc_split_reg_get_read_only (priv->gsr))
1129  read_only_reg = TRUE;
1130 
1131  /* Set available actions based on read only */
1133 
1134  /* If the register is not read only, make any modifying action active
1135  * to start with */
1136  if (!read_only_reg)
1137  {
1138  const char** iter;
1139  for (iter = readonly_inactive_actions; *iter; ++iter)
1140  {
1141  /* Set the action's sensitivity */
1142  GtkAction* action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page), *iter);
1143  gtk_action_set_sensitive (action, TRUE);
1144  }
1145  main_window_update_page_set_read_only_icon (GNC_PLUGIN_PAGE(page), FALSE);
1146 
1147  if (trans)
1148  read_only = xaccTransIsReadonlyByPostedDate (trans);
1149 
1150  voided = xaccTransHasSplitsInState (trans, VREC);
1151 
1152  action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page),
1153  "CutTransactionAction");
1154  gtk_action_set_sensitive (GTK_ACTION (action), !read_only & !voided);
1155 
1156  action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page),
1157  "PasteTransactionAction");
1158  gtk_action_set_sensitive (GTK_ACTION (action), !read_only & !voided);
1159 
1160  action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page),
1161  "DeleteTransactionAction");
1162  gtk_action_set_sensitive (GTK_ACTION (action), !read_only & !voided);
1163 
1164  if (cursor_class == CURSOR_CLASS_SPLIT)
1165  {
1166  action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page),
1167  "DuplicateTransactionAction");
1168  gtk_action_set_sensitive (GTK_ACTION (action), !read_only & !voided);
1169  }
1170 
1171  action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page),
1172  "RemoveTransactionSplitsAction");
1173  gtk_action_set_sensitive (GTK_ACTION (action), !read_only & !voided);
1174 
1175  /* Set 'Void' and 'Unvoid' */
1176  if (read_only)
1177  voided = TRUE;
1178 
1179  action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page),
1180  "VoidTransactionAction");
1181  gtk_action_set_sensitive (GTK_ACTION (action), !voided);
1182 
1183  if (read_only)
1184  voided = FALSE;
1185 
1186  action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page),
1187  "UnvoidTransactionAction");
1188  gtk_action_set_sensitive (GTK_ACTION (action), voided);
1189  }
1190 
1191  /* Set 'Open and Remove Linked Documents' */
1192  action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page),
1193  "LinkedTransactionOpenAction");
1194  if (trans)
1195  {
1196  uri = xaccTransGetDocLink (trans);
1197  gtk_action_set_sensitive (GTK_ACTION(action), (uri ? TRUE:FALSE));
1198  }
1199  /* Set 'ExecAssociatedInvoice'
1200  We can determine an invoice from a txn if either
1201  - it is an invoice transaction
1202  - it has splits with an invoice associated with it
1203  */
1204  action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page),
1205  "JumpLinkedInvoiceAction");
1206  if (trans)
1207  {
1208  invoices = invoices_from_transaction (trans);
1209  gtk_action_set_sensitive (GTK_ACTION (action), (invoices != NULL));
1210  g_list_free (invoices);
1211  }
1212 
1213  gnc_plugin_business_split_reg_ui_update (GNC_PLUGIN_PAGE (page));
1214 
1215  /* If we are read only, make any modifying action inactive */
1216  if (read_only_reg)
1217  {
1218  const char** iter;
1219  for (iter = readonly_inactive_actions; *iter; ++iter)
1220  {
1221  /* Set the action's sensitivity */
1222  GtkAction* action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page), *iter);
1223  gtk_action_set_sensitive (action, FALSE);
1224  }
1225  main_window_update_page_set_read_only_icon (GNC_PLUGIN_PAGE(page), TRUE);
1226  }
1227 
1228  /* Modifying action descriptions based on cursor class */
1229  {
1230  const char** iter, **label_iter, **tooltip_iter;
1231  gboolean curr_label_trans = FALSE;
1232  iter = tran_vs_split_actions;
1233  action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page), *iter);
1234  label_iter = tran_action_labels;
1235  if (g_strcmp0 (gtk_action_get_label (action), _ (*label_iter)) == 0)
1236  curr_label_trans = TRUE;
1237  if ((cursor_class == CURSOR_CLASS_SPLIT) && curr_label_trans)
1238  {
1239  label_iter = split_action_labels;
1240  tooltip_iter = split_action_tips;
1241  for (iter = tran_vs_split_actions; *iter; ++iter)
1242  {
1243  /* Adjust the action's label and tooltip */
1244  action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page), *iter);
1245  gtk_action_set_label (action, _ (*label_iter));
1246  gtk_action_set_tooltip (action, _ (*tooltip_iter));
1247  ++label_iter;
1248  ++tooltip_iter;
1249  }
1250  }
1251  else if ((cursor_class == CURSOR_CLASS_TRANS) && !curr_label_trans)
1252  {
1253  label_iter = tran_action_labels;
1254  tooltip_iter = tran_action_tips;
1255  for (iter = tran_vs_split_actions; *iter; ++iter)
1256  {
1257  /* Adjust the action's label and tooltip */
1258  action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE (page), *iter);
1259  gtk_action_set_label (action, _ (*label_iter));
1260  gtk_action_set_tooltip (action, _ (*tooltip_iter));
1261  ++label_iter;
1262  ++tooltip_iter;
1263  }
1264  }
1265  }
1266 }
1267 
1268 static void
1269 gnc_plugin_page_register_ui_initial_state (GncPluginPageRegister* page)
1270 {
1272  GtkActionGroup* action_group;
1273  GtkAction* action;
1274  Account* account;
1275  SplitRegister* reg;
1276  GNCLedgerDisplayType ledger_type;
1277  int i;
1278  gboolean is_readwrite = !qof_book_is_readonly (gnc_get_current_book());
1279 
1280  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
1281  account = gnc_plugin_page_register_get_account (page);
1282  action_group = gnc_plugin_page_get_action_group (GNC_PLUGIN_PAGE (page));
1283  gnc_plugin_update_actions (action_group, actions_requiring_account,
1284  "sensitive", is_readwrite && account != NULL);
1285 
1286  gnc_plugin_update_actions (action_group, actions_requiring_priced_account,
1287  "visible", account &&
1288  gnc_prefs_is_extra_enabled () &&
1289  xaccAccountIsPriced (account));
1290 
1291  /* Set "style" radio button */
1292  ledger_type = gnc_ledger_display_type (priv->ledger);
1293  gnc_plugin_update_actions (action_group, view_style_actions,
1294  "sensitive", ledger_type == LD_SINGLE);
1295 
1296  reg = gnc_ledger_display_get_split_register (priv->ledger);
1297  for (i = n_radio_entries_2 - 1; i > 0; i--)
1298  {
1299  DEBUG (" index %d: comparing %x to %x", i, radio_entries_2[i].value,
1300  reg->style);
1301  if (radio_entries_2[i].value == reg->style)
1302  {
1303  DEBUG ("match");
1304  break;
1305  }
1306  }
1307 
1308  /* Either a match was found, or fell out with i = 0 */
1309  action = gtk_action_group_get_action (action_group, radio_entries_2[i].name);
1310  g_signal_handlers_block_by_func (action,
1311  gnc_plugin_page_register_cmd_style_changed, page);
1312  gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1313  g_signal_handlers_unblock_by_func (action,
1314  gnc_plugin_page_register_cmd_style_changed, page);
1315 
1316  /* Set "double line" toggle button */
1317  action = gtk_action_group_get_action (action_group,
1318  "ViewStyleDoubleLineAction");
1319  g_signal_handlers_block_by_func (action,
1320  gnc_plugin_page_register_cmd_style_double_line, page);
1321  gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1322  reg->use_double_line);
1323  g_signal_handlers_unblock_by_func (action,
1324  gnc_plugin_page_register_cmd_style_double_line, page);
1325 }
1326 
1327 /* Virtual Functions */
1328 
1329 static const gchar*
1330 get_filter_default_num_of_days (GNCLedgerDisplayType ledger_type)
1331 {
1332  if (ledger_type == LD_GL)
1333  return DEFAULT_FILTER_NUM_DAYS_GL;
1334  else
1335  return "0";
1336 }
1337 
1338 /* For setting the focus on a register page, the default gnc_plugin
1339  * function for 'focus_page' is overridden so that the page focus
1340  * can be conditionally set. This is to allow for enabling the setting
1341  * of the sheet focus only when the page is the current one.
1342  */
1343 static void
1344 gnc_plugin_page_register_focus (GncPluginPage* plugin_page,
1345  gboolean on_current_page)
1346 {
1347  GncPluginPageRegister* page;
1349  GNCSplitReg* gsr;
1350 
1351  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
1352 
1353  page = GNC_PLUGIN_PAGE_REGISTER (plugin_page);
1354  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
1355 
1356  gsr = gnc_plugin_page_register_get_gsr (GNC_PLUGIN_PAGE (plugin_page));
1357 
1358  if (on_current_page)
1359  {
1360  priv->page_focus = TRUE;
1361 
1362  // Chain up to use parent version of 'focus_page' which will
1363  // use an idle_add as the page changed signal is emitted multiple times.
1364  GNC_PLUGIN_PAGE_CLASS (parent_class)->focus_page (plugin_page, TRUE);
1365  }
1366  else
1367  priv->page_focus = FALSE;
1368 
1369  // set the sheet focus setting
1370  gnc_split_reg_set_sheet_focus (gsr, priv->page_focus);
1371 }
1372 
1373 static GtkWidget*
1374 gnc_plugin_page_register_create_widget (GncPluginPage* plugin_page)
1375 {
1376  GncPluginPageRegister* page;
1378  GNCLedgerDisplayType ledger_type;
1379  GncWindow* gnc_window;
1380  guint numRows;
1381  GtkWidget* gsr;
1382  SplitRegister* reg;
1383  Account* acct;
1384  gchar* order;
1385  int filter_changed = 0;
1386  gboolean create_new_page = FALSE;
1387 
1388  ENTER ("page %p", plugin_page);
1389  page = GNC_PLUGIN_PAGE_REGISTER (plugin_page);
1390  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
1391 
1392  if (priv->widget != NULL)
1393  {
1394  LEAVE ("existing widget %p", priv->widget);
1395  return priv->widget;
1396  }
1397  // on create, the page will be the current page so set the focus flag
1398  priv->page_focus = TRUE;
1399 
1400  priv->widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
1401  gtk_box_set_homogeneous (GTK_BOX (priv->widget), FALSE);
1402  gtk_widget_show (priv->widget);
1403 
1404  // Set the name for this widget so it can be easily manipulated with css
1405  gtk_widget_set_name (GTK_WIDGET(priv->widget), "gnc-id-register-page");
1406 
1407  numRows = priv->lines_default;
1408  numRows = MIN (numRows, DEFAULT_LINES_AMOUNT);
1409 
1410  gnc_window = GNC_WINDOW(GNC_PLUGIN_PAGE(page)->window);
1411  gsr = gnc_split_reg_new (priv->ledger,
1412  gnc_window_get_gtk_window (gnc_window),
1413  numRows, priv->read_only);
1414  priv->gsr = (GNCSplitReg *)gsr;
1415 
1416  gtk_widget_show (gsr);
1417  gtk_box_pack_start (GTK_BOX (priv->widget), gsr, TRUE, TRUE, 0);
1418 
1419  g_signal_connect (G_OBJECT (gsr), "help-changed",
1420  G_CALLBACK (gnc_plugin_page_help_changed_cb),
1421  page);
1422 
1423  g_signal_connect (G_OBJECT (gsr), "show-popup-menu",
1424  G_CALLBACK (gnc_plugin_page_popup_menu_cb),
1425  page);
1426 
1427  reg = gnc_ledger_display_get_split_register (priv->ledger);
1428  gnc_split_register_config (reg, reg->type, reg->style,
1429  reg->use_double_line);
1430 
1431  gnc_plugin_page_register_ui_initial_state (page);
1432  gnc_plugin_page_register_ui_update (NULL, page);
1433 
1434  ledger_type = gnc_ledger_display_type (priv->ledger);
1435 
1436  {
1437  gchar** filter;
1438  gchar* filter_str;
1439  guint filtersize = 0;
1440  /* Set the sort order for the split register and status of save order button */
1441  priv->sd.save_order = FALSE;
1442  order = gnc_plugin_page_register_get_sort_order (plugin_page);
1443 
1444  PINFO ("Loaded Sort order is %s", order);
1445 
1446  gnc_split_reg_set_sort_type (priv->gsr, SortTypefromString (order));
1447 
1448  if (order && (g_strcmp0 (order, DEFAULT_SORT_ORDER) != 0))
1449  priv->sd.save_order = TRUE;
1450 
1451  priv->sd.original_save_order = priv->sd.save_order;
1452  g_free (order);
1453 
1454  priv->sd.reverse_order = gnc_plugin_page_register_get_sort_reversed (
1455  plugin_page);
1456  gnc_split_reg_set_sort_reversed (priv->gsr, priv->sd.reverse_order, FALSE);
1457  if (priv->sd.reverse_order)
1458  priv->sd.save_order = TRUE;
1459 
1460  priv->sd.original_reverse_order = priv->sd.reverse_order;
1461 
1462  /* Set the filter for the split register and status of save filter button */
1463  priv->fd.save_filter = FALSE;
1464 
1465  filter_str = gnc_plugin_page_register_get_filter (plugin_page);
1466  filter = g_strsplit (filter_str, ",", -1);
1467  filtersize = g_strv_length (filter);
1468  g_free (filter_str);
1469 
1470  PINFO ("Loaded Filter Status is %s", filter[0]);
1471 
1472  priv->fd.cleared_match = (gint)g_ascii_strtoll (filter[0], NULL, 16);
1473 
1474  if (filtersize > 0 && (g_strcmp0 (filter[0], DEFAULT_FILTER) != 0))
1475  filter_changed = filter_changed + 1;
1476 
1477  if (filtersize > 1 && (g_strcmp0 (filter[1], "0") != 0))
1478  {
1479  PINFO ("Loaded Filter Start Date is %s", filter[1]);
1480 
1481  priv->fd.start_time = gnc_plugin_page_register_filter_dmy2time (filter[1]);
1482  priv->fd.start_time = gnc_time64_get_day_start (priv->fd.start_time);
1483  filter_changed = filter_changed + 1;
1484  }
1485 
1486  if (filtersize > 2 && (g_strcmp0 (filter[2], "0") != 0))
1487  {
1488  PINFO ("Loaded Filter End Date is %s", filter[2]);
1489 
1490  priv->fd.end_time = gnc_plugin_page_register_filter_dmy2time (filter[2]);
1491  priv->fd.end_time = gnc_time64_get_day_end (priv->fd.end_time);
1492  filter_changed = filter_changed + 1;
1493  }
1494 
1495  // set the default for the number of days
1496  priv->fd.days = (gint)g_ascii_strtoll (
1497  get_filter_default_num_of_days (ledger_type), NULL, 10);
1498 
1499  if (filtersize > 3 &&
1500  (g_strcmp0 (filter[3], get_filter_default_num_of_days (ledger_type)) != 0))
1501  {
1502  PINFO ("Loaded Filter Days is %s", filter[3]);
1503 
1504  priv->fd.days = (gint)g_ascii_strtoll (filter[3], NULL, 10);
1505  filter_changed = filter_changed + 1;
1506  }
1507 
1508  if (filter_changed != 0)
1509  priv->fd.save_filter = TRUE;
1510 
1511  priv->fd.original_save_filter = priv->fd.save_filter;
1512  g_strfreev (filter);
1513  }
1514 
1515  if (ledger_type == LD_GL)
1516  {
1517  time64 start_time = 0, end_time = 0;
1518 
1519  if (reg->type == GENERAL_JOURNAL)
1520  {
1521  start_time = priv->fd.start_time;
1522  end_time = priv->fd.end_time;
1523  }
1524  else // search ledger and the like
1525  {
1526  priv->fd.days = 0;
1527  priv->fd.cleared_match = (gint)g_ascii_strtoll (DEFAULT_FILTER, NULL, 16);
1528  gnc_split_reg_set_sort_type (priv->gsr,
1529  SortTypefromString (DEFAULT_SORT_ORDER));
1530  priv->sd.reverse_order = FALSE;
1531  priv->fd.save_filter = FALSE;
1532  priv->sd.save_order = FALSE;
1533  }
1534 
1535  priv->fd.original_days = priv->fd.days;
1536 
1537  priv->fd.original_start_time = start_time;
1538  priv->fd.start_time = start_time;
1539  priv->fd.original_end_time = end_time;
1540  priv->fd.end_time = end_time;
1541  }
1542 
1543  // if enable_refresh is TRUE, default, come from creating
1544  // new page instead of restoring
1545  if (priv->enable_refresh == TRUE)
1546  {
1547  create_new_page = TRUE;
1548  priv->enable_refresh = FALSE; // disable refresh
1549  }
1550 
1551  /* Update Query with Filter Status and Dates */
1552  gnc_ppr_update_status_query (page);
1553  gnc_ppr_update_date_query (page);
1554 
1555  /* Now do the refresh if this is a new page instead of restore */
1556  if (create_new_page)
1557  {
1558  priv->enable_refresh = TRUE;
1559  gnc_ledger_display_refresh (priv->ledger);
1560  }
1561 
1562  // Set filter tooltip for summary bar
1563  gnc_plugin_page_register_set_filter_tooltip (page);
1564 
1565  plugin_page->summarybar = gsr_create_summary_bar (priv->gsr);
1566  if (plugin_page->summarybar)
1567  {
1568  gtk_widget_show_all (plugin_page->summarybar);
1569  gtk_box_pack_start (GTK_BOX (priv->widget), plugin_page->summarybar,
1570  FALSE, FALSE, 0);
1571 
1572  gnc_plugin_page_register_summarybar_position_changed (NULL, NULL, page);
1573  gnc_prefs_register_cb (GNC_PREFS_GROUP_GENERAL,
1574  GNC_PREF_SUMMARYBAR_POSITION_TOP,
1575  gnc_plugin_page_register_summarybar_position_changed,
1576  page);
1577  gnc_prefs_register_cb (GNC_PREFS_GROUP_GENERAL,
1578  GNC_PREF_SUMMARYBAR_POSITION_BOTTOM,
1579  gnc_plugin_page_register_summarybar_position_changed,
1580  page);
1581  }
1582 
1583  priv->event_handler_id = qof_event_register_handler
1584  ((QofEventHandler)gnc_plugin_page_register_event_handler, page);
1585  priv->component_manager_id =
1586  gnc_register_gui_component (GNC_PLUGIN_PAGE_REGISTER_NAME,
1587  gnc_plugin_page_register_refresh_cb,
1588  gnc_plugin_page_register_close_cb,
1589  page);
1590  gnc_gui_component_set_session (priv->component_manager_id,
1591  gnc_get_current_session());
1593  if (acct)
1594  gnc_gui_component_watch_entity (
1595  priv->component_manager_id, xaccAccountGetGUID (acct),
1596  QOF_EVENT_DESTROY | QOF_EVENT_MODIFY);
1597 
1598  gnc_split_reg_set_moved_cb
1599  (priv->gsr, (GFunc)gnc_plugin_page_register_ui_update, page);
1600 
1601  g_signal_connect (G_OBJECT (plugin_page), "inserted",
1602  G_CALLBACK (gnc_plugin_page_inserted_cb),
1603  NULL);
1604 
1605  /* DRH - Probably lots of other stuff from regWindowLedger should end up here. */
1606  LEAVE (" ");
1607  return priv->widget;
1608 }
1609 
1610 static void
1611 gnc_plugin_page_register_destroy_widget (GncPluginPage* plugin_page)
1612 {
1613  GncPluginPageRegister* page;
1615 
1616  ENTER ("page %p", plugin_page);
1617  page = GNC_PLUGIN_PAGE_REGISTER (plugin_page);
1618  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
1619 
1620  gnc_prefs_remove_cb_by_func (GNC_PREFS_GROUP_GENERAL,
1621  GNC_PREF_SUMMARYBAR_POSITION_TOP,
1622  gnc_plugin_page_register_summarybar_position_changed,
1623  page);
1624  gnc_prefs_remove_cb_by_func (GNC_PREFS_GROUP_GENERAL,
1625  GNC_PREF_SUMMARYBAR_POSITION_BOTTOM,
1626  gnc_plugin_page_register_summarybar_position_changed,
1627  page);
1628 
1629  // Remove the page_changed signal callback
1630  gnc_plugin_page_disconnect_page_changed (GNC_PLUGIN_PAGE (plugin_page));
1631 
1632  // Remove the page focus idle function if present
1633  g_idle_remove_by_data (GNC_PLUGIN_PAGE_REGISTER (plugin_page));
1634 
1635  if (priv->widget == NULL)
1636  return;
1637 
1638  if (priv->component_manager_id)
1639  {
1640  gnc_unregister_gui_component (priv->component_manager_id);
1641  priv->component_manager_id = 0;
1642  }
1643 
1644  if (priv->event_handler_id)
1645  {
1646  qof_event_unregister_handler (priv->event_handler_id);
1647  priv->event_handler_id = 0;
1648  }
1649 
1650  if (priv->sd.dialog)
1651  {
1652  gtk_widget_destroy (priv->sd.dialog);
1653  memset (&priv->sd, 0, sizeof (priv->sd));
1654  }
1655 
1656  if (priv->fd.dialog)
1657  {
1658  gtk_widget_destroy (priv->fd.dialog);
1659  memset (&priv->fd, 0, sizeof (priv->fd));
1660  }
1661 
1662  qof_query_destroy (priv->search_query);
1663  qof_query_destroy (priv->filter_query);
1664 
1665  gtk_widget_hide (priv->widget);
1666  gnc_ledger_display_close (priv->ledger);
1667  priv->ledger = NULL;
1668  LEAVE (" ");
1669 }
1670 
1671 static void
1672 gnc_plugin_page_register_window_changed (GncPluginPage* plugin_page,
1673  GtkWidget* window)
1674 {
1675  GncPluginPageRegister* page;
1677 
1678  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
1679 
1680  page = GNC_PLUGIN_PAGE_REGISTER (plugin_page);
1681  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
1682  priv->gsr->window =
1683  GTK_WIDGET (gnc_window_get_gtk_window (GNC_WINDOW (window)));
1684 }
1685 
1686 static const gchar* style_names[] =
1687 {
1688  "Ledger",
1689  "Auto Ledger",
1690  "Journal",
1691  NULL
1692 };
1693 
1694 #define KEY_REGISTER_TYPE "RegisterType"
1695 #define KEY_ACCOUNT_NAME "AccountName"
1696 #define KEY_ACCOUNT_GUID "AccountGuid"
1697 #define KEY_REGISTER_STYLE "RegisterStyle"
1698 #define KEY_DOUBLE_LINE "DoubleLineMode"
1699 
1700 #define LABEL_ACCOUNT "Account"
1701 #define LABEL_SUBACCOUNT "SubAccount"
1702 #define LABEL_GL "GL"
1703 #define LABEL_SEARCH "Search"
1704 
1705 
1715 static void
1716 gnc_plugin_page_register_save_page (GncPluginPage* plugin_page,
1717  GKeyFile* key_file,
1718  const gchar* group_name)
1719 {
1720  GncPluginPageRegister* page;
1722  GNCLedgerDisplayType ledger_type;
1723  SplitRegister* reg;
1724  Account* leader;
1725 
1726  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
1727  g_return_if_fail (key_file != NULL);
1728  g_return_if_fail (group_name != NULL);
1729 
1730  ENTER ("page %p, key_file %p, group_name %s", plugin_page, key_file,
1731  group_name);
1732 
1733  page = GNC_PLUGIN_PAGE_REGISTER (plugin_page);
1734  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
1735 
1736  reg = gnc_ledger_display_get_split_register (priv->ledger);
1737  ledger_type = gnc_ledger_display_type (priv->ledger);
1738  if (ledger_type > LD_GL)
1739  {
1740  LEAVE ("Unsupported ledger type");
1741  return;
1742  }
1743  if ((ledger_type == LD_SINGLE) || (ledger_type == LD_SUBACCOUNT))
1744  {
1745  const gchar* label;
1746  gchar* name;
1747  gchar acct_guid[GUID_ENCODING_LENGTH + 1];
1748  label = (ledger_type == LD_SINGLE) ? LABEL_ACCOUNT : LABEL_SUBACCOUNT;
1749  leader = gnc_ledger_display_leader (priv->ledger);
1750  g_key_file_set_string (key_file, group_name, KEY_REGISTER_TYPE, label);
1751  name = gnc_account_get_full_name (leader);
1752  g_key_file_set_string (key_file, group_name, KEY_ACCOUNT_NAME, name);
1753  g_free (name);
1754  guid_to_string_buff (xaccAccountGetGUID (leader), acct_guid);
1755  g_key_file_set_string (key_file, group_name, KEY_ACCOUNT_GUID, acct_guid);
1756  }
1757  else if (reg->type == GENERAL_JOURNAL)
1758  {
1759  g_key_file_set_string (key_file, group_name, KEY_REGISTER_TYPE,
1760  LABEL_GL);
1761  }
1762  else if (reg->type == SEARCH_LEDGER)
1763  {
1764  g_key_file_set_string (key_file, group_name, KEY_REGISTER_TYPE,
1765  LABEL_SEARCH);
1766  }
1767  else
1768  {
1769  LEAVE ("Unsupported register type");
1770  return;
1771  }
1772 
1773  g_key_file_set_string (key_file, group_name, KEY_REGISTER_STYLE,
1774  style_names[reg->style]);
1775  g_key_file_set_boolean (key_file, group_name, KEY_DOUBLE_LINE,
1776  reg->use_double_line);
1777 
1778  LEAVE(" ");
1779 }
1780 
1781 
1794 static void
1795 gnc_plugin_page_register_restore_edit_menu (GncPluginPage* page,
1796  GKeyFile* key_file,
1797  const gchar* group_name)
1798 {
1799  GtkAction* action;
1800  GError* error = NULL;
1801  gchar* style_name;
1802  gint i;
1803  gboolean use_double_line;
1804 
1805  ENTER (" ");
1806 
1807  /* Convert the style name to an index */
1808  style_name = g_key_file_get_string (key_file, group_name,
1809  KEY_REGISTER_STYLE, &error);
1810  for (i = 0 ; style_names[i]; i++)
1811  {
1812  if (g_ascii_strcasecmp (style_name, style_names[i]) == 0)
1813  {
1814  DEBUG ("Found match for style name: %s", style_name);
1815  break;
1816  }
1817  }
1818  g_free (style_name);
1819 
1820  /* Update the style menu action for this page */
1821  if (i <= REG_STYLE_JOURNAL)
1822  {
1823  DEBUG ("Setting style: %d", i);
1824  action = gnc_plugin_page_get_action (page, radio_entries_2[i].name);
1825  gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1826  }
1827 
1828  /* Update the double line action on this page */
1829  use_double_line =
1830  g_key_file_get_boolean (key_file, group_name, KEY_DOUBLE_LINE, &error);
1831  DEBUG ("Setting double_line_mode: %d", use_double_line);
1832  action = gnc_plugin_page_get_action (page, "ViewStyleDoubleLineAction");
1833  gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), use_double_line);
1834 
1835  LEAVE (" ");
1836 }
1837 
1838 
1848 static GncPluginPage*
1849 gnc_plugin_page_register_recreate_page (GtkWidget* window,
1850  GKeyFile* key_file,
1851  const gchar* group_name)
1852 {
1854  GncPluginPage* page;
1855  GError* error = NULL;
1856  gchar* reg_type, *acct_guid;
1857  GncGUID guid;
1858  Account* account = NULL;
1859  QofBook* book;
1860  gboolean include_subs;
1861 
1862  g_return_val_if_fail (key_file, NULL);
1863  g_return_val_if_fail (group_name, NULL);
1864  ENTER ("key_file %p, group_name %s", key_file, group_name);
1865 
1866  /* Create the new page. */
1867  reg_type = g_key_file_get_string (key_file, group_name,
1868  KEY_REGISTER_TYPE, &error);
1869  DEBUG ("Page type: %s", reg_type);
1870  if ((g_ascii_strcasecmp (reg_type, LABEL_ACCOUNT) == 0) ||
1871  (g_ascii_strcasecmp (reg_type, LABEL_SUBACCOUNT) == 0))
1872  {
1873  include_subs = (g_ascii_strcasecmp (reg_type, LABEL_SUBACCOUNT) == 0);
1874  DEBUG ("Include subs: %d", include_subs);
1875  book = qof_session_get_book (gnc_get_current_session());
1876  if (!book)
1877  {
1878  LEAVE("Session has no book");
1879  return NULL;
1880  }
1881  acct_guid = g_key_file_get_string (key_file, group_name,
1882  KEY_ACCOUNT_GUID, &error);
1883  if (string_to_guid (acct_guid, &guid)) //find account by guid
1884  {
1885  account = xaccAccountLookup (&guid, book);
1886  g_free (acct_guid);
1887  }
1888  if (account == NULL) //find account by full name
1889  {
1890  gchar* acct_name = g_key_file_get_string (key_file, group_name,
1891  KEY_ACCOUNT_NAME, &error);
1892  account = gnc_account_lookup_by_full_name (gnc_book_get_root_account (book),
1893  acct_name);
1894  g_free (acct_name);
1895  }
1896  if (account == NULL)
1897  {
1898  LEAVE ("Bad account name");
1899  g_free (reg_type);
1900  return NULL;
1901  }
1902  page = gnc_plugin_page_register_new (account, include_subs);
1903  }
1904  else if (g_ascii_strcasecmp (reg_type, LABEL_GL) == 0)
1905  {
1907  }
1908  else
1909  {
1910  LEAVE ("Bad ledger type");
1911  g_free (reg_type);
1912  return NULL;
1913  }
1914  g_free (reg_type);
1915 
1916  /* disable the refresh of the display ledger, this is for
1917  * sort/filter updates and double line/style changes */
1918  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
1919  priv->enable_refresh = FALSE;
1920 
1921  /* Recreate page in given window */
1922  gnc_plugin_page_set_use_new_window (page, FALSE);
1923 
1924  /* Install it now so we can them manipulate the created widget */
1925  gnc_main_window_open_page (GNC_MAIN_WINDOW (window), page);
1926 
1927  /* Now update the page to the last state it was in */
1928  gnc_plugin_page_register_restore_edit_menu (page, key_file, group_name);
1929 
1930  /* enable the refresh */
1931  priv->enable_refresh = TRUE;
1932  gnc_ledger_display_refresh (priv->ledger);
1933  LEAVE (" ");
1934  return page;
1935 }
1936 
1937 
1938 /*
1939  * Based on code from Epiphany (src/ephy-window.c)
1940  */
1941 static void
1942 gnc_plugin_page_register_update_edit_menu (GncPluginPage* page, gboolean hide)
1943 {
1945  GncPluginPageRegister* reg_page;
1946  GtkAction* action;
1947  gboolean can_copy = FALSE, can_cut = FALSE, can_paste = FALSE;
1948  gboolean has_selection;
1949  gboolean is_readwrite = !qof_book_is_readonly (gnc_get_current_book());
1950 
1951  reg_page = GNC_PLUGIN_PAGE_REGISTER (page);
1952  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (reg_page);
1953  has_selection = gnucash_register_has_selection (priv->gsr->reg);
1954 
1955  can_copy = has_selection;
1956  can_cut = is_readwrite && has_selection;
1957  can_paste = is_readwrite;
1958 
1959  action = gnc_plugin_page_get_action (page, "EditCopyAction");
1960  gtk_action_set_sensitive (action, can_copy);
1961  gtk_action_set_visible (action, !hide || can_copy);
1962  action = gnc_plugin_page_get_action (page, "EditCutAction");
1963  gtk_action_set_sensitive (action, can_cut);
1964  gtk_action_set_visible (action, !hide || can_cut);
1965  action = gnc_plugin_page_get_action (page, "EditPasteAction");
1966  gtk_action_set_sensitive (action, can_paste);
1967  gtk_action_set_visible (action, !hide || can_paste);
1968 }
1969 
1970 static gboolean is_scrubbing = FALSE;
1971 static gboolean show_abort_verify = TRUE;
1972 
1973 static gboolean
1974 finish_scrub (GncPluginPage* page)
1975 {
1976  gboolean ret = FALSE;
1977 
1978  if (is_scrubbing)
1979  {
1980  ret = gnc_verify_dialog (GTK_WINDOW(gnc_plugin_page_get_window
1981  (GNC_PLUGIN_PAGE(page))),
1982  FALSE,
1983  _("'Check & Repair' is currently running, do you want to abort it?"));
1984 
1985  show_abort_verify = FALSE;
1986 
1987  if (ret)
1988  gnc_set_abort_scrub (TRUE);
1989  }
1990  return ret;
1991 }
1992 
1993 static gboolean
1994 gnc_plugin_page_register_finish_pending (GncPluginPage* page)
1995 {
1997  GncPluginPageRegister* reg_page;
1998  SplitRegister* reg;
1999  GtkWidget* dialog, *window;
2000  gchar* name;
2001  gint response;
2002 
2003  if (is_scrubbing && show_abort_verify)
2004  {
2005  if (!finish_scrub (page))
2006  return FALSE;
2007  }
2008 
2009  reg_page = GNC_PLUGIN_PAGE_REGISTER (page);
2010  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (reg_page);
2011  reg = gnc_ledger_display_get_split_register (priv->ledger);
2012 
2013  if (!reg || !gnc_split_register_changed (reg))
2014  return TRUE;
2015 
2016  name = gnc_plugin_page_register_get_tab_name (page);
2017  window = gnc_plugin_page_get_window (page);
2018  dialog = gtk_message_dialog_new (GTK_WINDOW (window),
2019  GTK_DIALOG_DESTROY_WITH_PARENT,
2020  GTK_MESSAGE_WARNING,
2021  GTK_BUTTONS_NONE,
2022  /* Translators: %s is the name
2023  of the tab page */
2024  _ ("Save changes to %s?"), name);
2025  g_free (name);
2026  gtk_message_dialog_format_secondary_text
2027  (GTK_MESSAGE_DIALOG (dialog),
2028  "%s",
2029  _ ("This register has pending changes to a transaction. "
2030  "Would you like to save the changes to this transaction, "
2031  "discard the transaction, or cancel the operation?"));
2032  gnc_gtk_dialog_add_button (dialog, _ ("_Discard Transaction"),
2033  "edit-delete", GTK_RESPONSE_REJECT);
2034  gtk_dialog_add_button (GTK_DIALOG (dialog),
2035  _ ("_Cancel"), GTK_RESPONSE_CANCEL);
2036  gnc_gtk_dialog_add_button (dialog, _ ("_Save Transaction"),
2037  "document-save", GTK_RESPONSE_ACCEPT);
2038 
2039  response = gtk_dialog_run (GTK_DIALOG (dialog));
2040  gtk_widget_destroy (dialog);
2041 
2042  switch (response)
2043  {
2044  case GTK_RESPONSE_ACCEPT:
2045  gnc_split_register_save (reg, TRUE);
2046  return TRUE;
2047 
2048  case GTK_RESPONSE_REJECT:
2050  gnc_split_register_save (reg, TRUE);
2051  return TRUE;
2052 
2053  default:
2054  return FALSE;
2055  }
2056 }
2057 
2058 
2059 static gchar*
2060 gnc_plugin_page_register_get_tab_name (GncPluginPage* plugin_page)
2061 {
2063  GNCLedgerDisplayType ledger_type;
2064  GNCLedgerDisplay* ld;
2065  SplitRegister* reg;
2066  Account* leader;
2067 
2068  g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page),
2069  g_strdup (_("unknown")));
2070 
2071  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
2072  ld = priv->ledger;
2074  ledger_type = gnc_ledger_display_type (ld);
2075  leader = gnc_ledger_display_leader (ld);
2076 
2077  switch (ledger_type)
2078  {
2079  case LD_SINGLE:
2080  return g_strdup (xaccAccountGetName (leader));
2081 
2082  case LD_SUBACCOUNT:
2083  return g_strdup_printf ("%s+", xaccAccountGetName (leader));
2084 
2085  case LD_GL:
2086  switch (reg->type)
2087  {
2088  case GENERAL_JOURNAL:
2089  case INCOME_LEDGER:
2090  return g_strdup (_ ("General Journal"));
2091  case PORTFOLIO_LEDGER:
2092  return g_strdup (_ ("Portfolio"));
2093  case SEARCH_LEDGER:
2094  return g_strdup (_ ("Search Results"));
2095  default:
2096  break;
2097  }
2098  break;
2099 
2100  default:
2101  break;
2102  }
2103 
2104  return g_strdup (_ ("unknown"));
2105 }
2106 
2107 static gchar*
2108 gnc_plugin_page_register_get_tab_color (GncPluginPage* plugin_page)
2109 {
2111  GNCLedgerDisplayType ledger_type;
2112  GNCLedgerDisplay* ld;
2113  Account* leader;
2114  const char* color;
2115 
2116  g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page),
2117  g_strdup (_("unknown")));
2118 
2119  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
2120  ld = priv->ledger;
2121  ledger_type = gnc_ledger_display_type (ld);
2122  leader = gnc_ledger_display_leader (ld);
2123  color = NULL;
2124 
2125  if ((ledger_type == LD_SINGLE) || (ledger_type == LD_SUBACCOUNT))
2126  color = xaccAccountGetColor (leader);
2127 
2128  return g_strdup (color ? color : "Not Set");
2129 }
2130 
2131 static void
2132 gnc_plugin_page_register_check_for_empty_group (GKeyFile *state_file, const gchar *state_section)
2133 {
2134  gsize num_keys;
2135  gchar **keys = g_key_file_get_keys (state_file, state_section, &num_keys, NULL);
2136 
2137  if (num_keys == 0)
2138  gnc_state_drop_sections_for (state_section);
2139 
2140  g_strfreev (keys);
2141 }
2142 
2143 static gchar*
2144 gnc_plugin_page_register_get_filter_gcm (Account* leader)
2145 {
2146  GKeyFile* state_file = gnc_state_get_current();
2147  gchar* state_section;
2148  gchar acct_guid[GUID_ENCODING_LENGTH + 1];
2149  GError* error = NULL;
2150  char* filter = NULL;
2151 
2152  // get the filter from the .gcm file
2153  guid_to_string_buff (xaccAccountGetGUID (leader), acct_guid);
2154  state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", acct_guid, NULL);
2155  filter = g_key_file_get_string (state_file, state_section,
2156  KEY_PAGE_FILTER, &error);
2157 
2158  if (error)
2159  g_clear_error (&error);
2160  else
2161  g_strdelimit (filter, ";", ',');
2162 
2163  g_free (state_section);
2164  return filter;
2165 }
2166 
2167 static gchar*
2168 gnc_plugin_page_register_get_filter (GncPluginPage* plugin_page)
2169 {
2171  GNCLedgerDisplayType ledger_type;
2172  Account* leader;
2173  char* filter = NULL;
2174 
2175  g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page),
2176  g_strdup (_("unknown")));
2177 
2178  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
2179 
2180  ledger_type = gnc_ledger_display_type (priv->ledger);
2181  leader = gnc_ledger_display_leader (priv->ledger);
2182 
2183  // load from gcm file
2184  filter = gnc_plugin_page_register_get_filter_gcm (leader);
2185 
2186  if (filter)
2187  return filter;
2188 
2189  return g_strdup_printf ("%s,%s,%s,%s", DEFAULT_FILTER,
2190  "0", "0", get_filter_default_num_of_days (ledger_type));
2191 }
2192 
2193 static void
2194 gnc_plugin_page_register_set_filter_gcm (Account* leader, const gchar* filter,
2195  gchar* default_filter)
2196 {
2197  GKeyFile* state_file = gnc_state_get_current();
2198  gchar* state_section;
2199  gchar* filter_text;
2200  gchar acct_guid[GUID_ENCODING_LENGTH + 1];
2201 
2202  // save the filter to the .gcm file also
2203  guid_to_string_buff (xaccAccountGetGUID (leader), acct_guid);
2204  state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", acct_guid, NULL);
2205  if (!filter || (g_strcmp0 (filter, default_filter) == 0))
2206  {
2207  if (g_key_file_has_key (state_file, state_section, KEY_PAGE_FILTER, NULL))
2208  g_key_file_remove_key (state_file, state_section, KEY_PAGE_FILTER, NULL);
2209 
2210  gnc_plugin_page_register_check_for_empty_group (state_file, state_section);
2211  }
2212  else
2213  {
2214  filter_text = g_strdup (filter);
2215  g_strdelimit (filter_text, ",", ';'); // make it conform to .gcm file list
2216  g_key_file_set_string (state_file, state_section, KEY_PAGE_FILTER,
2217  filter_text);
2218  g_free (filter_text);
2219  }
2220  g_free (state_section);
2221 }
2222 
2223 void
2224 gnc_plugin_page_register_set_filter (GncPluginPage* plugin_page,
2225  const gchar* filter)
2226 {
2228  GNCLedgerDisplayType ledger_type;
2229  Account* leader;
2230  gchar* default_filter;
2231 
2232  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
2233 
2234  ledger_type = gnc_ledger_display_type (priv->ledger);
2235  leader = gnc_ledger_display_leader (priv->ledger);
2236 
2237  default_filter = g_strdup_printf ("%s,%s,%s,%s", DEFAULT_FILTER,
2238  "0", "0", get_filter_default_num_of_days (ledger_type));
2239 
2240  // save to gcm file
2241  gnc_plugin_page_register_set_filter_gcm (leader, filter, default_filter);
2242 
2243  g_free (default_filter);
2244  return;
2245 }
2246 
2247 static gchar*
2248 gnc_plugin_page_register_get_sort_order_gcm (Account* leader)
2249 {
2250  GKeyFile* state_file = gnc_state_get_current();
2251  gchar* state_section;
2252  gchar* sort_text;
2253  gchar acct_guid[GUID_ENCODING_LENGTH + 1];
2254  GError* error = NULL;
2255  char* sort_order = NULL;
2256 
2257  // get the sort_order from the .gcm file
2258  guid_to_string_buff (xaccAccountGetGUID (leader), acct_guid);
2259  state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", acct_guid, NULL);
2260  sort_text = g_key_file_get_string (state_file, state_section, KEY_PAGE_SORT,
2261  &error);
2262 
2263  if (error)
2264  g_clear_error (&error);
2265  else
2266  {
2267  sort_order = g_strdup (sort_text);
2268  g_free (sort_text);
2269  }
2270  g_free (state_section);
2271  return sort_order;
2272 }
2273 
2274 static gchar*
2275 gnc_plugin_page_register_get_sort_order (GncPluginPage* plugin_page)
2276 {
2278  Account* leader;
2279  char* sort_order = NULL;
2280 
2281  g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page),
2282  _ ("unknown"));
2283 
2284  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
2285 
2286  leader = gnc_ledger_display_leader (priv->ledger);
2287 
2288  // load from gcm file
2289  sort_order = gnc_plugin_page_register_get_sort_order_gcm (leader);
2290 
2291 
2292  return sort_order ? sort_order : g_strdup (DEFAULT_SORT_ORDER);
2293 }
2294 
2295 static void
2296 gnc_plugin_page_register_set_sort_order_gcm (Account* leader,
2297  const gchar* sort_order)
2298 {
2299  GKeyFile* state_file = gnc_state_get_current();
2300  gchar* state_section;
2301  gchar acct_guid[GUID_ENCODING_LENGTH + 1];
2302 
2303  // save sort_order to the .gcm file also
2304  guid_to_string_buff (xaccAccountGetGUID (leader), acct_guid);
2305  state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", acct_guid, NULL);
2306  if (!sort_order || (g_strcmp0 (sort_order, DEFAULT_SORT_ORDER) == 0))
2307  {
2308  if (g_key_file_has_key (state_file, state_section, KEY_PAGE_SORT, NULL))
2309  g_key_file_remove_key (state_file, state_section, KEY_PAGE_SORT, NULL);
2310 
2311  gnc_plugin_page_register_check_for_empty_group (state_file, state_section);
2312  }
2313  else
2314  g_key_file_set_string (state_file, state_section, KEY_PAGE_SORT, sort_order);
2315 
2316  g_free (state_section);
2317 }
2318 void
2319 gnc_plugin_page_register_set_sort_order (GncPluginPage* plugin_page,
2320  const gchar* sort_order)
2321 {
2323  Account* leader;
2324 
2325  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
2326 
2327  leader = gnc_ledger_display_leader (priv->ledger);
2328 
2329  // save to gcm file
2330  gnc_plugin_page_register_set_sort_order_gcm (leader, sort_order);
2331 }
2332 
2333 static gboolean
2334 gnc_plugin_page_register_get_sort_reversed_gcm (Account* leader)
2335 {
2336  GKeyFile* state_file = gnc_state_get_current();
2337  gchar* state_section;
2338  gchar acct_guid[GUID_ENCODING_LENGTH + 1];
2339  GError* error = NULL;
2340  gboolean sort_reversed = FALSE;
2341 
2342  // get the sort_reversed from the .gcm file
2343  guid_to_string_buff (xaccAccountGetGUID (leader), acct_guid);
2344  state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", acct_guid, NULL);
2345  sort_reversed = g_key_file_get_boolean (state_file, state_section,
2346  KEY_PAGE_SORT_REV, &error);
2347 
2348  if (error)
2349  g_clear_error (&error);
2350 
2351  g_free (state_section);
2352  return sort_reversed;
2353 }
2354 
2355 static gboolean
2356 gnc_plugin_page_register_get_sort_reversed (GncPluginPage* plugin_page)
2357 {
2359  Account* leader;
2360  gboolean sort_reversed = FALSE;
2361 
2362  g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page), FALSE);
2363 
2364  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
2365 
2366  leader = gnc_ledger_display_leader (priv->ledger);
2367 
2368  // load from gcm file
2369  sort_reversed = gnc_plugin_page_register_get_sort_reversed_gcm (leader);
2370  return sort_reversed;
2371 }
2372 
2373 static void
2374 gnc_plugin_page_register_set_sort_reversed_gcm (Account* leader,
2375  gboolean reverse_order)
2376 {
2377  GKeyFile* state_file = gnc_state_get_current();
2378  gchar* state_section;
2379  gchar acct_guid[GUID_ENCODING_LENGTH + 1];
2380 
2381  // save reverse_order to the .gcm file also
2382  guid_to_string_buff (xaccAccountGetGUID (leader), acct_guid);
2383  state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", acct_guid, NULL);
2384  if (!reverse_order)
2385  {
2386  if (g_key_file_has_key (state_file, state_section, KEY_PAGE_SORT_REV, NULL))
2387  g_key_file_remove_key (state_file, state_section, KEY_PAGE_SORT_REV, NULL);
2388 
2389  gnc_plugin_page_register_check_for_empty_group (state_file, state_section);
2390  }
2391  else
2392  g_key_file_set_boolean (state_file, state_section, KEY_PAGE_SORT_REV,
2393  reverse_order);
2394 
2395  g_free (state_section);
2396 }
2397 
2398 void
2399 gnc_plugin_page_register_set_sort_reversed (GncPluginPage* plugin_page,
2400  gboolean reverse_order)
2401 {
2403  Account* leader;
2404 
2405  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
2406  leader = gnc_ledger_display_leader (priv->ledger);
2407 
2408  // save to gcm file
2409  gnc_plugin_page_register_set_sort_reversed_gcm (leader, reverse_order);
2410 }
2411 
2412 static gchar*
2413 gnc_plugin_page_register_get_long_name (GncPluginPage* plugin_page)
2414 {
2416  GNCLedgerDisplayType ledger_type;
2417  GNCLedgerDisplay* ld;
2418  Account* leader;
2419 
2420  g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page),
2421  _ ("unknown"));
2422 
2423  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
2424  ld = priv->ledger;
2425  ledger_type = gnc_ledger_display_type (ld);
2426  leader = gnc_ledger_display_leader (ld);
2427 
2428  switch (ledger_type)
2429  {
2430  case LD_SINGLE:
2431  return gnc_account_get_full_name (leader);
2432 
2433  case LD_SUBACCOUNT:
2434  {
2435  gchar* account_full_name = gnc_account_get_full_name (leader);
2436  gchar* return_string = g_strdup_printf ("%s+", account_full_name);
2437  g_free ((gpointer*) account_full_name);
2438  return return_string;
2439  }
2440 
2441  default:
2442  break;
2443  }
2444 
2445  return NULL;
2446 }
2447 
2448 static void
2449 gnc_plugin_page_register_summarybar_position_changed (gpointer prefs,
2450  gchar* pref, gpointer user_data)
2451 {
2452  GncPluginPage* plugin_page;
2453  GncPluginPageRegister* page;
2455  GtkPositionType position = GTK_POS_BOTTOM;
2456 
2457  g_return_if_fail (user_data != NULL);
2458 
2459  if (!GNC_IS_PLUGIN_PAGE (user_data))
2460  return;
2461 
2462  plugin_page = GNC_PLUGIN_PAGE (user_data);
2463  page = GNC_PLUGIN_PAGE_REGISTER (user_data);
2464  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2465 
2466  if (priv == NULL)
2467  return;
2468 
2469  if (gnc_prefs_get_bool (GNC_PREFS_GROUP_GENERAL,
2470  GNC_PREF_SUMMARYBAR_POSITION_TOP))
2471  position = GTK_POS_TOP;
2472 
2473  gtk_box_reorder_child (GTK_BOX (priv->widget),
2474  plugin_page->summarybar,
2475  (position == GTK_POS_TOP ? 0 : -1));
2476 }
2477 
2483 Query*
2485 {
2486  GncPluginPageRegister* page;
2488 
2489  g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page), NULL);
2490 
2491  page = GNC_PLUGIN_PAGE_REGISTER (plugin_page);
2492  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2493  return gnc_ledger_display_get_query (priv->ledger);
2494 }
2495 
2496 /************************************************************/
2497 /* "Sort By" Dialog */
2498 /************************************************************/
2499 
2510 static void
2511 gnc_plugin_page_register_sort_book_option_changed (gpointer new_val,
2512  gpointer user_data)
2513 {
2515  GncPluginPageRegister* page = user_data;
2516  gboolean* new_data = (gboolean*)new_val;
2517 
2518  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2519 
2520  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2521  if (*new_data)
2522  {
2523  gtk_button_set_label (GTK_BUTTON (priv->sd.num_radio),
2524  _ ("Transaction Number"));
2525  gtk_button_set_label (GTK_BUTTON (priv->sd.act_radio), _ ("Number/Action"));
2526  }
2527  else
2528  {
2529  gtk_button_set_label (GTK_BUTTON (priv->sd.num_radio), _ ("Number"));
2530  gtk_button_set_label (GTK_BUTTON (priv->sd.act_radio), _ ("Action"));
2531  }
2532  gnc_split_reg_set_sort_type_force (priv->gsr, priv->gsr->sort_type, TRUE);
2533 }
2534 
2546 void
2548  gint response,
2549  GncPluginPageRegister* page)
2550 {
2552  GncPluginPage* plugin_page;
2553  SortType type;
2554  const gchar* order;
2555 
2556  g_return_if_fail (GTK_IS_DIALOG (dialog));
2557  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2558 
2559  ENTER (" ");
2560  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2561  plugin_page = GNC_PLUGIN_PAGE (page);
2562 
2563  if (response != GTK_RESPONSE_OK)
2564  {
2565  /* Restore the original sort order */
2566  gnc_split_reg_set_sort_reversed (priv->gsr, priv->sd.original_reverse_order,
2567  TRUE);
2568  priv->sd.reverse_order = priv->sd.original_reverse_order;
2569  gnc_split_reg_set_sort_type (priv->gsr, priv->sd.original_sort_type);
2570  priv->sd.save_order = priv->sd.original_save_order;
2571  }
2572  else
2573  {
2574  // clear the sort when unticking the save option
2575  if ((!priv->sd.save_order) && ((priv->sd.original_save_order) || (priv->sd.original_reverse_order)))
2576  {
2577  gnc_plugin_page_register_set_sort_order (plugin_page, DEFAULT_SORT_ORDER);
2578  gnc_plugin_page_register_set_sort_reversed (plugin_page, FALSE);
2579  }
2580  priv->sd.original_save_order = priv->sd.save_order;
2581 
2582  if (priv->sd.save_order)
2583  {
2584  type = gnc_split_reg_get_sort_type (priv->gsr);
2585  order = SortTypeasString (type);
2586  gnc_plugin_page_register_set_sort_order (plugin_page, order);
2587  gnc_plugin_page_register_set_sort_reversed (plugin_page,
2588  priv->sd.reverse_order);
2589  }
2590  }
2591  gnc_book_option_remove_cb (OPTION_NAME_NUM_FIELD_SOURCE,
2592  gnc_plugin_page_register_sort_book_option_changed,
2593  page);
2594  priv->sd.dialog = NULL;
2595  priv->sd.num_radio = NULL;
2596  priv->sd.act_radio = NULL;
2597  gtk_widget_destroy (GTK_WIDGET (dialog));
2598  LEAVE (" ");
2599 }
2600 
2601 
2610 void
2612  GncPluginPageRegister* page)
2613 {
2615  const gchar* name;
2616  SortType type;
2617 
2618  g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
2619  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2620 
2621  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2622  name = gtk_buildable_get_name (GTK_BUILDABLE (button));
2623  ENTER ("button %s(%p), page %p", name, button, page);
2624  type = SortTypefromString (name);
2625  gnc_split_reg_set_sort_type (priv->gsr, type);
2626  LEAVE (" ");
2627 }
2628 
2629 
2638 void
2640  GncPluginPageRegister* page)
2641 {
2643 
2644  g_return_if_fail (GTK_IS_CHECK_BUTTON (button));
2645  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2646 
2647  ENTER ("Save toggle button (%p), plugin_page %p", button, page);
2648 
2649  /* Compute the new save sort order */
2650  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2651 
2652  if (gtk_toggle_button_get_active (button))
2653  priv->sd.save_order = TRUE;
2654  else
2655  priv->sd.save_order = FALSE;
2656  LEAVE (" ");
2657 }
2658 
2667 void
2669  GncPluginPageRegister* page)
2670 
2671 {
2673 
2674  g_return_if_fail (GTK_IS_CHECK_BUTTON (button));
2675  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2676 
2677  ENTER ("Reverse toggle button (%p), plugin_page %p", button, page);
2678 
2679  /* Compute the new save sort order */
2680  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2681 
2682  priv->sd.reverse_order = gtk_toggle_button_get_active (button);
2683  gnc_split_reg_set_sort_reversed (priv->gsr, priv->sd.reverse_order, TRUE);
2684  LEAVE (" ");
2685 }
2686 
2687 /************************************************************/
2688 /* "Filter By" Dialog */
2689 /************************************************************/
2690 
2691 static void
2692 gnc_ppr_update_for_search_query (GncPluginPageRegister* page)
2693 {
2695  SplitRegister* reg;
2696 
2697  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2698  reg = gnc_ledger_display_get_split_register (priv->ledger);
2699 
2700  if (reg->type == SEARCH_LEDGER)
2701  {
2702  Query* query_tmp = gnc_ledger_display_get_query (priv->ledger);
2703 
2704  // if filter_query is NULL, then the dialogue find has been run
2705  // before coming here. if query_tmp does not equal filter_query
2706  // then the dialogue find has been run again before coming here
2707  if ((priv->filter_query == NULL) ||
2708  (!qof_query_equal (query_tmp, priv->filter_query)))
2709  {
2710  qof_query_destroy (priv->search_query);
2711  priv->search_query = qof_query_copy (query_tmp);
2712  }
2713  gnc_ledger_display_set_query (priv->ledger, priv->search_query);
2714  }
2715 }
2716 
2717 
2730 static void
2731 gnc_ppr_update_status_query (GncPluginPageRegister* page)
2732 {
2734  Query* query;
2735  SplitRegister* reg;
2736 
2737  ENTER (" ");
2738  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2739  if (!priv->ledger)
2740  {
2741  LEAVE ("no ledger");
2742  return;
2743  }
2744  // check if this a search register and save query
2745  gnc_ppr_update_for_search_query (page);
2746 
2747  query = gnc_ledger_display_get_query (priv->ledger);
2748  if (!query)
2749  {
2750  LEAVE ("no query found");
2751  return;
2752  }
2753 
2754  reg = gnc_ledger_display_get_split_register (priv->ledger);
2755 
2756  /* Remove the old status match */
2757  if (reg->type != SEARCH_LEDGER)
2758  {
2759  GSList *param_list = qof_query_build_param_list (SPLIT_RECONCILE, NULL);
2760  qof_query_purge_terms (query, param_list);
2761  g_slist_free (param_list);
2762  }
2763 
2764  /* Install the new status match */
2765  if (priv->fd.cleared_match != CLEARED_ALL)
2766  xaccQueryAddClearedMatch (query, priv->fd.cleared_match, QOF_QUERY_AND);
2767 
2768  // Set filter tooltip for summary bar
2769  gnc_plugin_page_register_set_filter_tooltip (page);
2770 
2771  // clear previous filter query and save current
2772  qof_query_destroy (priv->filter_query);
2773  priv->filter_query = qof_query_copy (query);
2774 
2775  if (priv->enable_refresh)
2776  gnc_ledger_display_refresh (priv->ledger);
2777  LEAVE (" ");
2778 }
2779 
2780 
2793 static void
2794 gnc_ppr_update_date_query (GncPluginPageRegister* page)
2795 {
2797  Query* query;
2798  SplitRegister* reg;
2799 
2800  ENTER (" ");
2801  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2802  if (!priv->ledger)
2803  {
2804  LEAVE ("no ledger");
2805  return;
2806  }
2807  // check if this a search register and save query
2808  gnc_ppr_update_for_search_query (page);
2809 
2810  query = gnc_ledger_display_get_query (priv->ledger);
2811 
2812  if (!query)
2813  {
2814  LEAVE ("no query");
2815  return;
2816  }
2817 
2818  reg = gnc_ledger_display_get_split_register (priv->ledger);
2819 
2820  /* Delete any existing old date spec. */
2821  if (reg->type != SEARCH_LEDGER)
2822  {
2823  GSList *param_list = qof_query_build_param_list (SPLIT_TRANS,
2824  TRANS_DATE_POSTED, NULL);
2825  qof_query_purge_terms (query, param_list);
2826  g_slist_free (param_list);
2827  }
2828 
2829  if (priv->fd.start_time || priv->fd.end_time)
2830  {
2831  /* Build a new spec */
2832  xaccQueryAddDateMatchTT (query,
2833  priv->fd.start_time != 0, priv->fd.start_time,
2834  priv->fd.end_time != 0, priv->fd.end_time,
2835  QOF_QUERY_AND);
2836  }
2837 
2838  if (priv->fd.days > 0)
2839  {
2840  time64 start;
2841  struct tm tm;
2842 
2843  gnc_tm_get_today_start (&tm);
2844 
2845  tm.tm_mday = tm.tm_mday - priv->fd.days;
2846  start = gnc_mktime (&tm);
2847  xaccQueryAddDateMatchTT (query, TRUE, start, FALSE, 0, QOF_QUERY_AND);
2848  }
2849 
2850  // Set filter tooltip for summary bar
2851  gnc_plugin_page_register_set_filter_tooltip (page);
2852 
2853  // clear previous filter query and save current
2854  qof_query_destroy (priv->filter_query);
2855  priv->filter_query = qof_query_copy (query);
2856 
2857  if (priv->enable_refresh)
2858  gnc_ledger_display_refresh (priv->ledger);
2859  LEAVE (" ");
2860 }
2861 
2862 
2863 /* This function converts a time64 value date to a string */
2864 static gchar*
2865 gnc_plugin_page_register_filter_time2dmy (time64 raw_time)
2866 {
2867  struct tm* timeinfo;
2868  gchar date_string[11];
2869 
2870  timeinfo = gnc_localtime (&raw_time);
2871  strftime (date_string, 11, "%d-%m-%Y", timeinfo);
2872  PINFO ("Date string is %s", date_string);
2873  gnc_tm_free (timeinfo);
2874 
2875  return g_strdup (date_string);
2876 }
2877 
2878 
2879 /* This function converts a string date to a time64 value */
2880 static time64
2881 gnc_plugin_page_register_filter_dmy2time (char* date_string)
2882 {
2883  struct tm when;
2884 
2885  PINFO ("Date string is %s", date_string);
2886  memset (&when, 0, sizeof (when));
2887 
2888  sscanf (date_string, "%d-%d-%d", &when.tm_mday,
2889  &when.tm_mon, &when.tm_year);
2890 
2891  when.tm_mon -= 1;
2892  when.tm_year -= 1900;
2893 
2894  return gnc_mktime (&when);
2895 }
2896 
2897 
2908 void
2910  GncPluginPageRegister* page)
2911 {
2913  const gchar* name;
2914  gint i, value;
2915 
2916  g_return_if_fail (GTK_IS_CHECK_BUTTON (button));
2917  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2918 
2919  name = gtk_buildable_get_name (GTK_BUILDABLE (button));
2920  ENTER ("toggle button %s (%p), plugin_page %p", name, button, page);
2921 
2922  /* Determine what status bit to change */
2923  value = CLEARED_NONE;
2924  for (i = 0; status_actions[i].action_name; i++)
2925  {
2926  if (g_strcmp0 (name, status_actions[i].action_name) == 0)
2927  {
2928  value = status_actions[i].value;
2929  break;
2930  }
2931  }
2932 
2933  /* Compute the new match status */
2934  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2935  if (gtk_toggle_button_get_active (button))
2936  priv->fd.cleared_match |= value;
2937  else
2938  priv->fd.cleared_match &= ~value;
2939  gnc_ppr_update_status_query (page);
2940  LEAVE (" ");
2941 }
2942 
2943 
2953 void
2955  GncPluginPageRegister* page)
2956 {
2958  GtkWidget* widget;
2959  gint i;
2960 
2961  g_return_if_fail (GTK_IS_BUTTON (button));
2962  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2963 
2964  ENTER ("(button %p, page %p)", button, page);
2965 
2966  /* Turn on all the check menu items */
2967  for (i = 0; status_actions[i].action_name; i++)
2968  {
2969  widget = status_actions[i].widget;
2970  g_signal_handlers_block_by_func (widget,
2972  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
2973  g_signal_handlers_unblock_by_func (widget,
2975  }
2976 
2977  /* Set the requested status */
2978  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2979  priv->fd.cleared_match = CLEARED_ALL;
2980  gnc_ppr_update_status_query (page);
2981  LEAVE (" ");
2982 }
2983 
2984 
2996 static void
2997 get_filter_times (GncPluginPageRegister* page)
2998 {
3000  time64 time_val;
3001 
3002  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3003  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (
3004  priv->fd.start_date_choose)))
3005  {
3006  time_val = gnc_date_edit_get_date (GNC_DATE_EDIT (priv->fd.start_date));
3007  time_val = gnc_time64_get_day_start (time_val);
3008  priv->fd.start_time = time_val;
3009  }
3010  else
3011  {
3012  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (
3013  priv->fd.start_date_today)))
3014  {
3015  priv->fd.start_time = gnc_time64_get_today_start();
3016  }
3017  else
3018  {
3019  priv->fd.start_time = 0;
3020  }
3021  }
3022 
3023  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (
3024  priv->fd.end_date_choose)))
3025  {
3026  time_val = gnc_date_edit_get_date (GNC_DATE_EDIT (priv->fd.end_date));
3027  time_val = gnc_time64_get_day_end (time_val);
3028  priv->fd.end_time = time_val;
3029  }
3030  else
3031  {
3032  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (
3033  priv->fd.start_date_today)))
3034  {
3035  priv->fd.end_time = gnc_time64_get_today_end();
3036  }
3037  else
3038  {
3039  priv->fd.end_time = 0;
3040  }
3041  }
3042 }
3043 
3044 
3056 void
3058  GncPluginPageRegister* page)
3059 {
3061  gboolean active;
3062  const gchar* name;
3063 
3064  g_return_if_fail (GTK_IS_RADIO_BUTTON (button));
3065  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3066 
3067  ENTER ("(button %p, page %p)", button, page);
3068  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3069  name = gtk_buildable_get_name (GTK_BUILDABLE (button));
3070  active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
3071 
3072  if (active && g_strcmp0 (name, "filter_show_range") == 0)
3073  {
3074  gtk_widget_set_sensitive (priv->fd.table, active);
3075  gtk_widget_set_sensitive (priv->fd.num_days, !active);
3076  get_filter_times (page);
3077  }
3078  else if (active && g_strcmp0 (name, "filter_show_days") == 0)
3079  {
3080  gtk_widget_set_sensitive (priv->fd.table, !active);
3081  gtk_widget_set_sensitive (priv->fd.num_days, active);
3082  gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->fd.num_days), priv->fd.days);
3083  }
3084  else
3085  {
3086  gtk_widget_set_sensitive (priv->fd.table, FALSE);
3087  gtk_widget_set_sensitive (priv->fd.num_days, FALSE);
3088  priv->fd.days = 0;
3089  priv->fd.start_time = 0;
3090  priv->fd.end_time = 0;
3091  }
3092  gnc_ppr_update_date_query (page);
3093  LEAVE (" ");
3094 }
3095 
3096 void
3098 {
3100 
3101  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
3102 
3103  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
3104 
3105  priv->fd.days = 0;
3106  priv->fd.start_time = 0;
3107  priv->fd.end_time = 0;
3108  priv->fd.cleared_match = (gint)g_ascii_strtoll (DEFAULT_FILTER, NULL, 16);
3109 
3110  gnc_ppr_update_date_query (GNC_PLUGIN_PAGE_REGISTER(plugin_page));
3111 }
3112 
3123 void
3125  GncPluginPageRegister* page)
3126 {
3128 
3129  g_return_if_fail (GTK_IS_SPIN_BUTTON (button));
3130  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3131 
3132  ENTER ("(button %p, page %p)", button, page);
3133  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3134 
3135  priv->fd.days = gtk_spin_button_get_value (GTK_SPIN_BUTTON (button));
3136  gnc_ppr_update_date_query (page);
3137  LEAVE (" ");
3138 }
3139 
3140 
3151 static void
3152 gnc_plugin_page_register_filter_gde_changed_cb (GtkWidget* unused,
3153  GncPluginPageRegister* page)
3154 {
3155  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3156 
3157  ENTER ("(widget %s(%p), page %p)",
3158  gtk_buildable_get_name (GTK_BUILDABLE (unused)), unused, page);
3159  get_filter_times (page);
3160  gnc_ppr_update_date_query (page);
3161  LEAVE (" ");
3162 }
3163 
3164 
3184 void
3186  GncPluginPageRegister* page)
3187 {
3189  const gchar* name;
3190  gboolean active;
3191 
3192  g_return_if_fail (GTK_IS_RADIO_BUTTON (radio));
3193  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3194 
3195  ENTER ("(radio %s(%p), page %p)",
3196  gtk_buildable_get_name (GTK_BUILDABLE (radio)), radio, page);
3197  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3198  if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio)))
3199  {
3200  LEAVE ("1st callback of pair. Defer to 2nd callback.");
3201  return;
3202  }
3203 
3204  name = gtk_buildable_get_name (GTK_BUILDABLE (radio));
3205  active = !g_strcmp0 (name, "start_date_choose");
3206  gtk_widget_set_sensitive (priv->fd.start_date, active);
3207  get_filter_times (page);
3208  gnc_ppr_update_date_query (page);
3209  LEAVE (" ");
3210 }
3211 
3212 
3232 void
3234  GncPluginPageRegister* page)
3235 {
3237  const gchar* name;
3238  gboolean active;
3239 
3240  g_return_if_fail (GTK_IS_RADIO_BUTTON (radio));
3241  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3242 
3243  ENTER ("(radio %s(%p), page %p)",
3244  gtk_buildable_get_name (GTK_BUILDABLE (radio)), radio, page);
3245  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3246  if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio)))
3247  {
3248  LEAVE ("1st callback of pair. Defer to 2nd callback.");
3249  return;
3250  }
3251 
3252  name = gtk_buildable_get_name (GTK_BUILDABLE (radio));
3253  active = !g_strcmp0 (name, "end_date_choose");
3254  gtk_widget_set_sensitive (priv->fd.end_date, active);
3255  get_filter_times (page);
3256  gnc_ppr_update_date_query (page);
3257  LEAVE (" ");
3258 }
3259 
3260 
3269 void
3271  GncPluginPageRegister* page)
3272 {
3274 
3275  g_return_if_fail (GTK_IS_CHECK_BUTTON (button));
3276  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3277 
3278  ENTER ("Save toggle button (%p), plugin_page %p", button, page);
3279 
3280  /* Compute the new save filter status */
3281  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3282  if (gtk_toggle_button_get_active (button))
3283  priv->fd.save_filter = TRUE;
3284  else
3285  priv->fd.save_filter = FALSE;
3286  LEAVE (" ");
3287 }
3288 
3289 
3301 void
3303  gint response,
3304  GncPluginPageRegister* page)
3305 {
3307  GncPluginPage* plugin_page;
3308 
3309  g_return_if_fail (GTK_IS_DIALOG (dialog));
3310  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3311 
3312  ENTER (" ");
3313  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3314  plugin_page = GNC_PLUGIN_PAGE (page);
3315 
3316  if (response != GTK_RESPONSE_OK)
3317  {
3318  /* Remove the old status match */
3319  priv->fd.cleared_match = priv->fd.original_cleared_match;
3320  priv->enable_refresh = FALSE;
3321  gnc_ppr_update_status_query (page);
3322  priv->enable_refresh = TRUE;
3323  priv->fd.start_time = priv->fd.original_start_time;
3324  priv->fd.end_time = priv->fd.original_end_time;
3325  priv->fd.days = priv->fd.original_days;
3326  priv->fd.save_filter = priv->fd.original_save_filter;
3327  gnc_ppr_update_date_query (page);
3328  }
3329  else
3330  {
3331  // clear the filter when unticking the save option
3332  if ((priv->fd.save_filter == FALSE) && (priv->fd.original_save_filter == TRUE))
3333  gnc_plugin_page_register_set_filter (plugin_page, NULL);
3334 
3335  priv->fd.original_save_filter = priv->fd.save_filter;
3336 
3337  if (priv->fd.save_filter)
3338  {
3339  gchar *filter;
3340  GList *flist = NULL;
3341 
3342  // cleared match
3343  flist = g_list_prepend
3344  (flist, g_strdup_printf ("0x%04x", priv->fd.cleared_match));
3345 
3346  // start time
3347  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->fd.start_date_choose)) && priv->fd.start_time != 0)
3348  flist = g_list_prepend (flist, gnc_plugin_page_register_filter_time2dmy (priv->fd.start_time));
3349  else
3350  flist = g_list_prepend (flist, g_strdup ("0"));
3351 
3352  // end time
3353  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->fd.end_date_choose))
3354  && priv->fd.end_time != 0)
3355  flist = g_list_prepend (flist, gnc_plugin_page_register_filter_time2dmy (priv->fd.end_time));
3356  else
3357  flist = g_list_prepend (flist, g_strdup ("0"));
3358 
3359  // number of days
3360  if (priv->fd.days > 0)
3361  flist = g_list_prepend (flist, g_strdup_printf ("%d", priv->fd.days));
3362  else
3363  flist = g_list_prepend (flist, g_strdup ("0"));
3364 
3365  flist = g_list_reverse (flist);
3366  filter = gnc_g_list_stringjoin (flist, ",");
3367  PINFO ("The filter to save is %s", filter);
3368  gnc_plugin_page_register_set_filter (plugin_page, filter);
3369  g_free (filter);
3370  g_list_free_full (flist, g_free);
3371  }
3372  }
3373  priv->fd.dialog = NULL;
3374  gtk_widget_destroy (GTK_WIDGET (dialog));
3375  LEAVE (" ");
3376 }
3377 
3378 static void
3379 gpp_update_match_filter_text (cleared_match_t match, const guint mask,
3380  const gchar* filter_name, GList **show, GList **hide)
3381 {
3382  if ((match & mask) == mask)
3383  *show = g_list_prepend (*show, g_strdup (filter_name));
3384  else
3385  *hide = g_list_prepend (*hide, g_strdup (filter_name));
3386 }
3387 
3388 static void
3389 gnc_plugin_page_register_set_filter_tooltip (GncPluginPageRegister* page)
3390 {
3392  GList *t_list = NULL;
3393 
3394  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3395 
3396  ENTER (" ");
3397  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3398 
3399  // filtered start time
3400  if (priv->fd.start_time != 0)
3401  {
3402  gchar* sdate = qof_print_date (priv->fd.start_time);
3403  t_list = g_list_prepend
3404  (t_list, g_strdup_printf ("%s %s", _("Start Date:"), sdate));
3405  g_free (sdate);
3406  }
3407 
3408  // filtered number of days
3409  if (priv->fd.days > 0)
3410  t_list = g_list_prepend
3411  (t_list, g_strdup_printf ("%s %d", _("Show previous number of days:"),
3412  priv->fd.days));
3413 
3414  // filtered end time
3415  if (priv->fd.end_time != 0)
3416  {
3417  gchar* edate = qof_print_date (priv->fd.end_time);
3418  t_list = g_list_prepend
3419  (t_list, g_strdup_printf ("%s %s", _("End Date:"), edate));
3420  g_free (edate);
3421  }
3422 
3423  // filtered match items
3424  if (priv->fd.cleared_match != CLEARED_ALL)
3425  {
3426  GList *show = NULL;
3427  GList *hide = NULL;
3428 
3429  gpp_update_match_filter_text (priv->fd.cleared_match, 0x01, _ ("Unreconciled"),
3430  &show, &hide);
3431  gpp_update_match_filter_text (priv->fd.cleared_match, 0x02, _ ("Cleared"),
3432  &show, &hide);
3433  gpp_update_match_filter_text (priv->fd.cleared_match, 0x04, _ ("Reconciled"),
3434  &show, &hide);
3435  gpp_update_match_filter_text (priv->fd.cleared_match, 0x08, _ ("Frozen"),
3436  &show, &hide);
3437  gpp_update_match_filter_text (priv->fd.cleared_match, 0x10, _ ("Voided"),
3438  &show, &hide);
3439 
3440  show = g_list_reverse (show);
3441  hide = g_list_reverse (hide);
3442 
3443  if (show)
3444  {
3445  char *str = gnc_g_list_stringjoin (show, ", ");
3446  t_list = g_list_prepend
3447  (t_list, g_strdup_printf ("%s %s", _("Show:"), str));
3448  g_free (str);
3449  }
3450 
3451  if (hide)
3452  {
3453  char *str = gnc_g_list_stringjoin (hide, ", ");
3454  t_list = g_list_prepend
3455  (t_list, g_strdup_printf ("%s %s", _("Hide:"), str));
3456  g_free (str);
3457  }
3458 
3459  g_list_free_full (show, g_free);
3460  g_list_free_full (hide, g_free);
3461  }
3462 
3463  t_list = g_list_reverse (t_list);
3464 
3465  if (t_list)
3466  t_list = g_list_prepend (t_list, g_strdup (_("Filter By:")));
3467 
3468  // free the existing text if present
3469  if (priv->gsr->filter_text != NULL)
3470  g_free (priv->gsr->filter_text);
3471 
3472  // set the tooltip text variable in the gsr
3473  priv->gsr->filter_text = gnc_g_list_stringjoin (t_list, "\n");
3474 
3475  g_list_free_full (t_list, g_free);
3476 
3477  LEAVE (" ");
3478 }
3479 
3480 
3481 static void
3482 gnc_plugin_page_register_update_page_icon (GncPluginPage* plugin_page)
3483 {
3485  gboolean read_only;
3486 
3487  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
3488 
3489  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
3490 
3491  if (qof_book_is_readonly (gnc_get_current_book()) ||
3492  gnc_split_reg_get_read_only (priv->gsr))
3493  read_only = TRUE;
3494  else
3495  read_only = FALSE;
3496 
3497  main_window_update_page_set_read_only_icon (GNC_PLUGIN_PAGE(plugin_page),
3498  read_only);
3499 }
3500 
3501 /************************************************************/
3502 /* Report Helper Functions */
3503 /************************************************************/
3504 
3505 static char*
3506 gnc_reg_get_name (GNCLedgerDisplay* ledger, gboolean for_window)
3507 {
3508  Account* leader;
3509  SplitRegister* reg;
3510  gchar* account_name;
3511  gchar* reg_name;
3512  gchar* name;
3513  GNCLedgerDisplayType ledger_type;
3514 
3515  if (ledger == NULL)
3516  return NULL;
3517 
3519  ledger_type = gnc_ledger_display_type (ledger);
3520 
3521  switch (reg->type)
3522  {
3523  case GENERAL_JOURNAL:
3524  case INCOME_LEDGER:
3525  if (for_window)
3526  reg_name = _ ("General Journal");
3527  else
3528  reg_name = _ ("Transaction Report");
3529  break;
3530  case PORTFOLIO_LEDGER:
3531  if (for_window)
3532  reg_name = _ ("Portfolio");
3533  else
3534  reg_name = _ ("Portfolio Report");
3535  break;
3536  case SEARCH_LEDGER:
3537  if (for_window)
3538  reg_name = _ ("Search Results");
3539  else
3540  reg_name = _ ("Search Results Report");
3541  break;
3542  default:
3543  if (for_window)
3544  reg_name = _ ("Register");
3545  else
3546  reg_name = _ ("Transaction Report");
3547  break;
3548  }
3549 
3550  leader = gnc_ledger_display_leader (ledger);
3551 
3552  if ((leader != NULL) && (ledger_type != LD_GL))
3553  {
3554  account_name = gnc_account_get_full_name (leader);
3555 
3556  if (ledger_type == LD_SINGLE)
3557  {
3558  name = g_strconcat (account_name, " - ", reg_name, NULL);
3559  }
3560  else
3561  {
3562  name = g_strconcat (account_name, " ", _ ("and subaccounts"), " - ", reg_name,
3563  NULL);
3564  }
3565  g_free (account_name);
3566  }
3567  else
3568  name = g_strdup (reg_name);
3569 
3570  return name;
3571 }
3572 
3573 static int
3574 report_helper (GNCLedgerDisplay* ledger, Split* split, Query* query)
3575 {
3576  SplitRegister* reg = gnc_ledger_display_get_split_register (ledger);
3577  Account* account;
3578  char* str;
3579  const char* tmp;
3580  swig_type_info* qtype;
3581  SCM args;
3582  SCM func;
3583  SCM arg;
3584 
3585  args = SCM_EOL;
3586 
3587  func = scm_c_eval_string ("gnc:register-report-create");
3588  g_return_val_if_fail (scm_is_procedure (func), -1);
3589 
3591  arg = scm_from_utf8_string (tmp ? tmp : _ ("Credit"));
3592  args = scm_cons (arg, args);
3593 
3595  arg = scm_from_utf8_string (tmp ? tmp : _ ("Debit"));
3596  args = scm_cons (arg, args);
3597 
3598  str = gnc_reg_get_name (ledger, FALSE);
3599  arg = scm_from_utf8_string (str ? str : "");
3600  args = scm_cons (arg, args);
3601  g_free (str);
3602 
3603  arg = SCM_BOOL (reg->use_double_line);
3604  args = scm_cons (arg, args);
3605 
3606  arg = SCM_BOOL (reg->type == GENERAL_JOURNAL || reg->type == INCOME_LEDGER
3607  || reg->type == SEARCH_LEDGER);
3608  args = scm_cons (arg, args);
3609 
3610  arg = SCM_BOOL (reg->style == REG_STYLE_JOURNAL);
3611  args = scm_cons (arg, args);
3612 
3613  if (!query)
3614  {
3615  query = gnc_ledger_display_get_query (ledger);
3616  g_return_val_if_fail (query != NULL, -1);
3617  }
3618 
3619  qtype = SWIG_TypeQuery ("_p__QofQuery");
3620  g_return_val_if_fail (qtype, -1);
3621 
3622  arg = SWIG_NewPointerObj (query, qtype, 0);
3623  args = scm_cons (arg, args);
3624  g_return_val_if_fail (arg != SCM_UNDEFINED, -1);
3625 
3626 
3627  if (split)
3628  {
3629  qtype = SWIG_TypeQuery ("_p_Split");
3630  g_return_val_if_fail (qtype, -1);
3631  arg = SWIG_NewPointerObj (split, qtype, 0);
3632  }
3633  else
3634  {
3635  arg = SCM_BOOL_F;
3636  }
3637  args = scm_cons (arg, args);
3638  g_return_val_if_fail (arg != SCM_UNDEFINED, -1);
3639 
3640 
3641  qtype = SWIG_TypeQuery ("_p_Account");
3642  g_return_val_if_fail (qtype, -1);
3643 
3644  account = gnc_ledger_display_leader (ledger);
3645  arg = SWIG_NewPointerObj (account, qtype, 0);
3646  args = scm_cons (arg, args);
3647  g_return_val_if_fail (arg != SCM_UNDEFINED, -1);
3648 
3649 
3650  /* Apply the function to the args */
3651  arg = scm_apply (func, args, SCM_EOL);
3652  g_return_val_if_fail (scm_is_exact (arg), -1);
3653 
3654  return scm_to_int (arg);
3655 }
3656 
3657 /************************************************************/
3658 /* Command callbacks */
3659 /************************************************************/
3660 
3661 static void
3662 gnc_plugin_page_register_cmd_print_check (GtkAction* action,
3663  GncPluginPageRegister* plugin_page)
3664 {
3666  SplitRegister* reg;
3667  Split* split;
3668  Transaction* trans;
3669  GList* splits = NULL, *item;
3670  GNCLedgerDisplayType ledger_type;
3671  Account* account;
3672  GtkWidget* window;
3673 
3674  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
3675 
3676  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
3677 
3678  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
3679  reg = gnc_ledger_display_get_split_register (priv->ledger);
3680  ledger_type = gnc_ledger_display_type (priv->ledger);
3681  window = gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (plugin_page));
3682  if (ledger_type == LD_SINGLE || ledger_type == LD_SUBACCOUNT)
3683  {
3684  account = gnc_plugin_page_register_get_account (plugin_page);
3686  trans = xaccSplitGetParent (split);
3687 
3688  if (split && trans)
3689  {
3690  if (xaccSplitGetAccount (split) == account)
3691  {
3692  splits = g_list_prepend (splits, split);
3693  gnc_ui_print_check_dialog_create (window, splits);
3694  g_list_free (splits);
3695  }
3696  else
3697  {
3698  /* This split is not for the account shown in this register. Get the
3699  split that anchors the transaction to the registor */
3700  split = gnc_split_register_get_current_trans_split (reg, NULL);
3701  if (split)
3702  {
3703  splits = g_list_prepend (splits, split);
3704  gnc_ui_print_check_dialog_create (window, splits);
3705  g_list_free (splits);
3706  }
3707  }
3708  }
3709  }
3710  else if (ledger_type == LD_GL && reg->type == SEARCH_LEDGER)
3711  {
3712  Account* common_acct = NULL;
3713 
3714  /* the following GList* splits must not be freed */
3715  splits = qof_query_run (gnc_ledger_display_get_query (priv->ledger));
3716 
3717  /* Make sure each split is from the same account */
3718  for (item = splits; item; item = g_list_next (item))
3719  {
3720  split = (Split*) item->data;
3721  if (common_acct == NULL)
3722  {
3723  common_acct = xaccSplitGetAccount (split);
3724  }
3725  else
3726  {
3727  if (xaccSplitGetAccount (split) != common_acct)
3728  {
3729  GtkWidget* dialog;
3730  gint response;
3731  const gchar* title = _ ("Print checks from multiple accounts?");
3732  const gchar* message =
3733  _ ("This search result contains splits from more than one account. "
3734  "Do you want to print the checks even though they are not all "
3735  "from the same account?");
3736  dialog = gtk_message_dialog_new (GTK_WINDOW (window),
3737  GTK_DIALOG_DESTROY_WITH_PARENT,
3738  GTK_MESSAGE_WARNING,
3739  GTK_BUTTONS_CANCEL,
3740  "%s", title);
3741  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
3742  "%s", message);
3743  gtk_dialog_add_button (GTK_DIALOG (dialog), _ ("_Print checks"),
3744  GTK_RESPONSE_YES);
3745  response = gnc_dialog_run (GTK_DIALOG (dialog),
3746  GNC_PREF_WARN_CHECKPRINTING_MULTI_ACCT);
3747  gtk_widget_destroy (dialog);
3748  if (response != GTK_RESPONSE_YES)
3749  {
3750  LEAVE ("Multiple accounts");
3751  return;
3752  }
3753  break;
3754  }
3755  }
3756  }
3757  gnc_ui_print_check_dialog_create (window, splits);
3758  }
3759  else
3760  {
3761  gnc_error_dialog (GTK_WINDOW (window), "%s",
3762  _ ("You can only print checks from a bank account register or search results."));
3763  LEAVE ("Unsupported ledger type");
3764  return;
3765  }
3766  LEAVE (" ");
3767 }
3768 
3769 
3770 static void
3771 gnc_plugin_page_register_cmd_cut (GtkAction* action,
3772  GncPluginPageRegister* page)
3773 {
3775 
3776  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3777 
3778  ENTER ("(action %p, page %p)", action, page);
3779  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3780  gnucash_register_cut_clipboard (priv->gsr->reg);
3781  LEAVE ("");
3782 }
3783 
3784 
3785 static void
3786 gnc_plugin_page_register_cmd_copy (GtkAction* action,
3787  GncPluginPageRegister* page)
3788 {
3790 
3791  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3792 
3793  ENTER ("(action %p, page %p)", action, page);
3794  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3795  gnucash_register_copy_clipboard (priv->gsr->reg);
3796  LEAVE ("");
3797 }
3798 
3799 
3800 static void
3801 gnc_plugin_page_register_cmd_paste (GtkAction* action,
3802  GncPluginPageRegister* page)
3803 {
3805 
3806  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3807 
3808  ENTER ("(action %p, page %p)", action, page);
3809  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3810  gnucash_register_paste_clipboard (priv->gsr->reg);
3811  LEAVE ("");
3812 }
3813 
3814 
3815 static void
3816 gnc_plugin_page_register_cmd_edit_account (GtkAction* action,
3817  GncPluginPageRegister* page)
3818 {
3819  Account* account;
3820  GtkWindow* parent = GTK_WINDOW (gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (
3821  page)));
3822  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3823 
3824  ENTER ("(action %p, page %p)", action, page);
3825  account = gnc_plugin_page_register_get_account (page);
3826  if (account)
3827  gnc_ui_edit_account_window (parent, account);
3828  LEAVE (" ");
3829 }
3830 
3831 
3832 static void
3833 gnc_plugin_page_register_cmd_find_account (GtkAction* action,
3834  GncPluginPageRegister* page)
3835 {
3836  GtkWidget* window;
3837 
3838  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3839 
3840  window = gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page));
3841  gnc_find_account_dialog (window, NULL);
3842 }
3843 
3844 
3845 static void
3846 gnc_plugin_page_register_cmd_find_transactions (GtkAction* action,
3847  GncPluginPageRegister* page)
3848 {
3850  GtkWindow* window;
3851 
3852  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3853 
3854  ENTER ("(action %p, page %p)", action, page);
3855  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3856  window = GTK_WINDOW (gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page)));
3857  gnc_ui_find_transactions_dialog_create (window, priv->ledger);
3858  LEAVE (" ");
3859 }
3860 
3861 
3862 static void
3863 gnc_plugin_page_register_cmd_edit_tax_options (GtkAction* action,
3864  GncPluginPageRegister* page)
3865 {
3867  GtkWidget *window;
3868  Account* account;
3869 
3870  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3871 
3872  ENTER ("(action %p, page %p)", action, page);
3873  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3874  window = gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page));
3875  account = gnc_plugin_page_register_get_account (page);
3876  gnc_tax_info_dialog (window, account);
3877  LEAVE (" ");
3878 }
3879 
3880 static void
3881 gnc_plugin_page_register_cmd_cut_transaction (GtkAction* action,
3882  GncPluginPageRegister* plugin_page)
3883 {
3885 
3886  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
3887 
3888  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
3889 
3890  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
3891  gsr_default_cut_txn_handler (priv->gsr, NULL);
3892  LEAVE (" ");
3893 }
3894 
3895 
3896 static void
3897 gnc_plugin_page_register_cmd_copy_transaction (GtkAction* action,
3898  GncPluginPageRegister* page)
3899 {
3901  SplitRegister* reg;
3902 
3903  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3904 
3905  ENTER ("(action %p, page %p)", action, page);
3906  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3907  reg = gnc_ledger_display_get_split_register (priv->ledger);
3909  LEAVE (" ");
3910 }
3911 
3912 
3913 static void
3914 gnc_plugin_page_register_cmd_paste_transaction (GtkAction* action,
3915  GncPluginPageRegister* page)
3916 {
3918  SplitRegister* reg;
3919 
3920  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3921 
3922  ENTER ("(action %p, page %p)", action, page);
3923  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3924  reg = gnc_ledger_display_get_split_register (priv->ledger);
3926  LEAVE (" ");
3927 }
3928 
3929 
3930 static void
3931 gnc_plugin_page_register_cmd_void_transaction (GtkAction* action,
3932  GncPluginPageRegister* page)
3933 {
3935  GtkWidget* dialog, *entry;
3936  SplitRegister* reg;
3937  Transaction* trans;
3938  GtkBuilder* builder;
3939  const char* reason;
3940  gint result;
3941  GtkWindow* window;
3942 
3943  ENTER ("(action %p, page %p)", action, page);
3944 
3945  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3946 
3947  window = GTK_WINDOW (gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page)));
3948  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3949  reg = gnc_ledger_display_get_split_register (priv->ledger);
3951  if (trans == NULL)
3952  return;
3953  if (xaccTransHasSplitsInState (trans, VREC))
3954  return;
3955  if (xaccTransHasReconciledSplits (trans) ||
3957  {
3958  gnc_error_dialog (window, "%s",
3959  _ ("You cannot void a transaction with reconciled or cleared splits."));
3960  return;
3961  }
3962  reason = xaccTransGetReadOnly (trans);
3963  if (reason)
3964  {
3965  gnc_error_dialog (window,
3966  _ ("This transaction is marked read-only with the comment: '%s'"), reason);
3967  return;
3968  }
3969 
3970  if (!gnc_plugin_page_register_finish_pending (GNC_PLUGIN_PAGE (page)))
3971  return;
3972 
3973  builder = gtk_builder_new();
3974  gnc_builder_add_from_file (builder, "gnc-plugin-page-register.glade",
3975  "void_transaction_dialog");
3976  dialog = GTK_WIDGET (gtk_builder_get_object (builder,
3977  "void_transaction_dialog"));
3978  entry = GTK_WIDGET (gtk_builder_get_object (builder, "reason"));
3979 
3980  gtk_window_set_transient_for (GTK_WINDOW (dialog), window);
3981 
3982  result = gtk_dialog_run (GTK_DIALOG (dialog));
3983  if (result == GTK_RESPONSE_OK)
3984  {
3985  reason = gtk_entry_get_text (GTK_ENTRY (entry));
3986  if (reason == NULL)
3987  reason = "";
3989  }
3990 
3991  /* All done. Get rid of it. */
3992  gtk_widget_destroy (dialog);
3993  g_object_unref (G_OBJECT (builder));
3994 }
3995 
3996 
3997 static void
3998 gnc_plugin_page_register_cmd_unvoid_transaction (GtkAction* action,
3999  GncPluginPageRegister* page)
4000 {
4002  SplitRegister* reg;
4003  Transaction* trans;
4004 
4005  ENTER ("(action %p, page %p)", action, page);
4006 
4007  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
4008 
4009  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
4010  reg = gnc_ledger_display_get_split_register (priv->ledger);
4012  if (!xaccTransHasSplitsInState (trans, VREC))
4013  return;
4015  LEAVE (" ");
4016 }
4017 
4018 
4019 static void
4020 gnc_plugin_page_register_cmd_reverse_transaction (GtkAction* action,
4021  GncPluginPageRegister* page)
4022 {
4024  SplitRegister* reg;
4025  GNCSplitReg* gsr;
4026  Transaction* trans, *new_trans;
4027  time64 date = gnc_time (NULL);
4028  GtkWidget *window;
4029  Account *account;
4030  Split *split;
4031 
4032  ENTER ("(action %p, page %p)", action, page);
4033 
4034  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
4035 
4036  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
4037  reg = gnc_ledger_display_get_split_register (priv->ledger);
4038  window = gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page));
4040  if (trans == NULL)
4041  return;
4042 
4044  account = xaccSplitGetAccount (split);
4045 
4046  if (!account)
4047  {
4048  LEAVE ("shouldn't try to reverse the blank transaction...");
4049  return;
4050  }
4051 
4052  new_trans = xaccTransGetReversedBy (trans);
4053  if (new_trans)
4054  {
4055  const char *rev = _("A reversing entry has already been created for this transaction.");
4056  const char *jump = _("Jump to the transaction?");
4057  if (gnc_verify_dialog (GTK_WINDOW (window), TRUE, "%s\n\n%s", rev, jump))
4058  goto jump_to_trans;
4059  else
4060  return;
4061  }
4062 
4063  if (!gnc_dup_time64_dialog (window, _("Reverse Transaction"),
4064  _("New Transaction Information"), &date))
4065  {
4066  LEAVE ("reverse cancelled");
4067  return;
4068  }
4069 
4070  gnc_suspend_gui_refresh();
4071  new_trans = xaccTransReverse (trans);
4072 
4073  /* Clear transaction level info */
4074  xaccTransSetDatePostedSecsNormalized (new_trans, date);
4075  xaccTransSetDateEnteredSecs (new_trans, gnc_time (NULL));
4076 
4077  gnc_resume_gui_refresh();
4078 
4079  jump_to_trans:
4080  /* Now jump to new trans */
4081  gsr = gnc_plugin_page_register_get_gsr (GNC_PLUGIN_PAGE (page));
4082  split = xaccTransFindSplitByAccount(new_trans, account);
4083 
4084  /* Test for visibility of split */
4085  if (gnc_split_reg_clear_filter_for_split (gsr, split))
4086  gnc_plugin_page_register_clear_current_filter (GNC_PLUGIN_PAGE(page));
4087 
4088  gnc_split_reg_jump_to_split (gsr, split);
4089  LEAVE (" ");
4090 }
4091 
4092 static gboolean
4093 gnc_plugin_page_register_show_fs_save (GncPluginPageRegister* page)
4094 {
4095  GncPluginPageRegisterPrivate* priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (
4096  page);
4097  GNCLedgerDisplayType ledger_type = gnc_ledger_display_type (priv->ledger);
4098  SplitRegister* reg = gnc_ledger_display_get_split_register (priv->ledger);
4099 
4100  if (ledger_type == LD_SINGLE || ledger_type == LD_SUBACCOUNT)
4101  return TRUE;
4102  else
4103  {
4104  switch (reg->type)
4105  {
4106  case GENERAL_JOURNAL:
4107  return TRUE;
4108  break;
4109 
4110  case INCOME_LEDGER:
4111  case PORTFOLIO_LEDGER:
4112  case SEARCH_LEDGER:
4113  default:
4114  return FALSE;
4115  break;
4116  }
4117  }
4118 }
4119 
4120 static void
4121 gnc_plugin_page_register_cmd_view_sort_by (GtkAction* action,
4122  GncPluginPageRegister* page)
4123 {
4125  SplitRegister* reg;
4126  GtkWidget* dialog, *button;
4127  GtkBuilder* builder;
4128  SortType sort;
4129  const gchar* name;
4130  gchar* title;
4131 
4132  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
4133  ENTER ("(action %p, page %p)", action, page);
4134 
4135  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
4136  if (priv->sd.dialog)
4137  {
4138  gtk_window_present (GTK_WINDOW (priv->sd.dialog));
4139  LEAVE ("existing dialog");
4140  return;
4141  }
4142 
4143  /* Create the dialog */
4144 
4145  builder = gtk_builder_new();
4146  gnc_builder_add_from_file (builder, "gnc-plugin-page-register.glade",
4147  "sort_by_dialog");
4148  dialog = GTK_WIDGET (gtk_builder_get_object (builder, "sort_by_dialog"));
4149  priv->sd.dialog = dialog;
4150  gtk_window_set_transient_for (GTK_WINDOW (dialog),
4151  gnc_window_get_gtk_window (GNC_WINDOW (GNC_PLUGIN_PAGE (page)->window)));
4152  /* Translators: The %s is the name of the plugin page */
4153  title = g_strdup_printf (_ ("Sort %s by..."),
4154  gnc_plugin_page_get_page_name (GNC_PLUGIN_PAGE (page)));
4155  gtk_window_set_title (GTK_WINDOW (dialog), title);
4156  g_free (title);
4157 
4158  /* Set the button for the current sort order */
4159  sort = gnc_split_reg_get_sort_type (priv->gsr);
4160  name = SortTypeasString (sort);
4161  button = GTK_WIDGET (gtk_builder_get_object (builder, name));
4162  DEBUG ("current sort %d, button %s(%p)", sort, name, button);
4163  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
4164  priv->sd.original_sort_type = sort;
4165 
4166  button = GTK_WIDGET (gtk_builder_get_object (builder, "sort_save"));
4167  if (priv->sd.save_order == TRUE)
4168  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
4169 
4170  // hide the save button if appropriate
4171  gtk_widget_set_visible (GTK_WIDGET (button),
4172  gnc_plugin_page_register_show_fs_save (page));
4173 
4174  /* Set the button for the current reverse_order order */
4175  button = GTK_WIDGET (gtk_builder_get_object (builder, "sort_reverse"));
4176  if (priv->sd.reverse_order == TRUE)
4177  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
4178  priv->sd.original_reverse_order = priv->sd.reverse_order;
4179 
4180  priv->sd.num_radio = GTK_WIDGET (gtk_builder_get_object (builder, "BY_NUM"));
4181  priv->sd.act_radio = GTK_WIDGET (gtk_builder_get_object (builder,
4182  "BY_ACTION"));
4183  /* Adjust labels related to Num/Action radio buttons based on book option */
4184  reg = gnc_ledger_display_get_split_register (priv->ledger);
4185  if (reg && !reg->use_tran_num_for_num_field)
4186  {
4187  gtk_button_set_label (GTK_BUTTON (priv->sd.num_radio),
4188  _ ("Transaction Number"));
4189  gtk_button_set_label (GTK_BUTTON (priv->sd.act_radio), _ ("Number/Action"));
4190  }
4191  gnc_book_option_register_cb (OPTION_NAME_NUM_FIELD_SOURCE,
4192  gnc_plugin_page_register_sort_book_option_changed,
4193  page);
4194 
4195  /* Wire it up */
4196  gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func,
4197  page);
4198 
4199  /* Show it */
4200  gtk_widget_show (dialog);
4201  g_object_unref (G_OBJECT (builder));
4202  LEAVE (" ");
4203 }
4204 
4205 static void
4206 gnc_plugin_page_register_cmd_view_filter_by (GtkAction* action,
4207  GncPluginPageRegister* page)
4208 {
4210  GtkWidget* dialog, *toggle, *button, *table, *hbox;
4211  time64 start_time, end_time, time_val;
4212  GtkBuilder* builder;
4213  gboolean sensitive, value;
4214  Query* query;
4215  gchar* title;
4216  int i;
4217 
4218  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
4219  ENTER ("(action %p, page %p)", action, page);
4220 
4221  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
4222  if (priv->fd.dialog)
4223  {
4224  gtk_window_present (GTK_WINDOW (priv->fd.dialog));
4225  LEAVE ("existing dialog");
4226  return;
4227  }
4228 
4229  /* Create the dialog */
4230  builder = gtk_builder_new();
4231  gnc_builder_add_from_file (builder, "gnc-plugin-page-register.glade",
4232  "days_adjustment");
4233  gnc_builder_add_from_file (builder, "gnc-plugin-page-register.glade",
4234  "filter_by_dialog");
4235  dialog = GTK_WIDGET (gtk_builder_get_object (builder, "filter_by_dialog"));
4236  priv->fd.dialog = dialog;
4237  gtk_window_set_transient_for (GTK_WINDOW (dialog),
4238  gnc_window_get_gtk_window (GNC_WINDOW (GNC_PLUGIN_PAGE (page)->window)));
4239 
4240  /* Translators: The %s is the name of the plugin page */
4241  title = g_strdup_printf (_ ("Filter %s by..."),
4242  gnc_plugin_page_get_page_name (GNC_PLUGIN_PAGE (page)));
4243  gtk_window_set_title (GTK_WINDOW (dialog), title);
4244  g_free (title);
4245 
4246  /* Set the check buttons for the current status */
4247  for (i = 0; status_actions[i].action_name; i++)
4248  {
4249  toggle = GTK_WIDGET (gtk_builder_get_object (builder,
4250  status_actions[i].action_name));
4251  value = priv->fd.cleared_match & status_actions[i].value;
4252  status_actions[i].widget = toggle;
4253  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), value);
4254  }
4255  priv->fd.original_cleared_match = priv->fd.cleared_match;
4256 
4257  button = GTK_WIDGET (gtk_builder_get_object (builder, "filter_save"));
4258  if (priv->fd.save_filter == TRUE)
4259  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
4260 
4261  // hide the save button if appropriate
4262  gtk_widget_set_visible (GTK_WIDGET (button),
4263  gnc_plugin_page_register_show_fs_save (page));
4264 
4265  /* Set up number of days */
4266  priv->fd.num_days = GTK_WIDGET (gtk_builder_get_object (builder,
4267  "filter_show_num_days"));
4268  button = GTK_WIDGET (gtk_builder_get_object (builder, "filter_show_days"));
4269 
4270  query = gnc_ledger_display_get_query (priv->ledger);
4271 
4272  if (priv->fd.days > 0) // using number of days
4273  {
4274  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
4275  gtk_widget_set_sensitive (GTK_WIDGET (priv->fd.num_days), TRUE);
4276  gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->fd.num_days), priv->fd.days);
4277  priv->fd.original_days = priv->fd.days;
4278 
4279  /* Set the start_time and end_time to 0 */
4280  start_time = 0;
4281  end_time = 0;
4282  }
4283  else
4284  {
4285  gtk_widget_set_sensitive (GTK_WIDGET (priv->fd.num_days), FALSE);
4286  priv->fd.original_days = 0;
4287  priv->fd.days = 0;
4288 
4289  /* Get the start and end times */
4290  xaccQueryGetDateMatchTT (query, &start_time, &end_time);
4291  }
4292 
4293  /* Set the date info */
4294  priv->fd.original_start_time = start_time;
4295  priv->fd.start_time = start_time;
4296  priv->fd.original_end_time = end_time;
4297  priv->fd.end_time = end_time;
4298 
4299  button = GTK_WIDGET (gtk_builder_get_object (builder, "filter_show_range"));
4300  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), start_time ||
4301  end_time);
4302  table = GTK_WIDGET (gtk_builder_get_object (builder, "select_range_table"));
4303  priv->fd.table = table;
4304  gtk_widget_set_sensitive (GTK_WIDGET (table), start_time || end_time);
4305 
4306  priv->fd.start_date_choose = GTK_WIDGET (gtk_builder_get_object (builder,
4307  "start_date_choose"));
4308  priv->fd.start_date_today = GTK_WIDGET (gtk_builder_get_object (builder,
4309  "start_date_today"));
4310  priv->fd.end_date_choose = GTK_WIDGET (gtk_builder_get_object (builder,
4311  "end_date_choose"));
4312  priv->fd.end_date_today = GTK_WIDGET (gtk_builder_get_object (builder,
4313  "end_date_today"));
4314 
4315  {
4316  /* Start date info */
4317  if (start_time == 0)
4318  {
4319  button = GTK_WIDGET (gtk_builder_get_object (builder, "start_date_earliest"));
4320  time_val = xaccQueryGetEarliestDateFound (query);
4321  sensitive = FALSE;
4322  }
4323  else
4324  {
4325  time_val = start_time;
4326  if ((start_time >= gnc_time64_get_today_start()) &&
4327  (start_time <= gnc_time64_get_today_end()))
4328  {
4329  button = priv->fd.start_date_today;
4330  sensitive = FALSE;
4331  }
4332  else
4333  {
4334  button = priv->fd.start_date_choose;
4335  sensitive = TRUE;
4336  }
4337  }
4338  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
4339  priv->fd.start_date = gnc_date_edit_new (gnc_time (NULL), FALSE, FALSE);
4340  hbox = GTK_WIDGET (gtk_builder_get_object (builder, "start_date_hbox"));
4341  gtk_box_pack_start (GTK_BOX (hbox), priv->fd.start_date, TRUE, TRUE, 0);
4342  gtk_widget_show (priv->fd.start_date);
4343  gtk_widget_set_sensitive (GTK_WIDGET (priv->fd.start_date), sensitive);
4344  gnc_date_edit_set_time (GNC_DATE_EDIT (priv->fd.start_date), time_val);
4345  g_signal_connect (G_OBJECT (priv->fd.start_date), "date-changed",
4346  G_CALLBACK (gnc_plugin_page_register_filter_gde_changed_cb),
4347  page);
4348  }
4349 
4350  {
4351  /* End date info */
4352  if (end_time == 0)
4353  {
4354  button = GTK_WIDGET (gtk_builder_get_object (builder, "end_date_latest"));
4355  time_val = xaccQueryGetLatestDateFound (query);
4356  sensitive = FALSE;
4357  }
4358  else
4359  {
4360  time_val = end_time;
4361  if ((end_time >= gnc_time64_get_today_start()) &&
4362  (end_time <= gnc_time64_get_today_end()))
4363  {
4364  button = priv->fd.end_date_today;
4365  sensitive = FALSE;
4366  }
4367  else
4368  {
4369  button = priv->fd.end_date_choose;
4370  sensitive = TRUE;
4371  }
4372  }
4373  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
4374  priv->fd.end_date = gnc_date_edit_new (gnc_time (NULL), FALSE, FALSE);
4375  hbox = GTK_WIDGET (gtk_builder_get_object (builder, "end_date_hbox"));
4376  gtk_box_pack_start (GTK_BOX (hbox), priv->fd.end_date, TRUE, TRUE, 0);
4377  gtk_widget_show (priv->fd.end_date);
4378  gtk_widget_set_sensitive (GTK_WIDGET (priv->fd.end_date), sensitive);
4379  gnc_date_edit_set_time (GNC_DATE_EDIT (priv->fd.end_date), time_val);
4380  g_signal_connect (G_OBJECT (priv->fd.end_date), "date-changed",
4381  G_CALLBACK (gnc_plugin_page_register_filter_gde_changed_cb),
4382  page);
4383  }
4384 
4385  /* Wire it up */
4386  gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func,
4387  page);
4388 
4389  /* Show it */
4390  gtk_widget_show (dialog);
4391  g_object_unref (G_OBJECT (builder));
4392  LEAVE (" ");
4393 }
4394 
4395 static void
4396 gnc_plugin_page_register_cmd_reload (GtkAction* action,
4397  GncPluginPageRegister* plugin_page)
4398 {
4400  SplitRegister* reg;
4401 
4402  ENTER ("(action %p, page %p)", action, plugin_page);
4403 
4404  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4405 
4406  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4407  reg = gnc_ledger_display_get_split_register (priv->ledger);
4408 
4409  /* Check for trans being edited */
4410  if (gnc_split_register_changed (reg))
4411  {
4412  LEAVE ("register has pending edits");
4413  return;
4414  }
4415  gnc_ledger_display_refresh (priv->ledger);
4416  LEAVE (" ");
4417 }
4418 
4419 static void
4420 gnc_plugin_page_register_cmd_style_changed (GtkAction* action,
4421  GtkRadioAction* current,
4422  GncPluginPageRegister* plugin_page)
4423 {
4425  SplitRegisterStyle value;
4426 
4427  ENTER ("(action %p, radio action %p, plugin_page %p)",
4428  action, current, plugin_page);
4429 
4430  g_return_if_fail (GTK_IS_ACTION (action));
4431  g_return_if_fail (GTK_IS_RADIO_ACTION (current));
4432  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4433 
4434  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4435  value = gtk_radio_action_get_current_value (current);
4436  gnc_split_reg_change_style (priv->gsr, value, priv->enable_refresh);
4437 
4438  gnc_plugin_page_register_ui_update (NULL, plugin_page);
4439  LEAVE (" ");
4440 }
4441 
4442 static void
4443 gnc_plugin_page_register_cmd_style_double_line (GtkToggleAction* action,
4444  GncPluginPageRegister* plugin_page)
4445 {
4447  SplitRegister* reg;
4448  gboolean use_double_line;
4449 
4450  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4451 
4452  g_return_if_fail (GTK_IS_ACTION (action));
4453  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4454 
4455  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4456  reg = gnc_ledger_display_get_split_register (priv->ledger);
4457 
4458  use_double_line = gtk_toggle_action_get_active (action);
4459  if (use_double_line != reg->use_double_line)
4460  {
4461  gnc_split_register_config (reg, reg->type, reg->style, use_double_line);
4462  if (priv->enable_refresh)
4463  gnc_ledger_display_refresh (priv->ledger);
4464  }
4465  LEAVE (" ");
4466 }
4467 
4468 static void
4469 gnc_plugin_page_register_cmd_transfer (GtkAction* action,
4470  GncPluginPageRegister* page)
4471 {
4472  Account* account;
4473  GncWindow* gnc_window;
4474  GtkWidget* window;
4475 
4476  ENTER ("(action %p, plugin_page %p)", action, page);
4477 
4478  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
4479 
4480  account = gnc_plugin_page_register_get_account (page);
4481  gnc_window = GNC_WINDOW (GNC_PLUGIN_PAGE (page)->window);
4482  window = GTK_WIDGET (gnc_window_get_gtk_window (gnc_window));
4483  gnc_xfer_dialog (window, account);
4484  LEAVE (" ");
4485 }
4486 
4487 static void
4488 gnc_plugin_page_register_cmd_reconcile (GtkAction* action,
4489  GncPluginPageRegister* page)
4490 {
4491  Account* account;
4492  GtkWindow* window;
4493  RecnWindow* recnData;
4494 
4495  ENTER ("(action %p, plugin_page %p)", action, page);
4496 
4497  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
4498 
4499  account = gnc_plugin_page_register_get_account (page);
4500 
4501  window = gnc_window_get_gtk_window (GNC_WINDOW (GNC_PLUGIN_PAGE (
4502  page)->window));
4503  recnData = recnWindow (GTK_WIDGET (window), account);
4504  gnc_ui_reconcile_window_raise (recnData);
4505  LEAVE (" ");
4506 }
4507 
4508 static void
4509 gnc_plugin_page_register_cmd_stock_assistant (GtkAction* action,
4510  GncPluginPageRegister* page)
4511 {
4512  Account *account;
4513  GtkWindow *window;
4514 
4515  ENTER ("(action %p, plugin_page %p)", action, page);
4516 
4517  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
4518  window = gnc_window_get_gtk_window (GNC_WINDOW (GNC_PLUGIN_PAGE (page)->window));
4519  account = gnc_plugin_page_register_get_account (page);
4520  gnc_stock_transaction_assistant (GTK_WIDGET (window), account);
4521 
4522  LEAVE (" ");
4523 }
4524 
4525 static void
4526 gnc_plugin_page_register_cmd_autoclear (GtkAction* action,
4527  GncPluginPageRegister* page)
4528 {
4529  Account* account;
4530  GtkWindow* window;
4531  AutoClearWindow* autoClearData;
4532 
4533  ENTER ("(action %p, plugin_page %p)", action, page);
4534 
4535  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
4536 
4537  account = gnc_plugin_page_register_get_account (page);
4538 
4539  window = gnc_window_get_gtk_window (GNC_WINDOW (GNC_PLUGIN_PAGE (
4540  page)->window));
4541  autoClearData = autoClearWindow (GTK_WIDGET (window), account);
4542  gnc_ui_autoclear_window_raise (autoClearData);
4543  LEAVE (" ");
4544 }
4545 
4546 static void
4547 gnc_plugin_page_register_cmd_stock_split (GtkAction* action,
4548  GncPluginPageRegister* page)
4549 {
4550  Account* account;
4551  GtkWindow* window;
4552 
4553  ENTER ("(action %p, plugin_page %p)", action, page);
4554 
4555  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
4556 
4557  account = gnc_plugin_page_register_get_account (page);
4558  window = gnc_window_get_gtk_window (GNC_WINDOW (GNC_PLUGIN_PAGE (page)->window));
4559  gnc_stock_split_dialog (GTK_WIDGET (window), account);
4560  LEAVE (" ");
4561 }
4562 
4563 static void
4564 gnc_plugin_page_register_cmd_lots (GtkAction* action,
4565  GncPluginPageRegister* page)
4566 {
4567  GtkWindow* window;
4568  Account* account;
4569 
4570  ENTER ("(action %p, plugin_page %p)", action, page);
4571 
4572  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
4573 
4574  window = gnc_window_get_gtk_window (GNC_WINDOW (GNC_PLUGIN_PAGE (
4575  page)->window));
4576  account = gnc_plugin_page_register_get_account (page);
4577  gnc_lot_viewer_dialog (window, account);
4578  LEAVE (" ");
4579 }
4580 
4581 static void
4582 gnc_plugin_page_register_cmd_enter_transaction (GtkAction* action,
4583  GncPluginPageRegister* plugin_page)
4584 {
4586 
4587  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4588 
4589  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4590 
4591  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4592  gnc_split_reg_enter (priv->gsr, FALSE);
4593  LEAVE (" ");
4594 }
4595 
4596 static void
4597 gnc_plugin_page_register_cmd_cancel_transaction (GtkAction* action,
4598  GncPluginPageRegister* plugin_page)
4599 {
4601 
4602  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4603 
4604  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4605 
4606  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4608  (gnc_ledger_display_get_split_register (priv->ledger));
4609  LEAVE (" ");
4610 }
4611 
4612 static void
4613 gnc_plugin_page_register_cmd_delete_transaction (GtkAction* action,
4614  GncPluginPageRegister* plugin_page)
4615 {
4617 
4618  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4619 
4620  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4621 
4622  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4623  gsr_default_delete_handler (priv->gsr, NULL);
4624  LEAVE (" ");
4625 
4626 }
4627 
4628 static void
4629 gnc_plugin_page_register_cmd_linked_transaction (GtkAction *action,
4630  GncPluginPageRegister* plugin_page)
4631 {
4633 
4634  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4635 
4636  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4637 
4638  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4639  gsr_default_doclink_handler (priv->gsr);
4640  gnc_plugin_page_register_ui_update (NULL, plugin_page);
4641  LEAVE (" ");
4642 }
4643 
4644 static void
4645 gnc_plugin_page_register_cmd_linked_transaction_open (GtkAction *action,
4646  GncPluginPageRegister* plugin_page)
4647 {
4649 
4650  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4651 
4652  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4653 
4654  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4655  gsr_default_doclink_open_handler (priv->gsr);
4656  LEAVE (" ");
4657 }
4658 
4659 static void
4660 gnc_plugin_page_register_cmd_linked_transaction_remove (GtkAction *action,
4661  GncPluginPageRegister* plugin_page)
4662 {
4664 
4665  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4666 
4667  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4668 
4669  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4670  gsr_default_doclink_remove_handler (priv->gsr);
4671  gnc_plugin_page_register_ui_update (NULL, plugin_page);
4672  LEAVE (" ");
4673 
4674 }
4675 
4676 static GncInvoice* invoice_from_split (Split* split)
4677 {
4678  GncInvoice* invoice;
4679  GNCLot* lot;
4680 
4681  if (!split)
4682  return NULL;
4683 
4684  lot = xaccSplitGetLot (split);
4685  if (!lot)
4686  return NULL;
4687 
4688  invoice = gncInvoiceGetInvoiceFromLot (lot);
4689  if (!invoice)
4690  return NULL;
4691 
4692  return invoice;
4693 }
4694 
4695 GList* invoices_from_transaction (Transaction* trans)
4696 {
4697  GList *invoices = NULL;
4698  GList *apar_splits;
4699  if (!trans) return NULL;
4700 
4701  apar_splits = xaccTransGetAPARAcctSplitList (trans, TRUE);
4702  if (!apar_splits) return NULL;
4703 
4704  for (GList *node = apar_splits; node; node = node->next)
4705  {
4706  GncInvoice* inv = invoice_from_split ((Split*) node->data);
4707  if (inv) invoices = g_list_prepend (invoices, inv);
4708  }
4709  g_list_free (apar_splits);
4710  return invoices;
4711 }
4712 
4713 static void
4714 gnc_plugin_page_register_cmd_jump_linked_invoice (GtkAction* action,
4715  GncPluginPageRegister* plugin_page)
4716 {
4718  SplitRegister* reg;
4719  GncInvoice* invoice;
4720  Transaction *txn;
4721  GtkWidget *window;
4722 
4723  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4724 
4725  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4726  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4727  reg = gnc_ledger_display_get_split_register (priv->gsr->ledger);
4729  invoice = invoice_from_split (gnc_split_register_get_current_split (reg));
4730  window = GNC_PLUGIN_PAGE(plugin_page)->window;
4731 
4732  if (!invoice)
4733  {
4734  GList *invoices = invoices_from_transaction (txn);
4735  if (!invoices)
4736  PERR ("shouldn't happen: if no invoices, function is never called");
4737  else if (!invoices->next)
4738  invoice = (GncInvoice*) invoices->data;
4739  else
4740  {
4741  GList *details = NULL;
4742  gint choice;
4743  const gchar *amt;
4744  for (GList *node = invoices; node; node = node->next)
4745  {
4746  GncInvoice* inv = node->data;
4747  gchar *date = qof_print_date (gncInvoiceGetDatePosted (inv));
4748  amt = xaccPrintAmount
4749  (gncInvoiceGetTotal (inv),
4750  gnc_account_print_info (gncInvoiceGetPostedAcc (inv), TRUE));
4751  details = g_list_prepend
4752  (details,
4753  /* Translators: %s refer to the following in
4754  order: invoice type, invoice ID, owner name,
4755  posted date, amount */
4756  g_strdup_printf (_("%s %s from %s, posted %s, amount %s"),
4757  gncInvoiceGetTypeString (inv),
4758  gncInvoiceGetID (inv),
4759  gncOwnerGetName (gncInvoiceGetOwner (inv)),
4760  date, amt));
4761  g_free (date);
4762  }
4763  details = g_list_reverse (details);
4764  choice = gnc_choose_radio_option_dialog
4765  (window, _("Select document"),
4766  _("Several documents are linked with this transaction. \
4767 Please choose one:"), _("Select"), 0, details);
4768  if (choice >= 0)
4769  invoice = (GncInvoice *)(g_list_nth (invoices, choice))->data;
4770  g_list_free_full (details, g_free);
4771  }
4772  g_list_free (invoices);
4773  }
4774 
4775  if (invoice)
4776  {
4777  GtkWindow *gtk_window = gnc_window_get_gtk_window (GNC_WINDOW (window));
4778  gnc_ui_invoice_edit (gtk_window, invoice);
4779  }
4780 
4781  LEAVE (" ");
4782 }
4783 
4784 static void
4785 gnc_plugin_page_register_cmd_blank_transaction (GtkAction* action,
4786  GncPluginPageRegister* plugin_page)
4787 {
4789  SplitRegister* reg;
4790 
4791  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4792 
4793  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4794 
4795  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4796  reg = gnc_ledger_display_get_split_register (priv->ledger);
4797 
4798  if (gnc_split_register_save (reg, TRUE))
4800 
4801  gnc_split_reg_jump_to_blank (priv->gsr);
4802  LEAVE (" ");
4803 }
4804 
4805 static void
4806 gnc_plugin_page_register_cmd_goto_date (GtkAction* action,
4807  GncPluginPageRegister* page)
4808 {
4809  GNCSplitReg* gsr;
4810  Query* query;
4811  time64 date = gnc_time (NULL);
4812  GList *splits;
4813 
4814  ENTER ("(action %p, plugin_page %p)", action, page);
4815  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
4816 
4817  if (!gnc_dup_time64_dialog (gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page)),
4818  _("Go to Date"), _("Go to Date"), &date))
4819  {
4820  LEAVE ("goto_date cancelled");
4821  return;
4822  }
4823 
4824  gsr = gnc_plugin_page_register_get_gsr (GNC_PLUGIN_PAGE (page));
4825  query = gnc_plugin_page_register_get_query (GNC_PLUGIN_PAGE (page));
4826  splits = g_list_copy (qof_query_run (query));
4827  splits = g_list_sort (splits, (GCompareFunc)xaccSplitOrder);
4828 
4829  for (GList *lp = splits; lp; lp = lp->next)
4830  {
4831  if (xaccTransGetDate (xaccSplitGetParent (lp->data)) >= date)
4832  {
4833  gnc_split_reg_jump_to_split (gsr, lp->data);
4834  break;
4835  }
4836  }
4837 
4838  g_list_free (splits);
4839  LEAVE (" ");
4840 }
4841 
4842 static void
4843 gnc_plugin_page_register_cmd_duplicate_transaction (GtkAction* action,
4844  GncPluginPageRegister* plugin_page)
4845 {
4847 
4848  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4849 
4850  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4851 
4852  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4854  (gnc_ledger_display_get_split_register (priv->ledger));
4855  LEAVE (" ");
4856 }
4857 
4858 static void
4859 gnc_plugin_page_register_cmd_reinitialize_transaction (GtkAction* action,
4860  GncPluginPageRegister* plugin_page)
4861 {
4863 
4864  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4865 
4866  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4867 
4868  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4869  gsr_default_reinit_handler (priv->gsr, NULL);
4870  LEAVE (" ");
4871 }
4872 
4873 static void
4874 gnc_plugin_page_register_cmd_expand_transaction (GtkToggleAction* action,
4875  GncPluginPageRegister* plugin_page)
4876 {
4878  SplitRegister* reg;
4879  gboolean expand;
4880 
4881  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4882 
4883  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4884 
4885  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4886  reg = gnc_ledger_display_get_split_register (priv->ledger);
4887  expand = gtk_toggle_action_get_active (action);
4889  LEAVE (" ");
4890 }
4891 
4894 static void
4895 gnc_plugin_page_register_cmd_exchange_rate (GtkAction* action,
4896  GncPluginPageRegister* plugin_page)
4897 {
4899  SplitRegister* reg;
4900 
4901  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4902 
4903  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4904 
4905  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4906  reg = gnc_ledger_display_get_split_register (priv->ledger);
4907 
4908  /* XXX Ignore the return value -- we don't care if this succeeds */
4909  (void)gnc_split_register_handle_exchange (reg, TRUE);
4910  LEAVE (" ");
4911 }
4912 
4913 static void
4914 gnc_plugin_page_register_cmd_jump (GtkAction* action,
4915  GncPluginPageRegister* plugin_page)
4916 {
4918  GncPluginPage* new_page;
4919  GtkWidget* window;
4920  GNCSplitReg* gsr;
4921  SplitRegister* reg;
4922  Account* account;
4923  Account* leader;
4924  Split* split;
4925 
4926  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
4927 
4928  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
4929 
4930  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
4931  window = GNC_PLUGIN_PAGE (plugin_page)->window;
4932  if (window == NULL)
4933  {
4934  LEAVE ("no window");
4935  return;
4936  }
4937 
4938  reg = gnc_ledger_display_get_split_register (priv->ledger);
4940  if (split == NULL)
4941  {
4942  LEAVE ("no split (1)");
4943  return;
4944  }
4945 
4946  account = xaccSplitGetAccount (split);
4947  if (account == NULL)
4948  {
4949  LEAVE ("no account");
4950  return;
4951  }
4952 
4953  leader = gnc_ledger_display_leader (priv->ledger);
4954  if (account == leader)
4955  {
4956  split = xaccSplitGetOtherSplit (split);
4957  if (split == NULL)
4958  {
4959  LEAVE ("no split (2)");
4960  return;
4961  }
4962 
4963  account = xaccSplitGetAccount (split);
4964  if (account == NULL)
4965  {
4966  LEAVE ("no account (2)");
4967  return;
4968  }
4969 
4970  if (account == leader)
4971  {
4972  LEAVE ("register open for account");
4973  return;
4974  }
4975  }
4976 
4977  new_page = gnc_plugin_page_register_new (account, FALSE);
4978  if (new_page == NULL)
4979  {
4980  LEAVE ("couldn't create new page");
4981  return;
4982  }
4983 
4984  gnc_main_window_open_page (GNC_MAIN_WINDOW (window), new_page);
4985  gsr = gnc_plugin_page_register_get_gsr (new_page);
4986 
4987  /* Test for visibility of split */
4988  if (gnc_split_reg_clear_filter_for_split (gsr, split))
4989  gnc_plugin_page_register_clear_current_filter (GNC_PLUGIN_PAGE(new_page));
4990 
4991  gnc_split_reg_jump_to_split (gsr, split);
4992  LEAVE (" ");
4993 }
4994 
4995 static void
4996 gnc_plugin_page_register_cmd_schedule (GtkAction* action,
4997  GncPluginPageRegister* plugin_page)
4998 {
5000  GtkWindow* window;
5001 
5002  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
5003 
5004  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
5005 
5006  window = GTK_WINDOW (gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (
5007  plugin_page)));
5008  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
5009  gsr_default_schedule_handler (priv->gsr, window);
5010  LEAVE (" ");
5011 }
5012 
5013 static void scrub_split (Split *split)
5014 {
5015  Account *acct;
5016  Transaction *trans;
5017  GNCLot *lot;
5018 
5019  g_return_if_fail (split);
5020  acct = xaccSplitGetAccount (split);
5021  trans = xaccSplitGetParent (split);
5022  lot = xaccSplitGetLot (split);
5023  g_return_if_fail (trans);
5024 
5025  xaccTransScrubOrphans (trans);
5026  xaccTransScrubImbalance (trans, gnc_get_current_root_account(), NULL);
5027  if (lot && xaccAccountIsAPARType (xaccAccountGetType (acct)))
5028  {
5029  gncScrubBusinessLot (lot);
5030  gncScrubBusinessSplit (split);
5031  }
5032 }
5033 
5034 static void
5035 gnc_plugin_page_register_cmd_scrub_current (GtkAction* action,
5036  GncPluginPageRegister* plugin_page)
5037 {
5039  Query* query;
5040  Split* split;
5041  SplitRegister* reg;
5042 
5043  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
5044 
5045  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
5046 
5047  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
5048  query = gnc_ledger_display_get_query (priv->ledger);
5049  if (query == NULL)
5050  {
5051  LEAVE ("no query found");
5052  return;
5053  }
5054 
5055  reg = gnc_ledger_display_get_split_register (priv->ledger);
5056 
5057  gnc_suspend_gui_refresh();
5058  scrub_split (gnc_split_register_get_current_split (reg));
5059  gnc_resume_gui_refresh();
5060  LEAVE (" ");
5061 }
5062 
5063 static gboolean
5064 scrub_kp_handler (GtkWidget *widget, GdkEventKey *event, gpointer data)
5065 {
5066  if (event->length == 0) return FALSE;
5067 
5068  switch (event->keyval)
5069  {
5070  case GDK_KEY_Escape:
5071  {
5072  gboolean abort_scrub = gnc_verify_dialog (GTK_WINDOW(widget), FALSE,
5073  _("'Check & Repair' is currently running, do you want to abort it?"));
5074 
5075  if (abort_scrub)
5076  gnc_set_abort_scrub (TRUE);
5077 
5078  return TRUE;
5079  }
5080  default:
5081  break;
5082  }
5083  return FALSE;
5084 }
5085 
5086 static void
5087 gnc_plugin_page_register_cmd_scrub_all (GtkAction* action,
5088  GncPluginPageRegister* plugin_page)
5089 {
5091  Query* query;
5092  GncWindow* window;
5093  GList* node, *splits;
5094  gint split_count = 0, curr_split_no = 0;
5095  gulong scrub_kp_handler_ID;
5096  const char* message = _ ("Checking splits in current register: %u of %u");
5097 
5098  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
5099 
5100  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
5101 
5102  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
5103  query = gnc_ledger_display_get_query (priv->ledger);
5104  if (!query)
5105  {
5106  LEAVE ("no query found");
5107  return;
5108  }
5109 
5110  gnc_suspend_gui_refresh();
5111  is_scrubbing = TRUE;
5112  gnc_set_abort_scrub (FALSE);
5113  window = GNC_WINDOW (GNC_PLUGIN_PAGE (plugin_page)->window);
5114  scrub_kp_handler_ID = g_signal_connect (G_OBJECT (window), "key-press-event",
5115  G_CALLBACK (scrub_kp_handler), NULL);
5116  gnc_window_set_progressbar_window (window);
5117 
5118  splits = qof_query_run (query);
5119  split_count = g_list_length (splits);
5120  for (node = splits; node && !gnc_get_abort_scrub (); node = node->next, curr_split_no++)
5121  {
5122  Split* split = node->data;
5123 
5124  if (!split) continue;
5125 
5126  PINFO ("Start processing split %d of %d",
5127  curr_split_no + 1, split_count);
5128 
5129  scrub_split (split);
5130 
5131  PINFO ("Finished processing split %d of %d",
5132  curr_split_no + 1, split_count);
5133 
5134  if (curr_split_no % 10 == 0)
5135  {
5136  char* progress_msg = g_strdup_printf (message, curr_split_no, split_count);
5137  gnc_window_show_progress (progress_msg, (100 * curr_split_no) / split_count);
5138  g_free (progress_msg);
5139  }
5140  }
5141 
5142  g_signal_handler_disconnect (G_OBJECT(window), scrub_kp_handler_ID);
5143  gnc_window_show_progress (NULL, -1.0);
5144  is_scrubbing = FALSE;
5145  show_abort_verify = TRUE;
5146  gnc_set_abort_scrub (FALSE);
5147 
5148  gnc_resume_gui_refresh();
5149  LEAVE (" ");
5150 }
5151 
5152 static void
5153 gnc_plugin_page_register_cmd_account_report (GtkAction* action,
5154  GncPluginPageRegister* plugin_page)
5155 {
5157  GncMainWindow* window;
5158  int id;
5159 
5160  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
5161 
5162  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
5163 
5164  window = GNC_MAIN_WINDOW (GNC_PLUGIN_PAGE (plugin_page)->window);
5165  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
5166  id = report_helper (priv->ledger, NULL, NULL);
5167  if (id >= 0)
5168  gnc_main_window_open_report (id, window);
5169  LEAVE (" ");
5170 }
5171 
5172 static void
5173 gnc_plugin_page_register_cmd_transaction_report (GtkAction* action,
5174  GncPluginPageRegister* plugin_page)
5175 {
5177  GncMainWindow* window;
5178  SplitRegister* reg;
5179  Split* split;
5180  Query* query;
5181  int id;
5182 
5183 
5184  ENTER ("(action %p, plugin_page %p)", action, plugin_page);
5185 
5186  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
5187 
5188  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
5189  reg = gnc_ledger_display_get_split_register (priv->ledger);
5190 
5192  if (!split)
5193  return;
5194 
5195  query = qof_query_create_for (GNC_ID_SPLIT);
5196 
5197  qof_query_set_book (query, gnc_get_current_book());
5198 
5199  xaccQueryAddGUIDMatch (query, xaccSplitGetGUID (split),
5200  GNC_ID_SPLIT, QOF_QUERY_AND);
5201 
5202  window = GNC_MAIN_WINDOW (GNC_PLUGIN_PAGE (plugin_page)->window);
5203  id = report_helper (priv->ledger, split, query);
5204  if (id >= 0)
5205  gnc_main_window_open_report (id, window);
5206  LEAVE (" ");
5207 }
5208 
5209 /************************************************************/
5210 /* Auxiliary functions */
5211 /************************************************************/
5212 
5213 void
5215  gint lines_default,
5216  gboolean read_only)
5217 {
5218  GncPluginPageRegister* page;
5220 
5221  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
5222 
5223  page = GNC_PLUGIN_PAGE_REGISTER (plugin_page);
5224  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
5225  priv->lines_default = lines_default;
5226  priv->read_only = read_only;
5227 }
5228 
5229 GNCSplitReg*
5231 {
5232  GncPluginPageRegister* page;
5234 
5235  g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page), NULL);
5236 
5237  page = GNC_PLUGIN_PAGE_REGISTER (plugin_page);
5238  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
5239 
5240  return priv->gsr;
5241 }
5242 
5243 static void
5244 gnc_plugin_page_help_changed_cb (GNCSplitReg* gsr,
5245  GncPluginPageRegister* register_page)
5246 {
5248  SplitRegister* reg;
5249  GncWindow* window;
5250  char* help;
5251 
5252  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (register_page));
5253 
5254  window = GNC_WINDOW (GNC_PLUGIN_PAGE (register_page)->window);
5255  if (!window)
5256  {
5257  // This routine can be called before the page is added to a
5258  // window.
5259  return;
5260  }
5261 
5262  // only update status text if on current page
5263  if (GNC_IS_MAIN_WINDOW(window) && (gnc_main_window_get_current_page
5264  (GNC_MAIN_WINDOW(window)) != GNC_PLUGIN_PAGE(register_page)))
5265  return;
5266 
5267  /* Get the text from the ledger */
5268  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (register_page);
5269  reg = gnc_ledger_display_get_split_register (priv->ledger);
5270  help = gnc_table_get_help (reg->table);
5271  gnc_window_set_status (window, GNC_PLUGIN_PAGE (register_page), help);
5272  g_free (help);
5273 }
5274 
5275 static void
5276 gnc_plugin_page_popup_menu_cb (GNCSplitReg* gsr,
5277  GncPluginPageRegister* register_page)
5278 {
5279  GncWindow* window;
5280 
5281  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (register_page));
5282 
5283  window = GNC_WINDOW (GNC_PLUGIN_PAGE (register_page)->window);
5284  if (!window)
5285  {
5286  // This routine can be called before the page is added to a
5287  // window.
5288  return;
5289  }
5290  gnc_main_window_popup_menu_cb (GTK_WIDGET (window),
5291  GNC_PLUGIN_PAGE (register_page));
5292 }
5293 
5294 static void
5295 gnc_plugin_page_register_refresh_cb (GHashTable* changes, gpointer user_data)
5296 {
5297  GncPluginPageRegister* page = user_data;
5299 
5300  g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
5301  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
5302 
5303  if (changes)
5304  {
5305  const EventInfo* ei;
5306  ei = gnc_gui_get_entity_events (changes, &priv->key);
5307  if (ei)
5308  {
5309  if (ei->event_mask & QOF_EVENT_DESTROY)
5310  {
5311  gnc_main_window_close_page (GNC_PLUGIN_PAGE (page));
5312  return;
5313  }
5314  if (ei->event_mask & QOF_EVENT_MODIFY)
5315  {
5316  }
5317  }
5318  }
5319  else
5320  {
5321  /* forced updates */
5322  gnucash_register_refresh_from_prefs (priv->gsr->reg);
5323  gtk_widget_queue_draw (priv->widget);
5324  }
5325 
5326  gnc_plugin_page_register_ui_update (NULL, page);
5327 }
5328 
5329 static void
5330 gnc_plugin_page_register_close_cb (gpointer user_data)
5331 {
5332  GncPluginPage* plugin_page = GNC_PLUGIN_PAGE (user_data);
5333  gnc_main_window_close_page (plugin_page);
5334 }
5335 
5344 static void
5345 gppr_account_destroy_cb (Account* account)
5346 {
5347  GncPluginPageRegister* page;
5349  GNCLedgerDisplayType ledger_type;
5350  const GncGUID* acct_guid;
5351  const GList* citem;
5352  GList* item, *kill = NULL;
5353 
5354  acct_guid = xaccAccountGetGUID (account);
5355 
5356  /* Find all windows that need to be killed. Don't kill them yet, as
5357  * that would affect the list being walked.*/
5358  citem = gnc_gobject_tracking_get_list (GNC_PLUGIN_PAGE_REGISTER_NAME);
5359  for (; citem; citem = g_list_next (citem))
5360  {
5361  page = (GncPluginPageRegister*)citem->data;
5362  priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
5363  ledger_type = gnc_ledger_display_type (priv->ledger);
5364  if (ledger_type == LD_GL)
5365  {
5366  kill = g_list_prepend (kill, page);
5367  /* kill it */
5368  }
5369  else if ((ledger_type == LD_SINGLE) || (ledger_type == LD_SUBACCOUNT))
5370  {
5371  if (guid_compare (acct_guid, &priv->key) == 0)
5372  {
5373  kill = g_list_prepend (kill, page);
5374  }
5375  }
5376  }
5377 
5378  kill = g_list_reverse (kill);
5379  /* Now kill them. */
5380  for (item = kill; item; item = g_list_next (item))
5381  {
5382  page = (GncPluginPageRegister*)item->data;
5383  gnc_main_window_close_page (GNC_PLUGIN_PAGE (page));
5384  }
5385  g_list_free (kill);
5386 }
5387 
5402 static void
5403 gnc_plugin_page_register_event_handler (QofInstance* entity,
5404  QofEventId event_type,
5405  GncPluginPageRegister* page,
5406  GncEventData* ed)
5407 {
5408  Transaction* trans;
5409  QofBook* book;
5410  GncPluginPage* visible_page;
5411  GtkWidget* window;
5412  gchar* label, *color;
5413 
5414  g_return_if_fail (page); /* Required */
5415  if (!GNC_IS_TRANS (entity) && !GNC_IS_ACCOUNT (entity))
5416  return;
5417 
5418  ENTER ("entity %p of type %d, page %p, event data %p",
5419  entity, event_type, page, ed);
5420 
5421  window = gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page));
5422 
5423  if (GNC_IS_ACCOUNT (entity))
5424  {
5425  if (GNC_IS_MAIN_WINDOW (window))
5426  {
5427  label = gnc_plugin_page_register_get_tab_name (GNC_PLUGIN_PAGE (page));
5428  main_window_update_page_name (GNC_PLUGIN_PAGE (page), label);
5429  color = gnc_plugin_page_register_get_tab_color (GNC_PLUGIN_PAGE (page));
5430  main_window_update_page_color (GNC_PLUGIN_PAGE (page), color);
5431  // update page icon if read only registers
5432  gnc_plugin_page_register_update_page_icon (GNC_PLUGIN_PAGE (page));
5433 
5434  g_free (color);
5435  g_free (label);
5436  }
5437  LEAVE ("tab name updated");
5438  return;
5439  }
5440 
5441  if (! (event_type & (QOF_EVENT_MODIFY | QOF_EVENT_DESTROY)))
5442  {
5443  LEAVE ("not a modify");
5444  return;
5445  }
5446  trans = GNC_TRANS (entity);
5447  book = qof_instance_get_book (QOF_INSTANCE (trans));
5448  if (!gnc_plugin_page_has_book (GNC_PLUGIN_PAGE (page), book))
5449  {
5450  LEAVE ("not in this book");
5451  return;
5452  }
5453 
5454  if (GNC_IS_MAIN_WINDOW (window))
5455  {
5456  visible_page = gnc_main_window_get_current_page (GNC_MAIN_WINDOW (window));
5457  if (visible_page != GNC_PLUGIN_PAGE (page))
5458  {
5459  LEAVE ("page not visible");
5460  return;
5461  }
5462  }
5463 
5464  gnc_plugin_page_register_ui_update (NULL, page);
5465  LEAVE (" ");
5466  return;
5467 }
5468 
5469 
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:1496
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:2723
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:2635
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:2596
#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.
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:1029
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:2425
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:2753
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:1350
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:2341
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:1310
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:2897
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:582
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:1359
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:2937
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:2054
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:1877
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