GnuCash c935c2f+
Loading...
Searching...
No Matches
Files | Data Structures | Macros | Enumerations | Functions
An Account Tree Plugin

Files

 

Data Structures

struct  delete_helper_t
 
struct  GncPluginPageAccountTreePrivate
 
struct  Adopter
 
struct  Adopters
 
struct  GncPluginPageAccountTree
 
struct  GncPluginPageAccountTreeClass
 

Macros

#define PLUGIN_PAGE_ACCT_TREE_CM_CLASS   "plugin-page-acct-tree"
 
#define STATE_SECTION   "Account Hierarchy"
 
#define DELETE_DIALOG_FILTER   "filter"
 
#define DELETE_DIALOG_ACCOUNT   "account"
 
#define DELETE_DIALOG_TRANS_MAS   "trans_mas"
 
#define DELETE_DIALOG_SA_MAS   "sa_mas"
 
#define DELETE_DIALOG_SA_TRANS_MAS   "sa_trans_mas"
 
#define DELETE_DIALOG_SA_TRANS   "sa_trans"
 
#define DELETE_DIALOG_SA_SPLITS   "sa_has_split"
 
#define DELETE_DIALOG_OK_BUTTON   "deletebutton"
 
#define GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(o)    ((GncPluginPageAccountTreePrivate*)gnc_plugin_page_account_tree_get_instance_private((GncPluginPageAccountTree*)o))
 
#define GNC_TYPE_PLUGIN_PAGE_ACCOUNT_TREE   (gnc_plugin_page_account_tree_get_type ())
 
#define GNC_PLUGIN_PAGE_ACCOUNT_TREE(obj)   (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNC_TYPE_PLUGIN_PAGE_ACCOUNT_TREE, GncPluginPageAccountTree))
 
#define GNC_PLUGIN_PAGE_ACCOUNT_TREE_CLASS(klass)   (G_TYPE_CHECK_CLASS_CAST ((klass), GNC_TYPE_PLUGIN_PAGE_ACCOUNT_TREE, GncPluginPageAccountTreeClass))
 
#define GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE(obj)   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNC_TYPE_PLUGIN_PAGE_ACCOUNT_TREE))
 
#define GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_PLUGIN_PAGE_ACCOUNT_TREE))
 
#define GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_PLUGIN_PAGE_ACCOUNT_TREE, GncPluginPageAccountTreeClass))
 
#define GNC_PLUGIN_PAGE_ACCOUNT_TREE_NAME   "GncPluginPageAccountTree"
 

Enumerations

enum  { ACCOUNT_SELECTED , LAST_SIGNAL }
 

Functions

void gppat_populate_trans_mas_list (GtkToggleButton *sa_mrb, GtkWidget *dialog)
 
void gppat_set_insensitive_iff_rb_active (GtkWidget *widget, GtkToggleButton *b)
 
GncPluginPagegnc_plugin_page_account_tree_new (void)
 Create a new "account tree" plugin page.
 
void gnc_plugin_page_account_tree_open (Account *account, GtkWindow *win)
 Given a pointer to an account, the account tree will open and the account will be selected (if any).
 
Accountgnc_plugin_page_account_tree_get_current_account (GncPluginPageAccountTree *page)
 Given a pointer to an account tree plugin page, return the selected account (if any).
 
GType gnc_plugin_page_account_tree_get_type (void)
 Retrieve the type number for an "account tree" plugin page.
 

Detailed Description

Macro Definition Documentation

◆ DELETE_DIALOG_ACCOUNT

#define DELETE_DIALOG_ACCOUNT   "account"

Definition at line 99 of file gnc-plugin-page-account-tree.cpp.

◆ DELETE_DIALOG_FILTER

#define DELETE_DIALOG_FILTER   "filter"

Definition at line 98 of file gnc-plugin-page-account-tree.cpp.

◆ DELETE_DIALOG_OK_BUTTON

#define DELETE_DIALOG_OK_BUTTON   "deletebutton"

Definition at line 105 of file gnc-plugin-page-account-tree.cpp.

◆ DELETE_DIALOG_SA_MAS

#define DELETE_DIALOG_SA_MAS   "sa_mas"

Definition at line 101 of file gnc-plugin-page-account-tree.cpp.

◆ DELETE_DIALOG_SA_SPLITS

#define DELETE_DIALOG_SA_SPLITS   "sa_has_split"

Definition at line 104 of file gnc-plugin-page-account-tree.cpp.

◆ DELETE_DIALOG_SA_TRANS

#define DELETE_DIALOG_SA_TRANS   "sa_trans"

Definition at line 103 of file gnc-plugin-page-account-tree.cpp.

◆ DELETE_DIALOG_SA_TRANS_MAS

#define DELETE_DIALOG_SA_TRANS_MAS   "sa_trans_mas"

Definition at line 102 of file gnc-plugin-page-account-tree.cpp.

◆ DELETE_DIALOG_TRANS_MAS

#define DELETE_DIALOG_TRANS_MAS   "trans_mas"

Definition at line 100 of file gnc-plugin-page-account-tree.cpp.

◆ GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE

#define GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE (   obj)    (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNC_TYPE_PLUGIN_PAGE_ACCOUNT_TREE))

Definition at line 49 of file gnc-plugin-page-account-tree.h.

◆ GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE_CLASS

#define GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE_CLASS (   klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_PLUGIN_PAGE_ACCOUNT_TREE))

Definition at line 50 of file gnc-plugin-page-account-tree.h.

◆ GNC_PLUGIN_PAGE_ACCOUNT_TREE

#define GNC_PLUGIN_PAGE_ACCOUNT_TREE (   obj)    (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNC_TYPE_PLUGIN_PAGE_ACCOUNT_TREE, GncPluginPageAccountTree))

Definition at line 47 of file gnc-plugin-page-account-tree.h.

◆ GNC_PLUGIN_PAGE_ACCOUNT_TREE_CLASS

#define GNC_PLUGIN_PAGE_ACCOUNT_TREE_CLASS (   klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GNC_TYPE_PLUGIN_PAGE_ACCOUNT_TREE, GncPluginPageAccountTreeClass))

Definition at line 48 of file gnc-plugin-page-account-tree.h.

◆ GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_CLASS

#define GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_CLASS (   obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_PLUGIN_PAGE_ACCOUNT_TREE, GncPluginPageAccountTreeClass))

Definition at line 51 of file gnc-plugin-page-account-tree.h.

◆ GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE

#define GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE (   o)     ((GncPluginPageAccountTreePrivate*)gnc_plugin_page_account_tree_get_instance_private((GncPluginPageAccountTree*)o))

Definition at line 121 of file gnc-plugin-page-account-tree.cpp.

