GnuCash c935c2f+
Loading...
Searching...
No Matches
gnc-plugin-page-register.cpp
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 <optional>
39
40#include <libguile.h>
41#include <gtk/gtk.h>
42#include <glib/gi18n.h>
43#include "swig-runtime.h"
44#include "guile-mappings.h"
45
47#include "gnc-plugin-register.h"
50#include "gnc-plugin-business.h"
51
52#include "dialog-account.h"
53#include "dialog-dup-trans.h"
54#include "dialog-find-account.h"
55#include "dialog-find-transactions.h"
56#include "dialog-print-check.h"
57#include "dialog-invoice.h"
58#include "dialog-transfer.h"
59#include "dialog-utils.h"
60#include "assistant-stock-split.h"
61#include "assistant-stock-transaction.h"
62#include "gnc-component-manager.h"
63#include "gnc-date.h"
64#include "gnc-date-edit.h"
65#include "gnc-engine.h"
66#include "gnc-event.h"
67#include "gnc-features.h"
68#include "gnc-glib-utils.h"
69#include "gnc-gnome-utils.h"
70#include "gnc-gobject-utils.h"
71#include "gnc-gui-query.h"
72#include "gnc-icons.h"
73#include "gnc-split-reg.h"
74#include "gnc-state.h"
75#include "gnc-prefs.h"
76#include "gnc-ui-util.h"
77#include "gnc-window.h"
78#include "gnc-main-window.h"
79#include "gnc-session.h"
80#include "gnc-ui.h"
81#include "gnc-warnings.h"
82#include "gnucash-sheet.h"
83#include "dialog-lot-viewer.h"
84#include "Scrub.h"
85#include "ScrubBusiness.h"
86#include "qof.h"
87#include "window-reconcile.h"
88#include "window-autoclear.h"
89#include "window-report.h"
90#include "engine-helpers.h"
91#include "qofbookslots.h"
92#include "gnc-gtk-utils.h"
93
94/* gschema: org.gnucash.GnuCash.general.register.JumpMultipleSplits */
95typedef enum : gint
96{
97 JUMP_DEFAULT = 0, /* Do nothing */
98 JUMP_LARGEST_VALUE_FIRST_SPLIT = 1,
99 JUMP_SMALLEST_VALUE_FIRST_SPLIT = 2,
100} GncPrefJumpMultSplits;
101
102/* This static indicates the debugging module that this .o belongs to. */
103static QofLogModule log_module = GNC_MOD_GUI;
104
105#define DEFAULT_LINES_AMOUNT 50
106
107static void gnc_plugin_page_register_finalize (GObject* object);
108
109/* static Account *gnc_plugin_page_register_get_current_account (GncPluginPageRegister *page); */
110
111static GtkWidget* gnc_plugin_page_register_create_widget (GncPluginPage*
112 plugin_page);
113static void gnc_plugin_page_register_destroy_widget (GncPluginPage*
114 plugin_page);
115static void gnc_plugin_page_register_window_changed (GncPluginPage*
116 plugin_page, GtkWidget* window);
117static gboolean gnc_plugin_page_register_focus_widget (GncPluginPage*
118 plugin_page);
119static void gnc_plugin_page_register_focus (GncPluginPage* plugin_page,
120 gboolean current_page);
121static void gnc_plugin_page_register_save_page (GncPluginPage* plugin_page,
122 GKeyFile* file, const gchar* group);
123static GncPluginPage* gnc_plugin_page_register_recreate_page (GtkWidget* window,
124 GKeyFile* file,
125 const gchar* group);
126static void gnc_plugin_page_register_update_edit_menu (GncPluginPage* plugin_page,
127 gboolean hide);
128static gboolean gnc_plugin_page_register_finish_pending (GncPluginPage* plugin_page);
129
130static gchar* gnc_plugin_page_register_get_tab_name (GncPluginPage*
131 plugin_page);
132static gchar* gnc_plugin_page_register_get_tab_color (GncPluginPage*
133 plugin_page);
134static gchar* gnc_plugin_page_register_get_long_name (GncPluginPage*
135 plugin_page);
136
137static void gnc_plugin_page_register_summarybar_position_changed (gpointer prefs,
138 gchar* pref,
139 gpointer user_data);
140
141/* Command callbacks */
142static void gnc_plugin_page_register_cmd_print_check (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
143static void gnc_plugin_page_register_cmd_cut (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
144static void gnc_plugin_page_register_cmd_copy (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
145static void gnc_plugin_page_register_cmd_paste (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
146static void gnc_plugin_page_register_cmd_edit_account (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
147static void gnc_plugin_page_register_cmd_find_account (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
148static void gnc_plugin_page_register_cmd_find_transactions (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
149static void gnc_plugin_page_register_cmd_edit_tax_options (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
150static void gnc_plugin_page_register_cmd_cut_transaction (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
151static void gnc_plugin_page_register_cmd_copy_transaction (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
152static void gnc_plugin_page_register_cmd_paste_transaction (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
153static void gnc_plugin_page_register_cmd_void_transaction (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
154static void gnc_plugin_page_register_cmd_unvoid_transaction (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
155static void gnc_plugin_page_register_cmd_reverse_transaction (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
156static void gnc_plugin_page_register_cmd_view_sort_by (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
157static void gnc_plugin_page_register_cmd_view_filter_by (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
158
159static void gnc_plugin_page_register_cmd_style_changed (GSimpleAction *simple, GVariant *parameter, gpointer user_data);
160static void gnc_plugin_page_register_cmd_style_double_line (GSimpleAction *simple, GVariant *parameter, gpointer user_data);
161static void gnc_plugin_page_register_cmd_expand_transaction (GSimpleAction *simple, GVariant *parameter, gpointer user_data);
162
163static void gnc_plugin_page_register_cmd_reconcile (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
164static void gnc_plugin_page_register_cmd_stock_assistant (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
165static void gnc_plugin_page_register_cmd_autoclear (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
166static void gnc_plugin_page_register_cmd_transfer (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
167static void gnc_plugin_page_register_cmd_stock_split (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
168static void gnc_plugin_page_register_cmd_lots (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
169static void gnc_plugin_page_register_cmd_enter_transaction (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
170static void gnc_plugin_page_register_cmd_cancel_transaction (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
171static void gnc_plugin_page_register_cmd_delete_transaction (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
172static void gnc_plugin_page_register_cmd_blank_transaction (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
173static void gnc_plugin_page_register_cmd_goto_date (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
174static void gnc_plugin_page_register_cmd_duplicate_transaction (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
175static void gnc_plugin_page_register_cmd_reinitialize_transaction (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
176static void gnc_plugin_page_register_cmd_exchange_rate (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
177static void gnc_plugin_page_register_cmd_jump (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
178static void gnc_plugin_page_register_cmd_reload (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
179static void gnc_plugin_page_register_cmd_schedule (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
180static void gnc_plugin_page_register_cmd_scrub_all (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
181static void gnc_plugin_page_register_cmd_scrub_current (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
182static void gnc_plugin_page_register_cmd_account_report (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
183static void gnc_plugin_page_register_cmd_transaction_report (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
184static void gnc_plugin_page_register_cmd_linked_transaction (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
185static void gnc_plugin_page_register_cmd_linked_transaction_open (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
186static void gnc_plugin_page_register_cmd_jump_linked_invoice (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
187
188static void gnc_plugin_page_help_changed_cb (GNCSplitReg* gsr,
190static void gnc_plugin_page_popup_menu_cb (GNCSplitReg* gsr,
192static void gnc_plugin_page_register_refresh_cb (GHashTable* changes,
193 gpointer user_data);
194static void gnc_plugin_page_register_close_cb (gpointer user_data);
195
196static void gnc_plugin_page_register_ui_update (gpointer various,
198static void gppr_account_destroy_cb (Account* account);
199static void gnc_plugin_page_register_event_handler (QofInstance* entity,
200 QofEventId event_type,
202 GncEventData* ed);
203
204static GncInvoice* invoice_from_split (Split* split);
205
206/************************************************************/
207/* Actions */
208/************************************************************/
209
210#define CUT_TRANSACTION_LABEL N_("Cu_t Transaction")
211#define COPY_TRANSACTION_LABEL N_("_Copy Transaction")
212#define PASTE_TRANSACTION_LABEL N_("_Paste Transaction")
213#define DUPLICATE_TRANSACTION_LABEL N_("Dup_licate Transaction")
214#define DELETE_TRANSACTION_LABEL N_("_Delete Transaction")
215/* Translators: This is a menu item that opens a dialog for linking an
216 external file or URL with the bill, invoice, transaction, or voucher or
217 removing such an link. */
218#define LINK_TRANSACTION_LABEL N_("_Manage Document Link…")
219/* Translators: This is a menu item that opens an external file or URI that may
220 be linked to the current bill, invoice, transaction, or voucher using
221 the operating system's default application for the file or URI mime type. */
222#define LINK_TRANSACTION_OPEN_LABEL N_("_Open Linked Document")
223/* Translators: This is a menu item that will open the bill, invoice, or voucher
224 that is posted to the current transaction if there is one. */
225#define JUMP_LINKED_INVOICE_LABEL N_("Jump to Business item")
226#define CUT_SPLIT_LABEL N_("Cu_t Split")
227#define COPY_SPLIT_LABEL N_("_Copy Split")
228#define PASTE_SPLIT_LABEL N_("_Paste Split")
229#define DUPLICATE_SPLIT_LABEL N_("Dup_licate Split")
230#define DELETE_SPLIT_LABEL N_("_Delete Split")
231#define CUT_TRANSACTION_TIP N_("Cut the selected transaction into clipboard")
232#define COPY_TRANSACTION_TIP N_("Copy the selected transaction into clipboard")
233#define PASTE_TRANSACTION_TIP N_("Paste the transaction from the clipboard")
234#define DUPLICATE_TRANSACTION_TIP N_("Make a copy of the current transaction")
235#define DELETE_TRANSACTION_TIP N_("Delete the current transaction")
236#define LINK_TRANSACTION_TIP N_("Add, change, or unlink the document linked with the current transaction")
237#define LINK_TRANSACTION_OPEN_TIP N_("Open the linked document for the current transaction")
238#define JUMP_LINKED_INVOICE_TIP N_("Jump to the linked invoice, bill, expense or credit note")
239#define CUT_SPLIT_TIP N_("Cut the selected split into clipboard")
240#define COPY_SPLIT_TIP N_("Copy the selected split into clipboard")
241#define PASTE_SPLIT_TIP N_("Paste the split from the clipboard")
242#define DUPLICATE_SPLIT_TIP N_("Make a copy of the current split")
243#define DELETE_SPLIT_TIP N_("Delete the current split")
244
245static GActionEntry gnc_plugin_page_register_actions [] =
246{
247 { "FilePrintAction", gnc_plugin_page_register_cmd_print_check, NULL, NULL, NULL },
248 { "EditCutAction", gnc_plugin_page_register_cmd_cut, NULL, NULL, NULL },
249 { "EditCopyAction", gnc_plugin_page_register_cmd_copy, NULL, NULL, NULL },
250 { "EditPasteAction", gnc_plugin_page_register_cmd_paste, NULL, NULL, NULL },
251 { "EditEditAccountAction", gnc_plugin_page_register_cmd_edit_account, NULL, NULL, NULL },
252 { "EditFindAccountAction", gnc_plugin_page_register_cmd_find_account, NULL, NULL, NULL },
253 { "EditFindTransactionsAction", gnc_plugin_page_register_cmd_find_transactions, NULL, NULL, NULL },
254 { "EditTaxOptionsAction", gnc_plugin_page_register_cmd_edit_tax_options, NULL, NULL, NULL },
255 { "CutTransactionAction", gnc_plugin_page_register_cmd_cut_transaction, NULL, NULL, NULL },
256 { "CopyTransactionAction", gnc_plugin_page_register_cmd_copy_transaction, NULL, NULL, NULL },
257 { "PasteTransactionAction", gnc_plugin_page_register_cmd_paste_transaction, NULL, NULL, NULL },
258 { "DuplicateTransactionAction", gnc_plugin_page_register_cmd_duplicate_transaction, NULL, NULL, NULL },
259 { "DeleteTransactionAction", gnc_plugin_page_register_cmd_delete_transaction, NULL, NULL, NULL },
260 { "RemoveTransactionSplitsAction", gnc_plugin_page_register_cmd_reinitialize_transaction, NULL, NULL, NULL },
261 { "RecordTransactionAction", gnc_plugin_page_register_cmd_enter_transaction, NULL, NULL, NULL },
262 { "CancelTransactionAction", gnc_plugin_page_register_cmd_cancel_transaction, NULL, NULL, NULL },
263 { "VoidTransactionAction", gnc_plugin_page_register_cmd_void_transaction, NULL, NULL, NULL },
264 { "UnvoidTransactionAction", gnc_plugin_page_register_cmd_unvoid_transaction, NULL, NULL, NULL },
265 { "ReverseTransactionAction", gnc_plugin_page_register_cmd_reverse_transaction, NULL, NULL, NULL },
266 { "LinkTransactionAction", gnc_plugin_page_register_cmd_linked_transaction, NULL, NULL, NULL },
267 { "LinkedTransactionOpenAction", gnc_plugin_page_register_cmd_linked_transaction_open, NULL, NULL, NULL },
268 { "JumpLinkedInvoiceAction", gnc_plugin_page_register_cmd_jump_linked_invoice, NULL, NULL, NULL },
269 { "ViewSortByAction", gnc_plugin_page_register_cmd_view_sort_by, NULL, NULL, NULL },
270 { "ViewFilterByAction", gnc_plugin_page_register_cmd_view_filter_by, NULL, NULL, NULL },
271 { "ViewRefreshAction", gnc_plugin_page_register_cmd_reload, NULL, NULL, NULL },
272 { "ActionsTransferAction", gnc_plugin_page_register_cmd_transfer, NULL, NULL, NULL },
273 { "ActionsReconcileAction", gnc_plugin_page_register_cmd_reconcile, NULL, NULL, NULL },
274 { "ActionsAutoClearAction", gnc_plugin_page_register_cmd_autoclear, NULL, NULL, NULL },
275 { "ActionsStockAssistantAction", gnc_plugin_page_register_cmd_stock_assistant, NULL, NULL, NULL },
276 { "ActionsStockSplitAction", gnc_plugin_page_register_cmd_stock_split, NULL, NULL, NULL },
277 { "ActionsLotsAction", gnc_plugin_page_register_cmd_lots, NULL, NULL, NULL },
278 { "BlankTransactionAction", gnc_plugin_page_register_cmd_blank_transaction, NULL, NULL, NULL },
279 { "GotoDateAction", gnc_plugin_page_register_cmd_goto_date, NULL, NULL, NULL },
280 { "EditExchangeRateAction", gnc_plugin_page_register_cmd_exchange_rate, NULL, NULL, NULL },
281 { "JumpTransactionAction", gnc_plugin_page_register_cmd_jump, NULL, NULL, NULL },
282 { "ScheduleTransactionAction", gnc_plugin_page_register_cmd_schedule, NULL, NULL, NULL },
283 { "ScrubAllAction", gnc_plugin_page_register_cmd_scrub_all, NULL, NULL, NULL },
284 { "ScrubCurrentAction", gnc_plugin_page_register_cmd_scrub_current, NULL, NULL, NULL },
285 { "ReportsAccountReportAction", gnc_plugin_page_register_cmd_account_report, NULL, NULL, NULL },
286 { "ReportsAcctTransReportAction", gnc_plugin_page_register_cmd_transaction_report, NULL, NULL, NULL },
287
288 { "ViewStyleDoubleLineAction", gnc_plugin_page_register_cmd_style_double_line, NULL, "false", NULL },
289 { "SplitTransactionAction", gnc_plugin_page_register_cmd_expand_transaction, NULL, "false", NULL },
290 { "ViewStyleRadioAction", gnc_plugin_page_register_cmd_style_changed, "i", "@i 0", NULL },
291};
292static guint gnc_plugin_page_register_n_actions = G_N_ELEMENTS(gnc_plugin_page_register_actions);
293
295static const gchar *gnc_plugin_load_ui_items [] =
296{
297 "FilePlaceholder3",
298 "EditPlaceholder1",
299 "EditPlaceholder2",
300 "EditPlaceholder3",
301 "EditPlaceholder5",
302 "ViewPlaceholder1",
303 "ViewPlaceholder2",
304 "ViewPlaceholder3",
305 "ViewPlaceholder4",
306 "TransPlaceholder0",
307 "TransPlaceholder1",
308 "TransPlaceholder2",
309 "TransPlaceholder3",
310 "TransPlaceholder4",
311 "ActionsPlaceholder4",
312 "ActionsPlaceholder5",
313 "ActionsPlaceholder6",
314 "ReportsPlaceholder1",
315 NULL,
316};
317
320static const gchar* actions_requiring_account[] =
321{
322 "EditEditAccountAction",
323 "ActionsReconcileAction",
324 "ActionsAutoClearAction",
325 "ActionsLotsAction",
326 NULL
327};
328
329static const gchar* actions_requiring_priced_account[] =
330{
331 "ActionsStockAssistantAction",
332 NULL
333};
334
336static GncToolBarShortNames toolbar_labels[] =
337{
338 { "ActionsTransferAction", N_ ("Transfer") },
339 { "RecordTransactionAction", N_ ("Enter") },
340 { "CancelTransactionAction", N_ ("Cancel") },
341 { "DeleteTransactionAction", N_ ("Delete") },
342 { "DuplicateTransactionAction", N_ ("Duplicate") },
343 { "SplitTransactionAction",
344 /* Translators: This is the label of a toolbar button. So keep it short. */
345 N_ ("Show Splits") },
346 { "JumpTransactionAction", N_ ("Jump") },
347 { "ScheduleTransactionAction", N_ ("Schedule") },
348 { "BlankTransactionAction", N_ ("Blank") },
349 { "ActionsReconcileAction", N_ ("Reconcile") },
350 { "ActionsStockAssistantAction", N_ ("Stock Assistant") },
351 { NULL, NULL },
352};
353
354/************************************************************/
355/* Data Structures */
356/************************************************************/
357
359{
360 GNCLedgerDisplay* ledger;
361 GNCSplitReg* gsr;
362
363 GtkWidget* widget;
364
365 gint event_handler_id;
366 gint component_manager_id;
367 GncGUID key; /* The guid of the Account we're watching */
368
369 gint lines_default;
370 gboolean read_only;
371 gboolean page_focus;
372 gboolean enable_refresh; // used to reduce ledger display refreshes
373 Query* search_query; // saved search query for comparison
374 Query* filter_query; // saved filter query for comparison
375
376 SortData sd;
377 FilterData fd;
378
380
381G_DEFINE_TYPE_WITH_PRIVATE (GncPluginPageRegister, gnc_plugin_page_register,
382 GNC_TYPE_PLUGIN_PAGE)
383
384#define GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE(o) \
385 ((GncPluginPageRegisterPrivate*)gnc_plugin_page_register_get_instance_private((GncPluginPageRegister*)o))
386
387/************************************************************/
388/* Implementation */
389/************************************************************/
390
391static GncPluginPage*
392gnc_plugin_page_register_new_common (GNCLedgerDisplay* ledger)
393{
396 GncPluginPage* plugin_page;
397 GNCSplitReg* gsr;
398 const GList* item;
399 GList* book_list;
400 gchar* label;
401 gchar* label_color;
402 QofQuery* q;
403
404 // added for version 4.0 onwards
405 if (!gnc_features_check_used (gnc_get_current_book(), GNC_FEATURE_REG_SORT_FILTER))
406 gnc_features_set_used (gnc_get_current_book(), GNC_FEATURE_REG_SORT_FILTER);
407
408 // added for version 4.14 onwards
409 if (!gnc_using_equity_type_opening_balance_account (gnc_get_current_book()))
410 gnc_set_use_equity_type_opening_balance_account (gnc_get_current_book());
411
412 /* Is there an existing page? */
413 gsr = GNC_SPLIT_REG(gnc_ledger_display_get_user_data (ledger));
414 if (gsr)
415 {
416 item = gnc_gobject_tracking_get_list (GNC_PLUGIN_PAGE_REGISTER_NAME);
417 for (; item; item = g_list_next (item))
418 {
419 page = (GncPluginPageRegister*)item->data;
420 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
421 if (priv->gsr == gsr)
422 return GNC_PLUGIN_PAGE (page);
423 }
424 }
425
426 page = GNC_PLUGIN_PAGE_REGISTER(g_object_new (GNC_TYPE_PLUGIN_PAGE_REGISTER, nullptr));
427 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
428 priv->ledger = ledger;
429 priv->key = *guid_null();
430
431 plugin_page = GNC_PLUGIN_PAGE (page);
432 label = gnc_plugin_page_register_get_tab_name (plugin_page);
433 gnc_plugin_page_set_page_name (plugin_page, label);
434 g_free (label);
435
436 label_color = gnc_plugin_page_register_get_tab_color (plugin_page);
437 gnc_plugin_page_set_page_color (plugin_page, label_color);
438 g_free (label_color);
439
440 label = gnc_plugin_page_register_get_long_name (plugin_page);
441 gnc_plugin_page_set_page_long_name (plugin_page, label);
442 g_free (label);
443
444 q = gnc_ledger_display_get_query (ledger);
445 book_list = qof_query_get_books (q);
446 for (item = book_list; item; item = g_list_next (item))
447 gnc_plugin_page_add_book (plugin_page, (QofBook*)item->data);
448 // Do not free the list. It is owned by the query.
449
450 priv->component_manager_id = 0;
451 return plugin_page;
452}
453
454static gpointer
455gnc_plug_page_register_check_commodity (Account* account, void* usr_data)
456{
457 // Check that account's commodity matches the commodity in usr_data
458 gnc_commodity* com0 = (gnc_commodity*) usr_data;
459 gnc_commodity* com1 = xaccAccountGetCommodity (account);
460 return gnc_commodity_equal (com1, com0) ? NULL : com1;
461}
462
464gnc_plugin_page_register_new (Account* account, gboolean subaccounts)
465{
466 GNCLedgerDisplay* ledger;
467 GncPluginPage* plugin_page;
469 gnc_commodity* com0;
470 gnc_commodity* com1;
471
472 ENTER ("account=%p, subaccounts=%s", account,
473 subaccounts ? "TRUE" : "FALSE");
474
475 com0 = gnc_account_get_currency_or_parent (account);
476 com1 = GNC_COMMODITY(gnc_account_foreach_descendant_until (account,
477 gnc_plug_page_register_check_commodity,
478 static_cast<gpointer>(com0)));
479
480 if (subaccounts)
481 ledger = gnc_ledger_display_subaccounts (account, com1 != NULL);
482 else
483 ledger = gnc_ledger_display_simple (account);
484
485 plugin_page = gnc_plugin_page_register_new_common (ledger);
486 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
487 priv->key = *xaccAccountGetGUID (account);
488
489 LEAVE ("%p", plugin_page);
490 return plugin_page;
491}
492
495{
496 GNCLedgerDisplay* ledger;
497
498 ledger = gnc_ledger_display_gl();
499 return gnc_plugin_page_register_new_common (ledger);
500}
501
503gnc_plugin_page_register_new_ledger (GNCLedgerDisplay* ledger)
504{
505 return gnc_plugin_page_register_new_common (ledger);
506}
507
508static void
509gnc_plugin_page_register_class_init (GncPluginPageRegisterClass* klass)
510{
511 GObjectClass* object_class = G_OBJECT_CLASS (klass);
512 GncPluginPageClass* gnc_plugin_class = GNC_PLUGIN_PAGE_CLASS (klass);
513
514 object_class->finalize = gnc_plugin_page_register_finalize;
515
516 gnc_plugin_class->tab_icon = GNC_ICON_ACCOUNT;
517 gnc_plugin_class->plugin_name = GNC_PLUGIN_PAGE_REGISTER_NAME;
518 gnc_plugin_class->create_widget = gnc_plugin_page_register_create_widget;
519 gnc_plugin_class->destroy_widget = gnc_plugin_page_register_destroy_widget;
520 gnc_plugin_class->window_changed = gnc_plugin_page_register_window_changed;
521 gnc_plugin_class->focus_page = gnc_plugin_page_register_focus;
522 gnc_plugin_class->save_page = gnc_plugin_page_register_save_page;
523 gnc_plugin_class->recreate_page = gnc_plugin_page_register_recreate_page;
524 gnc_plugin_class->update_edit_menu_actions = gnc_plugin_page_register_update_edit_menu;
525 gnc_plugin_class->finish_pending = gnc_plugin_page_register_finish_pending;
526 gnc_plugin_class->focus_page_function = gnc_plugin_page_register_focus_widget;
527
528 gnc_ui_register_account_destroy_callback (gppr_account_destroy_cb);
529}
530
531static void
532gnc_plugin_page_register_init (GncPluginPageRegister* page)
533{
535 GncPluginPage* plugin_page;
536 GSimpleActionGroup *simple_action_group;
537 gboolean use_new;
538
539 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
540
541 /* Init parent declared variables */
542 plugin_page = GNC_PLUGIN_PAGE (page);
543 use_new = gnc_prefs_get_bool (GNC_PREFS_GROUP_GENERAL_REGISTER,
544 GNC_PREF_USE_NEW);
545 g_object_set (G_OBJECT (page),
546 "page-name", _ ("General Journal"),
547 "ui-description", "gnc-plugin-page-register.ui",
548 "use-new-window", use_new,
549 NULL);
550
551 /* Create menu and toolbar information */
552 simple_action_group = gnc_plugin_page_create_action_group (plugin_page,
553 "GncPluginPageRegisterActions");
554 g_action_map_add_action_entries (G_ACTION_MAP(simple_action_group),
555 gnc_plugin_page_register_actions,
556 gnc_plugin_page_register_n_actions,
557 page);
558
559 priv->lines_default = DEFAULT_LINES_AMOUNT;
560 priv->read_only = FALSE;
561 priv->fd.cleared_match = CLEARED_ALL;
562 priv->fd.days = 0;
563 priv->enable_refresh = TRUE;
564 priv->search_query = NULL;
565 priv->filter_query = NULL;
566}
567
568static void
569gnc_plugin_page_register_finalize (GObject* object)
570{
571 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (object));
572
573 ENTER ("object %p", object);
574
575 G_OBJECT_CLASS (gnc_plugin_page_register_parent_class)->finalize (object);
576 LEAVE (" ");
577}
578
579Account*
581{
583 GNCLedgerDisplayType ledger_type;
584 Account* leader;
585
586 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
587 ledger_type = gnc_ledger_display_type (priv->ledger);
588 leader = gnc_ledger_display_leader (priv->ledger);
589
590 if ((ledger_type == LD_SINGLE) || (ledger_type == LD_SUBACCOUNT))
591 return leader;
592 return NULL;
593}
594
595Transaction*
597{
599 SplitRegister* reg;
600
601 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
602 reg = gnc_ledger_display_get_split_register (priv->ledger);
604}
605
610static gboolean
611gnc_plugin_page_register_focus_widget (GncPluginPage* plugin_page)
612{
613 if (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page))
614 {
615 GncWindow* gnc_window = GNC_WINDOW(GNC_PLUGIN_PAGE(plugin_page)->window);
616 GNCSplitReg *gsr = gnc_plugin_page_register_get_gsr (GNC_PLUGIN_PAGE(plugin_page));
617
618 if (GNC_IS_MAIN_WINDOW(GNC_PLUGIN_PAGE(plugin_page)->window))
619 {
620 /* Enable the Transaction menu */
621 GAction *action = gnc_main_window_find_action (GNC_MAIN_WINDOW(plugin_page->window), "TransactionAction");
622 g_simple_action_set_enabled (G_SIMPLE_ACTION(action), TRUE);
623 /* Disable the Schedule menu */
624 action = gnc_main_window_find_action (GNC_MAIN_WINDOW(plugin_page->window), "ScheduledAction");
625 g_simple_action_set_enabled (G_SIMPLE_ACTION(action), FALSE);
626
627 gnc_main_window_update_menu_and_toolbar (GNC_MAIN_WINDOW(plugin_page->window),
628 plugin_page,
629 gnc_plugin_load_ui_items);
630 }
631 else
632 {
633 GtkWidget *toolbar = gnc_window_get_toolbar (gnc_window);
634 GtkWidget *menubar = gnc_window_get_menubar (gnc_window);
635 GMenuModel *menubar_model = gnc_window_get_menubar_model (gnc_window);
636 GtkWidget *statusbar = gnc_window_get_statusbar (gnc_window);
637
638 // add tooltip redirect call backs
639 gnc_plugin_add_toolbar_tooltip_callbacks (toolbar, statusbar);
640 gnc_plugin_add_menu_tooltip_callbacks (menubar, menubar_model, statusbar);
641 }
642
643 // setup any short toolbar names
644 gnc_plugin_init_short_names (gnc_window_get_toolbar (gnc_window), toolbar_labels);
645
646 gnc_plugin_page_register_ui_update (NULL, GNC_PLUGIN_PAGE_REGISTER(plugin_page));
647
648 gnc_split_reg_focus_on_sheet (gsr);
649 }
650 return FALSE;
651}
652
653/* This is the list of actions which are switched inactive in a read-only book. */
654static const char* readonly_inactive_actions[] =
655{
656 "EditCutAction",
657 "EditPasteAction",
658 "CutTransactionAction",
659 "PasteTransactionAction",
660 "DuplicateTransactionAction",
661 "DeleteTransactionAction",
662 "RemoveTransactionSplitsAction",
663 "RecordTransactionAction",
664 "CancelTransactionAction",
665 "UnvoidTransactionAction",
666 "VoidTransactionAction",
667 "ReverseTransactionAction",
668 "ActionsTransferAction",
669 "ActionsReconcileAction",
670 "ActionsStockSplitAction",
671 "ScheduleTransactionAction",
672 "ScrubAllAction",
673 "ScrubCurrentAction",
674 "LinkTransactionAction",
675 NULL
676};
677
678/* This is the list of actions whose text needs to be changed based on whether */
679/* the current cursor class is transaction or split. */
680static const char* tran_vs_split_actions[] =
681{
682 "CutTransactionAction",
683 "CopyTransactionAction",
684 "PasteTransactionAction",
685 "DuplicateTransactionAction",
686 "DeleteTransactionAction",
687 NULL
688};
689
690/* This is the list of labels for when the current cursor class is transaction. */
691static const char* tran_action_labels[] =
692{
693 CUT_TRANSACTION_LABEL,
694 COPY_TRANSACTION_LABEL,
695 PASTE_TRANSACTION_LABEL,
696 DUPLICATE_TRANSACTION_LABEL,
697 DELETE_TRANSACTION_LABEL,
698 NULL
699};
700
701/* This is the list of tooltips for when the current cursor class is transaction. */
702static const char* tran_action_tips[] =
703{
704 CUT_TRANSACTION_TIP,
705 COPY_TRANSACTION_TIP,
706 PASTE_TRANSACTION_TIP,
707 DUPLICATE_TRANSACTION_TIP,
708 DELETE_TRANSACTION_TIP,
709 NULL
710};
711
712/* This is the list of labels for when the current cursor class is split. */
713static const char* split_action_labels[] =
714{
715 CUT_SPLIT_LABEL,
716 COPY_SPLIT_LABEL,
717 PASTE_SPLIT_LABEL,
718 DUPLICATE_SPLIT_LABEL,
719 DELETE_SPLIT_LABEL,
720 NULL
721};
722
723/* This is the list of tooltips for when the current cursor class is split. */
724static const char* split_action_tips[] =
725{
726 CUT_SPLIT_TIP,
727 COPY_SPLIT_TIP,
728 PASTE_SPLIT_TIP,
729 DUPLICATE_SPLIT_TIP,
730 DELETE_SPLIT_TIP,
731 NULL
732};
733
734static std::vector<GncInvoice*>
735invoices_from_transaction (const Transaction* trans)
736{
737 std::vector<GncInvoice*> rv;
738
739 g_return_val_if_fail (GNC_IS_TRANSACTION (trans), rv);
740
741 for (auto node = xaccTransGetSplitList (trans); node; node = g_list_next (node))
742 {
743 auto split = GNC_SPLIT(node->data);
744 auto account = xaccSplitGetAccount (split);
745 if (!account || !xaccAccountIsAPARType(xaccAccountGetType(account)))
746 continue;
747 auto inv = invoice_from_split (split);
748 if (inv)
749 rv.push_back (inv);
750 }
751 return rv;
752}
753
754static void
755gnc_plugin_page_register_ui_update (gpointer various,
757{
759 SplitRegister* reg;
760 GAction* action;
761 GNCLedgerDisplayType ledger_type;
762 gboolean expanded, voided, read_only = FALSE, read_only_reg = FALSE;
763 Transaction* trans;
764 CursorClass cursor_class;
765 const char* uri;
766 Account *account;
767 GncWindow* gnc_window = GNC_WINDOW(GNC_PLUGIN_PAGE(page)->window);
768
769 /* Set 'Split Transaction' */
770 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
771 reg = gnc_ledger_display_get_split_register (priv->ledger);
774
775 action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page), "SplitTransactionAction");
776 g_simple_action_set_enabled (G_SIMPLE_ACTION(action), reg->style == REG_STYLE_LEDGER);
777
778 /* Set "style" radio button */
779 ledger_type = gnc_ledger_display_type (priv->ledger);
780 action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page), "ViewStyleRadioAction");
781
782 g_simple_action_set_enabled (G_SIMPLE_ACTION(action), ledger_type != LD_GL);
783 g_action_change_state (G_ACTION(action), g_variant_new_int32 (reg->style));
784
785 /* Set double line */
786 action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page), "ViewStyleDoubleLineAction");
787 g_action_change_state (G_ACTION(action), g_variant_new_boolean (reg->use_double_line));
788
789 /* Split Expand */
790 action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page), "SplitTransactionAction");
791 g_simple_action_set_enabled (G_SIMPLE_ACTION(action), reg->style == REG_STYLE_LEDGER);
792
793 g_signal_handlers_block_by_func (action, (gpointer)gnc_plugin_page_register_cmd_expand_transaction, page);
794 g_action_change_state (G_ACTION(action), g_variant_new_boolean (expanded));
795 g_signal_handlers_unblock_by_func (action, (gpointer)gnc_plugin_page_register_cmd_expand_transaction, page);
796
798
799 /* Done like this as the register can be displayed in embedded window */
800 if (GNC_IS_MAIN_WINDOW(GNC_PLUGIN_PAGE(page)->window))
801 {
802 /* Enable the FilePrintAction */
803 action = gnc_main_window_find_action (GNC_MAIN_WINDOW(GNC_PLUGIN_PAGE(page)->window), "FilePrintAction");
804 g_simple_action_set_enabled (G_SIMPLE_ACTION(action), TRUE);
805
806 /* Set the vis of the StockAssistant */
807 gnc_main_window_set_vis_of_items_by_action (GNC_MAIN_WINDOW(GNC_PLUGIN_PAGE(page)->window),
808 actions_requiring_priced_account,
809 account &&
810 xaccAccountIsPriced (account));
811 }
812
813 /* If we are in a readonly book, or possibly a place holder
814 * account register make any modifying action inactive */
815 if (qof_book_is_readonly (gnc_get_current_book()) ||
816 gnc_split_reg_get_read_only (priv->gsr))
817 read_only_reg = TRUE;
818
819 gnc_plugin_set_actions_enabled (G_ACTION_MAP(gnc_plugin_page_get_action_group (GNC_PLUGIN_PAGE(page))),
820 actions_requiring_account,
821 !read_only_reg && account != NULL);
822
823 gnc_plugin_set_actions_enabled (G_ACTION_MAP(gnc_plugin_page_get_action_group (GNC_PLUGIN_PAGE(page))),
824 actions_requiring_priced_account,
825 account && xaccAccountIsPriced (account));
826
827 /* Set available actions based on read only */
829
830 if (cursor_class == CURSOR_CLASS_SPLIT)
831 {
832 if (GNC_IS_MAIN_WINDOW(GNC_PLUGIN_PAGE(page)->window))
833 gnc_plugin_page_set_menu_popup_qualifier (GNC_PLUGIN_PAGE(page), "split");
834 else
835 gnc_plugin_page_set_menu_popup_qualifier (GNC_PLUGIN_PAGE(page), "split-sx");
836 }
837 else
838 {
839 if (GNC_IS_MAIN_WINDOW(GNC_PLUGIN_PAGE(page)->window))
840 gnc_plugin_page_set_menu_popup_qualifier (GNC_PLUGIN_PAGE(page), "trans");
841 else
842 gnc_plugin_page_set_menu_popup_qualifier (GNC_PLUGIN_PAGE(page), "trans-sx");
843 }
844
845 /* If the register is not read only, make any modifying action active
846 * to start with */
847 if (!read_only_reg)
848 {
849 const char** iter;
850 for (iter = readonly_inactive_actions; *iter; ++iter)
851 {
852 /* Set the action's sensitivity */
853 GAction* action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page), *iter);
854 g_simple_action_set_enabled (G_SIMPLE_ACTION(action), TRUE);
855 }
856 main_window_update_page_set_read_only_icon (GNC_PLUGIN_PAGE(page), FALSE);
857
858 if (trans)
859 read_only = xaccTransIsReadonlyByPostedDate (trans);
860
861 voided = xaccTransHasSplitsInState (trans, VREC);
862
863 action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page),
864 "CutTransactionAction");
865 g_simple_action_set_enabled (G_SIMPLE_ACTION(action), !read_only & !voided);
866
867 action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page),
868 "PasteTransactionAction");
869 g_simple_action_set_enabled (G_SIMPLE_ACTION(action), !read_only & !voided);
870
871 action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page),
872 "DeleteTransactionAction");
873 g_simple_action_set_enabled (G_SIMPLE_ACTION(action), !read_only & !voided);
874
875 if (cursor_class == CURSOR_CLASS_SPLIT)
876 {
877 action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page),
878 "DuplicateTransactionAction");
879 g_simple_action_set_enabled (G_SIMPLE_ACTION(action), !read_only & !voided);
880 }
881
882 action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page),
883 "RemoveTransactionSplitsAction");
884 g_simple_action_set_enabled (G_SIMPLE_ACTION(action), !read_only & !voided);
885
886 /* Set 'Void' and 'Unvoid' */
887 if (read_only)
888 voided = TRUE;
889
890 action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page),
891 "VoidTransactionAction");
892 g_simple_action_set_enabled (G_SIMPLE_ACTION(action), !voided);
893
894 if (read_only)
895 voided = FALSE;
896
897 action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page),
898 "UnvoidTransactionAction");
899 g_simple_action_set_enabled (G_SIMPLE_ACTION(action), voided);
900 }
901
902 /* Set 'Open and Remove Linked Documents' */
903 action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page),
904 "LinkedTransactionOpenAction");
905 if (trans)
906 {
907 uri = xaccTransGetDocLink (trans);
908 g_simple_action_set_enabled (G_SIMPLE_ACTION(action), (uri ? TRUE:FALSE));
909 }
910 /* Set 'ExecAssociatedInvoice'
911 We can determine an invoice from a txn if either
912 - it is an invoice transaction
913 - it has splits with an invoice associated with it
914 */
915 action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page),
916 "JumpLinkedInvoiceAction");
917 if (trans)
918 {
919 auto invoices = invoices_from_transaction (trans);
920 g_simple_action_set_enabled (G_SIMPLE_ACTION(action), !invoices.empty());
921 }
922
923 gnc_plugin_business_split_reg_ui_update (GNC_PLUGIN_PAGE(page));
924
925 // Transaction/Split paste action
926 action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page),
927 "PasteTransactionAction");
928 g_simple_action_set_enabled (G_SIMPLE_ACTION(action),
930
931 /* If we are read only, make any modifying action inactive */
932 if (read_only_reg)
933 {
934 const char** iter;
935 for (iter = readonly_inactive_actions; *iter; ++iter)
936 {
937 /* Set the action's sensitivity */
938 GAction* action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page), *iter);
939 g_simple_action_set_enabled (G_SIMPLE_ACTION(action), FALSE);
940 }
941 main_window_update_page_set_read_only_icon (GNC_PLUGIN_PAGE(page), TRUE);
942 }
943
944 /* Modifying action descriptions based on cursor class */
945 {
946 GncMenuModelSearch *gsm = g_new0 (GncMenuModelSearch, 1);
947 gboolean found = FALSE;
948 const char** iter, **label_iter, **tooltip_iter;
949 gboolean curr_label_trans = FALSE;
950 iter = tran_vs_split_actions;
951 label_iter = tran_action_labels;
952
953 gsm->search_action_label = NULL;
954 gsm->search_action_name = *iter;
955 gsm->search_action_target = NULL;
956
957 found = gnc_menubar_model_find_item (gnc_window_get_menubar_model (gnc_window), gsm);
958
959 PINFO("Test for action '%s', found is %d, iter label is '%s'", *iter, found, _(*label_iter));
960
961 if (!found)
962 {
963 g_free (gsm);
964 return;
965 }
966
967 if (g_strcmp0 (gsm->search_action_label, _(*label_iter)) == 0)
968 curr_label_trans = TRUE;
969
970 g_free (gsm);
971
972 if ((cursor_class == CURSOR_CLASS_SPLIT) && curr_label_trans)
973 {
974 gboolean found = FALSE;
975 label_iter = split_action_labels;
976 tooltip_iter = split_action_tips;
977 for (iter = tran_vs_split_actions; *iter; ++iter)
978 {
979 /* Adjust the action's label and tooltip */
980 found = gnc_menubar_model_update_item (gnc_window_get_menubar_model (gnc_window),
981 *iter, NULL, _(*label_iter), NULL, _(*tooltip_iter));
982
983 PINFO("split model_item action '%s', found is %d, iter label is '%s'",
984 *iter, found, _(*label_iter));
985
986 ++label_iter;
987 ++tooltip_iter;
988 }
989 }
990 else if ((cursor_class == CURSOR_CLASS_TRANS) && !curr_label_trans)
991 {
992 gboolean found = FALSE;
993 label_iter = tran_action_labels;
994 tooltip_iter = tran_action_tips;
995 for (iter = tran_vs_split_actions; *iter; ++iter)
996 {
997 /* Adjust the action's label and tooltip */
998 found = gnc_menubar_model_update_item (gnc_window_get_menubar_model (gnc_window),
999 *iter, NULL, _(*label_iter), NULL, _(*tooltip_iter));
1000
1001 PINFO("trans model_item action '%s', found is %d, iter label is '%s'",
1002 *iter, found, _(*label_iter));
1003
1004 ++label_iter;
1005 ++tooltip_iter;
1006 }
1007 }
1008 // now add the callbacks to the replaced menu items.
1009 gnc_plugin_add_menu_tooltip_callbacks (gnc_window_get_menubar (gnc_window),
1010 gnc_window_get_menubar_model (gnc_window),
1011 gnc_window_get_statusbar (gnc_window));
1012
1013 // need to add any accelerator keys, default or user added
1014 gnc_add_accelerator_keys_for_menu (gnc_window_get_menubar (gnc_window),
1015 gnc_window_get_menubar_model (gnc_window),
1016 gnc_window_get_accel_group (gnc_window));
1017 }
1018}
1019
1020static void
1021gnc_plugin_page_register_ui_initial_state (GncPluginPageRegister* page)
1022{
1024 GSimpleActionGroup *simple_action_group;
1025 GAction *action;
1026 Account* account;
1027 SplitRegister* reg;
1028 GNCLedgerDisplayType ledger_type;
1029 gboolean is_readwrite = !qof_book_is_readonly (gnc_get_current_book());
1030
1031 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
1032 account = gnc_plugin_page_register_get_account (page);
1033
1034 /* Get the action group */
1035 simple_action_group = gnc_plugin_page_get_action_group (GNC_PLUGIN_PAGE(page));
1036 g_return_if_fail (G_IS_SIMPLE_ACTION_GROUP(simple_action_group));
1037
1038 gnc_plugin_set_actions_enabled (G_ACTION_MAP(simple_action_group), actions_requiring_account,
1039 is_readwrite && account != NULL);
1040
1041 /* Set "style" radio button */
1042 ledger_type = gnc_ledger_display_type (priv->ledger);
1043 action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page), "ViewStyleRadioAction");
1044 g_simple_action_set_enabled (G_SIMPLE_ACTION(action), ledger_type == LD_SINGLE);
1045
1046 reg = gnc_ledger_display_get_split_register (priv->ledger);
1047
1048 g_signal_handlers_block_by_func (action,
1049 (gpointer)gnc_plugin_page_register_cmd_style_changed, page);
1050 g_action_change_state (G_ACTION(action), g_variant_new_int32 (reg->style));
1051 g_signal_handlers_unblock_by_func (action,
1052 (gpointer)gnc_plugin_page_register_cmd_style_changed, page);
1053
1054 /* Set "double line" toggle button */
1055 action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page), "ViewStyleDoubleLineAction");
1056 g_signal_handlers_block_by_func (action,
1057 (gpointer)gnc_plugin_page_register_cmd_style_double_line, page);
1058 g_action_change_state (G_ACTION(action), g_variant_new_boolean (reg->use_double_line));
1059 g_signal_handlers_unblock_by_func (action,
1060 (gpointer)gnc_plugin_page_register_cmd_style_double_line, page);
1061}
1062
1063/* For setting the focus on a register page, the default gnc_plugin
1064 * function for 'focus_page' is overridden so that the page focus
1065 * can be conditionally set. This is to allow for enabling the setting
1066 * of the sheet focus only when the page is the current one.
1067 */
1068static void
1069gnc_plugin_page_register_focus (GncPluginPage* plugin_page,
1070 gboolean on_current_page)
1071{
1074 GNCSplitReg* gsr;
1075 gboolean main_window_is_quitting = FALSE;
1076
1077 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
1078
1079 page = GNC_PLUGIN_PAGE_REGISTER (plugin_page);
1080 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
1081
1082 gsr = gnc_plugin_page_register_get_gsr (GNC_PLUGIN_PAGE (plugin_page));
1083
1084 if (GNC_IS_MAIN_WINDOW(plugin_page->window))
1085 main_window_is_quitting = gnc_main_window_is_quitting (GNC_MAIN_WINDOW(plugin_page->window));
1086
1087 if (on_current_page)
1088 {
1089 priv->page_focus = TRUE;
1090
1091 // Chain up to use parent version of 'focus_page' which will
1092 // use an idle_add as the page changed signal is emitted multiple times.
1093 GNC_PLUGIN_PAGE_CLASS (gnc_plugin_page_register_parent_class)->focus_page (plugin_page, TRUE);
1094 }
1095 else
1096 priv->page_focus = FALSE;
1097
1098 // set the sheet focus setting
1099 gnc_split_reg_set_sheet_focus (gsr, priv->page_focus);
1100
1101 // No need to do a refresh on application closing
1102 if (on_current_page && !main_window_is_quitting)
1103 gnc_ledger_display_set_focus (priv->ledger, priv->page_focus);
1104}
1105
1106static void
1107gnc_ppr_update_filter_and_sort (GncPluginPage* plugin_page)
1108{
1109 GncPluginPageRegister *page = GNC_PLUGIN_PAGE_REGISTER(plugin_page);
1110 GncPluginPageRegisterPrivate *priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE(page);
1111
1112 ENTER("page %p", plugin_page);
1113
1114 priv->enable_refresh = FALSE; // disable refresh
1115
1116 // Load the saved register sort and filter properties
1117 gnc_ppr_sort_update_register (plugin_page);
1118 gnc_ppr_filter_update_register (plugin_page);
1119
1120 priv->enable_refresh = TRUE; // enable refresh
1121
1122 // Set filter tooltip for summary bar
1123 gnc_ppr_filter_set_tooltip (plugin_page, &priv->fd);
1124}
1125
1126static GtkWidget*
1127gnc_plugin_page_register_create_widget (GncPluginPage* plugin_page)
1128{
1131 GncWindow* gnc_window;
1132 guint numRows;
1133 GtkWidget* gsr;
1134 SplitRegister* reg;
1135 Account* acct;
1136
1137 ENTER ("page %p", plugin_page);
1138 page = GNC_PLUGIN_PAGE_REGISTER (plugin_page);
1139 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
1140
1141 if (priv->widget != NULL)
1142 {
1143 LEAVE ("existing widget %p", priv->widget);
1144 return priv->widget;
1145 }
1146
1147 priv->widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
1148 gtk_box_set_homogeneous (GTK_BOX (priv->widget), FALSE);
1149 gtk_widget_show (priv->widget);
1150
1151 // Set the name for this widget so it can be easily manipulated with css
1152 gtk_widget_set_name (GTK_WIDGET(priv->widget), "gnc-id-register-page");
1153
1154 numRows = priv->lines_default;
1155 numRows = MIN (numRows, DEFAULT_LINES_AMOUNT);
1156
1157 gnc_window = GNC_WINDOW(GNC_PLUGIN_PAGE(page)->window);
1158 gsr = gnc_split_reg_new (priv->ledger,
1159 gnc_window_get_gtk_window (gnc_window),
1160 numRows, priv->read_only);
1161 priv->gsr = (GNCSplitReg *)gsr;
1162 g_object_ref (gsr);
1163
1164 gtk_widget_show (gsr);
1165 gtk_box_pack_start (GTK_BOX (priv->widget), gsr, TRUE, TRUE, 0);
1166
1167 g_signal_connect (G_OBJECT (gsr), "help-changed",
1168 G_CALLBACK (gnc_plugin_page_help_changed_cb),
1169 page);
1170
1171 g_signal_connect (G_OBJECT (gsr), "show-popup-menu",
1172 G_CALLBACK (gnc_plugin_page_popup_menu_cb),
1173 page);
1174
1175 reg = gnc_ledger_display_get_split_register (priv->ledger);
1176 gnc_split_register_config (reg, reg->type, reg->style,
1177 reg->use_double_line);
1178
1179 gnc_plugin_page_register_ui_initial_state (page);
1180 gnc_plugin_page_register_ui_update (NULL, page);
1181
1182 // Now setup the sort and filter settings
1183 gnc_ppr_update_filter_and_sort (plugin_page);
1184
1185 plugin_page->summarybar = gsr_create_summary_bar (priv->gsr);
1186 if (plugin_page->summarybar)
1187 {
1188 gtk_widget_show_all (plugin_page->summarybar);
1189 gtk_box_pack_start (GTK_BOX (priv->widget), plugin_page->summarybar,
1190 FALSE, FALSE, 0);
1191
1192 gnc_plugin_page_register_summarybar_position_changed (NULL, NULL, page);
1193 gnc_prefs_register_cb (GNC_PREFS_GROUP_GENERAL,
1194 GNC_PREF_SUMMARYBAR_POSITION_TOP,
1195 (gpointer)gnc_plugin_page_register_summarybar_position_changed,
1196 page);
1197 gnc_prefs_register_cb (GNC_PREFS_GROUP_GENERAL,
1198 GNC_PREF_SUMMARYBAR_POSITION_BOTTOM,
1199 (gpointer)gnc_plugin_page_register_summarybar_position_changed,
1200 page);
1201 }
1202
1203 priv->event_handler_id = qof_event_register_handler
1204 ((QofEventHandler)gnc_plugin_page_register_event_handler, page);
1205 priv->component_manager_id =
1206 gnc_register_gui_component (GNC_PLUGIN_PAGE_REGISTER_NAME,
1207 gnc_plugin_page_register_refresh_cb,
1208 gnc_plugin_page_register_close_cb,
1209 page);
1210 gnc_gui_component_set_session (priv->component_manager_id,
1211 gnc_get_current_session());
1213 if (acct)
1214 gnc_gui_component_watch_entity (
1215 priv->component_manager_id, xaccAccountGetGUID (acct),
1216 QOF_EVENT_DESTROY | QOF_EVENT_MODIFY);
1217
1218 gnc_split_reg_set_moved_cb
1219 (priv->gsr, (GFunc)gnc_plugin_page_register_ui_update, page);
1220
1221 g_signal_connect (G_OBJECT (plugin_page), "inserted",
1222 G_CALLBACK (gnc_plugin_page_inserted_cb),
1223 NULL);
1224
1225 /* DRH - Probably lots of other stuff from regWindowLedger should end up here. */
1226 LEAVE (" ");
1227 return priv->widget;
1228}
1229
1230static void
1231gnc_plugin_page_register_destroy_widget (GncPluginPage* plugin_page)
1232{
1235
1236 ENTER ("page %p", plugin_page);
1237 page = GNC_PLUGIN_PAGE_REGISTER (plugin_page);
1238 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
1239
1240 gnc_prefs_remove_cb_by_func (GNC_PREFS_GROUP_GENERAL,
1241 GNC_PREF_SUMMARYBAR_POSITION_TOP,
1242 (gpointer)gnc_plugin_page_register_summarybar_position_changed,
1243 page);
1244 gnc_prefs_remove_cb_by_func (GNC_PREFS_GROUP_GENERAL,
1245 GNC_PREF_SUMMARYBAR_POSITION_BOTTOM,
1246 (gpointer)gnc_plugin_page_register_summarybar_position_changed,
1247 page);
1248
1249 // Remove the page_changed signal callback
1250 gnc_plugin_page_disconnect_page_changed (GNC_PLUGIN_PAGE (plugin_page));
1251
1252 // Remove the page focus idle function if present
1253 g_idle_remove_by_data (GNC_PLUGIN_PAGE_REGISTER (plugin_page));
1254
1255 if (priv->widget == NULL)
1256 return;
1257
1258 if (priv->component_manager_id)
1259 {
1260 gnc_unregister_gui_component (priv->component_manager_id);
1261 priv->component_manager_id = 0;
1262 }
1263
1264 if (priv->event_handler_id)
1265 {
1266 qof_event_unregister_handler (priv->event_handler_id);
1267 priv->event_handler_id = 0;
1268 }
1269
1270 if (priv->sd.dialog)
1271 {
1272 gtk_widget_destroy (priv->sd.dialog);
1273 memset (&priv->sd, 0, sizeof (priv->sd));
1274 }
1275
1276 if (priv->fd.dialog)
1277 {
1278 gtk_widget_destroy (priv->fd.dialog);
1279 memset (&priv->fd, 0, sizeof (priv->fd));
1280 }
1281
1282 qof_query_destroy (priv->search_query);
1283 qof_query_destroy (priv->filter_query);
1284
1285 gtk_widget_hide (priv->widget);
1286
1287 g_object_unref(priv->widget);
1288 priv->widget = NULL;
1289
1290 gnc_ledger_display_close (priv->ledger);
1291 priv->ledger = NULL;
1292
1293 LEAVE (" ");
1294}
1295
1296static void
1297gnc_plugin_page_register_window_changed (GncPluginPage* plugin_page,
1298 GtkWidget* window)
1299{
1302
1303 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
1304
1305 page = GNC_PLUGIN_PAGE_REGISTER (plugin_page);
1306 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
1307 priv->gsr->window =
1308 GTK_WIDGET (gnc_window_get_gtk_window (GNC_WINDOW (window)));
1309}
1310
1311static const gchar* style_names[] =
1312{
1313 "Ledger",
1314 "Auto Ledger",
1315 "Journal",
1316 NULL
1317};
1318
1319#define KEY_REGISTER_TYPE "RegisterType"
1320#define KEY_ACCOUNT_NAME "AccountName"
1321#define KEY_ACCOUNT_GUID "AccountGuid"
1322#define KEY_REGISTER_STYLE "RegisterStyle"
1323#define KEY_DOUBLE_LINE "DoubleLineMode"
1324
1325#define LABEL_ACCOUNT "Account"
1326#define LABEL_SUBACCOUNT "SubAccount"
1327#define LABEL_GL "GL"
1328#define LABEL_SEARCH "Search"
1329
1330
1340static void
1341gnc_plugin_page_register_save_page (GncPluginPage* plugin_page,
1342 GKeyFile* key_file,
1343 const gchar* group_name)
1344{
1347 GNCLedgerDisplayType ledger_type;
1348 SplitRegister* reg;
1349 Account* leader;
1350
1351 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
1352 g_return_if_fail (key_file != NULL);
1353 g_return_if_fail (group_name != NULL);
1354
1355 ENTER ("page %p, key_file %p, group_name %s", plugin_page, key_file,
1356 group_name);
1357
1358 page = GNC_PLUGIN_PAGE_REGISTER (plugin_page);
1359 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
1360
1361 reg = gnc_ledger_display_get_split_register (priv->ledger);
1362 ledger_type = gnc_ledger_display_type (priv->ledger);
1363 if (ledger_type > LD_GL)
1364 {
1365 LEAVE ("Unsupported ledger type");
1366 return;
1367 }
1368 if ((ledger_type == LD_SINGLE) || (ledger_type == LD_SUBACCOUNT))
1369 {
1370 const gchar* label;
1371 gchar* name;
1372 gchar acct_guid[GUID_ENCODING_LENGTH + 1];
1373 label = (ledger_type == LD_SINGLE) ? LABEL_ACCOUNT : LABEL_SUBACCOUNT;
1374 leader = gnc_ledger_display_leader (priv->ledger);
1375 g_key_file_set_string (key_file, group_name, KEY_REGISTER_TYPE, label);
1376 name = gnc_account_get_full_name (leader);
1377 g_key_file_set_string (key_file, group_name, KEY_ACCOUNT_NAME, name);
1378 g_free (name);
1379 guid_to_string_buff (xaccAccountGetGUID (leader), acct_guid);
1380 g_key_file_set_string (key_file, group_name, KEY_ACCOUNT_GUID, acct_guid);
1381 }
1382 else if (reg->type == GENERAL_JOURNAL)
1383 {
1384 g_key_file_set_string (key_file, group_name, KEY_REGISTER_TYPE,
1385 LABEL_GL);
1386 }
1387 else if (reg->type == SEARCH_LEDGER)
1388 {
1389 g_key_file_set_string (key_file, group_name, KEY_REGISTER_TYPE,
1390 LABEL_SEARCH);
1391 }
1392 else
1393 {
1394 LEAVE ("Unsupported register type");
1395 return;
1396 }
1397
1398 g_key_file_set_string (key_file, group_name, KEY_REGISTER_STYLE,
1399 style_names[reg->style]);
1400 g_key_file_set_boolean (key_file, group_name, KEY_DOUBLE_LINE,
1401 reg->use_double_line);
1402
1403 LEAVE(" ");
1404}
1405
1406
1419static void
1420gnc_plugin_page_register_restore_edit_menu (GncPluginPage* plugin_page,
1421 GKeyFile* key_file,
1422 const gchar* group_name)
1423{
1424 GAction* action;
1425 GVariant *state;
1426 GError* error = NULL;
1427 gchar* style_name;
1428 gint i;
1429 gboolean use_double_line;
1430
1431 ENTER (" ");
1432
1433 /* Convert the style name to an index */
1434 style_name = g_key_file_get_string (key_file, group_name,
1435 KEY_REGISTER_STYLE, &error);
1436 for (i = 0 ; style_names[i]; i++)
1437 {
1438 if (g_ascii_strcasecmp (style_name, style_names[i]) == 0)
1439 {
1440 DEBUG ("Found match for style name: %s", style_name);
1441 break;
1442 }
1443 }
1444 g_free (style_name);
1445
1446 /* Update the style menu action for this page */
1447 if (i <= REG_STYLE_JOURNAL)
1448 {
1449 DEBUG ("Setting style: %d", i);
1450 action = gnc_plugin_page_get_action (plugin_page, "ViewStyleRadioAction");
1451 g_action_activate (G_ACTION(action), g_variant_new_int32 (i));
1452 }
1453
1454 /* Update the double line action on this page */
1455 use_double_line = g_key_file_get_boolean (key_file, group_name,
1456 KEY_DOUBLE_LINE, &error);
1457 DEBUG ("Setting double_line_mode: %d", use_double_line);
1458 action = gnc_plugin_page_get_action (plugin_page, "ViewStyleDoubleLineAction");
1459
1460 state = g_action_get_state (G_ACTION(action));
1461
1462 if (use_double_line != g_variant_get_boolean (state))
1463 g_action_activate (G_ACTION(action), NULL);
1464
1465 g_variant_unref (state);
1466
1467 LEAVE (" ");
1468}
1469
1470
1480static GncPluginPage*
1481gnc_plugin_page_register_recreate_page (GtkWidget* window,
1482 GKeyFile* key_file,
1483 const gchar* group_name)
1484{
1486 GncPluginPage* plugin_page;
1487 GError* error = NULL;
1488 gchar* reg_type, *acct_guid;
1489 GncGUID guid;
1490 Account* account = NULL;
1491 QofBook* book;
1492 gboolean include_subs;
1493
1494 g_return_val_if_fail (key_file, NULL);
1495 g_return_val_if_fail (group_name, NULL);
1496 ENTER ("key_file %p, group_name %s", key_file, group_name);
1497
1498 /* Create the new page. */
1499 reg_type = g_key_file_get_string (key_file, group_name,
1500 KEY_REGISTER_TYPE, &error);
1501 DEBUG ("Page type: %s", reg_type);
1502 if ((g_ascii_strcasecmp (reg_type, LABEL_ACCOUNT) == 0) ||
1503 (g_ascii_strcasecmp (reg_type, LABEL_SUBACCOUNT) == 0))
1504 {
1505 include_subs = (g_ascii_strcasecmp (reg_type, LABEL_SUBACCOUNT) == 0);
1506 DEBUG ("Include subs: %d", include_subs);
1507 book = qof_session_get_book (gnc_get_current_session());
1508 if (!book)
1509 {
1510 LEAVE("Session has no book");
1511 return NULL;
1512 }
1513 acct_guid = g_key_file_get_string (key_file, group_name,
1514 KEY_ACCOUNT_GUID, &error);
1515 if (string_to_guid (acct_guid, &guid)) //find account by guid
1516 {
1517 account = xaccAccountLookup (&guid, book);
1518 g_free (acct_guid);
1519 }
1520 if (account == NULL) //find account by full name
1521 {
1522 gchar* acct_name = g_key_file_get_string (key_file, group_name,
1523 KEY_ACCOUNT_NAME, &error);
1524 account = gnc_account_lookup_by_full_name (gnc_book_get_root_account (book),
1525 acct_name);
1526 g_free (acct_name);
1527 }
1528 if (account == NULL)
1529 {
1530 LEAVE ("Bad account name");
1531 g_free (reg_type);
1532 return NULL;
1533 }
1534 plugin_page = gnc_plugin_page_register_new (account, include_subs);
1535 }
1536 else if (g_ascii_strcasecmp (reg_type, LABEL_GL) == 0)
1537 {
1538 plugin_page = gnc_plugin_page_register_new_gl();
1539 }
1540 else
1541 {
1542 LEAVE ("Bad ledger type");
1543 g_free (reg_type);
1544 return NULL;
1545 }
1546 g_free (reg_type);
1547
1548 /* disable the refresh of the display ledger, this is for
1549 * sort/filter updates and double line/style changes */
1550 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
1551 priv->enable_refresh = FALSE;
1552
1553 /* Recreate page in given window */
1554 gnc_plugin_page_set_use_new_window (plugin_page, FALSE);
1555
1556 /* Install it now so we can them manipulate the created widget */
1557 gnc_main_window_open_page (GNC_MAIN_WINDOW (window), plugin_page);
1558
1559 /* Now update the page to the last state it was in */
1560 gnc_plugin_page_register_restore_edit_menu (plugin_page, key_file, group_name);
1561
1562 /* enable the refresh */
1563 priv->enable_refresh = TRUE;
1564 LEAVE (" ");
1565 return plugin_page;
1566}
1567
1568
1569/*
1570 * Based on code from Epiphany (src/ephy-window.c)
1571 */
1572static void
1573gnc_plugin_page_register_update_edit_menu (GncPluginPage* plugin_page, gboolean hide)
1574{
1577 GAction* action;
1578 gboolean can_copy = FALSE, can_cut = FALSE, can_paste = FALSE;
1579 gboolean has_selection;
1580 gboolean is_readwrite = !qof_book_is_readonly (gnc_get_current_book());
1581
1582 page = GNC_PLUGIN_PAGE_REGISTER (plugin_page);
1583 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
1584 has_selection = gnucash_register_has_selection (priv->gsr->reg);
1585
1586 can_copy = has_selection;
1587 can_cut = is_readwrite && has_selection;
1588 can_paste = is_readwrite;
1589
1590 action = gnc_plugin_page_get_action (plugin_page, "EditCopyAction");
1591 g_simple_action_set_enabled (G_SIMPLE_ACTION(action), can_copy);
1592 action = gnc_plugin_page_get_action (plugin_page, "EditCutAction");
1593 g_simple_action_set_enabled (G_SIMPLE_ACTION(action), can_cut);
1594 action = gnc_plugin_page_get_action (plugin_page, "EditPasteAction");
1595 g_simple_action_set_enabled (G_SIMPLE_ACTION(action), can_paste);
1596}
1597
1598static gboolean is_scrubbing = FALSE;
1599static gboolean show_abort_verify = TRUE;
1600
1601static const char*
1602check_repair_abort_YN = N_("'Check & Repair' is currently running, do you want to abort it?");
1603
1604static gboolean
1605finish_scrub (GncPluginPage* plugin_page)
1606{
1607 gboolean ret = FALSE;
1608
1609 if (is_scrubbing)
1610 {
1611 ret = gnc_verify_dialog (GTK_WINDOW(gnc_plugin_page_get_window (GNC_PLUGIN_PAGE(plugin_page))),
1612 false, "%s", _(check_repair_abort_YN));
1613
1614 show_abort_verify = FALSE;
1615
1616 if (ret)
1617 gnc_set_abort_scrub (TRUE);
1618 }
1619 return ret;
1620}
1621
1622static gboolean
1623gnc_plugin_page_register_finish_pending (GncPluginPage* plugin_page)
1624{
1627 SplitRegister* reg;
1628 GtkWidget* dialog, *window;
1629 gchar* name;
1630 gint response;
1631
1632 if (is_scrubbing && show_abort_verify)
1633 {
1634 if (!finish_scrub (plugin_page))
1635 return FALSE;
1636 }
1637
1638 page = GNC_PLUGIN_PAGE_REGISTER (plugin_page);
1639 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
1640 reg = gnc_ledger_display_get_split_register (priv->ledger);
1641
1642 if (!reg || !gnc_split_register_changed (reg))
1643 return TRUE;
1644
1645 name = gnc_plugin_page_register_get_tab_name (plugin_page);
1646 window = gnc_plugin_page_get_window (plugin_page);
1647 dialog = gtk_message_dialog_new (GTK_WINDOW (window),
1648 GTK_DIALOG_DESTROY_WITH_PARENT,
1649 GTK_MESSAGE_WARNING,
1650 GTK_BUTTONS_NONE,
1651 /* Translators: %s is the name
1652 of the tab page */
1653 _ ("Save changes to %s?"), name);
1654 g_free (name);
1655 gtk_message_dialog_format_secondary_text
1656 (GTK_MESSAGE_DIALOG (dialog),
1657 "%s",
1658 _ ("This register has pending changes to a transaction. "
1659 "Would you like to save the changes to this transaction, "
1660 "discard the transaction, or cancel the operation?"));
1661 gnc_gtk_dialog_add_button (dialog, _ ("_Discard Transaction"),
1662 "edit-delete", GTK_RESPONSE_REJECT);
1663 gtk_dialog_add_button (GTK_DIALOG (dialog),
1664 _ ("_Cancel"), GTK_RESPONSE_CANCEL);
1665 gnc_gtk_dialog_add_button (dialog, _ ("_Save Transaction"),
1666 "document-save", GTK_RESPONSE_ACCEPT);
1667
1668 response = gtk_dialog_run (GTK_DIALOG (dialog));
1669 gtk_widget_destroy (dialog);
1670
1671 switch (response)
1672 {
1673 case GTK_RESPONSE_ACCEPT:
1674 gnc_split_register_save (reg, TRUE);
1675 return TRUE;
1676
1677 case GTK_RESPONSE_REJECT:
1679 gnc_split_register_save (reg, TRUE);
1680 return TRUE;
1681
1682 default:
1683 return FALSE;
1684 }
1685}
1686
1687
1688static gchar*
1689gnc_plugin_page_register_get_tab_name (GncPluginPage* plugin_page)
1690{
1692 GNCLedgerDisplayType ledger_type;
1693 GNCLedgerDisplay* ld;
1694 SplitRegister* reg;
1695 Account* leader;
1696
1697 g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page),
1698 g_strdup (_("unknown")));
1699
1700 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
1701 ld = priv->ledger;
1703 ledger_type = gnc_ledger_display_type (ld);
1704 leader = gnc_ledger_display_leader (ld);
1705
1706 switch (ledger_type)
1707 {
1708 case LD_SINGLE:
1709 return g_strdup (xaccAccountGetName (leader));
1710
1711 case LD_SUBACCOUNT:
1712 return g_strdup_printf ("%s+", xaccAccountGetName (leader));
1713
1714 case LD_GL:
1715 switch (reg->type)
1716 {
1717 case GENERAL_JOURNAL:
1718 case INCOME_LEDGER:
1719 return g_strdup (_ ("General Journal"));
1720 case PORTFOLIO_LEDGER:
1721 return g_strdup (_ ("Portfolio"));
1722 case SEARCH_LEDGER:
1723 return g_strdup (_ ("Search Results"));
1724 default:
1725 break;
1726 }
1727 break;
1728
1729 default:
1730 break;
1731 }
1732
1733 return g_strdup (_ ("unknown"));
1734}
1735
1736static gchar*
1737gnc_plugin_page_register_get_tab_color (GncPluginPage* plugin_page)
1738{
1740 GNCLedgerDisplayType ledger_type;
1741 GNCLedgerDisplay* ld;
1742 Account* leader;
1743 const char* color;
1744
1745 g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page),
1746 g_strdup (_("unknown")));
1747
1748 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
1749 ld = priv->ledger;
1750 ledger_type = gnc_ledger_display_type (ld);
1751 leader = gnc_ledger_display_leader (ld);
1752 color = NULL;
1753
1754 if ((ledger_type == LD_SINGLE) || (ledger_type == LD_SUBACCOUNT))
1755 color = xaccAccountGetColor (leader);
1756
1757 return g_strdup (color ? color : "Not Set");
1758}
1759
1760static gchar*
1761gnc_plugin_page_register_get_long_name (GncPluginPage* plugin_page)
1762{
1764 GNCLedgerDisplayType ledger_type;
1765 GNCLedgerDisplay* ld;
1766 Account* leader;
1767
1768 g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page),
1769 _ ("unknown"));
1770
1771 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
1772 ld = priv->ledger;
1773 ledger_type = gnc_ledger_display_type (ld);
1774 leader = gnc_ledger_display_leader (ld);
1775
1776 switch (ledger_type)
1777 {
1778 case LD_SINGLE:
1779 return gnc_account_get_full_name (leader);
1780
1781 case LD_SUBACCOUNT:
1782 {
1783 gchar* account_full_name = gnc_account_get_full_name (leader);
1784 gchar* return_string = g_strdup_printf ("%s+", account_full_name);
1785 g_free ((gpointer*) account_full_name);
1786 return return_string;
1787 }
1788
1789 default:
1790 break;
1791 }
1792
1793 return NULL;
1794}
1795
1796static void
1797gnc_plugin_page_register_summarybar_position_changed (gpointer prefs,
1798 gchar* pref,
1799 gpointer user_data)
1800{
1801 GncPluginPage* plugin_page;
1804 GtkPositionType position = GTK_POS_BOTTOM;
1805
1806 g_return_if_fail (user_data != NULL);
1807
1808 if (!GNC_IS_PLUGIN_PAGE (user_data))
1809 return;
1810
1811 plugin_page = GNC_PLUGIN_PAGE (user_data);
1812 page = GNC_PLUGIN_PAGE_REGISTER (user_data);
1813 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
1814
1815 if (priv == NULL)
1816 return;
1817
1818 if (gnc_prefs_get_bool (GNC_PREFS_GROUP_GENERAL,
1819 GNC_PREF_SUMMARYBAR_POSITION_TOP))
1820 position = GTK_POS_TOP;
1821
1822 gtk_box_reorder_child (GTK_BOX (priv->widget),
1823 plugin_page->summarybar,
1824 (position == GTK_POS_TOP ? 0 : -1));
1825}
1826
1827static void
1828gnc_plugin_page_register_update_page_icon (GncPluginPage* plugin_page)
1829{
1831 gboolean read_only;
1832
1833 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
1834
1835 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
1836
1837 if (qof_book_is_readonly (gnc_get_current_book()) ||
1838 gnc_split_reg_get_read_only (priv->gsr))
1839 read_only = TRUE;
1840 else
1841 read_only = FALSE;
1842
1843 main_window_update_page_set_read_only_icon (GNC_PLUGIN_PAGE(plugin_page),
1844 read_only);
1845}
1846
1852Query*
1854{
1857
1858 g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page), NULL);
1859
1860 page = GNC_PLUGIN_PAGE_REGISTER (plugin_page);
1861 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
1862 return gnc_ledger_display_get_query (priv->ledger);
1863}
1864
1865void
1867{
1869
1870 ENTER(" ");
1871 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE(page);
1872
1873 // clear previous filter query and save current
1874 qof_query_destroy (priv->filter_query);
1875 priv->filter_query = qof_query_copy (query);
1876
1877 if (priv->enable_refresh)
1878 gnc_ledger_display_refresh (priv->ledger);
1879 LEAVE(" ");
1880}
1881
1882void
1884{
1886 SplitRegister* reg;
1887
1888 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
1889 reg = gnc_ledger_display_get_split_register (priv->ledger);
1890
1891 if (reg->type == SEARCH_LEDGER)
1892 {
1893 Query* query_tmp = gnc_ledger_display_get_query (priv->ledger);
1894
1895 // if filter_query is NULL, then the dialogue find has been run
1896 // before coming here. if query_tmp does not equal filter_query
1897 // then the dialogue find has been run again before coming here
1898 if ((priv->filter_query == NULL) ||
1899 (!qof_query_equal (query_tmp, priv->filter_query)))
1900 {
1901 qof_query_destroy (priv->search_query);
1902 priv->search_query = qof_query_copy (query_tmp);
1903 }
1904 gnc_ledger_display_set_query (priv->ledger, priv->search_query);
1905 }
1906}
1907
1908void
1910 gboolean enable_refresh)
1911{
1913
1914 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER(page));
1915
1916 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE(page);
1917
1918 priv->enable_refresh = enable_refresh;
1919}
1920
1921void
1923{
1924 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER(plugin_page));
1925
1927}
1928
1929/************************************************************/
1930/* Report Helper Functions */
1931/************************************************************/
1932
1933static char*
1934gnc_reg_get_name (GNCLedgerDisplay* ledger, gboolean for_window)
1935{
1936 Account* leader;
1937 SplitRegister* reg;
1938 gchar* account_name;
1939 gchar* reg_name;
1940 gchar* name;
1941 GNCLedgerDisplayType ledger_type;
1942
1943 if (ledger == NULL)
1944 return NULL;
1945
1947 ledger_type = gnc_ledger_display_type (ledger);
1948
1949 switch (reg->type)
1950 {
1951 case GENERAL_JOURNAL:
1952 case INCOME_LEDGER:
1953 if (for_window)
1954 reg_name = _ ("General Journal");
1955 else
1956 reg_name = _ ("Transaction Report");
1957 break;
1958 case PORTFOLIO_LEDGER:
1959 if (for_window)
1960 reg_name = _ ("Portfolio");
1961 else
1962 reg_name = _ ("Portfolio Report");
1963 break;
1964 case SEARCH_LEDGER:
1965 if (for_window)
1966 reg_name = _ ("Search Results");
1967 else
1968 reg_name = _ ("Search Results Report");
1969 break;
1970 default:
1971 if (for_window)
1972 reg_name = _ ("Register");
1973 else
1974 reg_name = _ ("Transaction Report");
1975 break;
1976 }
1977
1978 leader = gnc_ledger_display_leader (ledger);
1979
1980 if ((leader != NULL) && (ledger_type != LD_GL))
1981 {
1982 account_name = gnc_account_get_full_name (leader);
1983
1984 if (ledger_type == LD_SINGLE)
1985 {
1986 name = g_strconcat (account_name, " - ", reg_name, NULL);
1987 }
1988 else
1989 {
1990 name = g_strconcat (account_name, " ", _ ("and subaccounts"), " - ", reg_name,
1991 NULL);
1992 }
1993 g_free (account_name);
1994 }
1995 else
1996 name = g_strdup (reg_name);
1997
1998 return name;
1999}
2000
2001static int
2002report_helper (GNCLedgerDisplay* ledger, Split* split, Query* query)
2003{
2004 SplitRegister* reg = gnc_ledger_display_get_split_register (ledger);
2005 Account* account;
2006 char* str;
2007 const char* tmp;
2008 swig_type_info* qtype;
2009 SCM args;
2010 SCM func;
2011 SCM arg;
2012
2013 args = SCM_EOL;
2014
2015 func = scm_c_eval_string ("gnc:register-report-create");
2016 g_return_val_if_fail (scm_is_procedure (func), -1);
2017
2019 arg = scm_from_utf8_string (tmp ? tmp : _ ("Credit"));
2020 args = scm_cons (arg, args);
2021
2023 arg = scm_from_utf8_string (tmp ? tmp : _ ("Debit"));
2024 args = scm_cons (arg, args);
2025
2026 str = gnc_reg_get_name (ledger, FALSE);
2027 arg = scm_from_utf8_string (str ? str : "");
2028 args = scm_cons (arg, args);
2029 g_free (str);
2030
2031 arg = SCM_BOOL (reg->use_double_line);
2032 args = scm_cons (arg, args);
2033
2034 arg = SCM_BOOL (reg->type == GENERAL_JOURNAL || reg->type == INCOME_LEDGER
2035 || reg->type == SEARCH_LEDGER);
2036 args = scm_cons (arg, args);
2037
2038 arg = SCM_BOOL (reg->style == REG_STYLE_JOURNAL);
2039 args = scm_cons (arg, args);
2040
2041 if (!query)
2042 {
2043 query = gnc_ledger_display_get_query (ledger);
2044 g_return_val_if_fail (query != NULL, -1);
2045 }
2046
2047 qtype = SWIG_TypeQuery ("_p__QofQuery");
2048 g_return_val_if_fail (qtype, -1);
2049
2050 arg = SWIG_NewPointerObj (query, qtype, 0);
2051 args = scm_cons (arg, args);
2052 g_return_val_if_fail (arg != SCM_UNDEFINED, -1);
2053
2054
2055 if (split)
2056 {
2057 qtype = SWIG_TypeQuery ("_p_Split");
2058 g_return_val_if_fail (qtype, -1);
2059 arg = SWIG_NewPointerObj (split, qtype, 0);
2060 }
2061 else
2062 {
2063 arg = SCM_BOOL_F;
2064 }
2065 args = scm_cons (arg, args);
2066 g_return_val_if_fail (arg != SCM_UNDEFINED, -1);
2067
2068
2069 qtype = SWIG_TypeQuery ("_p_Account");
2070 g_return_val_if_fail (qtype, -1);
2071
2072 account = gnc_ledger_display_leader (ledger);
2073 arg = SWIG_NewPointerObj (account, qtype, 0);
2074 args = scm_cons (arg, args);
2075 g_return_val_if_fail (arg != SCM_UNDEFINED, -1);
2076
2077
2078 /* Apply the function to the args */
2079 arg = scm_apply (func, args, SCM_EOL);
2080 g_return_val_if_fail (scm_is_exact (arg), -1);
2081
2082 return scm_to_int (arg);
2083}
2084
2085/************************************************************/
2086/* Command callbacks */
2087/************************************************************/
2088
2089static void
2090gnc_plugin_page_register_cmd_print_check (GSimpleAction *simple,
2091 GVariant *paramter,
2092 gpointer user_data)
2093{
2094 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2096 SplitRegister* reg;
2097 Split* split;
2098 Transaction* trans;
2099 GList* splits = NULL, *item;
2100 GNCLedgerDisplayType ledger_type;
2101 Account* account, *subaccount = NULL;
2102 GtkWidget* window;
2103
2104 ENTER ("(action %p, page %p)", simple, page);
2105
2106 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2107
2108 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2109 reg = gnc_ledger_display_get_split_register (priv->ledger);
2110 ledger_type = gnc_ledger_display_type (priv->ledger);
2111 window = gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page));
2112 if (ledger_type == LD_SINGLE || ledger_type == LD_SUBACCOUNT)
2113 {
2114 account = gnc_plugin_page_register_get_account (page);
2116 trans = xaccSplitGetParent (split);
2117 if (ledger_type == LD_SUBACCOUNT)
2118 {
2119 /* Set up subaccount printing, where the check amount matches the
2120 * value displayed in the register. */
2121 subaccount = account;
2122 }
2123
2124 if (split && trans)
2125 {
2126 if (xaccSplitGetAccount (split) == account)
2127 {
2128 splits = g_list_prepend (splits, split);
2129 gnc_ui_print_check_dialog_create (window, splits, subaccount);
2130 g_list_free (splits);
2131 }
2132 else
2133 {
2134 /* This split is not for the account shown in this register. Get the
2135 split that anchors the transaction to the registor */
2137 if (split)
2138 {
2139 splits = g_list_prepend (splits, split);
2140 gnc_ui_print_check_dialog_create (window, splits, subaccount);
2141 g_list_free (splits);
2142 }
2143 }
2144 }
2145 }
2146 else if (ledger_type == LD_GL && reg->type == SEARCH_LEDGER)
2147 {
2148 Account* common_acct = NULL;
2149
2150 /* the following GList* splits must not be freed */
2151 splits = qof_query_run (gnc_ledger_display_get_query (priv->ledger));
2152
2153 /* Make sure each split is from the same account */
2154 for (item = splits; item; item = g_list_next (item))
2155 {
2156 split = (Split*) item->data;
2157 if (common_acct == NULL)
2158 {
2159 common_acct = xaccSplitGetAccount (split);
2160 }
2161 else
2162 {
2163 if (xaccSplitGetAccount (split) != common_acct)
2164 {
2165 GtkWidget* dialog;
2166 gint response;
2167 const gchar* title = _ ("Print checks from multiple accounts?");
2168 const gchar* message =
2169 _ ("This search result contains splits from more than one account. "
2170 "Do you want to print the checks even though they are not all "
2171 "from the same account?");
2172 dialog = gtk_message_dialog_new (GTK_WINDOW (window),
2173 GTK_DIALOG_DESTROY_WITH_PARENT,
2174 GTK_MESSAGE_WARNING,
2175 GTK_BUTTONS_CANCEL,
2176 "%s", title);
2177 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
2178 "%s", message);
2179 gtk_dialog_add_button (GTK_DIALOG (dialog), _ ("_Print checks"),
2180 GTK_RESPONSE_YES);
2181 response = gnc_dialog_run (GTK_DIALOG (dialog),
2182 GNC_PREF_WARN_CHECKPRINTING_MULTI_ACCT);
2183 gtk_widget_destroy (dialog);
2184 if (response != GTK_RESPONSE_YES)
2185 {
2186 LEAVE ("Multiple accounts");
2187 return;
2188 }
2189 break;
2190 }
2191 }
2192 }
2193 gnc_ui_print_check_dialog_create (window, splits, NULL);
2194 }
2195 else
2196 {
2197 gnc_error_dialog (GTK_WINDOW (window), "%s",
2198 _ ("You can only print checks from a bank account register or search results."));
2199 LEAVE ("Unsupported ledger type");
2200 return;
2201 }
2202 LEAVE (" ");
2203}
2204
2205
2206static void
2207gnc_plugin_page_register_cmd_cut (GSimpleAction *simple,
2208 GVariant *paramter,
2209 gpointer user_data)
2210{
2211 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2213
2214 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2215
2216 ENTER ("(action %p, page %p)", simple, page);
2217 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2218
2219 GtkWidget *widget = gtk_window_get_focus(GTK_WINDOW (priv->gsr->window));
2220 const char *name = gtk_widget_get_name(widget);
2221 if (strcmp(name, "GnucashSheet") != 0)
2222 {
2223 gtk_editable_cut_clipboard( GTK_EDITABLE(widget));
2224 LEAVE("Not cut from GnucashSheet");
2225
2226 return;
2227 }
2228
2229 gnucash_register_cut_clipboard (priv->gsr->reg);
2230 LEAVE ("");
2231}
2232
2233
2234static void
2235gnc_plugin_page_register_cmd_copy (GSimpleAction *simple,
2236 GVariant *paramter,
2237 gpointer user_data)
2238{
2239 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2241
2242 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2243
2244 ENTER ("(action %p, page %p)", simple, page);
2245 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2246
2247 GtkWidget *widget = gtk_window_get_focus(GTK_WINDOW (priv->gsr->window));
2248 const char *name = gtk_widget_get_name(widget);
2249 if (strcmp(name, "GnucashSheet") != 0)
2250 {
2251 gtk_editable_copy_clipboard( GTK_EDITABLE(widget));
2252 LEAVE("Not copied from GnucashSheet");
2253
2254 return;
2255 }
2256
2257 gnucash_register_copy_clipboard (priv->gsr->reg);
2258 LEAVE ("");
2259}
2260
2261
2262static void
2263gnc_plugin_page_register_cmd_paste (GSimpleAction *simple,
2264 GVariant *paramter,
2265 gpointer user_data)
2266{
2267 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2269
2270 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2271
2272 ENTER ("(action %p, page %p)", simple, page);
2273 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2274
2275 GtkWidget *widget = gtk_window_get_focus(GTK_WINDOW (priv->gsr->window));
2276 const char *name = gtk_widget_get_name(widget);
2277 if (strcmp(name, "GnucashSheet") != 0)
2278 {
2279 gtk_editable_paste_clipboard( GTK_EDITABLE(widget));
2280 LEAVE("Not pasted to GnucashSheet");
2281
2282 return;
2283 }
2284
2285 gnucash_register_paste_clipboard (priv->gsr->reg);
2286 LEAVE ("");
2287}
2288
2289
2290static void
2291gnc_plugin_page_register_cmd_edit_account (GSimpleAction *simple,
2292 GVariant *paramter,
2293 gpointer user_data)
2294{
2295 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2296 Account* account;
2297 GtkWindow* parent = GTK_WINDOW(gnc_plugin_page_get_window (GNC_PLUGIN_PAGE(page)));
2298 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2299
2300 ENTER ("(action %p, page %p)", simple, page);
2301 account = gnc_plugin_page_register_get_account (page);
2302 if (account)
2303 gnc_ui_edit_account_window (parent, account);
2304 LEAVE (" ");
2305}
2306
2307
2308static void
2309gnc_plugin_page_register_cmd_find_account (GSimpleAction *simple,
2310 GVariant *paramter,
2311 gpointer user_data)
2312{
2313 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2314 GtkWidget* window;
2315
2316 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2317
2318 window = gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page));
2319 gnc_find_account_dialog (window, NULL);
2320}
2321
2322
2323static void
2324gnc_plugin_page_register_cmd_find_transactions (GSimpleAction *simple,
2325 GVariant *paramter,
2326 gpointer user_data)
2327{
2328 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2330 GtkWindow* window;
2331
2332 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2333
2334 ENTER ("(action %p, page %p)", simple, page);
2335 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2336 window = GTK_WINDOW (gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page)));
2337 gnc_ui_find_transactions_dialog_create (window, priv->ledger);
2338 LEAVE (" ");
2339}
2340
2341
2342static void
2343gnc_plugin_page_register_cmd_edit_tax_options (GSimpleAction *simple,
2344 GVariant *paramter,
2345 gpointer user_data)
2346{
2347 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2348 GtkWidget *window;
2349 Account* account;
2350
2351 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2352
2353 ENTER ("(action %p, page %p)", simple, page);
2354 window = gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page));
2355 account = gnc_plugin_page_register_get_account (page);
2356 gnc_tax_info_dialog (window, account);
2357 LEAVE (" ");
2358}
2359
2360static void
2361gnc_plugin_page_register_cmd_cut_transaction (GSimpleAction *simple,
2362 GVariant *paramter,
2363 gpointer user_data)
2364{
2365 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2367
2368 ENTER ("(action %p, page %p)", simple, page);
2369
2370 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2371
2372 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2373 gsr_default_cut_txn_handler (priv->gsr, NULL);
2374
2375 // Transaction/Split paste action
2376 GAction *action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page),
2377 "PasteTransactionAction");
2378 g_simple_action_set_enabled (G_SIMPLE_ACTION(action),
2380 LEAVE (" ");
2381}
2382
2383
2384static void
2385gnc_plugin_page_register_cmd_copy_transaction (GSimpleAction *simple,
2386 GVariant *paramter,
2387 gpointer user_data)
2388{
2389 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2391 SplitRegister* reg;
2392
2393 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2394
2395 ENTER ("(action %p, page %p)", simple, page);
2396 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2397 reg = gnc_ledger_display_get_split_register (priv->ledger);
2399
2400 // Transaction/Split paste action
2401 GAction *action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page),
2402 "PasteTransactionAction");
2403 g_simple_action_set_enabled (G_SIMPLE_ACTION(action),
2405 LEAVE (" ");
2406}
2407
2408
2409static void
2410gnc_plugin_page_register_cmd_paste_transaction (GSimpleAction *simple,
2411 GVariant *paramter,
2412 gpointer user_data)
2413{
2414 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2416 SplitRegister* reg;
2417
2418 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2419
2420 ENTER ("(action %p, page %p)", simple, page);
2421 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2422 reg = gnc_ledger_display_get_split_register (priv->ledger);
2424 LEAVE (" ");
2425}
2426
2427
2428static void
2429gnc_plugin_page_register_cmd_void_transaction (GSimpleAction *simple,
2430 GVariant *paramter,
2431 gpointer user_data)
2432{
2433 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2435 GtkWidget* dialog, *entry;
2436 SplitRegister* reg;
2437 Transaction* trans;
2438 GtkBuilder* builder;
2439 const char* reason;
2440 gint result;
2441 GtkWindow* window;
2442
2443 ENTER ("(action %p, page %p)", simple, page);
2444
2445 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2446
2447 window = GTK_WINDOW (gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page)));
2448 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2449 reg = gnc_ledger_display_get_split_register (priv->ledger);
2451 if (trans == NULL)
2452 return;
2453 if (xaccTransHasSplitsInState (trans, VREC))
2454 return;
2455 if (xaccTransHasReconciledSplits (trans) ||
2457 {
2458 gnc_error_dialog (window, "%s",
2459 _ ("You cannot void a transaction with reconciled or cleared splits."));
2460 return;
2461 }
2462 reason = xaccTransGetReadOnly (trans);
2463 if (reason)
2464 {
2465 gnc_error_dialog (window,
2466 _ ("This transaction is marked read-only with the comment: '%s'"), reason);
2467 return;
2468 }
2469
2470 if (!gnc_plugin_page_register_finish_pending (GNC_PLUGIN_PAGE (page)))
2471 return;
2472
2473 builder = gtk_builder_new();
2474 gnc_builder_add_from_file (builder, "gnc-plugin-page-register.glade",
2475 "void_transaction_dialog");
2476 dialog = GTK_WIDGET (gtk_builder_get_object (builder,
2477 "void_transaction_dialog"));
2478 entry = GTK_WIDGET (gtk_builder_get_object (builder, "reason"));
2479
2480 gtk_window_set_transient_for (GTK_WINDOW (dialog), window);
2481
2482 result = gtk_dialog_run (GTK_DIALOG (dialog));
2483 if (result == GTK_RESPONSE_OK)
2484 {
2485 reason = gtk_entry_get_text (GTK_ENTRY (entry));
2486 if (reason == NULL)
2487 reason = "";
2489 }
2490
2491 /* All done. Get rid of it. */
2492 gtk_widget_destroy (dialog);
2493 g_object_unref (G_OBJECT (builder));
2494}
2495
2496
2497static void
2498gnc_plugin_page_register_cmd_unvoid_transaction (GSimpleAction *simple,
2499 GVariant *paramter,
2500 gpointer user_data)
2501{
2502 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2504 SplitRegister* reg;
2505 Transaction* trans;
2506
2507 ENTER ("(action %p, page %p)", simple, page);
2508
2509 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2510
2511 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2512 reg = gnc_ledger_display_get_split_register (priv->ledger);
2514 if (!xaccTransHasSplitsInState (trans, VREC))
2515 return;
2517 LEAVE (" ");
2518}
2519
2520static std::optional<time64>
2521input_date (GtkWidget * parent, const char *window_title, const char* title)
2522{
2523 time64 rv = gnc_time (nullptr);
2524 if (!gnc_dup_time64_dialog (parent, window_title, title, &rv))
2525 return {};
2526
2527 return rv;
2528}
2529
2530static void
2531gnc_plugin_page_register_cmd_reverse_transaction (GSimpleAction *simple,
2532 GVariant *paramter,
2533 gpointer user_data)
2534{
2535 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2537 SplitRegister* reg;
2538 GNCSplitReg* gsr;
2539 Transaction* trans, *new_trans;
2540 GtkWidget *window;
2541 Account *account;
2542 Split *split;
2543
2544 ENTER ("(action %p, page %p)", simple, page);
2545
2546 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2547
2548 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2549 reg = gnc_ledger_display_get_split_register (priv->ledger);
2550 window = gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page));
2552 if (trans == NULL)
2553 return;
2554
2556 account = xaccSplitGetAccount (split);
2557
2558 if (!account)
2559 {
2560 LEAVE ("shouldn't try to reverse the blank transaction...");
2561 return;
2562 }
2563
2564 new_trans = xaccTransGetReversedBy (trans);
2565 if (new_trans)
2566 {
2567 const char *rev = _("A reversing entry has already been created for this transaction.");
2568 const char *jump = _("Jump to the transaction?");
2569 if (!gnc_verify_dialog (GTK_WINDOW (window), TRUE, "%s\n\n%s", rev, jump))
2570 {
2571 LEAVE ("reverse cancelled");
2572 return;
2573 }
2574 }
2575 else
2576 {
2577 auto date = input_date (window, _("Reverse Transaction"), _("New Transaction Information"));
2578 if (!date)
2579 {
2580 LEAVE ("reverse cancelled");
2581 return;
2582 }
2583
2584 gnc_suspend_gui_refresh ();
2585 new_trans = xaccTransReverse (trans);
2586
2587 /* Clear transaction level info */
2588 xaccTransSetDatePostedSecsNormalized (new_trans, date.value());
2589 xaccTransSetDateEnteredSecs (new_trans, gnc_time (NULL));
2590
2591 gnc_resume_gui_refresh();
2592 }
2593
2594 /* Now jump to new trans */
2595 gsr = gnc_plugin_page_register_get_gsr (GNC_PLUGIN_PAGE (page));
2596 split = xaccTransFindSplitByAccount(new_trans, account);
2597
2598 /* Test for visibility of split */
2599 if (gnc_split_reg_clear_filter_for_split (gsr, split))
2600 gnc_plugin_page_register_clear_current_filter (GNC_PLUGIN_PAGE(page));
2601
2602 gnc_split_reg_jump_to_split (gsr, split);
2603 LEAVE (" ");
2604}
2605
2606static bool
2607gnc_plugin_page_register_show_fs_save (GncPluginPageRegister* page)
2608{
2609 GncPluginPageRegisterPrivate* priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2610 GNCLedgerDisplayType ledger_type = gnc_ledger_display_type (priv->ledger);
2611 SplitRegister* reg = gnc_ledger_display_get_split_register (priv->ledger);
2612
2613 if (ledger_type == LD_SINGLE || ledger_type == LD_SUBACCOUNT)
2614 return true;
2615 else
2616 {
2617 switch (reg->type)
2618 {
2619 case GENERAL_JOURNAL:
2620 return true;
2621 break;
2622
2623 case INCOME_LEDGER:
2624 case PORTFOLIO_LEDGER:
2625 case SEARCH_LEDGER:
2626 default:
2627 return false;
2628 break;
2629 }
2630 }
2631}
2632
2633static void
2634gnc_plugin_page_register_cmd_view_sort_by (GSimpleAction *simple,
2635 GVariant *paramter,
2636 gpointer user_data)
2637{
2638 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2640
2641 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER(page));
2642 ENTER ("(action %p, page %p)", simple, page);
2643
2644 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE(page);
2645 if (priv->sd.dialog)
2646 {
2647 gtk_window_present (GTK_WINDOW (priv->sd.dialog));
2648 LEAVE("existing dialog");
2649 return;
2650 }
2651
2652 SplitRegister* reg = gnc_ledger_display_get_split_register (priv->ledger);
2653 bool show_save_button = gnc_plugin_page_register_show_fs_save (page);
2654
2655 gnc_ppr_sort_dialog (GNC_PLUGIN_PAGE(page), reg,
2656 &priv->sd, show_save_button);
2657}
2658
2659static void
2660gnc_plugin_page_register_cmd_view_filter_by (GSimpleAction *simple,
2661 GVariant *paramter,
2662 gpointer user_data)
2663{
2664 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2666
2667 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER(page));
2668 ENTER ("(action %p, page %p)", simple, page);
2669
2670 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE(page);
2671 if (priv->fd.dialog)
2672 {
2673 gtk_window_present (GTK_WINDOW(priv->fd.dialog));
2674 LEAVE ("existing dialog");
2675 return;
2676 }
2677
2678 Query* query = gnc_ledger_display_get_query (priv->ledger);
2679 bool show_save_button = gnc_plugin_page_register_show_fs_save (page);
2680
2681 gnc_ppr_filter_by (GNC_PLUGIN_PAGE(page), query,
2682 &priv->fd, show_save_button);
2683
2684 LEAVE (" ");
2685}
2686
2687static void
2688gnc_plugin_page_register_cmd_reload (GSimpleAction *simple,
2689 GVariant *paramter,
2690 gpointer user_data)
2691{
2692 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2694 SplitRegister* reg;
2695
2696 ENTER ("(action %p, page %p)", simple, page);
2697
2698 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2699
2700 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2701 reg = gnc_ledger_display_get_split_register (priv->ledger);
2702
2703 /* Check for trans being edited */
2705 {
2706 LEAVE ("register has pending edits");
2707 return;
2708 }
2709 gnc_ledger_display_refresh (priv->ledger);
2710 LEAVE (" ");
2711}
2712
2713static void
2714gnc_plugin_page_register_cmd_style_changed (GSimpleAction *simple,
2715 GVariant *parameter,
2716 gpointer user_data)
2717{
2718 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2720 SplitRegisterStyle value;
2721
2722 ENTER ("(action %p, page %p)", simple, page);
2723
2724 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2725
2726 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2727
2728 value = (SplitRegisterStyle)g_variant_get_int32 (parameter);
2729
2730 g_action_change_state (G_ACTION(simple), parameter);
2731
2732 gnc_split_reg_change_style (priv->gsr, value, priv->enable_refresh);
2733
2734 gnc_plugin_page_register_ui_update (NULL, page);
2735 LEAVE (" ");
2736}
2737
2738static void
2739gnc_plugin_page_register_cmd_style_double_line (GSimpleAction *simple,
2740 GVariant *parameter,
2741 gpointer user_data)
2742{
2743 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2745 SplitRegister* reg;
2746 gboolean use_double_line;
2747 GVariant *state;
2748
2749 ENTER ("(action %p, page %p)", simple, page);
2750
2751 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER(page));
2752
2753 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2754 reg = gnc_ledger_display_get_split_register (priv->ledger);
2755
2756 state = g_action_get_state (G_ACTION(simple));
2757
2758 g_action_change_state (G_ACTION(simple), g_variant_new_boolean (!g_variant_get_boolean (state)));
2759
2760 use_double_line = !g_variant_get_boolean (state);
2761
2762 if (use_double_line != reg->use_double_line)
2763 {
2764 gnc_split_register_config (reg, reg->type, reg->style, use_double_line);
2765 if (priv->enable_refresh)
2766 gnc_ledger_display_refresh (priv->ledger);
2767 }
2768 g_variant_unref (state);
2769 LEAVE (" ");
2770}
2771
2772static void
2773gnc_plugin_page_register_cmd_transfer (GSimpleAction *simple,
2774 GVariant *paramter,
2775 gpointer user_data)
2776{
2777 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2778 Account* account;
2779 GncWindow* gnc_window;
2780 GtkWidget* window;
2781
2782 ENTER ("(action %p, page %p)", simple, page);
2783
2784 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2785
2786 account = gnc_plugin_page_register_get_account (page);
2787 gnc_window = GNC_WINDOW (GNC_PLUGIN_PAGE (page)->window);
2788 window = GTK_WIDGET (gnc_window_get_gtk_window (gnc_window));
2789 gnc_xfer_dialog (window, account);
2790 LEAVE (" ");
2791}
2792
2793static void
2794gnc_plugin_page_register_cmd_reconcile (GSimpleAction *simple,
2795 GVariant *paramter,
2796 gpointer user_data)
2797{
2798 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2799 Account* account;
2800 GtkWindow* window;
2801 RecnWindow* recnData;
2802
2803 ENTER ("(action %p, page %p)", simple, page);
2804
2805 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2806
2807 /* To prevent mistakes involving saving an edited transaction after
2808 * finishing a reconciliation (reverting the reconcile state), require
2809 * pending activity on the current register to be finished.
2810 *
2811 * The reconcile window isn't modal so it's still possible to start editing
2812 * a transaction after opening it, but at that point the user should know
2813 * what they're doing is unsafe.
2814 */
2815 if (!gnc_plugin_page_register_finish_pending (GNC_PLUGIN_PAGE (page)))
2816 return;
2817
2818 account = gnc_plugin_page_register_get_account (page);
2819
2820 window = gnc_window_get_gtk_window (GNC_WINDOW (GNC_PLUGIN_PAGE (
2821 page)->window));
2822 recnData = recnWindow (GTK_WIDGET (window), account);
2823 gnc_ui_reconcile_window_raise (recnData);
2824 LEAVE (" ");
2825}
2826
2827static void
2828gnc_plugin_page_register_cmd_stock_assistant (GSimpleAction *simple,
2829 GVariant *paramter,
2830 gpointer user_data)
2831{
2832 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2833 Account *account;
2834 GtkWindow *window;
2835
2836 ENTER ("(action %p, page %p)", simple, page);
2837
2838 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2839 window = gnc_window_get_gtk_window (GNC_WINDOW (GNC_PLUGIN_PAGE (page)->window));
2840 account = gnc_plugin_page_register_get_account (page);
2841 gnc_stock_transaction_assistant (GTK_WIDGET (window), account);
2842
2843 LEAVE (" ");
2844}
2845
2846static void
2847gnc_plugin_page_register_cmd_autoclear (GSimpleAction *simple,
2848 GVariant *paramter,
2849 gpointer user_data)
2850{
2851 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2852 Account* account;
2853 GtkWindow* window;
2854 AutoClearWindow* autoClearData;
2855
2856 ENTER ("(action %p, page %p)", simple, page);
2857
2858 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2859
2860 account = gnc_plugin_page_register_get_account (page);
2861
2862 window = gnc_window_get_gtk_window (GNC_WINDOW (GNC_PLUGIN_PAGE (
2863 page)->window));
2864 autoClearData = autoClearWindow (GTK_WIDGET (window), account);
2865 gnc_ui_autoclear_window_raise (autoClearData);
2866 LEAVE (" ");
2867}
2868
2869static void
2870gnc_plugin_page_register_cmd_stock_split (GSimpleAction *simple,
2871 GVariant *paramter,
2872 gpointer user_data)
2873{
2874 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2875 Account* account;
2876 GtkWindow* window;
2877
2878 ENTER ("(action %p, page %p)", simple, page);
2879
2880 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2881
2882 account = gnc_plugin_page_register_get_account (page);
2883 window = gnc_window_get_gtk_window (GNC_WINDOW (GNC_PLUGIN_PAGE (page)->window));
2884 gnc_stock_split_dialog (GTK_WIDGET (window), account);
2885 LEAVE (" ");
2886}
2887
2888static void
2889gnc_plugin_page_register_cmd_lots (GSimpleAction *simple,
2890 GVariant *paramter,
2891 gpointer user_data)
2892{
2893 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2894 GtkWindow* window;
2895 Account* account;
2896
2897 ENTER ("(action %p, page %p)", simple, page);
2898
2899 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2900
2901 window = gnc_window_get_gtk_window (GNC_WINDOW (GNC_PLUGIN_PAGE (
2902 page)->window));
2903 account = gnc_plugin_page_register_get_account (page);
2904 gnc_lot_viewer_dialog (window, account);
2905 LEAVE (" ");
2906}
2907
2908static void
2909gnc_plugin_page_register_cmd_enter_transaction (GSimpleAction *simple,
2910 GVariant *paramter,
2911 gpointer user_data)
2912{
2913 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2915
2916 ENTER ("(action %p, page %p)", simple, page);
2917
2918 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2919
2920 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2921 gnc_split_reg_enter (priv->gsr, FALSE);
2922 LEAVE (" ");
2923}
2924
2925static void
2926gnc_plugin_page_register_cmd_cancel_transaction (GSimpleAction *simple,
2927 GVariant *paramter,
2928 gpointer user_data)
2929{
2930 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2932
2933 ENTER ("(action %p, page %p)", simple, page);
2934
2935 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2936
2937 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2940 LEAVE (" ");
2941}
2942
2943static void
2944gnc_plugin_page_register_cmd_delete_transaction (GSimpleAction *simple,
2945 GVariant *paramter,
2946 gpointer user_data)
2947{
2948 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2950
2951 ENTER ("(action %p, page %p)", simple, page);
2952
2953 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2954
2955 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2956 gsr_default_delete_handler (priv->gsr, NULL);
2957 LEAVE (" ");
2958
2959}
2960
2961static void
2962gnc_plugin_page_register_cmd_linked_transaction (GSimpleAction *simple,
2963 GVariant *paramter,
2964 gpointer user_data)
2965{
2966 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2968
2969 ENTER ("(action %p, page %p)", simple, page);
2970
2971 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2972
2973 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2974 gsr_default_doclink_handler (priv->gsr);
2975 gnc_plugin_page_register_ui_update (NULL, page);
2976 LEAVE (" ");
2977}
2978
2979static void
2980gnc_plugin_page_register_cmd_linked_transaction_open (GSimpleAction *simple,
2981 GVariant *paramter,
2982 gpointer user_data)
2983{
2984 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
2986
2987 ENTER ("(action %p, page %p)", simple, page);
2988
2989 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
2990
2991 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
2992 gsr_default_doclink_open_handler (priv->gsr);
2993 LEAVE (" ");
2994}
2995
2996static GncInvoice*
2997invoice_from_split (Split* split)
2998{
2999 GncInvoice* invoice;
3000 GNCLot* lot;
3001
3002 if (!split)
3003 return NULL;
3004
3005 lot = xaccSplitGetLot (split);
3006 if (!lot)
3007 return NULL;
3008
3009 invoice = gncInvoiceGetInvoiceFromLot (lot);
3010 if (!invoice)
3011 return NULL;
3012
3013 return invoice;
3014}
3015
3016
3017static void
3018gnc_plugin_page_register_cmd_jump_linked_invoice (GSimpleAction *simple,
3019 GVariant *paramter,
3020 gpointer user_data)
3021{
3022 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
3024 SplitRegister* reg;
3025 GncInvoice* invoice;
3026 Transaction *txn;
3027 GtkWidget *window;
3028
3029 ENTER ("(action %p, page %p)", simple, page);
3030
3031 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3032 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3033 reg = gnc_ledger_display_get_split_register (priv->gsr->ledger);
3035 invoice = invoice_from_split (gnc_split_register_get_current_split (reg));
3036 window = GNC_PLUGIN_PAGE(page)->window;
3037
3038 if (!invoice)
3039 {
3040 auto invoices = invoices_from_transaction (txn);
3041 if (invoices.empty())
3042 PERR ("shouldn't happen: if no invoices, function is never called");
3043 else if (invoices.size() == 1)
3044 invoice = invoices[0];
3045 else
3046 {
3047 GList *details = NULL;
3048 gint choice;
3049 const gchar *amt;
3050 for (const auto& inv : invoices)
3051 {
3052 gchar *date = qof_print_date (gncInvoiceGetDatePosted (inv));
3053 amt = xaccPrintAmount
3054 (gncInvoiceGetTotal (inv),
3055 gnc_account_print_info (gncInvoiceGetPostedAcc (inv), TRUE));
3056 details = g_list_prepend
3057 (details,
3058 /* Translators: %s refer to the following in
3059 order: invoice type, invoice ID, owner name,
3060 posted date, amount */
3061 g_strdup_printf (_("%s %s from %s, posted %s, amount %s"),
3062 gncInvoiceGetTypeString (inv),
3063 gncInvoiceGetID (inv),
3064 gncOwnerGetName (gncInvoiceGetOwner (inv)),
3065 date, amt));
3066 g_free (date);
3067 }
3068 details = g_list_reverse (details);
3069 choice = gnc_choose_radio_option_dialog
3070 (window, _("Select Business Item"),
3071 _("Several business items are linked with this transaction. \
3072Please choose one:"), _("Select"), 0, details);
3073 if ((choice >= 0) && ((size_t)choice < invoices.size()))
3074 invoice = invoices[choice];
3075 g_list_free_full (details, g_free);
3076 }
3077 }
3078
3079 if (invoice)
3080 {
3081 GtkWindow *gtk_window = gnc_window_get_gtk_window (GNC_WINDOW (window));
3082 gnc_ui_invoice_edit (gtk_window, invoice);
3083 }
3084
3085 LEAVE (" ");
3086}
3087
3088static void
3089gnc_plugin_page_register_cmd_blank_transaction (GSimpleAction *simple,
3090 GVariant *paramter,
3091 gpointer user_data)
3092{
3093 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
3095 SplitRegister* reg;
3096
3097 ENTER ("(action %p, page %p)", simple, page);
3098
3099 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3100
3101 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3102 reg = gnc_ledger_display_get_split_register (priv->ledger);
3103
3104 if (gnc_split_register_save (reg, TRUE))
3106
3107 gnc_split_reg_jump_to_blank (priv->gsr);
3108 LEAVE (" ");
3109}
3110
3111static bool
3112find_after_date (Split *split, time64* find_date)
3113{
3114 auto trans = xaccSplitGetParent (split);
3115 return !(xaccSplitGetAccount (split) != nullptr &&
3116 xaccTransGetDate (trans) >= *find_date &&
3117 xaccTransCountSplits (trans) != 1);
3118}
3119
3120static void
3121gnc_plugin_page_register_cmd_goto_date (GSimpleAction *simple,
3122 GVariant *paramter,
3123 gpointer user_data)
3124{
3125 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
3126 GNCSplitReg* gsr;
3127 Query* query;
3128 GList *splits;
3129 GtkWidget *window = gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page));
3130
3131 ENTER ("(action %p, page %p)", simple, page);
3132 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3133
3134 auto date = input_date (window, _("Go to Date"), _("Go to Date"));
3135
3136 if (!date)
3137 {
3138 LEAVE ("goto_date cancelled");
3139 return;
3140 }
3141
3142 gsr = gnc_plugin_page_register_get_gsr (GNC_PLUGIN_PAGE (page));
3143 query = gnc_plugin_page_register_get_query (GNC_PLUGIN_PAGE (page));
3144 splits = g_list_copy (qof_query_run (query));
3145 splits = g_list_sort (splits, (GCompareFunc)xaccSplitOrder);
3146
3147 // if gl register, there could be blank splits from other open registers
3148 // included in split list so check for and ignore them
3149 auto it = g_list_find_custom (splits, &date.value(), (GCompareFunc)find_after_date);
3150
3151 if (it)
3152 gnc_split_reg_jump_to_split (gsr, GNC_SPLIT(it->data));
3153 else
3154 gnc_split_reg_jump_to_blank (gsr);
3155
3156 g_list_free (splits);
3157 LEAVE (" ");
3158}
3159
3160static void
3161gnc_plugin_page_register_cmd_duplicate_transaction (GSimpleAction *simple,
3162 GVariant *paramter,
3163 gpointer user_data)
3164{
3165 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
3167
3168 ENTER ("(action %p, page %p)", simple, page);
3169
3170 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3171
3172 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3175 LEAVE (" ");
3176}
3177
3178static void
3179gnc_plugin_page_register_cmd_reinitialize_transaction (GSimpleAction *simple,
3180 GVariant *paramter,
3181 gpointer user_data)
3182{
3183 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
3185
3186 ENTER ("(action %p, page %p)", simple, page);
3187
3188 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3189
3190 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3191 gsr_default_reinit_handler (priv->gsr, NULL);
3192 LEAVE (" ");
3193}
3194
3195static void
3196gnc_plugin_page_register_cmd_expand_transaction (GSimpleAction *simple,
3197 GVariant *parameter,
3198 gpointer user_data)
3199{
3200 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
3202 SplitRegister* reg;
3203 gboolean expand;
3204 GVariant *state;
3205
3206 ENTER ("(action %p, page %p)", simple, page);
3207
3208 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3209
3210 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3211 reg = gnc_ledger_display_get_split_register (priv->ledger);
3212
3213 state = g_action_get_state (G_ACTION(simple));
3214
3215 g_action_change_state (G_ACTION(simple), g_variant_new_boolean (!g_variant_get_boolean (state)));
3216
3217 expand = !g_variant_get_boolean (state);
3218
3220 g_variant_unref (state);
3221 LEAVE (" ");
3222}
3223
3226static void
3227gnc_plugin_page_register_cmd_exchange_rate (GSimpleAction *simple,
3228 GVariant *paramter,
3229 gpointer user_data)
3230{
3231 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
3233 SplitRegister* reg;
3234
3235 ENTER ("(action %p, page %p)", simple, page);
3236
3237 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3238
3239 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3240 reg = gnc_ledger_display_get_split_register (priv->ledger);
3241
3242 /* XXX Ignore the return value -- we don't care if this succeeds */
3243 (void)gnc_split_register_handle_exchange (reg, TRUE);
3244 LEAVE (" ");
3245}
3246
3247static Split*
3248jump_multiple_splits_by_single_account (Account *account, Split *split)
3249{
3250 Transaction *trans;
3251 SplitList *splits;
3252 Account *other_account = NULL;
3253 Split *other_split = NULL;
3254
3255 trans = xaccSplitGetParent(split);
3256 if (!trans)
3257 return NULL;
3258
3259 for (splits = xaccTransGetSplitList(trans); splits; splits = splits->next)
3260 {
3261 Split *s = (Split*)splits->data;
3263
3264 if (!xaccTransStillHasSplit(trans, s))
3265 continue;
3266
3267 if (a == account)
3268 continue;
3269
3270 if (other_split)
3271 {
3272 if (other_account != a)
3273 return NULL;
3274
3275 continue;
3276 }
3277
3278 other_account = a;
3279 other_split = s;
3280 }
3281
3282 // Jump to the same account so that the right warning is triggered
3283 if (!other_split)
3284 other_split = split;
3285
3286 return other_split;
3287}
3288
3289static Split*
3290jump_multiple_splits_by_value (Account *account, Split *split, gboolean largest)
3291{
3292 Transaction *trans;
3293 SplitList *splits;
3294 Split *other_split = NULL;
3295 gnc_numeric best;
3296 int cmp = largest ? 1 : -1;
3297
3298 trans = xaccSplitGetParent(split);
3299 if (!trans)
3300 return NULL;
3301
3302 for (splits = xaccTransGetSplitList(trans); splits; splits = splits->next)
3303 {
3304 Split *s = (Split*)splits->data;
3305 gnc_numeric value;
3306
3307 if (!xaccTransStillHasSplit(trans, s))
3308 continue;
3309
3310 if (xaccSplitGetAccount(s) == account)
3311 continue;
3312
3314 if (gnc_numeric_check(value))
3315 continue;
3316
3317 /* For splits with the same value as the best, the first split
3318 * encountered is used.
3319 */
3320 if (other_split && gnc_numeric_compare(value, best) != cmp)
3321 continue;
3322
3323 best = value;
3324 other_split = s;
3325 }
3326
3327 // Jump to the same account so that the right warning is triggered
3328 if (!other_split)
3329 other_split = split;
3330
3331 return other_split;
3332}
3333
3334static Split*
3335jump_multiple_splits (Account* account, Split *split)
3336{
3337 GncPrefJumpMultSplits mode = (GncPrefJumpMultSplits)gnc_prefs_get_enum(GNC_PREFS_GROUP_GENERAL_REGISTER, GNC_PREF_JUMP_MULT_SPLITS);
3338
3339 switch (mode)
3340 {
3341 case JUMP_LARGEST_VALUE_FIRST_SPLIT:
3342 return jump_multiple_splits_by_value (account, split, TRUE);
3343
3344 case JUMP_SMALLEST_VALUE_FIRST_SPLIT:
3345 return jump_multiple_splits_by_value (account, split, FALSE);
3346
3347 case JUMP_DEFAULT:
3348 default:
3349 break;
3350 }
3351
3352 // If there's only one other account, use that one
3353 return jump_multiple_splits_by_single_account (account, split);
3354}
3355
3356static void
3357gnc_plugin_page_register_cmd_jump (GSimpleAction *simple,
3358 GVariant *paramter,
3359 gpointer user_data)
3360{
3361 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
3363 GncPluginPage* new_plugin_page;
3364 GtkWidget* window;
3365 GNCSplitReg* gsr;
3366 SplitRegister* reg;
3367 Account* account;
3368 Account* leader;
3369 Split* split;
3370 Split* other_split;
3371 gboolean multiple_splits;
3372
3373 ENTER ("(action %p, page %p)", simple, page);
3374
3375 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3376
3377 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3378 window = GNC_PLUGIN_PAGE (page)->window;
3379 if (window == NULL)
3380 {
3381 LEAVE ("no window");
3382 return;
3383 }
3384
3385 reg = gnc_ledger_display_get_split_register (priv->ledger);
3387 if (split == NULL)
3388 {
3389 LEAVE ("no split (1)");
3390 return;
3391 }
3392
3393 account = xaccSplitGetAccount (split);
3394 if (account == NULL)
3395 {
3396 LEAVE ("no account");
3397 return;
3398 }
3399
3400 other_split = xaccSplitGetOtherSplit (split);
3401 multiple_splits = other_split == NULL;
3402
3403 leader = gnc_ledger_display_leader (priv->ledger);
3404 if (account == leader)
3405 {
3407 if (cursor_class == CURSOR_CLASS_SPLIT)
3408 {
3409 /* If you've selected the transaction itself, we jump to the "other"
3410 * account corresponding to the anchoring split.
3411 *
3412 * If you've selected the split for another account, we jump to that
3413 * split's account (account != leader, so this block is never
3414 * reached).
3415 *
3416 * If you've selected a split for this account, for consistency with
3417 * selecting the split of another account we should do nothing.
3418 * You're already on the account for the split you selected. Jumping
3419 * to the "other" account now would make the "multiple split"
3420 * options confusing.
3421 *
3422 * We could jump to a different anchoring split but that'll be very
3423 * subtle and only cause problems because it'll have to save any
3424 * modifications to the current register.
3425 */
3426 LEAVE ("split for this account");
3427 return;
3428 }
3429
3430 if (multiple_splits)
3431 {
3432 other_split = jump_multiple_splits (account, split);
3433 }
3434 if (other_split == NULL)
3435 {
3436 GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW(window),
3437 (GtkDialogFlags)(GTK_DIALOG_MODAL
3438 | GTK_DIALOG_DESTROY_WITH_PARENT),
3439 GTK_MESSAGE_ERROR,
3440 GTK_BUTTONS_NONE,
3441 "%s",
3442 _("Unable to jump to other account"));
3443
3444 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG(dialog),
3445 "%s", _("This transaction involves more than one other account. Select a specific split to jump to that account."));
3446 gtk_dialog_add_button (GTK_DIALOG(dialog), _("_OK"), GTK_RESPONSE_OK);
3447 gnc_dialog_run (GTK_DIALOG(dialog), GNC_PREF_WARN_REG_TRANS_JUMP_MULTIPLE_SPLITS);
3448 gtk_widget_destroy (dialog);
3449
3450 LEAVE ("no split (2)");
3451 return;
3452 }
3453
3454 split = other_split;
3455
3456 account = xaccSplitGetAccount (split);
3457 if (account == NULL)
3458 {
3459 LEAVE ("no account (2)");
3460 return;
3461 }
3462
3463 if (account == leader)
3464 {
3465 GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW(window),
3466 (GtkDialogFlags)(GTK_DIALOG_MODAL
3467 | GTK_DIALOG_DESTROY_WITH_PARENT),
3468 GTK_MESSAGE_ERROR,
3469 GTK_BUTTONS_NONE,
3470 "%s",
3471 _("Unable to jump to other account"));
3472
3473 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG(dialog),
3474 "%s", _("This transaction only involves the current account so there is no other account to jump to."));
3475 gtk_dialog_add_button (GTK_DIALOG(dialog), _("_OK"), GTK_RESPONSE_OK);
3476 gnc_dialog_run (GTK_DIALOG(dialog), GNC_PREF_WARN_REG_TRANS_JUMP_SINGLE_ACCOUNT);
3477 gtk_widget_destroy (dialog);
3478
3479 LEAVE ("register open for account");
3480 return;
3481 }
3482 }
3483
3484 new_plugin_page = gnc_plugin_page_register_new (account, FALSE);
3485 if (new_plugin_page == NULL)
3486 {
3487 LEAVE ("couldn't create new page");
3488 return;
3489 }
3490
3491 gnc_main_window_open_page (GNC_MAIN_WINDOW (window), new_plugin_page);
3492 gsr = gnc_plugin_page_register_get_gsr (new_plugin_page);
3493
3494 SplitRegister *new_page_reg = gnc_ledger_display_get_split_register (gsr->ledger);
3495 gboolean jump_twice = FALSE;
3496
3497 /* Selecting the split (instead of just the transaction to open the "other"
3498 * account) requires jumping a second time after expanding the transaction,
3499 * in the basic and auto ledger modes.
3500 */
3501 if (new_page_reg->style != REG_STYLE_JOURNAL)
3502 jump_twice = TRUE;
3503
3504 /* Test for visibility of split */
3505 if (gnc_split_reg_clear_filter_for_split (gsr, split))
3506 gnc_plugin_page_register_clear_current_filter (GNC_PLUGIN_PAGE(new_plugin_page));
3507
3508 gnc_split_reg_jump_to_split (gsr, split);
3509
3510 if (multiple_splits && jump_twice)
3511 {
3512 /* Expand the transaction for the basic and auto ledger to identify the
3513 * split in this register, but only if there are more than two splits.
3514 */
3515 gnc_split_register_expand_current_trans (new_page_reg, TRUE);
3516 gnc_split_reg_jump_to_split (gsr, split);
3517 }
3518 LEAVE (" ");
3519}
3520
3521static void
3522gnc_plugin_page_register_cmd_schedule (GSimpleAction *simple,
3523 GVariant *paramter,
3524 gpointer user_data)
3525{
3526 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
3528 GtkWindow* window;
3529
3530 ENTER ("(action %p, page %p)", simple, page);
3531
3532 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3533
3534 window = GTK_WINDOW (gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (
3535 page)));
3536 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3537 gsr_default_schedule_handler (priv->gsr, window);
3538 LEAVE (" ");
3539}
3540
3541static void
3542scrub_split (Split *split)
3543{
3544 Account *acct;
3545 Transaction *trans;
3546 GNCLot *lot;
3547
3548 g_return_if_fail (split);
3549 acct = xaccSplitGetAccount (split);
3550 trans = xaccSplitGetParent (split);
3551 lot = xaccSplitGetLot (split);
3552 g_return_if_fail (trans);
3553
3554 xaccTransScrubOrphans (trans);
3555 xaccTransScrubImbalance (trans, gnc_get_current_root_account(), NULL);
3556 if (lot && xaccAccountIsAPARType (xaccAccountGetType (acct)))
3557 {
3558 gncScrubBusinessLot (lot);
3559 gncScrubBusinessSplit (split);
3560 }
3561}
3562
3563static void
3564gnc_plugin_page_register_cmd_scrub_current (GSimpleAction *simple,
3565 GVariant *paramter,
3566 gpointer user_data)
3567{
3568 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
3570 Query* query;
3571 SplitRegister* reg;
3572
3573 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3574
3575 ENTER ("(action %p, page %p)", simple, page);
3576
3577 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3578 query = gnc_ledger_display_get_query (priv->ledger);
3579 if (query == NULL)
3580 {
3581 LEAVE ("no query found");
3582 return;
3583 }
3584
3585 reg = gnc_ledger_display_get_split_register (priv->ledger);
3586
3587 gnc_suspend_gui_refresh();
3588 scrub_split (gnc_split_register_get_current_split (reg));
3589 gnc_resume_gui_refresh();
3590 LEAVE (" ");
3591}
3592
3593static gboolean
3594scrub_kp_handler (GtkWidget *widget, GdkEventKey *event, gpointer data)
3595{
3596 if (event->length == 0) return FALSE;
3597
3598 switch (event->keyval)
3599 {
3600 case GDK_KEY_Escape:
3601 {
3602 auto abort_scrub = gnc_verify_dialog (GTK_WINDOW(widget), false,
3603 "%s", _(check_repair_abort_YN));
3604
3605 if (abort_scrub)
3606 gnc_set_abort_scrub (TRUE);
3607
3608 return TRUE;
3609 }
3610 default:
3611 break;
3612 }
3613 return FALSE;
3614}
3615
3616static void
3617gnc_plugin_page_register_cmd_scrub_all (GSimpleAction *simple,
3618 GVariant *paramter,
3619 gpointer user_data)
3620{
3621 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
3623 Query* query;
3624 GncWindow* window;
3625 GList* node, *splits;
3626 gint split_count = 0, curr_split_no = 0;
3627 gulong scrub_kp_handler_ID;
3628 const char* message = _ ("Checking splits in current register: %u of %u");
3629
3630 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3631
3632 ENTER ("(action %p, page %p)", simple, page);
3633
3634 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3635 query = gnc_ledger_display_get_query (priv->ledger);
3636 if (!query)
3637 {
3638 LEAVE ("no query found");
3639 return;
3640 }
3641
3642 gnc_suspend_gui_refresh();
3643 is_scrubbing = TRUE;
3644 gnc_set_abort_scrub (FALSE);
3645 window = GNC_WINDOW (GNC_PLUGIN_PAGE (page)->window);
3646 scrub_kp_handler_ID = g_signal_connect (G_OBJECT (window), "key-press-event",
3647 G_CALLBACK (scrub_kp_handler), NULL);
3648 gnc_window_set_progressbar_window (window);
3649
3650 splits = qof_query_run (query);
3651 split_count = g_list_length (splits);
3652 for (node = splits; node && !gnc_get_abort_scrub (); node = node->next, curr_split_no++)
3653 {
3654 auto split = GNC_SPLIT(node->data);
3655
3656 if (!split) continue;
3657
3658 PINFO ("Start processing split %d of %d",
3659 curr_split_no + 1, split_count);
3660
3661 scrub_split (split);
3662
3663 PINFO ("Finished processing split %d of %d",
3664 curr_split_no + 1, split_count);
3665
3666 if (curr_split_no % 10 == 0)
3667 {
3668 char* progress_msg = g_strdup_printf (message, curr_split_no, split_count);
3669 gnc_window_show_progress (progress_msg, (100 * curr_split_no) / split_count);
3670 g_free (progress_msg);
3671 }
3672 }
3673
3674 g_signal_handler_disconnect (G_OBJECT(window), scrub_kp_handler_ID);
3675 gnc_window_show_progress (NULL, -1.0);
3676 is_scrubbing = FALSE;
3677 show_abort_verify = TRUE;
3678 gnc_set_abort_scrub (FALSE);
3679
3680 gnc_resume_gui_refresh();
3681 LEAVE (" ");
3682}
3683
3684static void
3685gnc_plugin_page_register_cmd_account_report (GSimpleAction *simple,
3686 GVariant *paramter,
3687 gpointer user_data)
3688{
3689 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
3691 GncMainWindow* window;
3692 int id;
3693
3694 ENTER ("(action %p, page %p)", simple, page);
3695
3696 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3697
3698 window = GNC_MAIN_WINDOW (GNC_PLUGIN_PAGE (page)->window);
3699 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3700 id = report_helper (priv->ledger, NULL, NULL);
3701 if (id >= 0)
3702 gnc_main_window_open_report (id, window);
3703 LEAVE (" ");
3704}
3705
3706static void
3707gnc_plugin_page_register_cmd_transaction_report (GSimpleAction *simple,
3708 GVariant *paramter,
3709 gpointer user_data)
3710{
3711 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
3713 GncMainWindow* window;
3714 SplitRegister* reg;
3715 Split* split;
3716 Query* query;
3717 int id;
3718
3719
3720 ENTER ("(action %p, page %p)", simple, page);
3721
3722 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3723
3724 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3725 reg = gnc_ledger_display_get_split_register (priv->ledger);
3726
3728 if (!split)
3729 return;
3730
3731 query = qof_query_create_for (GNC_ID_SPLIT);
3732
3733 qof_query_set_book (query, gnc_get_current_book());
3734
3735 xaccQueryAddGUIDMatch (query, xaccSplitGetGUID (split),
3736 GNC_ID_SPLIT, QOF_QUERY_AND);
3737
3738 window = GNC_MAIN_WINDOW (GNC_PLUGIN_PAGE (page)->window);
3739 id = report_helper (priv->ledger, split, query);
3740 if (id >= 0)
3741 gnc_main_window_open_report (id, window);
3742 LEAVE (" ");
3743}
3744
3745/************************************************************/
3746/* Auxiliary functions */
3747/************************************************************/
3748
3749void
3751 gint lines_default,
3752 gboolean read_only)
3753{
3756
3757 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
3758
3759 page = GNC_PLUGIN_PAGE_REGISTER (plugin_page);
3760 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3761 priv->lines_default = lines_default;
3762 priv->read_only = read_only;
3763}
3764
3765GNCSplitReg*
3767{
3770
3771 g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page), NULL);
3772
3773 page = GNC_PLUGIN_PAGE_REGISTER (plugin_page);
3774 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3775
3776 return priv->gsr;
3777}
3778
3779FilterData *
3781{
3782 g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER(plugin_page), NULL);
3783
3784 GncPluginPageRegister* page = GNC_PLUGIN_PAGE_REGISTER(plugin_page);
3785 GncPluginPageRegisterPrivate* priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE(page);
3786
3787 return &priv->fd;
3788}
3789
3790SortData *
3792{
3793 g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER(plugin_page), NULL);
3794
3795 GncPluginPageRegister* page = GNC_PLUGIN_PAGE_REGISTER(plugin_page);
3796 GncPluginPageRegisterPrivate* priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE(page);
3797
3798 return &priv->sd;
3799}
3800
3801static void
3802gnc_plugin_page_help_changed_cb (GNCSplitReg* gsr,
3804{
3806 SplitRegister* reg;
3807 GncWindow* window;
3808 char* help;
3809
3810 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3811
3812 window = GNC_WINDOW (GNC_PLUGIN_PAGE (page)->window);
3813 if (!window)
3814 {
3815 // This routine can be called before the page is added to a
3816 // window.
3817 return;
3818 }
3819
3820 // only update status text if on current page
3821 if (GNC_IS_MAIN_WINDOW(window) && (gnc_main_window_get_current_page
3822 (GNC_MAIN_WINDOW(window)) != GNC_PLUGIN_PAGE(page)))
3823 return;
3824
3825 /* Get the text from the ledger */
3826 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3827 reg = gnc_ledger_display_get_split_register (priv->ledger);
3828 help = gnc_table_get_help (reg->table);
3829 gnc_window_set_status (window, GNC_PLUGIN_PAGE (page), help);
3830 g_free (help);
3831}
3832
3833static void
3834gnc_plugin_page_popup_menu_cb (GNCSplitReg* gsr,
3836{
3837 GncWindow* window;
3838
3839 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3840
3841 window = GNC_WINDOW (GNC_PLUGIN_PAGE (page)->window);
3842 if (!window)
3843 {
3844 // This routine can be called before the page is added to a
3845 // window.
3846 return;
3847 }
3848 gnc_main_window_popup_menu_cb (GTK_WIDGET (window),
3849 GNC_PLUGIN_PAGE (page));
3850}
3851
3852static void
3853gnc_plugin_page_register_refresh_cb (GHashTable* changes, gpointer user_data)
3854{
3855 auto page = GNC_PLUGIN_PAGE_REGISTER(user_data);
3857
3858 g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
3859 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3860
3861 if (changes)
3862 {
3863 const EventInfo* ei;
3864 ei = gnc_gui_get_entity_events (changes, &priv->key);
3865 if (ei)
3866 {
3867 if (ei->event_mask & QOF_EVENT_DESTROY)
3868 {
3869 gnc_main_window_close_page (GNC_PLUGIN_PAGE (page));
3870 return;
3871 }
3872 if (ei->event_mask & QOF_EVENT_MODIFY)
3873 {
3874 }
3875 }
3876 }
3877 else
3878 {
3879 /* forced updates */
3880 gnucash_register_refresh_from_prefs (priv->gsr->reg);
3881 gtk_widget_queue_draw (priv->widget);
3882 }
3883
3884 gnc_plugin_page_register_ui_update (NULL, page);
3885}
3886
3887static void
3888gnc_plugin_page_register_close_cb (gpointer user_data)
3889{
3890 GncPluginPage* plugin_page = GNC_PLUGIN_PAGE (user_data);
3891 gnc_main_window_close_page (plugin_page);
3892}
3893
3902static void
3903gppr_account_destroy_cb (Account* account)
3904{
3907 GNCLedgerDisplayType ledger_type;
3908 const GncGUID* acct_guid;
3909 const GList* citem;
3910 GList* item, *kill = NULL;
3911
3912 acct_guid = xaccAccountGetGUID (account);
3913
3914 /* Find all windows that need to be killed. Don't kill them yet, as
3915 * that would affect the list being walked.*/
3916 citem = gnc_gobject_tracking_get_list (GNC_PLUGIN_PAGE_REGISTER_NAME);
3917 for (; citem; citem = g_list_next (citem))
3918 {
3919 page = (GncPluginPageRegister*)citem->data;
3920 priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3921 ledger_type = gnc_ledger_display_type (priv->ledger);
3922 if (ledger_type == LD_GL)
3923 {
3924 kill = g_list_prepend (kill, page);
3925 /* kill it */
3926 }
3927 else if ((ledger_type == LD_SINGLE) || (ledger_type == LD_SUBACCOUNT))
3928 {
3929 if (guid_compare (acct_guid, &priv->key) == 0)
3930 {
3931 kill = g_list_prepend (kill, page);
3932 }
3933 }
3934 }
3935
3936 kill = g_list_reverse (kill);
3937 /* Now kill them. */
3938 for (item = kill; item; item = g_list_next (item))
3939 {
3940 page = (GncPluginPageRegister*)item->data;
3941 gnc_main_window_close_page (GNC_PLUGIN_PAGE (page));
3942 }
3943 g_list_free (kill);
3944}
3945
3960static void
3961gnc_plugin_page_register_event_handler (QofInstance* entity,
3962 QofEventId event_type,
3964 GncEventData* ed)
3965{
3966 Transaction* trans;
3967 QofBook* book;
3968 GncPluginPage* visable_plugin_page;
3969 GtkWidget* window;
3970
3971 g_return_if_fail (page); /* Required */
3972 if (!GNC_IS_TRANS (entity) && !GNC_IS_ACCOUNT (entity))
3973 return;
3974
3975 ENTER ("entity %p of type %d, page %p, event data %p",
3976 entity, event_type, page, ed);
3977
3978 window = gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page));
3979
3980 if (GNC_IS_ACCOUNT (entity))
3981 {
3982 if (GNC_IS_MAIN_WINDOW (window))
3983 {
3984 GncPluginPageRegisterPrivate *priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
3985
3986 if (!gnc_ledger_display_leader (priv->ledger))
3987 {
3988 LEAVE ("account is NULL");
3989 return;
3990 }
3991
3992 gchar *name = gnc_plugin_page_register_get_tab_name (GNC_PLUGIN_PAGE (page));
3993 main_window_update_page_name (GNC_PLUGIN_PAGE (page), name);
3994
3995 gchar *long_name = gnc_plugin_page_register_get_long_name (GNC_PLUGIN_PAGE (page));
3996 main_window_update_page_long_name (GNC_PLUGIN_PAGE (page), long_name);
3997
3998 gchar *color = gnc_plugin_page_register_get_tab_color (GNC_PLUGIN_PAGE (page));
3999 main_window_update_page_color (GNC_PLUGIN_PAGE (page), color);
4000 // update page icon if read only registers
4001 gnc_plugin_page_register_update_page_icon (GNC_PLUGIN_PAGE (page));
4002
4003 g_free (color);
4004 g_free (name);
4005 g_free (long_name);
4006 }
4007 LEAVE ("tab contents updated");
4008 return;
4009 }
4010
4011 if (! (event_type & (QOF_EVENT_MODIFY | QOF_EVENT_DESTROY)))
4012 {
4013 LEAVE ("not a modify");
4014 return;
4015 }
4016 trans = GNC_TRANS (entity);
4017 book = qof_instance_get_book (QOF_INSTANCE (trans));
4018 if (!gnc_plugin_page_has_book (GNC_PLUGIN_PAGE (page), book))
4019 {
4020 LEAVE ("not in this book");
4021 return;
4022 }
4023
4024 if (GNC_IS_MAIN_WINDOW (window))
4025 {
4026 visable_plugin_page = gnc_main_window_get_current_page (GNC_MAIN_WINDOW (window));
4027 if (visable_plugin_page != GNC_PLUGIN_PAGE (page))
4028 {
4029 LEAVE ("page not visible");
4030 return;
4031 }
4032 }
4033
4034 gnc_plugin_page_register_ui_update (NULL, page);
4035 LEAVE (" ");
4036 return;
4037}
4038
4039
Cleanup functions for business objects.
convert single-entry accounts to clean double-entry
This file contains the functions to present a gui to the user for creating a new account or editing a...
Date and Time handling routines.
All type declarations for the whole Gnucash engine.
Additional event handling code.
Utility functions for file access.
GLib helper routines.
Gnome specific utility functions.
Gobject helper routines.
gtk helper routines.
Functions for adding content to a window.
Functions providing menu items from scheme code.
Functions providing a register page for the GnuCash UI.
Generic api to store and retrieve preferences.
Functions to load, save and get gui state.
utility functions for the GnuCash UI
Functions that are supported by all types of windows.
Public declarations of GnucashRegister class.
const char * xaccAccountGetName(const Account *acc)
Get the account's name.
Definition Account.cpp:3289
const char * xaccAccountGetColor(const Account *acc)
Get the account's color.
Definition Account.cpp:3350
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:3305
gnc_commodity * gnc_account_get_currency_or_parent(const Account *account)
Returns a gnc_commodity that is a currency, suitable for being a Transaction's currency.
Definition Account.cpp:3415
GNCAccountType xaccAccountGetType(const Account *acc)
Returns the account's account type.
Definition Account.cpp:3267
#define xaccAccountGetGUID(X)
Definition Account.h:252
gboolean xaccAccountIsPriced(const Account *acc)
Returns true if the account is a stock, mutual fund or currency, otherwise false.
Definition Account.cpp:4551
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 'func' on each...
Definition Account.cpp:3244
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Get the account's commodity
Definition Account.cpp:3408
Account * xaccAccountLookup(const GncGUID *guid, QofBook *book)
The xaccAccountLookup() subroutine will return the account associated with the given id,...
Definition Account.cpp:2050
QofBook * qof_session_get_book(const QofSession *session)
Returns the QofBook of this session.
gboolean qof_book_is_readonly(const QofBook *book)
Return whether the book is read only.
Definition qofbook.cpp:497
gboolean gnc_commodity_equal(const gnc_commodity *a, const gnc_commodity *b)
This routine returns TRUE if the two commodities are equal.
GSimpleActionGroup * gnc_plugin_page_create_action_group(GncPluginPage *page, const gchar *group_name)
Create the GSimpleActionGroup object associated with this page.
void gnc_plugin_page_set_use_new_window(GncPluginPage *page, gboolean use_new)
Set the "use new window" setting associated with this page.
GtkWidget * gnc_plugin_page_get_window(GncPluginPage *page)
Retrieve a pointer to the GncMainWindow (GtkWindow) containing this page.
void gnc_plugin_page_disconnect_page_changed(GncPluginPage *page)
Disconnect the page_changed_id signal callback.
gboolean gnc_plugin_page_has_book(GncPluginPage *page, QofBook *book)
Query a page to see if it has a reference to a given book.
GAction * gnc_plugin_page_get_action(GncPluginPage *page, const gchar *name)
Retrieve a GAction object associated with this page.
void gnc_plugin_page_set_menu_popup_qualifier(GncPluginPage *page, const char *menu_qualifier)
Set a qualifier string for this page.
void gnc_plugin_page_add_book(GncPluginPage *page, QofBook *book)
Add a book reference to the specified page.
void gnc_plugin_page_inserted_cb(GncPluginPage *page, gpointer user_data)
Set up the page_changed callback for when the current page is changed.
GSimpleActionGroup * gnc_plugin_page_get_action_group(GncPluginPage *page)
Retrieve the GSimpleActionGroup object associated with this page.
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Definition gnc-date.h:87
char * qof_print_date(time64 t)
Convenience; calls through to qof_print_date_dmy_buff().
Definition gnc-date.cpp:610
time64 gnc_time(time64 *tbuf)
get the current time
Definition gnc-date.cpp:262
Transaction * xaccTransReverse(Transaction *orig)
xaccTransReverse creates a Transaction that reverses the given transaction by inverting all the numer...
gboolean xaccTransHasSplitsInState(const Transaction *trans, const char state)
FIXME: document me.
Transaction * xaccTransGetReversedBy(const Transaction *trans)
Returns the transaction that reversed the given transaction.
const char * xaccTransGetDocLink(const Transaction *trans)
Gets the transaction Document Link.
gboolean xaccAccountIsAPARType(GNCAccountType t)
Convenience function to check if the account is a valid business account type (meaning an Accounts Pa...
Definition Account.cpp:4527
gboolean xaccTransHasReconciledSplits(const Transaction *trans)
FIXME: document me.
void xaccTransSetDateEnteredSecs(Transaction *trans, time64 secs)
Modify the date of when the transaction was entered.
void xaccTransSetDatePostedSecsNormalized(Transaction *trans, time64 time)
This function sets the posted date of the transaction, specified by a time64 (see ctime(3)).
SplitList * xaccTransGetSplitList(const Transaction *trans)
The xaccTransGetSplitList() method returns a GList of the splits in a transaction.
int xaccTransCountSplits(const Transaction *trans)
Returns the number of splits in this transaction.
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,...
Definition Account.cpp:3163
gboolean xaccTransIsReadonlyByPostedDate(const Transaction *trans)
Returns TRUE if this Transaction is read-only because its posted-date is older than the "auto-readonl...
GList SplitList
GList of Split.
Definition gnc-engine.h:207
const char * xaccTransGetReadOnly(Transaction *trans)
Returns a non-NULL value if this Transaction was marked as read-only with some specific "reason" text...
time64 xaccTransGetDate(const Transaction *trans)
Retrieve the posted date of the transaction.
void qof_event_unregister_handler(gint handler_id)
Unregister an event handler.
Definition qofevent.cpp:103
void(* QofEventHandler)(QofInstance *ent, QofEventId event_type, gpointer handler_data, gpointer event_data)
Handler invoked when an event is generated.
Definition qofevent.h:89
gint qof_event_register_handler(QofEventHandler handler, gpointer user_data)
Register a handler for events.
Definition qofevent.cpp:73
gint QofEventId
Define the type of events allowed.
Definition qofevent.h:45
const GncGUID * guid_null(void)
Returns a GncGUID which is guaranteed to never reference any entity.
Definition guid.cpp:165
#define GUID_ENCODING_LENGTH
Number of characters needed to encode a guid as a string not including the null terminator.
Definition guid.h:84
gchar * guid_to_string_buff(const GncGUID *guid, gchar *str)
The guid_to_string_buff() routine puts a null-terminated string encoding of the id into the memory po...
Definition guid.cpp:208
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.
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.
void main_window_update_page_color(GncPluginPage *page, const gchar *color_in)
Update the color on the page tabs in the main window.
gboolean gnc_main_window_is_quitting(GncMainWindow *window)
Check if the main window is quitting.
GAction * gnc_main_window_find_action(GncMainWindow *window, const gchar *action_name)
Find the GAction in the main window.
void main_window_update_page_name(GncPluginPage *page, const gchar *name_in)
Update the name of the page in the main 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...
void gnc_main_window_open_page(GncMainWindow *window, GncPluginPage *page)
Display a data plugin page in a window.
void gnc_main_window_set_vis_of_items_by_action(GncMainWindow *window, const gchar **action_names, gboolean vis)
Show or hide menu and toolbar items based on a NULL terminated list of action names.
void main_window_update_page_long_name(GncPluginPage *page, const gchar *long_name_in)
Update the long name of the page in the main window.
void gnc_main_window_update_menu_and_toolbar(GncMainWindow *window, GncPluginPage *page, const gchar **ui_updates)
Update the main window menu with the placeholders listed in ui_updates and load the page specific too...
void gnc_main_window_close_page(GncPluginPage *page)
Remove a data plugin page from a window and display the previous page.
GNCLedgerDisplay * gnc_ledger_display_gl(void)
opens up a general ledger window
Query * gnc_ledger_display_get_query(GNCLedgerDisplay *ld)
return the query associated with a ledger
GNCLedgerDisplay * gnc_ledger_display_simple(Account *account)
opens up a register window to display a single account
void gnc_ledger_display_refresh(GNCLedgerDisplay *ld)
redisplay/redraw only the indicated window.
void gnc_ledger_display_close(GNCLedgerDisplay *ld)
close the window
void gnc_ledger_display_set_query(GNCLedgerDisplay *ledger_display, Query *q)
Set the query used for a register.
Account * gnc_ledger_display_leader(GNCLedgerDisplay *ld)
Implementations.
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.
SplitRegister * gnc_ledger_display_get_split_register(GNCLedgerDisplay *ld)
return the split register associated with a ledger display
void gnc_ledger_display_set_focus(GNCLedgerDisplay *ld, gboolean focus)
Mark the ledger as being in focus (refresh immediately) or not.
const GList * gnc_gobject_tracking_get_list(const gchar *name)
Get a list of all known objects of a specified type.
gboolean gnc_menubar_model_find_item(GMenuModel *menu_model, GncMenuModelSearch *gsm)
Find a GtkMenu item from the action name.
gboolean gnc_menubar_model_update_item(GMenuModel *menu_model, const gchar *action_name, const gchar *target, const gchar *label, const gchar *accel_name, const gchar *tooltip)
Update the GMenuModel item based on the action name by copying existing item, removing it and inserti...
void gnc_add_accelerator_keys_for_menu(GtkWidget *menu, GMenuModel *model, GtkAccelGroup *accel_group)
Add accelerator keys for menu item widgets.
void gnc_ui_edit_account_window(GtkWindow *parent, Account *account)
Display a window for editing the attributes of an existing account.
const char * xaccPrintAmount(gnc_numeric val, GNCPrintAmountInfo info)
Make a string representation of a gnc_numeric.
QofBook * qof_instance_get_book(gconstpointer inst)
Return the book pointer.
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...
GncInvoice * gncInvoiceGetInvoiceFromLot(GNCLot *lot)
Given a LOT, find and return the Invoice attached to the lot.
#define PINFO(format, args...)
Print an informational note.
Definition qoflog.h:256
#define DEBUG(format, args...)
Print a debugging message.
Definition qoflog.h:264
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition qoflog.h:282
#define PERR(format, args...)
Log a serious error.
Definition qoflog.h:244
#define ENTER(format, args...)
Print a function entry debugging message.
Definition qoflog.h:272
void gnc_plugin_add_menu_tooltip_callbacks(GtkWidget *menubar, GMenuModel *menubar_model, GtkWidget *statusbar)
This function adds the tooltip callbacks to make the tooltips appear in the status bar.
Definition gnc-plugin.c:268
void gnc_plugin_init_short_names(GtkWidget *toolbar, GncToolBarShortNames *toolbar_labels)
Add "short" labels to existing actions.
Definition gnc-plugin.c:229
void gnc_plugin_set_actions_enabled(GActionMap *action_map, const gchar **action_names, gboolean enable)
This function sets the sensitivity of a GAction in a specific group.
Definition gnc-plugin.c:250
void gnc_plugin_add_toolbar_tooltip_callbacks(GtkWidget *toolbar, GtkWidget *statusbar)
This function adds the tooltip callbacks to make the tooltips appear in the status bar.
Definition gnc-plugin.c:299
GNCNumericErrorCode gnc_numeric_check(gnc_numeric in)
Check for error signal in value.
gnc_numeric gnc_numeric_abs(gnc_numeric a)
Returns a newly created gnc_numeric that is the absolute value of the given gnc_numeric value.
int gnc_numeric_compare(gnc_numeric a, gnc_numeric b)
Returns 1 if a>b, -1 if b>a, 0 if a == b
void gnc_prefs_remove_cb_by_func(const gchar *group, const gchar *pref_name, gpointer func, gpointer user_data)
Remove a function that was registered for a callback when the given preference changed.
gulong gnc_prefs_register_cb(const char *group, const gchar *pref_name, gpointer func, gpointer user_data)
Register a callback that gets triggered when the given preference changes.
gint gnc_prefs_get_enum(const gchar *group, const gchar *pref_name)
Get an enum value from the preferences backend.
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Get a boolean value from the preferences backend.
gboolean qof_query_equal(const QofQuery *q1, const QofQuery *q2)
Compare two queries for equality.
GList * qof_query_get_books(QofQuery *q)
Return the list of books we're using.
QofQuery * qof_query_copy(QofQuery *q)
Make a copy of the indicated query.
void qof_query_set_book(QofQuery *query, QofBook *book)
Set the book to be searched.
void qof_query_destroy(QofQuery *query)
Frees the resources associate with a Query object.
GList * qof_query_run(QofQuery *query)
Perform the query, return the results.
Transaction * gnc_plugin_page_register_get_current_txn(GncPluginPageRegister *page)
Get the currently selected transaction in this register page.
void gnc_plugin_page_register_update_for_search_query(GncPluginPageRegister *page)
This checks if the register is a search register and if so saves the query.
void gnc_ppr_filter_clear_current_filter(GncPluginPage *plugin_page)
This function is used to clear the current filter so that a specific split can be shown in the regist...
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.
FilterData * gnc_plugin_page_register_get_filter_data(GncPluginPage *plugin_page)
Get the FilterData data structure associated with this register page.
void gnc_ppr_filter_set_tooltip(GncPluginPage *plugin_page, FilterData *fd)
This function is used to update the tooltip shown in the register which shows a summary of the curren...
SortData * gnc_plugin_page_register_get_sort_data(GncPluginPage *plugin_page)
Get the SortData data structure associated with this register page.
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_ppr_filter_by(GncPluginPage *plugin_page, Query *query, FilterData *fd, bool show_save_button)
This function is called for the filter dialog.
void gnc_plugin_page_register_clear_current_filter(GncPluginPage *plugin_page)
This function clears the registers current filter.
GncPluginPage * gnc_plugin_page_register_new_gl(void)
Create a new "register" plugin page containing a general journal.
void gnc_ppr_filter_update_register(GncPluginPage *plugin_page)
This function is called to update the register.
void gnc_plugin_page_register_query_update(GncPluginPageRegister *page, Query *query)
This updates the query after the filters have been applied.
Account * gnc_plugin_page_register_get_account(GncPluginPageRegister *page)
Get the Account associated with this register page.
void gnc_ppr_sort_dialog(GncPluginPage *plugin_page, SplitRegister *reg, SortData *sd, bool show_save_button)
This function is called for the sort dialog.
GncPluginPage * gnc_plugin_page_register_new_ledger(GNCLedgerDisplay *ledger)
Create a new "register" plugin page, given a pointer to an already created ledger.
GncPluginPage * gnc_plugin_page_register_new(Account *account, gboolean subaccounts)
Create a new "register" plugin page, given a pointer to an account.
void gnc_ppr_sort_update_register(GncPluginPage *plugin_page)
This function is called to update the register.
GNCSplitReg * gnc_plugin_page_register_get_gsr(GncPluginPage *plugin_page)
Get the GNCSplitReg data structure associated with this register page.
void gnc_plugin_register_set_enable_refresh(GncPluginPageRegister *page, gboolean enable_refresh)
This allows controlling when refreshes happen, used to reduce refreshes when different aspects of the...
gboolean gncScrubBusinessSplit(Split *split)
The gncScrubBusinessSplit() function will fix all issues found with the given split.
void xaccTransScrubOrphans(Transaction *trans)
The xaccTransScrubOrphans() method scrubs only the splits in the given transaction.
Definition Scrub.cpp:179
void gnc_set_abort_scrub(gboolean abort)
The gnc_set_abort_scrub () method causes a currently running scrub operation to stop,...
Definition Scrub.cpp:75
gboolean gncScrubBusinessLot(GNCLot *lot)
The gncScrubBusinessLot() function makes sure that the indicated lot has all the correct properties r...
void xaccTransScrubImbalance(Transaction *trans, Account *root, Account *account)
Correct transaction imbalances.
Definition Scrub.cpp:845
gboolean gnc_split_register_current_trans_expanded(SplitRegister *reg)
Return TRUE if current trans is expanded and style is REG_STYLE_LEDGER.
SplitRegisterStyle
Register styles.
gboolean gnc_split_register_changed(SplitRegister *reg)
Returns TRUE if the register has changed cells.
gboolean gnc_split_register_save(SplitRegister *reg, gboolean do_commit)
Copy the contents of the current cursor to a split.
Split * gnc_split_register_get_current_split(SplitRegister *reg)
Returns the split at which the cursor is currently located.
Split * gnc_split_register_get_current_trans_split(SplitRegister *reg, VirtualCellLocation *trans_split_loc)
Gets the anchoring split of the transaction at the current cursor location, which may be on the trans...
Transaction * gnc_split_register_get_current_trans(SplitRegister *reg)
Gets the transaction at the current cursor location, which may be on the transaction itself or on any...
const char * gnc_split_register_get_credit_string(SplitRegister *reg)
Return the credit string used in the register.
gboolean gnc_split_register_has_copied_item(void)
Return TRUE if copied_item holds a transaction or split.
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,...
void gnc_split_register_paste_current(SplitRegister *reg)
Pastes a previous copied entity onto the current entity, but only if the copied and current entity ha...
void gnc_split_register_unvoid_current_trans(SplitRegister *reg)
Unvoids the transaction associated with the current cursor, if non-NULL.
const char * gnc_split_register_get_debit_string(SplitRegister *reg)
Return the debit string used in the register.
void gnc_split_register_void_current_trans(SplitRegister *reg, const char *reason)
Voids the transaction associated with the current cursor, if non-NULL.
void gnc_split_register_redraw(SplitRegister *reg)
Causes a redraw of the register window associated with reg.
void gnc_split_register_expand_current_trans(SplitRegister *reg, gboolean expand)
Expand the current transaction if it is collapsed.
void gnc_split_register_copy_current(SplitRegister *reg)
Makes a copy of the current entity, either a split or a transaction, so that it can be pasted later.
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_split_register_config(SplitRegister *reg, SplitRegisterType newtype, SplitRegisterStyle newstyle, gboolean use_double_line)
Sets a split register's type, style or line use.
CursorClass
Types of cursors.
CursorClass gnc_split_register_get_current_cursor_class(SplitRegister *reg)
Returns the class of a register's current cursor.
Split * gnc_split_register_duplicate_current(SplitRegister *reg)
Duplicates either the current transaction or the current split depending on the register mode and cur...
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
gint xaccSplitOrder(const Split *sa, const Split *sb)
The xaccSplitOrder(sa,sb) method is useful for sorting.
Definition Split.cpp:1536
#define xaccSplitGetGUID(X)
Definition Split.h:579
#define VREC
split is void
Definition Split.h:77
GNCLot * xaccSplitGetLot(const Split *split)
Returns the pointer to the debited/credited Lot where this split belongs to, or NULL if it doesn't be...
Definition Split.cpp:1920
gnc_numeric xaccSplitGetValue(const Split *split)
Returns the value of this split in the transaction's commodity.
Account * xaccSplitGetAccount(const Split *split)
Returns the account of this split, which was set through xaccAccountInsertSplit().
Split * xaccSplitGetOtherSplit(const Split *split)
The xaccSplitGetOtherSplit() is a convenience routine that returns the other of a pair of splits.
#define CREC
The Split has been cleared
Definition Split.h:73
void gnc_features_set_used(QofBook *book, const gchar *feature)
Indicate that the current book uses the given feature.
STRUCTS.
The type used to store guids in C.
Definition guid.h:75
The class data structure for a content plugin.
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...
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...
void(* focus_page)(GncPluginPage *plugin_page, gboolean on_current_page)
Perform plugin specific actions to set the focus.
const gchar * tab_icon
The relative name of the icon that should be shown on the tab for this page.
const gchar * plugin_name
The textual name of this plugin.
void(* destroy_widget)(GncPluginPage *plugin_page)
Function called to destroy the display widget for a particular type of plugin.
gboolean(* finish_pending)(GncPluginPage *plugin_page)
This function vector is called to finish any outstanding activities.
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...
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.
GtkWidget *(* create_widget)(GncPluginPage *plugin_page)
Function called to create the display widget for a particular type of plugin.
gboolean(* focus_page_function)(GncPluginPage *plugin_page)
This function performs specific actions to set the focus on a specific widget.
The instance data structure for a content plugin.
GtkWidget * window
The window that contains the display widget for this plugin.
GtkWidget * summarybar
The summary bar widget (if any) that is associated with this plugin.
A structure for defining alternate action names for use in the toolbar.
QofBook reference.
Definition qofbook-p.hpp:47
A Query.
Definition qofquery.cpp:75