148 {
149void gppat_populate_trans_mas_list(GtkToggleButton *sa_mrb, GtkWidget *dialog);
150void gppat_set_insensitive_iff_rb_active(GtkWidget *widget, GtkToggleButton *b);
151}
152
153/* Command callbacks */
154static void gnc_plugin_page_account_tree_cmd_new_account (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
155static void gnc_plugin_page_account_tree_cmd_file_new_hierarchy (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
156static void gnc_plugin_page_account_tree_cmd_open_account (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
157static void gnc_plugin_page_account_tree_cmd_open_subaccounts (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
158static void gnc_plugin_page_account_tree_cmd_edit_account (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
159static void gnc_plugin_page_account_tree_cmd_find_account (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
160static void gnc_plugin_page_account_tree_cmd_find_account_popup (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
161static void gnc_plugin_page_account_tree_cmd_delete_account (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
162static void gnc_plugin_page_account_tree_cmd_renumber_accounts (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
163static void gnc_plugin_page_account_tree_cmd_view_filter_by (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
164static void gnc_plugin_page_account_tree_cmd_reconcile (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
165static void gnc_plugin_page_account_tree_cmd_refresh (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
166static void gnc_plugin_page_account_tree_cmd_autoclear (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
167static void gnc_plugin_page_account_tree_cmd_transfer (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
168static void gnc_plugin_page_account_tree_cmd_stock_split (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
169static void gnc_plugin_page_account_tree_cmd_stock_assistant (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
170static void gnc_plugin_page_account_tree_cmd_edit_tax_options (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
171static void gnc_plugin_page_account_tree_cmd_lots (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
172static void gnc_plugin_page_account_tree_cmd_scrub (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
173static void gnc_plugin_page_account_tree_cmd_scrub_sub (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
174static void gnc_plugin_page_account_tree_cmd_scrub_all (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
175static void gnc_plugin_page_account_tree_cmd_cascade_account_properties (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
176
177/* Account Deletion Actions. */
178static int confirm_delete_account (GSimpleAction *simple,
180 Account* sta, Account* saa,
181 delete_helper_t delete_res);
182static void do_delete_account (Account* account, Account* saa, Account* sta,
183 Account* ta);
184
185
186
187static guint plugin_page_signals[LAST_SIGNAL] = { 0 };
188
189
190static GActionEntry gnc_plugin_page_account_tree_actions [] =
191{
192 { "FileNewAccountAction", gnc_plugin_page_account_tree_cmd_new_account, NULL, NULL, NULL },
193 { "FileAddAccountHierarchyAssistantAction", gnc_plugin_page_account_tree_cmd_file_new_hierarchy, NULL, NULL, NULL },
194 { "EditOpenAccountAction", gnc_plugin_page_account_tree_cmd_open_account, NULL, NULL, NULL },
195 { "EditOpenSubaccountsAction", gnc_plugin_page_account_tree_cmd_open_subaccounts, NULL, NULL, NULL },
196 { "EditEditAccountAction", gnc_plugin_page_account_tree_cmd_edit_account, NULL, NULL, NULL },
197 { "EditDeleteAccountAction", gnc_plugin_page_account_tree_cmd_delete_account, NULL, NULL, NULL },
198 { "EditCascadeAccountAction", gnc_plugin_page_account_tree_cmd_cascade_account_properties, NULL, NULL, NULL },
199 { "EditFindAccountAction", gnc_plugin_page_account_tree_cmd_find_account, NULL, NULL, NULL },
200 { "EditFindAccountPopupAction", gnc_plugin_page_account_tree_cmd_find_account_popup, NULL, NULL, NULL },
201 { "EditRenumberSubaccountsAction", gnc_plugin_page_account_tree_cmd_renumber_accounts, NULL, NULL, NULL },
202 { "EditTaxOptionsAction", gnc_plugin_page_account_tree_cmd_edit_tax_options, NULL, NULL, NULL },
203 { "ViewFilterByAction", gnc_plugin_page_account_tree_cmd_view_filter_by, NULL, NULL, NULL },
204 { "ViewRefreshAction", gnc_plugin_page_account_tree_cmd_refresh, NULL, NULL, NULL },
205 { "ActionsReconcileAction", gnc_plugin_page_account_tree_cmd_reconcile, NULL, NULL, NULL },
206 { "ActionsAutoClearAction", gnc_plugin_page_account_tree_cmd_autoclear, NULL, NULL, NULL },
207 { "ActionsTransferAction", gnc_plugin_page_account_tree_cmd_transfer, NULL, NULL, NULL },
208 { "ActionsStockSplitAction", gnc_plugin_page_account_tree_cmd_stock_split, NULL, NULL, NULL },
209 { "ActionsStockAssistantAction", gnc_plugin_page_account_tree_cmd_stock_assistant, NULL, NULL, NULL },
210 { "ActionsLotsAction", gnc_plugin_page_account_tree_cmd_lots, NULL, NULL, NULL },
211 { "ScrubAction", gnc_plugin_page_account_tree_cmd_scrub, NULL, NULL, NULL },
212 { "ScrubSubAction", gnc_plugin_page_account_tree_cmd_scrub_sub, NULL, NULL, NULL },
213 { "ScrubAllAction", gnc_plugin_page_account_tree_cmd_scrub_all, NULL, NULL, NULL },
214};
216static guint gnc_plugin_page_account_tree_n_actions = G_N_ELEMENTS(gnc_plugin_page_account_tree_actions);
217
219static const gchar *gnc_plugin_load_ui_items [] =
220{
221 "FilePlaceholder3",
222 "EditPlaceholder1",
223 "EditPlaceholder2",
224 "EditPlaceholder3",
225 "EditPlaceholder5",
226 "ViewPlaceholder1",
227 "ViewPlaceholder4",
228 "ActionsPlaceholder4",
229 "ActionsPlaceholder5",
230 "ActionsPlaceholder6",
231 NULL,
232};
233
234
235
236
239static const gchar *actions_requiring_account_rw[] =
240{
241 "EditEditAccountAction",
242 "EditDeleteAccountAction",
243 "ActionsReconcileAction",
244 "ActionsAutoClearAction",
245 NULL
246};
247
250static const gchar *actions_requiring_subaccounts_rw[] =
251{
252 "EditRenumberSubaccountsAction",
253 "EditCascadeAccountAction",
254 NULL
255};
256
259static const gchar *actions_requiring_account_always[] =
260{
261 "EditOpenAccountAction",
262 "EditOpenSubaccountsAction",
263 "ActionsLotsAction",
264 NULL
265};
266
267static const gchar* actions_requiring_priced_account[] =
268{
269 "ActionsStockAssistantAction",
270 NULL
271};
272
273/* This is the list of actions which are switched inactive in a read-only book. */
274static const gchar* readonly_inactive_actions[] =
275{
276 "FileNewAccountAction",
277 "FileAddAccountHierarchyAssistantAction",
278 "EditEditAccountAction",
279 "EditDeleteAccountAction",
280 "ActionsTransferAction",
281 "ActionsReconcileAction",
282 "ActionsAutoClearAction",
283 "ActionsStockSplitAction",
284 "ScrubAction",
285 "ScrubSubAction",
286 "ScrubAllAction",
287 NULL
288};
289
291static GncToolBarShortNames toolbar_labels[] =
292{
293 { "EditOpenAccountAction", N_("Open") },
294 { "EditEditAccountAction", N_("Edit") },
295 { "FileNewAccountAction", N_("New") },
296 { "EditDeleteAccountAction", N_("Delete") },
297 { NULL, NULL },
298};
299
302{
303 ENTER(" ");
304 auto plugin_page = GNC_PLUGIN_PAGE_ACCOUNT_TREE
305 (g_object_new (GNC_TYPE_PLUGIN_PAGE_ACCOUNT_TREE, nullptr));
306
307 LEAVE("new account tree page %p", plugin_page);
308 return GNC_PLUGIN_PAGE (plugin_page);
309}
310
311G_DEFINE_TYPE_WITH_PRIVATE(GncPluginPageAccountTree, gnc_plugin_page_account_tree, GNC_TYPE_PLUGIN_PAGE)
312
313static gboolean show_abort_verify = TRUE;
314
315static void
316prepare_scrubbing ()
317{
318 gnc_suspend_gui_refresh ();
319 gnc_set_abort_scrub (FALSE);
320}
321
322static void
323finish_scrubbing (GncWindow *window, gulong handler_id)
324{
325 g_signal_handler_disconnect (G_OBJECT(window), handler_id);
326 show_abort_verify = TRUE;
327 gnc_resume_gui_refresh ();
328}
329
330static const char*
331check_repair_abort_YN = N_("'Check & Repair' is currently running, do you want to abort it?");
332
333static gboolean
334gnc_plugin_page_account_finish_pending (GncPluginPage* page)
335{
337 {
338 if (show_abort_verify)
339 {
340 gboolean ret = gnc_verify_dialog (GTK_WINDOW(gnc_plugin_page_get_window
341 (GNC_PLUGIN_PAGE(page))), FALSE,
342 "%s", _(check_repair_abort_YN));
343
344 show_abort_verify = FALSE;
345
346 if (ret)
347 gnc_set_abort_scrub (TRUE);
348
349 return ret; // verify response
350 }
351 else
352 {
353 if (gnc_get_abort_scrub ())
354 return TRUE; // close
355 else
356 return FALSE; // no close
357 }
358 }
359 else
360 return TRUE; // normal close
361}
362
363static void
364gnc_plugin_page_account_tree_class_init (GncPluginPageAccountTreeClass *klass)
365{
366 GObjectClass *object_class = G_OBJECT_CLASS (klass);
367 GncPluginPageClass *gnc_plugin_class = GNC_PLUGIN_PAGE_CLASS(klass);
368
369 object_class->finalize = gnc_plugin_page_account_tree_finalize;
370
371 gnc_plugin_class->tab_icon = GNC_ICON_ACCOUNT;
372 gnc_plugin_class->plugin_name = GNC_PLUGIN_PAGE_ACCOUNT_TREE_NAME;
373 gnc_plugin_class->create_widget = gnc_plugin_page_account_tree_create_widget;
374 gnc_plugin_class->destroy_widget = gnc_plugin_page_account_tree_destroy_widget;
375 gnc_plugin_class->save_page = gnc_plugin_page_account_tree_save_page;
376 gnc_plugin_class->recreate_page = gnc_plugin_page_account_tree_recreate_page;
377 gnc_plugin_class->focus_page_function = gnc_plugin_page_account_tree_focus_widget;
378 gnc_plugin_class->finish_pending = gnc_plugin_page_account_finish_pending;
379
380 plugin_page_signals[ACCOUNT_SELECTED] =
381 g_signal_new ("account_selected",
382 G_OBJECT_CLASS_TYPE (object_class),
383 G_SIGNAL_RUN_FIRST,
384 G_STRUCT_OFFSET (GncPluginPageAccountTreeClass, account_selected),
385 NULL, NULL,
386 g_cclosure_marshal_VOID__POINTER,
387 G_TYPE_NONE, 1,
388 G_TYPE_POINTER);
389}
390
391static void
392gnc_plugin_page_account_tree_init (GncPluginPageAccountTree *plugin_page)
393{
394 GSimpleActionGroup *simple_action_group = NULL;
396 GncPluginPage *parent;
397 const GList *page_list;
398
399 ENTER("page %p", plugin_page);
400 priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(plugin_page);
401
402 /* Init parent declared variables */
403 parent = GNC_PLUGIN_PAGE(plugin_page);
404 g_object_set (G_OBJECT(plugin_page),
405 "page-name", _("Accounts"),
406 "ui-description", "gnc-plugin-page-account-tree.ui",
407 NULL);
408 g_signal_connect (G_OBJECT (plugin_page), "selected",
409 G_CALLBACK (gnc_plugin_page_account_tree_selected), plugin_page);
410
411 /* change me when the system supports multiple books */
412 gnc_plugin_page_add_book (parent, gnc_get_current_book());
413
414 /* Is this the first accounts page? */
415 page_list =
416 gnc_gobject_tracking_get_list (GNC_PLUGIN_PAGE_ACCOUNT_TREE_NAME);
417 if (!page_list || plugin_page == page_list->data)
418 {
419 g_object_set_data (G_OBJECT(plugin_page), PLUGIN_PAGE_IMMUTABLE,
420 GINT_TO_POINTER(1));
421 }
422
423 /* Create menu and toolbar information */
424 simple_action_group = gnc_plugin_page_create_action_group (parent, "GncPluginPageAccountTreeActions");
425 g_action_map_add_action_entries (G_ACTION_MAP(simple_action_group),
426 gnc_plugin_page_account_tree_actions,
427 gnc_plugin_page_account_tree_n_actions,
428 plugin_page);
429
430 /* Visible types */
431 priv->fd.visible_types = -1; /* Start with all types */
432 priv->fd.show_hidden = FALSE;
433 priv->fd.show_unused = TRUE;
434 priv->fd.show_zero_total = TRUE;
435 priv->fd.filter_override = g_hash_table_new (g_direct_hash, g_direct_equal);
436
437 LEAVE("page %p, priv %p, action group %p",
438 plugin_page, priv, simple_action_group);
439}
440
441static void
442gnc_plugin_page_account_tree_finalize (GObject *object)
443{
446
447 ENTER("object %p", object);
448 page = GNC_PLUGIN_PAGE_ACCOUNT_TREE (object);
449 g_return_if_fail (GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE (page));
450 priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
451 g_return_if_fail (priv != NULL);
452
453 G_OBJECT_CLASS (gnc_plugin_page_account_tree_parent_class)->finalize (object);
454 LEAVE(" ");
455}
456
457void
458gnc_plugin_page_account_tree_open (Account *account, GtkWindow *win)
459{
462 GncPluginPage *plugin_page = NULL;
463 const GList *page_list;
464 GtkWidget *window;
465
466 /* Find Accounts page */
467 page_list = gnc_gobject_tracking_get_list(GNC_PLUGIN_PAGE_ACCOUNT_TREE_NAME);
468
469 // If we have a window, look for account page in that window
470 if (gnc_list_length_cmp (page_list, 0))
471 {
472 if (win != NULL)
473 {
474 for ( ; page_list; page_list = g_list_next(page_list))
475 {
476 plugin_page = GNC_PLUGIN_PAGE(page_list->data);
477 if (GTK_WINDOW(plugin_page->window) == win)
478 break;
479 }
480 }
481 else // if no window, open first account page in list
482 plugin_page = GNC_PLUGIN_PAGE(page_list->data);
483 }
484 else // we have no account pages, create one
485 plugin_page = gnc_plugin_page_account_tree_new ();
486
487 g_return_if_fail(plugin_page);
488 window = plugin_page->window;
489
490 gnc_main_window_open_page (GNC_MAIN_WINDOW(window), plugin_page);
491
492 page = GNC_PLUGIN_PAGE_ACCOUNT_TREE (plugin_page);
493 priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
494
495 if (account != NULL)
496 {
497 Account *root_account = gnc_get_current_root_account ();
498 Account *parent_account = NULL;
499 Account *temp_account = account;
500
501 g_hash_table_insert (priv->fd.filter_override, account, account);
502
503 // make sure we override all the parent accounts to root
504 while (parent_account != root_account)
505 {
506 parent_account = gnc_account_get_parent (temp_account);
507
508 g_hash_table_insert (priv->fd.filter_override, parent_account, parent_account);
509 temp_account = parent_account;
510 }
511 gnc_tree_view_account_refilter (GNC_TREE_VIEW_ACCOUNT(priv->tree_view));
512 gnc_tree_view_account_set_selected_account (GNC_TREE_VIEW_ACCOUNT(priv->tree_view), account);
513 }
514}
515
516Account *
518{
520 Account *account;
521
522 priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
523 ENTER("page %p (tree view %p)", page, priv->tree_view);
524 account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(priv->tree_view));
525 if (account == NULL)
526 {
527 LEAVE("no account");
528 return NULL;
529 }
530
531 LEAVE("account %p", account);
532 return account;
533}
534
539static gboolean
540gnc_plugin_page_account_tree_focus_widget (GncPluginPage *account_plugin_page)
541{
542 if (GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE(account_plugin_page))
543 {
544 GncPluginPageAccountTreePrivate *priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(account_plugin_page);
545 GtkTreeView *view = GTK_TREE_VIEW(priv->tree_view);
546
547 /* Disable the Transaction Menu */
548 GAction *action = gnc_main_window_find_action (GNC_MAIN_WINDOW(account_plugin_page->window), "TransactionAction");
549 g_simple_action_set_enabled (G_SIMPLE_ACTION(action), FALSE);
550 /* Disable the Schedule menu */
551 action = gnc_main_window_find_action (GNC_MAIN_WINDOW(account_plugin_page->window), "ScheduledAction");
552 g_simple_action_set_enabled (G_SIMPLE_ACTION(action), FALSE);
553
554 gnc_main_window_update_menu_and_toolbar (GNC_MAIN_WINDOW(account_plugin_page->window),
555 account_plugin_page,
556 gnc_plugin_load_ui_items);
557
558 // setup any short toolbar names
559 gnc_main_window_init_short_names (GNC_MAIN_WINDOW(account_plugin_page->window), toolbar_labels);
560
561 /* Disable the FilePrintAction */
562 action = gnc_main_window_find_action (GNC_MAIN_WINDOW(account_plugin_page->window), "FilePrintAction");
563 g_simple_action_set_enabled (G_SIMPLE_ACTION(action), FALSE);
564
565 if (!gtk_widget_is_focus (GTK_WIDGET(view)))
566 gtk_widget_grab_focus (GTK_WIDGET(view));
567 }
568 return FALSE;
569}
570
571/* Virtual Functions */
572
573static void
574gnc_plugin_page_account_refresh_cb (GHashTable *changes, gpointer user_data)
575{
576 /* We're only looking for forced updates here. */
577 if (!changes)
578 gnc_plugin_page_account_tree_cmd_refresh(NULL, NULL, user_data);
579}
580
581static void
582gnc_plugin_page_account_tree_close_cb (gpointer user_data)
583{
584 GncPluginPage *plugin_page = GNC_PLUGIN_PAGE(user_data);
585 gnc_main_window_close_page(plugin_page);
586}
587
588static void
589gnc_plugin_page_account_editing_started_cd (gpointer various, GncPluginPageRegister *page)
590{
591 GncPluginPage *plugin_page = GNC_PLUGIN_PAGE(page);
592 GAction *action = gnc_main_window_find_action_in_group (GNC_MAIN_WINDOW(plugin_page->window),
593 "GncPluginPageAccountTreeActions",
594 "EditDeleteAccountAction");
595 if (action != NULL)
596 g_simple_action_set_enabled (G_SIMPLE_ACTION(action), FALSE);
597}
598
599static void
600gnc_plugin_page_account_editing_finished_cb (gpointer various, GncPluginPageRegister *page)
601{
602 GncPluginPage *plugin_page = GNC_PLUGIN_PAGE(page);
603 GAction *action = gnc_main_window_find_action_in_group (GNC_MAIN_WINDOW(plugin_page->window),
604 "GncPluginPageAccountTreeActions",
605 "EditDeleteAccountAction");
606 if (action != NULL)
607 g_simple_action_set_enabled (G_SIMPLE_ACTION(action), TRUE);
608}
609
610static GtkWidget *
611gnc_plugin_page_account_tree_create_widget (GncPluginPage *plugin_page)
612{
615 GtkTreeSelection *selection;
616 GtkTreeView *tree_view;
617 GtkWidget *scrolled_window;
618 GtkTreeViewColumn *col;
619
620 ENTER("page %p", plugin_page);
621 page = GNC_PLUGIN_PAGE_ACCOUNT_TREE (plugin_page);
622 priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
623 if (priv->widget != NULL)
624 {
625 LEAVE("widget = %p", priv->widget);
626 return priv->widget;
627 }
628
629 priv->widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
630 gtk_box_set_homogeneous (GTK_BOX (priv->widget), FALSE);
631 gtk_widget_show (priv->widget);
632
633 // Set the name for this widget so it can be easily manipulated with css
634 gtk_widget_set_name (GTK_WIDGET(priv->widget), "gnc-id-account-page");
635
636 scrolled_window = gtk_scrolled_window_new (NULL, NULL);
637 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
638 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
639 gtk_widget_show (scrolled_window);
640 gtk_box_pack_start (GTK_BOX (priv->widget), scrolled_window,
641 TRUE, TRUE, 0);
642
643 tree_view = gnc_tree_view_account_new(FALSE);
645 GNC_TREE_VIEW(tree_view), "description");
646 g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1));
648 GNC_TREE_VIEW(tree_view), "total");
649 g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1));
650 gnc_tree_view_configure_columns(GNC_TREE_VIEW(tree_view));
651 g_object_set(G_OBJECT(tree_view),
652 "state-section", STATE_SECTION,
653 "show-column-menu", TRUE,
654 NULL);
655
656 /* No name handler; then the user can't click on the name of the
657 account to open its register. */
658 gnc_tree_view_account_set_code_edited(GNC_TREE_VIEW_ACCOUNT(tree_view),
659 gnc_tree_view_account_code_edited_cb);
660 gnc_tree_view_account_set_description_edited(GNC_TREE_VIEW_ACCOUNT(tree_view),
661 gnc_tree_view_account_description_edited_cb);
662 gnc_tree_view_account_set_notes_edited(GNC_TREE_VIEW_ACCOUNT(tree_view),
663 gnc_tree_view_account_notes_edited_cb);
664
665 // Setup some callbacks so menu actions can be disabled/enabled
666 gnc_tree_view_account_set_editing_started_cb(GNC_TREE_VIEW_ACCOUNT(tree_view),
667 (GFunc)gnc_plugin_page_account_editing_started_cd, page);
668 gnc_tree_view_account_set_editing_finished_cb(GNC_TREE_VIEW_ACCOUNT(tree_view),
669 (GFunc)gnc_plugin_page_account_editing_finished_cb, page);
670
671 priv->tree_view = tree_view;
672 selection = gtk_tree_view_get_selection(tree_view);
673 g_signal_connect (G_OBJECT (selection), "changed",
674 G_CALLBACK (gnc_plugin_page_account_tree_selection_changed_cb), page);
675 g_signal_connect (G_OBJECT (tree_view), "button-press-event",
676 G_CALLBACK (gnc_plugin_page_account_tree_button_press_cb), page);
677 g_signal_connect (G_OBJECT (tree_view), "row-activated",
678 G_CALLBACK (gnc_plugin_page_account_tree_double_click_cb), page);
679
680 gtk_tree_view_set_headers_visible(tree_view, TRUE);
681 gnc_plugin_page_account_tree_selection_changed_cb (NULL, page);
682 gtk_widget_show (GTK_WIDGET (tree_view));
683 gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET(tree_view));
684
685 priv->fd.tree_view = GNC_TREE_VIEW_ACCOUNT(priv->tree_view);
687 GNC_TREE_VIEW_ACCOUNT(tree_view),
689
690 priv->component_id =
691 gnc_register_gui_component(PLUGIN_PAGE_ACCT_TREE_CM_CLASS,
692 gnc_plugin_page_account_refresh_cb,
693 gnc_plugin_page_account_tree_close_cb,
694 page);
695 gnc_gui_component_set_session (priv->component_id,
696 gnc_get_current_session());
697
698 plugin_page->summarybar = gnc_main_window_summary_new();
699 gtk_box_pack_start (GTK_BOX (priv->widget), plugin_page->summarybar,
700 FALSE, FALSE, 0);
701 gtk_widget_show(plugin_page->summarybar);
702 gnc_plugin_page_account_tree_summarybar_position_changed(NULL, NULL, page);
703 gnc_prefs_register_cb (GNC_PREFS_GROUP_GENERAL,
704 GNC_PREF_SUMMARYBAR_POSITION_TOP,
705 (gpointer)gnc_plugin_page_account_tree_summarybar_position_changed,
706 page);
707 gnc_prefs_register_cb (GNC_PREFS_GROUP_GENERAL,
708 GNC_PREF_SUMMARYBAR_POSITION_BOTTOM,
709 (gpointer)gnc_plugin_page_account_tree_summarybar_position_changed,
710 page);
711
712 gnc_prefs_register_cb(GNC_PREFS_GROUP_ACCT_SUMMARY, GNC_PREF_START_CHOICE_ABS,
713 (gpointer)accounting_period_changed_cb, page);
714 gnc_prefs_register_cb(GNC_PREFS_GROUP_ACCT_SUMMARY, GNC_PREF_START_DATE,
715 (gpointer)accounting_period_changed_cb, page);
716 gnc_prefs_register_cb(GNC_PREFS_GROUP_ACCT_SUMMARY, GNC_PREF_START_PERIOD,
717 (gpointer)accounting_period_changed_cb, page);
718 gnc_prefs_register_cb(GNC_PREFS_GROUP_ACCT_SUMMARY, GNC_PREF_END_CHOICE_ABS,
719 (gpointer)accounting_period_changed_cb, page);
720 gnc_prefs_register_cb(GNC_PREFS_GROUP_ACCT_SUMMARY, GNC_PREF_END_DATE,
721 (gpointer)accounting_period_changed_cb, page);
722 gnc_prefs_register_cb(GNC_PREFS_GROUP_ACCT_SUMMARY, GNC_PREF_END_PERIOD,
723 (gpointer)accounting_period_changed_cb, page);
724
725 g_signal_connect (G_OBJECT(plugin_page), "inserted",
726 G_CALLBACK(gnc_plugin_page_inserted_cb),
727 NULL);
728
729 // Read account filter state information from account section
730 gnc_tree_view_account_restore_filter (GNC_TREE_VIEW_ACCOUNT(priv->tree_view), &priv->fd,
731 gnc_state_get_current(), gnc_tree_view_get_state_section (GNC_TREE_VIEW(priv->tree_view)));
732
733 LEAVE("widget = %p", priv->widget);
734 return priv->widget;
735}
736
737static void
738gnc_plugin_page_account_tree_destroy_widget (GncPluginPage *plugin_page)
739{
742
743 ENTER("page %p", plugin_page);
744 page = GNC_PLUGIN_PAGE_ACCOUNT_TREE (plugin_page);
745 priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
746
747 gnc_prefs_remove_cb_by_func (GNC_PREFS_GROUP_GENERAL,
748 GNC_PREF_SUMMARYBAR_POSITION_TOP,
749 (gpointer)gnc_plugin_page_account_tree_summarybar_position_changed,
750 page);
751 gnc_prefs_remove_cb_by_func (GNC_PREFS_GROUP_GENERAL,
752 GNC_PREF_SUMMARYBAR_POSITION_BOTTOM,
753 (gpointer)gnc_plugin_page_account_tree_summarybar_position_changed,
754 page);
755
756 gnc_prefs_remove_cb_by_func(GNC_PREFS_GROUP_ACCT_SUMMARY, GNC_PREF_START_CHOICE_ABS,
757 (gpointer)accounting_period_changed_cb, page);
758 gnc_prefs_remove_cb_by_func(GNC_PREFS_GROUP_ACCT_SUMMARY, GNC_PREF_START_DATE,
759 (gpointer)accounting_period_changed_cb, page);
760 gnc_prefs_remove_cb_by_func(GNC_PREFS_GROUP_ACCT_SUMMARY, GNC_PREF_START_PERIOD,
761 (gpointer)accounting_period_changed_cb, page);
762 gnc_prefs_remove_cb_by_func(GNC_PREFS_GROUP_ACCT_SUMMARY, GNC_PREF_END_CHOICE_ABS,
763 (gpointer)accounting_period_changed_cb, page);
764 gnc_prefs_remove_cb_by_func(GNC_PREFS_GROUP_ACCT_SUMMARY, GNC_PREF_END_DATE,
765 (gpointer)accounting_period_changed_cb, page);
766 gnc_prefs_remove_cb_by_func(GNC_PREFS_GROUP_ACCT_SUMMARY, GNC_PREF_END_PERIOD,
767 (gpointer)accounting_period_changed_cb, page);
768
769 // Save account filter state information to account section
770 gnc_tree_view_account_save_filter (GNC_TREE_VIEW_ACCOUNT(priv->tree_view), &priv->fd,
771 gnc_state_get_current(), gnc_tree_view_get_state_section (GNC_TREE_VIEW(priv->tree_view)));
772
773 // Destroy the filter override hash table
774 g_hash_table_destroy(priv->fd.filter_override);
775
776 // Remove the page_changed signal callback
777 gnc_plugin_page_disconnect_page_changed (GNC_PLUGIN_PAGE(plugin_page));
778
779 // Remove the page focus idle function if present
780 g_idle_remove_by_data (plugin_page);
781
782 if (priv->widget)
783 {
784 g_object_unref(G_OBJECT(priv->widget));
785 priv->widget = NULL;
786 }
787
788 if (priv->component_id)
789 {
790 gnc_unregister_gui_component(priv->component_id);
791 priv->component_id = 0;
792 }
793
794 priv->tree_view = NULL;
795 LEAVE("widget destroyed");
796}
797
798static void
799update_inactive_actions (GncPluginPage *plugin_page)
800{
802 GSimpleActionGroup *simple_action_group = NULL;
803 Account *account = NULL;
804 gboolean allow_write = !qof_book_is_readonly (gnc_get_current_book());
805 gboolean has_account = FALSE;
806 gboolean subaccounts = FALSE;
807
808 g_return_if_fail (plugin_page && GNC_IS_PLUGIN_PAGE(plugin_page));
809
810 priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE (plugin_page);
811
812 if (gtk_tree_view_get_selection (priv->tree_view))
813 {
814 account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(priv->tree_view));
815 has_account = (account != NULL);
816 subaccounts = (account && gnc_account_n_children (account) != 0);
817 /* Check here for placeholder accounts, etc. */
818 }
819
820 /* Get the action group */
821 simple_action_group = gnc_plugin_page_get_action_group (plugin_page);
822 g_return_if_fail (G_IS_SIMPLE_ACTION_GROUP (simple_action_group));
823
824 /* Set the action's sensitivity */
825 gnc_plugin_set_actions_enabled (G_ACTION_MAP(simple_action_group), readonly_inactive_actions,
826 allow_write);
827 gnc_plugin_set_actions_enabled (G_ACTION_MAP(simple_action_group), actions_requiring_account_rw,
828 allow_write && has_account);
829 gnc_plugin_set_actions_enabled (G_ACTION_MAP(simple_action_group), actions_requiring_account_always,
830 has_account);
831 gnc_plugin_set_actions_enabled (G_ACTION_MAP(simple_action_group), actions_requiring_subaccounts_rw,
832 allow_write && subaccounts);
833 gnc_plugin_set_actions_enabled (G_ACTION_MAP(simple_action_group), actions_requiring_priced_account,
834 account && xaccAccountIsPriced (account));
835
836 g_signal_emit (plugin_page, plugin_page_signals[ACCOUNT_SELECTED], 0, account);
837}
838
843static void
844gnc_plugin_page_account_tree_selected (GObject *object, gpointer user_data)
845{
846 GncPluginPage *plugin_page = GNC_PLUGIN_PAGE (object);
847 g_return_if_fail (GNC_IS_PLUGIN_PAGE (plugin_page));
848 update_inactive_actions(plugin_page);
849}
850
860static void
861gnc_plugin_page_account_tree_save_page (GncPluginPage *plugin_page,
862 GKeyFile *key_file,
863 const gchar *group_name)
864{
865 GncPluginPageAccountTree *account_page;
867
868 g_return_if_fail (GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE(plugin_page));
869 g_return_if_fail (key_file != NULL);
870 g_return_if_fail (group_name != NULL);
871
872 ENTER("page %p, key_file %p, group_name %s", plugin_page, key_file,
873 group_name);
874
875 account_page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(plugin_page);
876 priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(account_page);
877
878 gnc_tree_view_account_save(GNC_TREE_VIEW_ACCOUNT(priv->tree_view),
879 &priv->fd, key_file, group_name);
880 LEAVE(" ");
881}
882
883
884
894static GncPluginPage *
895gnc_plugin_page_account_tree_recreate_page (GtkWidget *window,
896 GKeyFile *key_file,
897 const gchar *group_name)
898{
899 GncPluginPageAccountTree *account_page;
901 GncPluginPage *page;
902
903 g_return_val_if_fail(key_file, NULL);
904 g_return_val_if_fail(group_name, NULL);
905 ENTER("key_file %p, group_name %s", key_file, group_name);
906
907 /* Create the new page. */
909 account_page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(page);
910 priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(account_page);
911
912 /* Install it now so we can then manipulate the created widget */
913 gnc_main_window_open_page(GNC_MAIN_WINDOW(window), page);
914
915 gnc_tree_view_account_restore(GNC_TREE_VIEW_ACCOUNT(priv->tree_view),
916 &priv->fd, key_file, group_name);
917 LEAVE(" ");
918 return page;
919}
920
921
922/* Callbacks */
923
924static void
925gnc_plugin_page_account_tree_summarybar_position_changed (gpointer prefs,
926 gchar* pref,
927 gpointer user_data)
928{
929 GncPluginPage *plugin_page;
932 GtkPositionType position = GTK_POS_BOTTOM;
933
934 g_return_if_fail(user_data != NULL);
935
936 plugin_page = GNC_PLUGIN_PAGE(user_data);
937 page = GNC_PLUGIN_PAGE_ACCOUNT_TREE (user_data);
938 priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
939
940 if (gnc_prefs_get_bool (GNC_PREFS_GROUP_GENERAL, GNC_PREF_SUMMARYBAR_POSITION_TOP))
941 position = GTK_POS_TOP;
942
943 gtk_box_reorder_child(GTK_BOX(priv->widget),
944 plugin_page->summarybar,
945 (position == GTK_POS_TOP ? 0 : -1) );
946}
947
955static gboolean
956gnc_plugin_page_account_tree_button_press_cb (GtkWidget *widget,
957 GdkEventButton *event,
958 GncPluginPage *page)
959{
960
961 g_return_val_if_fail(GNC_IS_PLUGIN_PAGE(page), FALSE);
962
963 ENTER("widget %p, event %p, page %p", widget, event, page);
964 gnc_main_window_button_press_cb(widget, event, page);
965 LEAVE(" ");
966
967 /* Always return FALSE. This will let the tree view callback run as
968 * well which will select the item under the cursor. By the time
969 * the user sees the menu both callbacks will have run and the menu
970 * actions will operate on the just-selected account. */
971 return FALSE;
972}
973
974static void
975gppat_open_account_common (GncPluginPageAccountTree *page,
976 Account *account,
977 gboolean include_subs)
978{
979 GtkWidget *window;
980 GncPluginPage *new_page;
981
982 if (account == NULL)
983 return;
984
985 window = GNC_PLUGIN_PAGE (page)->window;
986 new_page = gnc_plugin_page_register_new (account, include_subs);
987 gnc_main_window_open_page (GNC_MAIN_WINDOW(window), new_page);
988}
989
990static void
991gnc_plugin_page_account_tree_double_click_cb (GtkTreeView *treeview,
992 GtkTreePath *path,
993 GtkTreeViewColumn *col,
995{
996 GtkTreeModel *model;
997 GtkTreeIter iter;
998
999 g_return_if_fail (GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE (page));
1000 g_return_if_fail (treeview);
1001
1002 model = gtk_tree_view_get_model(treeview);
1003 if (gtk_tree_model_get_iter(model, &iter, path))
1004 {
1005 Account *account = gnc_tree_view_account_get_account_from_path (GNC_TREE_VIEW_ACCOUNT(treeview), path);
1006 if (xaccAccountGetPlaceholder (account))
1007 {
1008 /* This is a placeholder account. Only only show/hide
1009 * subaccount list if there is one.
1010 */
1011 if (gtk_tree_model_iter_has_child(model, &iter))
1012 {
1013 /* There are children,
1014 * just expand or collapse the row. */
1015 if (gtk_tree_view_row_expanded(treeview, path))
1016 gtk_tree_view_collapse_row(treeview, path);
1017 else
1018 gtk_tree_view_expand_row(treeview, path, FALSE);
1019 }
1020 }
1021 else
1022 {
1023 /* No placeholder account, so open its register */
1024 gppat_open_account_common (page, account, FALSE);
1025 }
1026 }
1027}
1028
1029static void
1030gnc_plugin_page_account_tree_selection_changed_cb (GtkTreeSelection *selection,
1032{
1033 GncPluginPage *plugin_page = GNC_PLUGIN_PAGE(page);
1034 update_inactive_actions (plugin_page);
1035}
1036
1037static void
1038accounting_period_changed_cb (gpointer prefs, gchar *pref, gpointer user_data)
1039{
1040 gnc_plugin_page_account_tree_cmd_refresh (NULL, NULL, user_data);
1041}
1042
1043/* Command callbacks */
1044static void
1045gnc_plugin_page_account_tree_cmd_new_account (GSimpleAction *simple,
1046 GVariant *paramter,
1047 gpointer user_data)
1048{
1049 auto page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(user_data);
1051 GtkWindow *parent = GTK_WINDOW (gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page)));
1052 gnc_ui_new_account_window (parent, gnc_get_current_book(),
1053 account);
1054}
1055
1056static void
1057gnc_plugin_page_account_tree_cmd_file_new_hierarchy (GSimpleAction *simple,
1058 GVariant *paramter,
1059 gpointer user_data)
1060{
1061 gnc_ui_hierarchy_assistant(FALSE);
1062}
1063
1064static void
1065gnc_plugin_page_account_tree_cmd_open_account (GSimpleAction *simple,
1066 GVariant *paramter,
1067 gpointer user_data)
1068{
1069 auto page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(user_data);
1070 Account *account;
1071
1072 g_return_if_fail (GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE (page));
1074 gppat_open_account_common (page, account, FALSE);
1075}
1076
1077static void
1078gnc_plugin_page_account_tree_cmd_open_subaccounts (GSimpleAction *simple,
1079 GVariant *paramter,
1080 gpointer user_data)
1081{
1082 auto page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(user_data);
1083 Account *account;
1084
1085 g_return_if_fail (GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE (page));
1087 gppat_open_account_common (page, account, TRUE);
1088}
1089
1090static void
1091gnc_plugin_page_account_tree_cmd_edit_account (GSimpleAction *simple,
1092 GVariant *paramter,
1093 gpointer user_data)
1094{
1095 auto page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(user_data);
1096 Account *account;
1097 GtkWindow *parent = GTK_WINDOW (gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page)));
1098 ENTER("action %p, page %p", simple, page);
1099
1101 g_return_if_fail (account != NULL);
1102
1103 gnc_ui_edit_account_window (parent, account);
1104 LEAVE(" ");
1105}
1106
1107static void
1108gnc_plugin_page_account_tree_cmd_find_account (GSimpleAction *simple,
1109 GVariant *paramter,
1110 gpointer user_data)
1111{
1112 auto page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(user_data);
1113 GtkWidget *window;
1114
1115 ENTER("action %p, page %p", simple, page);
1116
1117 window = gnc_plugin_page_get_window(GNC_PLUGIN_PAGE(page));
1118
1119 gnc_find_account_dialog (window, NULL);
1120 LEAVE(" ");
1121}
1122
1123static void
1124gnc_plugin_page_account_tree_cmd_find_account_popup (GSimpleAction *simple,
1125 GVariant *paramter,
1126 gpointer user_data)
1127{
1128 auto page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(user_data);
1129 Account *account = NULL;
1130 GtkWidget *window;
1131
1132 ENTER("action %p, page %p", simple, page);
1133
1135
1136 window = gnc_plugin_page_get_window(GNC_PLUGIN_PAGE(page));
1137
1138 gnc_find_account_dialog (window, account);
1139 LEAVE(" ");
1140}
1141
1142static void
1143gnc_plugin_page_account_tree_cmd_cascade_account_properties (GSimpleAction *simple,
1144 GVariant *paramter,
1145 gpointer user_data)
1146{
1147 auto page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(user_data);
1148 Account *account = NULL;
1149 GtkWidget *window;
1150
1151 ENTER("action %p, page %p", simple, page);
1152
1154
1155 window = gnc_plugin_page_get_window (GNC_PLUGIN_PAGE(page));
1156
1157 if (account != NULL)
1158 gnc_account_cascade_properties_dialog (window, account);
1159
1160 LEAVE(" ");
1161}
1162
1163static gpointer
1164delete_account_helper (Account * account, gpointer data)
1165{
1166 auto helper_res = static_cast<delete_helper_t*>(data);
1167 auto& splits{xaccAccountGetSplits (account)};
1168 auto split_ro = [](auto s) -> bool { return xaccTransGetReadOnly (xaccSplitGetParent (s)); };
1169
1170 helper_res->has_splits = !splits.empty();
1171 helper_res->has_ro_splits = std::any_of (splits.begin(), splits.end(), split_ro);
1172
1173 return GINT_TO_POINTER (helper_res->has_splits || helper_res->has_ro_splits);
1174}
1175
1176/***
1177 *** The OK button of a Delete Account dialog is insensitive if
1178 *** and only if a sensitive account selector contains no accounts.
1179 ***/
1180static void
1181set_ok_sensitivity(GtkWidget *dialog)
1182{
1183 gboolean sensitive;
1184
1185 auto sa_mas = GTK_WIDGET(g_object_get_data(G_OBJECT(dialog), DELETE_DIALOG_SA_MAS));
1186 auto trans_mas = GTK_WIDGET(g_object_get_data(G_OBJECT(dialog), DELETE_DIALOG_TRANS_MAS));
1187
1188 sensitive = ((!sa_mas ||
1189 !gtk_widget_is_sensitive (sa_mas) ||
1190 gnc_account_sel_get_visible_account_num (GNC_ACCOUNT_SEL (sa_mas))) &&
1191 (!trans_mas ||
1192 !gtk_widget_is_sensitive (trans_mas) ||
1193 gnc_account_sel_get_visible_account_num (GNC_ACCOUNT_SEL (trans_mas))));
1194
1195 auto button = GTK_WIDGET(g_object_get_data(G_OBJECT(dialog), DELETE_DIALOG_OK_BUTTON));
1196 gtk_widget_set_sensitive(button, sensitive);
1197}
1198
1199static GList *
1200gppat_get_exclude_list (Account *acc, gboolean exclude_subaccounts)
1201{
1202 GList *acct_list = NULL;
1203
1204 if (exclude_subaccounts)
1205 acct_list = gnc_account_get_descendants (acc);
1206
1207 acct_list = g_list_prepend (acct_list, acc);
1208
1209 return acct_list;
1210}
1211
1212static void
1213gppat_populate_gas_list(GtkWidget *dialog,
1214 GNCAccountSel *gas,
1215 gboolean exclude_subaccounts)
1216{
1217 Account *account;
1218 GList *filter;
1219 GList *exclude;
1220
1221 g_return_if_fail(GTK_IS_DIALOG(dialog));
1222 if (gas == NULL)
1223 return;
1224 account = GNC_ACCOUNT(g_object_get_data(G_OBJECT(dialog), DELETE_DIALOG_ACCOUNT));
1225 filter = static_cast<GList*>(g_object_get_data(G_OBJECT(dialog), DELETE_DIALOG_FILTER));
1226
1227 /* Setting the account type filter triggers GNCAccountSel population. */
1228 gnc_account_sel_set_acct_filters (gas, filter, NULL);
1229
1230 /* Accounts to be deleted must be excluded from GAS. */
1231 exclude = gppat_get_exclude_list (account, exclude_subaccounts);
1232 gnc_account_sel_set_acct_exclude_filter (gas, exclude);
1233 g_list_free (exclude);
1234
1235 gnc_account_sel_set_account (gas, NULL, TRUE);
1236
1237 /* The sensitivity of the OK button needs to be reevaluated. */
1238 set_ok_sensitivity(dialog);
1239}
1240
1241void
1242gppat_populate_trans_mas_list(GtkToggleButton *sa_mrb,
1243 GtkWidget *dialog)
1244{
1245 g_return_if_fail(GTK_IS_DIALOG(dialog));
1246
1247 /* Cannot move transactions to subaccounts if they are to be deleted. */
1248 auto trans_mas = GTK_WIDGET(g_object_get_data(G_OBJECT(dialog), DELETE_DIALOG_TRANS_MAS));
1249 gppat_populate_gas_list(dialog, GNC_ACCOUNT_SEL(trans_mas), !gtk_toggle_button_get_active(sa_mrb));
1250}
1251
1252/* Note that the emitting object (the toggle button) and the signal data
1253 * are swapped in below callback function. This is a gtkbuilder feature:
1254 * it swaps if you explicitly set an object for a signal handler in the
1255 * gtkbuilder xml file.
1256 */
1257void
1258gppat_set_insensitive_iff_rb_active(GtkWidget *widget, GtkToggleButton *b)
1259{
1260 GtkWidget *dialog = gtk_widget_get_toplevel(widget);
1261 auto subaccount_trans = GTK_WIDGET(g_object_get_data(G_OBJECT(dialog), DELETE_DIALOG_SA_TRANS));
1262 auto sa_mas = GTK_WIDGET(g_object_get_data(G_OBJECT(dialog), DELETE_DIALOG_SA_MAS));
1263 auto have_splits = g_object_get_data(G_OBJECT(dialog), DELETE_DIALOG_SA_SPLITS) != nullptr;
1264
1265 gtk_widget_set_sensitive(widget, !gtk_toggle_button_get_active(b));
1266
1267 // If we have subaccount splits & delete subaccounts, enable subaccount_trans
1268 if ((have_splits) && !gtk_widget_is_sensitive(sa_mas))
1269 gtk_widget_set_sensitive(subaccount_trans, TRUE);
1270 else
1271 gtk_widget_set_sensitive(subaccount_trans, FALSE);
1272
1273 set_ok_sensitivity(dialog);
1274}
1275
1276static GtkWidget *
1277gppat_setup_account_selector (GtkBuilder *builder, GtkWidget *dialog,
1278 const gchar *hbox, const gchar *sel_name)
1279{
1280 GtkWidget *selector = gnc_account_sel_new();
1281 GtkWidget *box = GTK_WIDGET(gtk_builder_get_object (builder, hbox));
1282
1283 gtk_box_pack_start (GTK_BOX(box), selector, TRUE, TRUE, 0);
1284
1285 // placeholder accounts are OK for this GAS
1286 if (g_strcmp0 (sel_name, DELETE_DIALOG_SA_MAS) == 0)
1287 g_object_set (selector, "hide-placeholder", FALSE, NULL);
1288
1289 g_object_set_data(G_OBJECT(dialog), sel_name, selector);
1290
1291 gppat_populate_gas_list(dialog, GNC_ACCOUNT_SEL(selector), TRUE);
1292 gtk_widget_show_all(box);
1293
1294 return selector;
1295}
1296
1297static int
1298commodity_mismatch_dialog (const Account* account, GtkWindow* parent)
1299{
1300 int response;
1301 char *account_name = gnc_account_get_full_name (account);
1302 char* message = g_strdup_printf (
1303 _("Account %s does not have the same currency as the one you're "
1304 "moving transactions from.\nAre you sure you want to do this?"),
1305 account_name);
1306 GtkWidget* error_dialog =
1307 gtk_message_dialog_new (parent, GTK_DIALOG_DESTROY_WITH_PARENT,
1308 GTK_MESSAGE_ERROR, GTK_BUTTONS_NONE,
1309 "%s", message);
1310 gtk_dialog_add_buttons (GTK_DIALOG(error_dialog),
1311 _("_Pick another account"), GTK_RESPONSE_CANCEL,
1312 _("_Do it anyway"), GTK_RESPONSE_ACCEPT,
1313 (gchar *)NULL);
1314 response = gtk_dialog_run (GTK_DIALOG (error_dialog));
1315 gtk_widget_destroy (error_dialog);
1316 g_free (message);
1317 g_free (account_name);
1318 return response;
1319}
1320
1321typedef struct
1322{
1323 Account *new_account;
1324 Account *old_account;
1325 GNCAccountSel *selector;
1326 gboolean match;
1327 gboolean for_account;
1328} Adopter;
1329
1330static void
1331adopter_set_account_and_match (Adopter* adopter)
1332{
1333 if (!(adopter->selector &&
1334 gtk_widget_is_sensitive (GTK_WIDGET (adopter->selector))))
1335 return;
1336 adopter->new_account = gnc_account_sel_get_account(adopter->selector);
1337/* We care about the commodity only if we're moving transactions. */
1338 if (!adopter->for_account && adopter->old_account && adopter->new_account)
1339 adopter->match =
1340 xaccAccountGetCommodity (adopter->new_account) ==
1341 xaccAccountGetCommodity (adopter->old_account);
1342}
1343
1344static void
1345adopter_init (Adopter* adopter, GtkWidget *selector, Account* account,
1346 gboolean for_account)
1347{
1348 adopter->selector = GNC_ACCOUNT_SEL (selector);
1349 adopter->new_account = NULL;
1350 adopter->old_account = account;
1351 adopter->match = TRUE;
1352 adopter->for_account = for_account;
1353}
1354
1355static gboolean
1356adopter_match (Adopter* adopter, GtkWindow *parent)
1357{
1358 int result;
1359 if (adopter->match || adopter->for_account)
1360 return TRUE;
1361 result = commodity_mismatch_dialog (adopter->new_account, parent);
1362 return (result == GTK_RESPONSE_ACCEPT);
1363}
1364
1365typedef struct
1366{
1367 Adopter trans;
1368 Adopter subacct;
1369 Adopter subtrans;
1370 delete_helper_t delete_res;
1371} Adopters;
1372
1373static Account*
1374account_subaccount (Account* account)
1375{
1376 Account* subaccount = NULL;
1377 GList *subs = gnc_account_get_children (account);
1378 if (!gnc_list_length_cmp (subs, 1))
1379 subaccount = GNC_ACCOUNT(subs->data);
1380 g_list_free (subs);
1381 return subaccount;
1382}
1383
1384static GtkWidget*
1385account_delete_dialog (Account *account, GtkWindow *parent, Adopters* adopt)
1386{
1387 GtkWidget *dialog = NULL;
1388 GtkWidget *widget = NULL;
1389 gchar *title = NULL;
1390 GtkBuilder *builder = gtk_builder_new();
1391 gchar *acct_name = gnc_account_get_full_name(account);
1392 GList* filter = g_list_prepend(NULL, (gpointer)xaccAccountGetType(account));
1393
1394 if (!acct_name)
1395 acct_name = g_strdup (_("(no name)"));
1396
1397 gnc_builder_add_from_file (builder, "dialog-account.glade", "account_delete_dialog");
1398
1399 dialog = GTK_WIDGET(gtk_builder_get_object (builder, "account_delete_dialog"));
1400 gtk_window_set_transient_for(GTK_WINDOW(dialog), parent);
1401
1402 /* FIXME: Same account type used for subaccount. */
1403 g_object_set_data_full (G_OBJECT(dialog), DELETE_DIALOG_FILTER, filter,
1404 (GDestroyNotify) g_list_free);
1405 g_object_set_data(G_OBJECT(dialog), DELETE_DIALOG_ACCOUNT, account);
1406 widget = GTK_WIDGET(gtk_builder_get_object (builder, "header"));
1407 title = g_strdup_printf(_("Deleting account %s"), acct_name);
1408 gtk_label_set_text(GTK_LABEL(widget), title);
1409 g_free(title);
1410 g_free(acct_name);
1411
1412 widget = GTK_WIDGET(gtk_builder_get_object (builder, DELETE_DIALOG_OK_BUTTON));
1413 g_object_set_data(G_OBJECT(dialog), DELETE_DIALOG_OK_BUTTON, widget);
1414
1415 // Add the account selectors and enable sections as appropriate
1416 // setup transactions selector
1417 adopter_init (&adopt->trans,
1418 gppat_setup_account_selector (builder, dialog,
1419 "trans_mas_hbox",
1420 DELETE_DIALOG_TRANS_MAS),
1421 account, FALSE);
1422
1423 // Does the selected account have splits
1424 if (!xaccAccountGetSplits(account).empty())
1425 {
1426 delete_helper_t delete_res2 = { FALSE, FALSE };
1427
1428 delete_account_helper(account, &delete_res2);
1429 if (delete_res2.has_ro_splits)
1430 {
1431 gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object (builder, "trans_rw")));
1432 widget = GTK_WIDGET(gtk_builder_get_object (builder, "trans_drb"));
1433 gtk_widget_set_sensitive(widget, FALSE);
1434 }
1435 else
1436 gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object (builder, "trans_ro")));
1437 }
1438 else
1439 {
1440 gtk_widget_set_sensitive (GTK_WIDGET(gtk_builder_get_object (builder, "transactions")), FALSE);
1441 gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object (builder, "trans_ro")));
1442 }
1443
1444 // setup subaccount account selector
1445 adopter_init (&adopt->subacct,
1446 gppat_setup_account_selector (builder, dialog,
1447 "sa_mas_hbox",
1448 DELETE_DIALOG_SA_MAS),
1449 account, TRUE);
1450
1451 // setup subaccount transaction selector
1452 adopter_init (&adopt->subtrans,
1453 gppat_setup_account_selector (builder, dialog,
1454 "sa_trans_mas_hbox",
1455 DELETE_DIALOG_SA_TRANS_MAS),
1456 account_subaccount (account), FALSE);
1457 g_object_set_data(G_OBJECT(dialog), DELETE_DIALOG_SA_TRANS,
1458 GTK_WIDGET(gtk_builder_get_object (builder, "subaccount_trans")));
1459
1460 if (gnc_account_n_children(account) > 0)
1461 {
1462 // Check for RO txns in descendants
1463 gnc_account_foreach_descendant_until(account, delete_account_helper,
1464 &adopt->delete_res);
1465 if (adopt->delete_res.has_splits)
1466 {
1467 if (adopt->delete_res.has_ro_splits)
1468 {
1469 gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object (builder, "sa_trans_rw")));
1470 widget = GTK_WIDGET(gtk_builder_get_object (builder, "sa_trans_drb"));
1471 gtk_widget_set_sensitive(widget, FALSE);
1472 }
1473 else
1474 gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object (builder, "sa_trans_ro")));
1475
1476 g_object_set_data(G_OBJECT(dialog), DELETE_DIALOG_SA_SPLITS, GINT_TO_POINTER(1));
1477 }
1478 else
1479 {
1480 g_object_set_data(G_OBJECT(dialog), DELETE_DIALOG_SA_SPLITS, GINT_TO_POINTER(0));
1481 gtk_widget_set_sensitive (GTK_WIDGET(gtk_builder_get_object (builder, "subaccount_trans")), FALSE);
1482 gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object (builder, "sa_trans_ro")));
1483 }
1484 }
1485 else
1486 {
1487 gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object (builder, "subaccounts")), FALSE);
1488 gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object (builder, "subaccount_trans")), FALSE);
1489 gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object (builder, "sa_trans_ro")));
1490 }
1491
1492 /* default to cancel */
1493 gtk_dialog_set_default_response (GTK_DIALOG(dialog), GTK_RESPONSE_CANCEL);
1494
1495 gtk_builder_connect_signals(builder, dialog);
1496 g_object_unref(G_OBJECT(builder));
1497
1498 return dialog;
1499}
1500
1501static void
1502gnc_plugin_page_account_tree_cmd_delete_account (GSimpleAction *simple,
1503 GVariant *paramter,
1504 gpointer user_data)
1505{
1506 auto page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(user_data);
1508 gchar *acct_name;
1509 GtkWidget *window;
1510 Adopters adopt;
1511 GList* list;
1512 gint response;
1513 GtkWidget *dialog = NULL;
1514
1515 if (account == NULL)
1516 return;
1517
1519 return;
1520
1521 memset (&adopt, 0, sizeof (adopt));
1522 /* If the account has objects referring to it, show the list - the account can't be deleted until these
1523 references are dealt with. */
1524 list = qof_instance_get_referring_object_list(QOF_INSTANCE(account));
1525 if (list != NULL)
1526 {
1527#define EXPLANATION _("The list below shows objects which make use of the account which you want to delete.\nBefore you can delete it, you must either delete those objects or else modify them so they make use\nof another account")
1528
1529 gnc_ui_object_references_show(EXPLANATION, list);
1530 g_list_free(list);
1531 return;
1532 }
1533 g_list_free (list);
1534
1535 window = gnc_plugin_page_get_window(GNC_PLUGIN_PAGE(page));
1536 acct_name = gnc_account_get_full_name(account);
1537 if (!acct_name)
1538 acct_name = g_strdup (_("(no name)"));
1539
1540 if (gnc_account_n_children(account) > 1) {
1541 gchar* message = g_strdup_printf(_("The account \"%s\" has more than one subaccount.\n\nMove the subaccounts or delete them before attempting to delete this account."), acct_name);
1542 gnc_error_dialog(GTK_WINDOW(window),"%s", message);
1543 g_free (message);
1544 g_free(acct_name);
1545 return;
1546 }
1547 g_free (acct_name);
1548
1549 // If no transaction or children just delete it.
1550 if (xaccAccountGetSplits (account).empty() && gnc_account_n_children (account) == 0)
1551 {
1552 do_delete_account (account, NULL, NULL, NULL);
1553 return;
1554 }
1555
1556 dialog = account_delete_dialog (account, GTK_WINDOW (window), &adopt);
1557
1558 while (TRUE)
1559 {
1560 response = gtk_dialog_run(GTK_DIALOG(dialog));
1561
1562 if (response != GTK_RESPONSE_ACCEPT)
1563 {
1564 gtk_widget_destroy(dialog);
1565 return;
1566 }
1567 adopter_set_account_and_match (&adopt.trans);
1568 adopter_set_account_and_match (&adopt.subacct);
1569 adopter_set_account_and_match (&adopt.subtrans);
1570
1571 if (adopter_match (&adopt.trans, GTK_WINDOW (window)) &&
1572 adopter_match (&adopt.subacct, GTK_WINDOW (window)) &&
1573 adopter_match (&adopt.subtrans, GTK_WINDOW (window)))
1574 break;
1575 }
1576 gtk_widget_destroy(dialog);
1577 if (confirm_delete_account (simple, page, adopt.trans.new_account,
1578 adopt.subtrans.new_account,
1579 adopt.subacct.new_account,
1580 adopt.delete_res) == GTK_RESPONSE_ACCEPT)
1581 {
1582 do_delete_account (account, adopt.subacct.new_account,
1583 adopt.subtrans.new_account, adopt.trans.new_account);
1584 }
1585}
1586
1587static int
1588confirm_delete_account (GSimpleAction *simple, GncPluginPageAccountTree *page,
1589 Account* ta, Account* sta, Account* saa,
1590 delete_helper_t delete_res)
1591{
1593 GtkWidget* window = gnc_plugin_page_get_window(GNC_PLUGIN_PAGE(page));
1594 gint response;
1595
1596 char *lines[6] = {0};
1597 char *message;
1598 int i = 0;
1599 GtkWidget *dialog;
1600 gchar* acct_name = gnc_account_get_full_name(account);
1601
1602 lines[i] = g_strdup_printf (_("The account %s will be deleted."),
1603 acct_name);
1604 g_free(acct_name);
1605
1606 if (!xaccAccountGetSplits (account).empty())
1607 {
1608 if (ta)
1609 {
1610 char *name = gnc_account_get_full_name(ta);
1611 lines[++i] = g_strdup_printf (_("All transactions in this account "
1612 "will be moved to the account %s."),
1613 name);
1614 g_free (name);
1615 }
1616 else
1617 {
1618 lines[++i] = g_strdup (_("All transactions in this account "
1619 "will be deleted."));
1620 }
1621 }
1622 if (gnc_account_n_children(account))
1623 {
1624 if (saa)
1625 {
1626 char *name = gnc_account_get_full_name(saa);
1627 lines[++i] = g_strdup_printf (_("Its sub-account will be "
1628 "moved to the account %s."), name);
1629 g_free (name);
1630 }
1631 else
1632 {
1633 lines[++i] = g_strdup (_("Its subaccount will be deleted."));
1634 if (sta)
1635 {
1636 char *name = gnc_account_get_full_name(sta);
1637 lines[++i] = g_strdup_printf (_("All sub-account transactions "
1638 "will be moved to the "
1639 "account %s."), name);
1640 g_free (name);
1641 }
1642 else if (delete_res.has_splits)
1643 {
1644 lines[++i] = g_strdup(_("All sub-account transactions "
1645 "will be deleted."));
1646 }
1647 }
1648 }
1649
1650 lines[++i] = _("Are you sure you want to do this?");
1651
1652 message = g_strjoinv(" ", lines);
1653 for (int j = 0; j < i; ++j) // Don't try to free the last one, it's const.
1654 g_free (lines[j]);
1655
1656 dialog = gtk_message_dialog_new(GTK_WINDOW(window),
1657 GTK_DIALOG_DESTROY_WITH_PARENT,
1658 GTK_MESSAGE_QUESTION,
1659 GTK_BUTTONS_NONE,
1660 "%s", message);
1661 g_free(message);
1662 gtk_dialog_add_buttons(GTK_DIALOG(dialog),
1663 _("_Cancel"), GTK_RESPONSE_CANCEL,
1664 _("_Delete"), GTK_RESPONSE_ACCEPT,
1665 (gchar *)NULL);
1666 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_CANCEL);
1667 response = gtk_dialog_run(GTK_DIALOG(dialog));
1668 gtk_widget_destroy(dialog);
1669 return response;
1670}
1671
1672void
1673do_delete_account (Account* account, Account* saa, Account* sta, Account* ta)
1674{
1675 GList *acct_list, *ptr;
1676 const GncGUID *guid;
1677 gchar guidstr[GUID_ENCODING_LENGTH+1];
1678
1679 gnc_set_busy_cursor(NULL, TRUE);
1680 gnc_suspend_gui_refresh ();
1681
1682 /* Move subaccounts and transactions if this was requested */
1683 xaccAccountBeginEdit (account);
1684 if (saa)
1685 {
1687 acct_list = gnc_account_get_children(account);
1688 for (ptr = acct_list; ptr; ptr = g_list_next(ptr))
1689 gnc_account_append_child (saa, GNC_ACCOUNT(ptr->data));
1690 g_list_free(acct_list);
1692 }
1693 else if (sta)
1694 {
1695 /* Move the splits of its subaccounts, if any. */
1696 gnc_account_foreach_descendant(account,
1697 (AccountCb)xaccAccountMoveAllSplits,
1698 sta);
1699 }
1700 else
1701 {
1702 gnc_account_foreach_descendant (account,
1703 [](auto acc, [[maybe_unused]] auto data)
1705 nullptr);
1706 }
1707 if (ta)
1708 {
1709 /* Move the splits of the account to be deleted. */
1710 xaccAccountMoveAllSplits (account, ta);
1711 }
1712 else
1713 {
1715 }
1716 xaccAccountCommitEdit (account);
1717
1718 /* Drop all references from the state file for
1719 * any subaccount the account still has
1720 */
1721 acct_list = gnc_account_get_children(account);
1722 for (ptr = acct_list; ptr; ptr = g_list_next(ptr))
1723 {
1724 guid = xaccAccountGetGUID (ptr->data);
1725 guid_to_string_buff (guid, guidstr);
1727 }
1728 g_list_free(acct_list);
1729
1730 /* Drop all references from the state file for this account
1731 */
1732 guid = xaccAccountGetGUID (account);
1733 guid_to_string_buff (guid, guidstr);
1735
1736 /*
1737 * Finally, delete the account, any subaccounts it may still
1738 * have, and any splits it or its subaccounts may still have.
1739 */
1740 xaccAccountBeginEdit (account);
1741 xaccAccountDestroy (account);
1742 gnc_resume_gui_refresh ();
1743 gnc_unset_busy_cursor(NULL);
1744}
1745
1746static void
1747gnc_plugin_page_account_tree_cmd_renumber_accounts (GSimpleAction *simple,
1748 GVariant *paramter,
1749 gpointer user_data)
1750{
1751 auto page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(user_data);
1752 Account *account;
1753 GtkWidget *window;
1754
1755 window = gnc_plugin_page_get_window(GNC_PLUGIN_PAGE(page));
1757 if (!window || !account)
1758 return;
1759
1760 gnc_account_renumber_create_dialog(window, account);
1761}
1762
1763static void
1764gnc_plugin_page_account_tree_cmd_refresh (GSimpleAction *simple,
1765 GVariant *paramter,
1766 gpointer user_data)
1767{
1768 auto page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(user_data);
1770
1771 g_return_if_fail(GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE(page));
1772
1773 priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
1774
1775 gnc_tree_view_account_clear_model_cache (GNC_TREE_VIEW_ACCOUNT(priv->tree_view));
1776 gtk_widget_queue_draw (priv->widget);
1777}
1778
1779/*********************/
1780
1781static void
1782gnc_plugin_page_account_tree_cmd_view_filter_by (GSimpleAction *simple,
1783 GVariant *paramter,
1784 gpointer user_data)
1785{
1786 auto page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(user_data);
1788
1789 g_return_if_fail(GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE(page));
1790 ENTER("(action %p, page %p)", simple, page);
1791
1792 priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
1793 account_filter_dialog_create(&priv->fd, GNC_PLUGIN_PAGE(page));
1794 LEAVE(" ");
1795}
1796
1797static void
1798gnc_plugin_page_account_tree_cmd_reconcile (GSimpleAction *simple,
1799 GVariant *paramter,
1800 gpointer user_data)
1801{
1802 auto page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(user_data);
1803 GtkWidget *window;
1804 Account *account;
1805 RecnWindow *recnData;
1806
1808 g_return_if_fail (account != NULL);
1809
1810 /* To prevent mistakes involving saving an edited transaction after
1811 * finishing a reconciliation (reverting the reconcile state), we could look
1812 * at all open registers and determine if any of them have a transaction
1813 * being edited that involves the account to be reconciled.
1814 *
1815 * However, the reconcile window isn't modal so it's still possible to start
1816 * editing a transaction after opening it. Assume the user knows what
1817 * they're doing if they start a reconciliation from the account tree and
1818 * don't attempt to stop them.
1819 */
1820
1821 window = GNC_PLUGIN_PAGE (page)->window;
1822 recnData = recnWindow (window, account);
1823 gnc_ui_reconcile_window_raise (recnData);
1824}
1825
1826static void
1827gnc_plugin_page_account_tree_cmd_autoclear (GSimpleAction *simple,
1828 GVariant *paramter,
1829 gpointer user_data)
1830{
1831 auto page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(user_data);
1832 GtkWidget *window;
1833 Account *account;
1834 AutoClearWindow *autoClearData;
1835
1837 g_return_if_fail (account != NULL);
1838
1839 window = GNC_PLUGIN_PAGE (page)->window;
1840 autoClearData = autoClearWindow (window, account);
1841 gnc_ui_autoclear_window_raise (autoClearData);
1842}
1843
1844static void
1845gnc_plugin_page_account_tree_cmd_transfer (GSimpleAction *simple,
1846 GVariant *paramter,
1847 gpointer user_data)
1848{
1849 auto page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(user_data);
1850 GtkWidget *window;
1851 Account *account;
1852
1854 window = GNC_PLUGIN_PAGE (page)->window;
1855 gnc_xfer_dialog (window, account);
1856}
1857
1858static void
1859gnc_plugin_page_account_tree_cmd_stock_split (GSimpleAction *simple,
1860 GVariant *paramter,
1861 gpointer user_data)
1862{
1863 auto page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(user_data);
1864 GtkWidget *window;
1865 Account *account;
1866
1868 window = GNC_PLUGIN_PAGE (page)->window;
1869 gnc_stock_split_dialog (window, account);
1870}
1871
1872static void
1873gnc_plugin_page_account_tree_cmd_stock_assistant (GSimpleAction *simple,
1874 GVariant *paramter,
1875 gpointer user_data)
1876{
1877 auto page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(user_data);
1878 Account *account;
1879 GtkWidget *window;
1880
1881 ENTER ("(action %p, page %p)", simple, page);
1882
1884 window = GNC_PLUGIN_PAGE(page)->window;
1885 gnc_stock_transaction_assistant (window, account);
1886
1887 LEAVE (" ");
1888}
1889
1890static void
1891gnc_plugin_page_account_tree_cmd_edit_tax_options (GSimpleAction *simple,
1892 GVariant *paramter,
1893 gpointer user_data)
1894{
1895 auto page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(user_data);
1896 GtkWidget *window;
1897 Account *account;
1898
1900 window = GNC_PLUGIN_PAGE (page)->window;
1901 gnc_tax_info_dialog (window, account);
1902}
1903
1904static void
1905gnc_plugin_page_account_tree_cmd_lots (GSimpleAction *simple,
1906 GVariant *paramter,
1907 gpointer user_data)
1908{
1909 auto page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(user_data);
1911 GtkWidget *window = GNC_PLUGIN_PAGE (page)->window;
1912 gnc_lot_viewer_dialog (GTK_WINDOW(window), account);
1913}
1914
1915static gboolean
1916scrub_kp_handler (GtkWidget *widget, GdkEventKey *event, gpointer data)
1917{
1918 if (event->length == 0) return FALSE;
1919
1920 switch (event->keyval)
1921 {
1922 case GDK_KEY_Escape:
1923 {
1924 gboolean abort_scrub = gnc_verify_dialog (GTK_WINDOW(widget), FALSE,
1925 "%s", _(check_repair_abort_YN));
1926
1927 if (abort_scrub)
1928 gnc_set_abort_scrub (TRUE);
1929
1930 return TRUE;
1931 }
1932 default:
1933 break;
1934 }
1935 return FALSE;
1936}
1937
1938static void
1939gnc_plugin_page_account_tree_cmd_scrub (GSimpleAction *simple,
1940 GVariant *paramter,
1941 gpointer user_data)
1942{
1943 auto page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(user_data);
1945 GncWindow *window;
1946 gulong scrub_kp_handler_ID;
1947
1948 g_return_if_fail (account != NULL);
1949
1950 prepare_scrubbing ();
1951
1952 window = GNC_WINDOW(GNC_PLUGIN_PAGE (page)->window);
1953 scrub_kp_handler_ID = g_signal_connect (G_OBJECT(window), "key-press-event",
1954 G_CALLBACK(scrub_kp_handler), NULL);
1955 gnc_window_set_progressbar_window (window);
1956
1957 xaccAccountScrubOrphans (account, gnc_window_show_progress);
1958 xaccAccountScrubImbalance (account, gnc_window_show_progress);
1959
1960 // XXX: Lots/capital gains scrubbing is disabled
1961 if (g_getenv("GNC_AUTO_SCRUB_LOTS") != NULL)
1962 xaccAccountScrubLots(account);
1963
1964 gncScrubBusinessAccount(account, gnc_window_show_progress);
1965
1966 finish_scrubbing (window, scrub_kp_handler_ID);
1967}
1968
1969static void
1970gnc_plugin_page_account_tree_cmd_scrub_sub (GSimpleAction *simple,
1971 GVariant *paramter,
1972 gpointer user_data)
1973{
1974 auto page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(user_data);
1976 GncWindow *window;
1977 gulong scrub_kp_handler_ID;
1978
1979 g_return_if_fail (account != NULL);
1980
1981 prepare_scrubbing ();
1982
1983 window = GNC_WINDOW(GNC_PLUGIN_PAGE (page)->window);
1984 scrub_kp_handler_ID = g_signal_connect (G_OBJECT(window), "key-press-event",
1985 G_CALLBACK(scrub_kp_handler), NULL);
1986 gnc_window_set_progressbar_window (window);
1987
1988 xaccAccountTreeScrubOrphans (account, gnc_window_show_progress);
1989 xaccAccountTreeScrubImbalance (account, gnc_window_show_progress);
1990
1991 // XXX: Lots/capital gains scrubbing is disabled
1992 if (g_getenv("GNC_AUTO_SCRUB_LOTS") != NULL)
1993 xaccAccountTreeScrubLots(account);
1994
1995 gncScrubBusinessAccountTree(account, gnc_window_show_progress);
1996
1997 finish_scrubbing (window, scrub_kp_handler_ID);
1998}
1999
2000static void
2001gnc_plugin_page_account_tree_cmd_scrub_all (GSimpleAction *simple,
2002 GVariant *paramter,
2003 gpointer user_data)
2004{
2005 auto page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(user_data);
2006 Account *root = gnc_get_current_root_account ();
2007 GncWindow *window;
2008 gulong scrub_kp_handler_ID;
2009
2010 prepare_scrubbing ();
2011
2012 window = GNC_WINDOW(GNC_PLUGIN_PAGE (page)->window);
2013 scrub_kp_handler_ID = g_signal_connect (G_OBJECT(window), "key-press-event",
2014 G_CALLBACK(scrub_kp_handler), NULL);
2015 gnc_window_set_progressbar_window (window);
2016
2017 xaccAccountTreeScrubOrphans (root, gnc_window_show_progress);
2018 xaccAccountTreeScrubImbalance (root, gnc_window_show_progress);
2019 // XXX: Lots/capital gains scrubbing is disabled
2020 if (g_getenv("GNC_AUTO_SCRUB_LOTS") != NULL)
2021 xaccAccountTreeScrubLots(root);
2022
2023 gncScrubBusinessAccountTree(root, gnc_window_show_progress);
2024
2025 finish_scrubbing (window, scrub_kp_handler_ID);
2026}
2027
void xaccAccountCommitEdit(Account *acc)
ThexaccAccountCommitEdit() subroutine is the second phase of a two-phase-commit wrapper for account u...
Definition Account.cpp:1516
void xaccAccountDestroyAllTransactions(Account *acc)
Destroy all of the transactions that parent splits in an account.
Definition Account.cpp:1600
void xaccAccountBeginEdit(Account *acc)
The xaccAccountBeginEdit() subroutine is the first phase of a two-phase-commit wrapper for account up...
Definition Account.cpp:1475
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
void gnc_account_append_child(Account *new_parent, Account *child)
This function will remove from the child account any pre-existing parent relationship,...
Definition Account.cpp:2836
GNCAccountType xaccAccountGetType(const Account *acc)
Returns the account's account type.
Definition Account.cpp:3267
GList * gnc_account_get_descendants(const Account *account)
This routine returns a flat list of all of the accounts that are descendants of the specified account...
Definition Account.cpp:3044
GList * gnc_account_get_children(const Account *account)
This routine returns a GList of all children accounts of the specified account.
Definition Account.cpp:2960
#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
void xaccAccountDestroy(Account *acc)
The xaccAccountDestroy() routine can be used to get rid of an account.
Definition Account.cpp:1590
Account * gnc_account_get_parent(const Account *acc)
This routine returns a pointer to the parent of the specified account.
Definition Account.cpp:2935
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
gint gnc_account_n_children(const Account *account)
Return the number of children of the specified account.
Definition Account.cpp:2976
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Get the account's commodity
Definition Account.cpp:3408
gboolean qof_book_is_readonly(const QofBook *book)
Return whether the book is read only.
Definition qofbook.cpp:497
GSimpleActionGroup * gnc_plugin_page_create_action_group(GncPluginPage *page, const gchar *group_name)
Create the GSimpleActionGroup object 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.
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.
gboolean xaccAccountGetPlaceholder(const Account *acc)
Get the "placeholder" flag for an account.
Definition Account.cpp:4119
void xaccAccountMoveAllSplits(Account *accfrom, Account *accto)
The xaccAccountMoveAllSplits() routine reassigns each of the splits in accfrom to accto.
Definition Account.cpp:2196
const char * xaccTransGetReadOnly(Transaction *trans)
Returns a non-NULL value if this Transaction was marked as read-only with some specific "reason" text...
#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
GAction * gnc_main_window_find_action_in_group(GncMainWindow *window, const gchar *group_name, const gchar *action_name)
Find the GAction in a specific action group for window.
gboolean gnc_main_window_all_finish_pending(void)
Tell all pages in all windows to finish any outstanding activities.
gboolean gnc_main_window_button_press_cb(GtkWidget *whatever, GdkEventButton *event, GncPluginPage *page)
Callback function invoked when the user clicks in the content of any Gnucash window.
GAction * gnc_main_window_find_action(GncMainWindow *window, const gchar *action_name)
Find the GAction in the main window.
void gnc_main_window_init_short_names(GncMainWindow *window, GncToolBarShortNames *toolbar_labels)
Update the labels of the toolbar items with short names.
void gnc_main_window_open_page(GncMainWindow *window, GncPluginPage *page)
Display a data plugin page in a 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.
void gnc_plugin_page_account_tree_open(Account *account, GtkWindow *win)
Given a pointer to an account, the account tree will open and the account will be selected (if any).
Account * gnc_plugin_page_account_tree_get_current_account(GncPluginPageAccountTree *page)
Given a pointer to an account tree plugin page, return the selected account (if any).
GncPluginPage * gnc_plugin_page_account_tree_new(void)
Create a new "account tree" plugin page.
gint gnc_state_drop_sections_for(const gchar *partial_name)
Drop all sections from the state file whose name contains partial_name.
Definition gnc-state.c:260
GKeyFile * gnc_state_get_current(void)
Returns a pointer to the most recently loaded state.
Definition gnc-state.c:248
void gnc_tree_view_configure_columns(GncTreeView *view)
Make all the correct columns visible, respecting their default visibility setting,...
const gchar * gnc_tree_view_get_state_section(GncTreeView *view)
Get the name of the state section this tree view is associated with.
GtkTreeViewColumn * gnc_tree_view_find_column_by_name(GncTreeView *view, const gchar *wanted)
Find a tree column given the "pref name" used with saved state.
const GList * gnc_gobject_tracking_get_list(const gchar *name)
Get a list of all known objects of a specified type.
void gnc_ui_edit_account_window(GtkWindow *parent, Account *account)
Display a window for editing the attributes of an existing account.
void gnc_ui_new_account_window(GtkWindow *parent, QofBook *book, Account *parent_acct)
Display a window for creating a new account.
void gnc_tree_view_account_clear_model_cache(GncTreeViewAccount *view)
This function clears the tree model account cache so the values will be updated/refreshed.
void gnc_tree_view_account_set_editing_finished_cb(GncTreeViewAccount *view, GFunc editing_finished_cb, gpointer editing_cb_data)
Setup the callback for when the user finishes editing the account tree so actions can be enabled like...
void gnc_tree_view_account_refilter(GncTreeViewAccount *view)
This function forces the account tree filter to be evaluated.
Account * gnc_tree_view_account_get_account_from_path(GncTreeViewAccount *view, GtkTreePath *s_path)
This function returns the account associated with the specified path.
GtkTreeView * gnc_tree_view_account_new(gboolean show_root)
Create a new account tree view.
gboolean gnc_plugin_page_account_tree_filter_accounts(Account *account, gpointer user_data)
This function tells the account tree view whether or not to filter out a particular account.
Account * gnc_tree_view_account_get_selected_account(GncTreeViewAccount *view)
This function returns the account associated with the selected item in the account tree view.
void gnc_tree_view_account_set_selected_account(GncTreeViewAccount *view, Account *account)
This function selects an account in the account tree view.
void gnc_tree_view_account_set_editing_started_cb(GncTreeViewAccount *view, GFunc editing_started_cb, gpointer editing_cb_data)
Setup the callback for when the user starts editing the account tree so actions can be disabled like ...
void gnc_tree_view_account_set_filter(GncTreeViewAccount *view, gnc_tree_view_account_filter_func func, gpointer data, GSourceFunc destroy)
This function attaches a filter function to the given account tree.
gint gnc_list_length_cmp(const GList *list, size_t len)
Scans the GList elements the minimum number of iterations required to test it against a specified siz...
GList * qof_instance_get_referring_object_list(const QofInstance *inst)
Returns a list of objects which refer to a specific object.
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition qoflog.h:282
#define ENTER(format, args...)
Print a function entry debugging message.
Definition qoflog.h:272
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_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.
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Get a boolean value from the preferences backend.
GncPluginPage * gnc_plugin_page_register_new(Account *account, gboolean subaccounts)
Create a new "register" plugin page, given a pointer to an account.
void gncScrubBusinessAccountTree(Account *acc, QofPercentageFunc percentagefunc)
The gncScrubBusinessAccountTreeLots() function will call gncScrubBusinessAccount() on the given accou...
void gncScrubBusinessAccount(Account *acc, QofPercentageFunc percentagefunc)
The gncScrubBusinessAccount() function will call all scrub functions relevant for a given account on ...
gboolean gnc_get_ongoing_scrub(void)
The gnc_get_ongoing_scrub () method returns TRUE if a scrub operation is ongoing.
Definition Scrub.cpp:87
void xaccAccountScrubLots(Account *acc)
The xaccAccountScrubLots() routine makes sure that every split in the account is assigned to a lot,...
Definition Scrub3.cpp:159
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
void xaccAccountScrubOrphans(Account *acc, QofPercentageFunc percentagefunc)
The xaccAccountScrubOrphans() method performs this scrub only for the indicated account,...
Definition Scrub.cpp:167
void xaccAccountTreeScrubOrphans(Account *acc, QofPercentageFunc percentagefunc)
The xaccAccountTreeScrubOrphans() method performs this scrub for the indicated account and its childr...
Definition Scrub.cpp:173
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
STRUCTS.
The type used to store guids in C.
Definition guid.h:75
The class data structure for a content plugin.
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...
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.
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.

◆ GNC_PLUGIN_PAGE_ACCOUNT_TREE_NAME

#define GNC_PLUGIN_PAGE_ACCOUNT_TREE_NAME   "GncPluginPageAccountTree"

Definition at line 53 of file gnc-plugin-page-account-tree.h.

◆ GNC_TYPE_PLUGIN_PAGE_ACCOUNT_TREE

#define GNC_TYPE_PLUGIN_PAGE_ACCOUNT_TREE   (gnc_plugin_page_account_tree_get_type ())

Definition at line 46 of file gnc-plugin-page-account-tree.h.

◆ PLUGIN_PAGE_ACCT_TREE_CM_CLASS

#define PLUGIN_PAGE_ACCT_TREE_CM_CLASS   "plugin-page-acct-tree"

Definition at line 95 of file gnc-plugin-page-account-tree.cpp.

◆ STATE_SECTION

#define STATE_SECTION   "Account Hierarchy"

Definition at line 96 of file gnc-plugin-page-account-tree.cpp.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum

Definition at line 107 of file gnc-plugin-page-account-tree.cpp.

108{
109 ACCOUNT_SELECTED,
110 LAST_SIGNAL
111};

Function Documentation

◆ gnc_plugin_page_account_tree_get_current_account()

Account * gnc_plugin_page_account_tree_get_current_account ( GncPluginPageAccountTree page)

Given a pointer to an account tree plugin page, return the selected account (if any).

Parameters
pageThe "account tree" page.
Returns
The currently selected account. NULL if no account is selected.

Definition at line 518 of file gnc-plugin-page-account-tree.cpp.

519{
521 Account *account;
522
523 priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
524 ENTER("page %p (tree view %p)", page, priv->tree_view);
525 account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(priv->tree_view));
526 if (account == NULL)
527 {
528 LEAVE("no account");
529 return NULL;
530 }
531
532 LEAVE("account %p", account);
533 return account;
534}

◆ gnc_plugin_page_account_tree_get_type()

GType gnc_plugin_page_account_tree_get_type ( void  )

Retrieve the type number for an "account tree" plugin page.

Returns
The type number.

◆ gnc_plugin_page_account_tree_new()

GncPluginPage * gnc_plugin_page_account_tree_new ( void  )

Create a new "account tree" plugin page.

Returns
The newly created plugin page.

Definition at line 302 of file gnc-plugin-page-account-tree.cpp.

303{
304 ENTER(" ");
305 auto plugin_page = GNC_PLUGIN_PAGE_ACCOUNT_TREE
306 (g_object_new (GNC_TYPE_PLUGIN_PAGE_ACCOUNT_TREE, nullptr));
307
308 LEAVE("new account tree page %p", plugin_page);
309 return GNC_PLUGIN_PAGE (plugin_page);
310}

◆ gnc_plugin_page_account_tree_open()

void gnc_plugin_page_account_tree_open ( Account account,
GtkWindow *  win 
)

Given a pointer to an account, the account tree will open and the account will be selected (if any).

Parameters
accountThe "account" to be selected.
winThe "window" where the account tree is to be selected.

Definition at line 459 of file gnc-plugin-page-account-tree.cpp.

460{
463 GncPluginPage *plugin_page = NULL;
464 const GList *page_list;
465 GtkWidget *window;
466
467 /* Find Accounts page */
468 page_list = gnc_gobject_tracking_get_list(GNC_PLUGIN_PAGE_ACCOUNT_TREE_NAME);
469
470 // If we have a window, look for account page in that window
471 if (gnc_list_length_cmp (page_list, 0))
472 {
473 if (win != NULL)
474 {
475 for ( ; page_list; page_list = g_list_next(page_list))
476 {
477 plugin_page = GNC_PLUGIN_PAGE(page_list->data);
478 if (GTK_WINDOW(plugin_page->window) == win)
479 break;
480 }
481 }
482 else // if no window, open first account page in list
483 plugin_page = GNC_PLUGIN_PAGE(page_list->data);
484 }
485 else // we have no account pages, create one
486 plugin_page = gnc_plugin_page_account_tree_new ();
487
488 g_return_if_fail(plugin_page);
489 window = plugin_page->window;
490
491 gnc_main_window_open_page (GNC_MAIN_WINDOW(window), plugin_page);
492
493 page = GNC_PLUGIN_PAGE_ACCOUNT_TREE (plugin_page);
494 priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
495
496 if (account != NULL)
497 {
498 Account *root_account = gnc_get_current_root_account ();
499 Account *parent_account = NULL;
500 Account *temp_account = account;
501
502 g_hash_table_insert (priv->fd.filter_override, account, account);
503
504 // make sure we override all the parent accounts to root
505 while (parent_account != root_account)
506 {
507 parent_account = gnc_account_get_parent (temp_account);
508
509 g_hash_table_insert (priv->fd.filter_override, parent_account, parent_account);
510 temp_account = parent_account;
511 }
512 gnc_tree_view_account_refilter (GNC_TREE_VIEW_ACCOUNT(priv->tree_view));
513 gnc_tree_view_account_set_selected_account (GNC_TREE_VIEW_ACCOUNT(priv->tree_view), account);
514 }
515}

◆ gppat_populate_trans_mas_list()

void gppat_populate_trans_mas_list ( GtkToggleButton *  sa_mrb,
GtkWidget *  dialog 
)

Definition at line 1243 of file gnc-plugin-page-account-tree.cpp.

1245{
1246 g_return_if_fail(GTK_IS_DIALOG(dialog));
1247
1248 /* Cannot move transactions to subaccounts if they are to be deleted. */
1249 auto trans_mas = GTK_WIDGET(g_object_get_data(G_OBJECT(dialog), DELETE_DIALOG_TRANS_MAS));
1250 gppat_populate_gas_list(dialog, GNC_ACCOUNT_SEL(trans_mas), !gtk_toggle_button_get_active(sa_mrb));
1251}

◆ gppat_set_insensitive_iff_rb_active()

void gppat_set_insensitive_iff_rb_active ( GtkWidget *  widget,
GtkToggleButton *  b 
)

Definition at line 1259 of file gnc-plugin-page-account-tree.cpp.

1260{
1261 GtkWidget *dialog = gtk_widget_get_toplevel(widget);
1262 auto subaccount_trans = GTK_WIDGET(g_object_get_data(G_OBJECT(dialog), DELETE_DIALOG_SA_TRANS));
1263 auto sa_mas = GTK_WIDGET(g_object_get_data(G_OBJECT(dialog), DELETE_DIALOG_SA_MAS));
1264 auto have_splits = g_object_get_data(G_OBJECT(dialog), DELETE_DIALOG_SA_SPLITS) != nullptr;
1265
1266 gtk_widget_set_sensitive(widget, !gtk_toggle_button_get_active(b));
1267
1268 // If we have subaccount splits & delete subaccounts, enable subaccount_trans
1269 if ((have_splits) && !gtk_widget_is_sensitive(sa_mas))
1270 gtk_widget_set_sensitive(subaccount_trans, TRUE);
1271 else
1272 gtk_widget_set_sensitive(subaccount_trans, FALSE);
1273
1274 set_ok_sensitivity(dialog);
1275}