gnc-plugin-page-account-tree.c

Go to the documentation of this file.
00001 /* 
00002  * gnc-plugin-page-account-tree.c -- 
00003  *
00004  * Copyright (C) 2003 Jan Arne Petersen <jpetersen@uni-bonn.de>
00005  * Copyright (C) 2003,2005,2006 David Hampton <hampton@employees.org>
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License as
00009  * published by the Free Software Foundation; either version 2 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, contact:
00019  *
00020  * Free Software Foundation           Voice:  +1-617-542-5942
00021  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
00022  * Boston, MA  02110-1301,  USA       gnu@gnu.org
00023  */
00024 
00035 #include "config.h"
00036 
00037 #include <gtk/gtk.h>
00038 #include <glib/gi18n.h>
00039 #include "gnc-plugin-page-account-tree.h"
00040 #include "gnc-plugin-page-register.h"
00041 
00042 #include "Scrub.h"
00043 #include "Scrub3.h"
00044 #include "Transaction.h"
00045 #include "dialog-account.h"
00046 #include "dialog-transfer.h"
00047 #include "dialog-utils.h"
00048 #include "druid-hierarchy.h"
00049 #include "gnc-account-sel.h"
00050 #include "gnc-component-manager.h"
00051 #include "gnc-engine.h"
00052 #include "gnc-gconf-utils.h"
00053 #include "gnc-gnome-utils.h"
00054 #include "gnc-gobject-utils.h"
00055 #include "gnc-html.h"
00056 #include "gnc-icons.h"
00057 #include "gnc-plugin-account-tree.h"
00058 #include "gnc-session.h"
00059 #include "gnc-split-reg.h"
00060 #include "gnc-tree-view-account.h"
00061 #include "gnc-tree-model-account-types.h"
00062 #include "gnc-ui.h"
00063 #include "gnc-ui-util.h"
00064 #include "lot-viewer.h"
00065 #include "window-reconcile.h"
00066 #include "window-main-summarybar.h"
00067 
00068 /* This static indicates the debugging module that this .o belongs to.  */
00069 static QofLogModule log_module = GNC_MOD_GUI;
00070 
00071 #define PLUGIN_PAGE_ACCT_TREE_CM_CLASS "plugin-page-acct-tree"
00072 #define GCONF_SECTION "window/pages/account_tree"
00073 
00074 #define DELETE_DIALOG_FILTER  "filter"
00075 #define DELETE_DIALOG_ACCOUNT "account"
00076 
00077 enum {
00078   ACCOUNT_SELECTED,
00079   LAST_SIGNAL
00080 };
00081 
00082 typedef struct GncPluginPageAccountTreePrivate
00083 {
00084         GtkWidget   *widget;
00085         GtkTreeView *tree_view;
00086         gint         component_id;
00087         AccountFilterDialog fd;
00088 } GncPluginPageAccountTreePrivate;
00089 
00090 #define GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(o)  \
00091    (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_PLUGIN_PAGE_ACCOUNT_TREE, GncPluginPageAccountTreePrivate))
00092 
00093 static GObjectClass *parent_class = NULL;
00094 
00095 /************************************************************
00096  *                        Prototypes                        *
00097  ************************************************************/
00098 /* Plugin Actions */
00099 static void gnc_plugin_page_account_tree_class_init (GncPluginPageAccountTreeClass *klass);
00100 static void gnc_plugin_page_account_tree_init (GncPluginPageAccountTree *plugin_page);
00101 static void gnc_plugin_page_account_tree_finalize (GObject *object);
00102 
00103 static GtkWidget *gnc_plugin_page_account_tree_create_widget (GncPluginPage *plugin_page);
00104 static void gnc_plugin_page_account_tree_destroy_widget (GncPluginPage *plugin_page);
00105 static void gnc_plugin_page_account_tree_save_page (GncPluginPage *plugin_page, GKeyFile *file, const gchar *group);
00106 static GncPluginPage *gnc_plugin_page_account_tree_recreate_page (GtkWidget *window, GKeyFile *file, const gchar *group);
00107 
00108 /* Callbacks */
00109 static void gnc_plugin_page_account_tree_summarybar_position_changed(GConfEntry *entry,
00110                                                                      gpointer user_data);
00111 static gboolean gnc_plugin_page_account_tree_button_press_cb (GtkWidget *widget,
00112                                                               GdkEventButton *event,
00113                                                               GncPluginPage *page);
00114 static void gnc_plugin_page_account_tree_double_click_cb (GtkTreeView        *treeview,
00115                                                           GtkTreePath        *path,
00116                                                           GtkTreeViewColumn  *col,
00117                                                           GncPluginPageAccountTree *page);
00118 
00119 static void gnc_plugin_page_account_tree_selection_changed_cb (GtkTreeSelection *selection,
00120                                                                GncPluginPageAccountTree *page);
00121 void gppat_populate_tmas_list(GtkToggleButton *dmrb, gpointer tmas);
00122 void gppat_set_insensitive_iff_rb_active(GtkToggleButton *b, GtkWidget *widget);
00123 
00124 /* Command callbacks */
00125 static void gnc_plugin_page_account_tree_cmd_new_account (GtkAction *action, GncPluginPageAccountTree *plugin_page);
00126 static void gnc_plugin_page_account_tree_cmd_file_new_hierarchy (GtkAction *action, GncPluginPageAccountTree *plugin_page);
00127 static void gnc_plugin_page_account_tree_cmd_open_account (GtkAction *action, GncPluginPageAccountTree *page);
00128 static void gnc_plugin_page_account_tree_cmd_open_subaccounts (GtkAction *action, GncPluginPageAccountTree *page);
00129 static void gnc_plugin_page_account_tree_cmd_edit_account (GtkAction *action, GncPluginPageAccountTree *page);
00130 static void gnc_plugin_page_account_tree_cmd_delete_account (GtkAction *action, GncPluginPageAccountTree *page);
00131 static void gnc_plugin_page_account_tree_cmd_renumber_accounts (GtkAction *action, GncPluginPageAccountTree *page);
00132 static void gnc_plugin_page_account_tree_cmd_view_filter_by (GtkAction *action, GncPluginPageAccountTree *plugin_page);
00133 static void gnc_plugin_page_account_tree_cmd_reconcile (GtkAction *action, GncPluginPageAccountTree *page);
00134 static void gnc_plugin_page_account_tree_cmd_transfer (GtkAction *action, GncPluginPageAccountTree *page);
00135 static void gnc_plugin_page_account_tree_cmd_stock_split (GtkAction *action, GncPluginPageAccountTree *page);
00136 static void gnc_plugin_page_account_tree_cmd_lots (GtkAction *action, GncPluginPageAccountTree *page);
00137 static void gnc_plugin_page_account_tree_cmd_scrub (GtkAction *action, GncPluginPageAccountTree *page);
00138 static void gnc_plugin_page_account_tree_cmd_scrub_sub (GtkAction *action, GncPluginPageAccountTree *page);
00139 static void gnc_plugin_page_account_tree_cmd_scrub_all (GtkAction *action, GncPluginPageAccountTree *page);
00140 
00141 
00142 static guint plugin_page_signals[LAST_SIGNAL] = { 0 };
00143 
00144 
00145 static GtkActionEntry gnc_plugin_page_account_tree_actions [] = {
00146         /* Toplevel */
00147         { "FakeToplevel", NULL, "", NULL, NULL, NULL },
00148 
00149         /* File menu */
00150         { "FileNewAccountAction", GNC_STOCK_NEW_ACCOUNT, N_("New _Account..."), NULL,
00151           N_("Create a new Account"),
00152           G_CALLBACK (gnc_plugin_page_account_tree_cmd_new_account) },
00153         { "FileAddAccountHierarchyDruidAction", GNC_STOCK_NEW_ACCOUNT, N_("New Account _Hierarchy..."), NULL,
00154           N_("Extend the current book by merging with new account type categories"),
00155           G_CALLBACK (gnc_plugin_page_account_tree_cmd_file_new_hierarchy) },
00156         { "FileOpenAccountAction", GNC_STOCK_OPEN_ACCOUNT, N_("Open _Account"), NULL,
00157           N_("Open the selected account"),
00158           G_CALLBACK (gnc_plugin_page_account_tree_cmd_open_account) },
00159         { "FileOpenSubaccountsAction", GNC_STOCK_OPEN_ACCOUNT, N_("Open _Subaccounts"), NULL,
00160           N_("Open the selected account and all its subaccounts"),
00161           G_CALLBACK (gnc_plugin_page_account_tree_cmd_open_subaccounts) },
00162 
00163         /* Edit menu */
00164         { "EditEditAccountAction", GNC_STOCK_EDIT_ACCOUNT, N_("Edit _Account"), "<control>e",
00165           N_("Edit the selected account"),
00166           G_CALLBACK (gnc_plugin_page_account_tree_cmd_edit_account) },
00167         { "EditDeleteAccountAction", GNC_STOCK_DELETE_ACCOUNT, N_("_Delete Account..."), "Delete",
00168           N_("Delete selected account"),
00169           G_CALLBACK (gnc_plugin_page_account_tree_cmd_delete_account) },
00170         { "EditRenumberSubaccountsAction", NULL, N_("_Renumber Subaccounts..."), NULL,
00171           N_("Renumber the children of the selected account"),
00172           G_CALLBACK (gnc_plugin_page_account_tree_cmd_renumber_accounts) },
00173 
00174         /* View menu */
00175         { "ViewFilterByAction", NULL, N_("_Filter By..."), NULL, NULL,
00176           G_CALLBACK (gnc_plugin_page_account_tree_cmd_view_filter_by) },
00177 
00178         /* Actions menu */
00179         { "ActionsReconcileAction", NULL, N_("_Reconcile..."), NULL,
00180           N_("Reconcile the selected account"),
00181           G_CALLBACK (gnc_plugin_page_account_tree_cmd_reconcile) },
00182         { "ActionsTransferAction", NULL, N_("_Transfer..."), "<control>t",
00183           N_("Transfer funds from one account to another"),
00184           G_CALLBACK (gnc_plugin_page_account_tree_cmd_transfer) },
00185         { "ActionsStockSplitAction", NULL, N_("Stoc_k Split..."), NULL,
00186           N_("Record a stock split or a stock merger"),
00187           G_CALLBACK (gnc_plugin_page_account_tree_cmd_stock_split) },
00188         { "ActionsLotsAction", NULL, N_("View _Lots..."), NULL,
00189           N_("Bring up the lot viewer/editor window"),
00190           G_CALLBACK (gnc_plugin_page_account_tree_cmd_lots) },
00191         { "ScrubAction", NULL, N_("Check & Repair A_ccount"), NULL,
00192           N_("Check for and repair unbalanced transactions and orphan splits " "in this account"),
00193           G_CALLBACK (gnc_plugin_page_account_tree_cmd_scrub) },
00194         { "ScrubSubAction", NULL, N_("Check & Repair Su_baccounts"), NULL,
00195           N_("Check for and repair unbalanced transactions and orphan splits "
00196              "in this account and its subaccounts"),
00197           G_CALLBACK (gnc_plugin_page_account_tree_cmd_scrub_sub) },
00198         { "ScrubAllAction", NULL, N_("Check & Repair A_ll"), NULL,
00199           N_("Check for and repair unbalanced transactions and orphan splits " "in all accounts"),
00200           G_CALLBACK (gnc_plugin_page_account_tree_cmd_scrub_all) },
00201 };
00203 static guint gnc_plugin_page_account_tree_n_actions = G_N_ELEMENTS (gnc_plugin_page_account_tree_actions);
00204 
00205 
00208 static const gchar *actions_requiring_account[] = {
00209         "FileOpenAccountAction",
00210         "FileOpenSubaccountsAction",
00211         "EditEditAccountAction",
00212         "EditDeleteAccountAction",
00213         "ActionsReconcileAction",
00214         "ActionsLotsAction",
00215         NULL
00216 };
00217 
00218 
00220 static action_toolbar_labels toolbar_labels[] = {
00221   { "FileOpenAccountAction",        N_("Open") },
00222   { "EditEditAccountAction",        N_("Edit") },
00223   { "FileNewAccountAction",         N_("New") },
00224   { "EditDeleteAccountAction",      N_("Delete") },
00225   { NULL, NULL },
00226 };
00227 
00228 
00229 GType
00230 gnc_plugin_page_account_tree_get_type (void)
00231 {
00232         static GType gnc_plugin_page_account_tree_type = 0;
00233 
00234         if (gnc_plugin_page_account_tree_type == 0) {
00235                 static const GTypeInfo our_info = {
00236                         sizeof (GncPluginPageAccountTreeClass),
00237                         NULL,
00238                         NULL,
00239                         (GClassInitFunc) gnc_plugin_page_account_tree_class_init,
00240                         NULL,
00241                         NULL,
00242                         sizeof (GncPluginPageAccountTree),
00243                         0,
00244                         (GInstanceInitFunc) gnc_plugin_page_account_tree_init
00245                 };
00246                 
00247                 gnc_plugin_page_account_tree_type = g_type_register_static (GNC_TYPE_PLUGIN_PAGE,
00248                                                                             GNC_PLUGIN_PAGE_ACCOUNT_TREE_NAME,
00249                                                                             &our_info, 0);
00250         }
00251 
00252         return gnc_plugin_page_account_tree_type;
00253 }
00254 
00255 GncPluginPage *
00256 gnc_plugin_page_account_tree_new (void)
00257 {
00258         GncPluginPageAccountTree *plugin_page;
00259 
00260         ENTER(" ");
00261         plugin_page = g_object_new (GNC_TYPE_PLUGIN_PAGE_ACCOUNT_TREE,
00262                               NULL);
00263 
00264         LEAVE("new account tree page %p", plugin_page);
00265         return GNC_PLUGIN_PAGE (plugin_page);
00266 }
00267 
00268 static void
00269 gnc_plugin_page_account_tree_class_init (GncPluginPageAccountTreeClass *klass)
00270 {
00271         GObjectClass *object_class = G_OBJECT_CLASS (klass);
00272         GncPluginPageClass *gnc_plugin_class = GNC_PLUGIN_PAGE_CLASS(klass);
00273 
00274         parent_class = g_type_class_peek_parent (klass);
00275 
00276         object_class->finalize = gnc_plugin_page_account_tree_finalize;
00277 
00278         gnc_plugin_class->tab_icon        = GNC_STOCK_ACCOUNT;
00279         gnc_plugin_class->plugin_name     = GNC_PLUGIN_PAGE_ACCOUNT_TREE_NAME;
00280         gnc_plugin_class->create_widget   = gnc_plugin_page_account_tree_create_widget;
00281         gnc_plugin_class->destroy_widget  = gnc_plugin_page_account_tree_destroy_widget;
00282         gnc_plugin_class->save_page       = gnc_plugin_page_account_tree_save_page;
00283         gnc_plugin_class->recreate_page   = gnc_plugin_page_account_tree_recreate_page;
00284 
00285         g_type_class_add_private(klass, sizeof(GncPluginPageAccountTreePrivate));
00286 
00287         plugin_page_signals[ACCOUNT_SELECTED] =
00288           g_signal_new ("account_selected",
00289                         G_OBJECT_CLASS_TYPE (object_class),
00290                         G_SIGNAL_RUN_FIRST,
00291                         G_STRUCT_OFFSET (GncPluginPageAccountTreeClass, account_selected),
00292                         NULL, NULL,
00293                         g_cclosure_marshal_VOID__POINTER,
00294                         G_TYPE_NONE, 1,
00295                         G_TYPE_POINTER);
00296 }
00297 
00298 static void
00299 gnc_plugin_page_account_tree_init (GncPluginPageAccountTree *plugin_page)
00300 {
00301         GtkActionGroup *action_group;
00302         GncPluginPageAccountTreePrivate *priv;
00303         GncPluginPage *parent;
00304         const GList *page_list;
00305 
00306         ENTER("page %p", plugin_page);
00307         priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(plugin_page);
00308 
00309         /* Init parent declared variables */
00310         parent = GNC_PLUGIN_PAGE(plugin_page);
00311         g_object_set(G_OBJECT(plugin_page),
00312                      "page-name",      _("Accounts"),
00313                      "page-uri",       "default:",
00314                      "ui-description", "gnc-plugin-page-account-tree-ui.xml",
00315                      NULL);
00316 
00317         /* change me when the system supports multiple books */
00318         gnc_plugin_page_add_book(parent, gnc_get_current_book());
00319 
00320         /* Is this the first accounts page? */
00321         page_list =
00322           gnc_gobject_tracking_get_list(GNC_PLUGIN_PAGE_ACCOUNT_TREE_NAME);
00323         if (plugin_page == page_list->data) {
00324           g_object_set_data(G_OBJECT(plugin_page), PLUGIN_PAGE_IMMUTABLE,
00325                             GINT_TO_POINTER(1));
00326         }
00327 
00328         /* Create menu and toolbar information */
00329         action_group =
00330           gnc_plugin_page_create_action_group(parent,
00331                                               "GncPluginPageAccountTreeActions");
00332         gtk_action_group_add_actions(action_group,
00333                                      gnc_plugin_page_account_tree_actions,
00334                                      gnc_plugin_page_account_tree_n_actions,
00335                                      plugin_page);
00336         gnc_plugin_init_short_names (action_group, toolbar_labels);
00337 
00338         /* Visisble types */
00339         priv->fd.visible_types = -1; /* Start with all types */
00340         priv->fd.show_hidden = FALSE;
00341         priv->fd.show_zero_total = TRUE;
00342         
00343         LEAVE("page %p, priv %p, action group %p",
00344               plugin_page, priv, action_group);
00345 }
00346 
00347 static void
00348 gnc_plugin_page_account_tree_finalize (GObject *object)
00349 {
00350         GncPluginPageAccountTree *page;
00351         GncPluginPageAccountTreePrivate *priv;
00352 
00353         ENTER("object %p", object);
00354         page = GNC_PLUGIN_PAGE_ACCOUNT_TREE (object);
00355         g_return_if_fail (GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE (page));
00356         priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
00357         g_return_if_fail (priv != NULL);
00358 
00359         G_OBJECT_CLASS (parent_class)->finalize (object);
00360         LEAVE(" ");
00361 }
00362 
00363 Account *
00364 gnc_plugin_page_account_tree_get_current_account (GncPluginPageAccountTree *page)
00365 {
00366         GncPluginPageAccountTreePrivate *priv;
00367         Account *account;
00368 
00369         priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
00370         ENTER("page %p (tree view %p)", page, priv->tree_view);
00371         account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(priv->tree_view));
00372         if (account == NULL) {
00373                 LEAVE("no account");
00374                 return NULL;
00375         }
00376 
00377         LEAVE("account %p", account);
00378         return account;
00379 }
00380 
00381 
00382 /* Virtual Functions */
00383 
00384 static void
00385 gnc_plugin_page_account_refresh_cb (GHashTable *changes, gpointer user_data)
00386 {
00387   GncPluginPageAccountTree *page = user_data;
00388   GncPluginPageAccountTreePrivate *priv;
00389 
00390   g_return_if_fail(GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE(page));
00391 
00392   /* We're only looking for forced updates here. */
00393   if (changes)
00394     return;
00395 
00396   priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
00397   gtk_widget_queue_draw(priv->widget);
00398 }
00399 
00400 static void
00401 gnc_plugin_page_account_tree_close_cb (gpointer user_data)
00402 {
00403   GncPluginPage *plugin_page;
00404   GncPluginPageAccountTree *page;
00405 
00406   plugin_page = GNC_PLUGIN_PAGE(user_data);
00407   page = GNC_PLUGIN_PAGE_ACCOUNT_TREE (plugin_page);
00408   gnc_main_window_close_page(plugin_page);
00409 }
00410 
00411 static GtkWidget *
00412 gnc_plugin_page_account_tree_create_widget (GncPluginPage *plugin_page)
00413 {
00414         GncPluginPageAccountTree *page;
00415         GncPluginPageAccountTreePrivate *priv;
00416         GtkTreeSelection *selection;
00417         GtkTreeView *tree_view;
00418         GtkWidget *scrolled_window;
00419         GtkTreeViewColumn *col;
00420 
00421         ENTER("page %p", plugin_page);
00422         page = GNC_PLUGIN_PAGE_ACCOUNT_TREE (plugin_page);
00423         priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
00424         if (priv->widget != NULL) {
00425                 LEAVE("widget = %p", priv->widget);
00426                 return priv->widget;
00427         }
00428 
00429         priv->widget = gtk_vbox_new (FALSE, 0);
00430         gtk_widget_show (priv->widget);
00431 
00432         scrolled_window = gtk_scrolled_window_new (NULL, NULL);
00433         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
00434                                         GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
00435         gtk_widget_show (scrolled_window);
00436         gtk_box_pack_start (GTK_BOX (priv->widget), scrolled_window,
00437                             TRUE, TRUE, 0);
00438 
00439         tree_view = gnc_tree_view_account_new(FALSE);
00440         col = gnc_tree_view_find_column_by_name(
00441             GNC_TREE_VIEW(tree_view), "description");
00442         g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1));
00443         col = gnc_tree_view_find_column_by_name(
00444             GNC_TREE_VIEW(tree_view), "total");
00445         g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1));
00446         gnc_tree_view_configure_columns(GNC_TREE_VIEW(tree_view));
00447         g_object_set(G_OBJECT(tree_view),
00448                      "gconf-section", GCONF_SECTION,
00449                      "show-column-menu", TRUE,
00450                      NULL);
00451 
00452         /* No name handler; then the user can't click on the name of the
00453            account to open its register. */
00454         gnc_tree_view_account_set_code_edited(GNC_TREE_VIEW_ACCOUNT(tree_view),
00455                                               gnc_tree_view_account_code_edited_cb);
00456         gnc_tree_view_account_set_description_edited(GNC_TREE_VIEW_ACCOUNT(tree_view),
00457                                                      gnc_tree_view_account_description_edited_cb);
00458         gnc_tree_view_account_set_notes_edited(GNC_TREE_VIEW_ACCOUNT(tree_view),
00459                                                gnc_tree_view_account_notes_edited_cb);
00460 
00461         priv->tree_view = tree_view;
00462         selection = gtk_tree_view_get_selection(tree_view);
00463         g_signal_connect (G_OBJECT (selection), "changed",
00464                           G_CALLBACK (gnc_plugin_page_account_tree_selection_changed_cb), page);
00465         g_signal_connect (G_OBJECT (tree_view), "button-press-event",
00466                           G_CALLBACK (gnc_plugin_page_account_tree_button_press_cb), page);
00467         g_signal_connect (G_OBJECT (tree_view), "row-activated",
00468                           G_CALLBACK (gnc_plugin_page_account_tree_double_click_cb), page);
00469 
00470         gtk_tree_view_set_headers_visible(tree_view, TRUE);
00471         gnc_plugin_page_account_tree_selection_changed_cb (NULL, page);
00472         gtk_widget_show (GTK_WIDGET (tree_view));
00473         gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET(tree_view));
00474 
00475         priv->fd.tree_view = GNC_TREE_VIEW_ACCOUNT(priv->tree_view);
00476         gnc_tree_view_account_set_filter (
00477             GNC_TREE_VIEW_ACCOUNT(tree_view),
00478             gnc_plugin_page_account_tree_filter_accounts, &priv->fd, NULL);
00479 
00480         priv->component_id =
00481           gnc_register_gui_component(PLUGIN_PAGE_ACCT_TREE_CM_CLASS,
00482                                      gnc_plugin_page_account_refresh_cb,
00483                                      gnc_plugin_page_account_tree_close_cb,
00484                                      page);
00485         gnc_gui_component_set_session (priv->component_id,
00486                                        gnc_get_current_session());
00487 
00488         plugin_page->summarybar = gnc_main_window_summary_new();
00489         gtk_box_pack_start (GTK_BOX (priv->widget), plugin_page->summarybar,
00490                             FALSE, FALSE, 0);
00491         gtk_widget_show(plugin_page->summarybar);
00492         gnc_plugin_page_account_tree_summarybar_position_changed(NULL, page);
00493         gnc_gconf_general_register_cb(KEY_SUMMARYBAR_POSITION,
00494                 gnc_plugin_page_account_tree_summarybar_position_changed,
00495                 page);
00496 
00497         LEAVE("widget = %p", priv->widget);
00498         return priv->widget;
00499 }
00500 
00501 static void
00502 gnc_plugin_page_account_tree_destroy_widget (GncPluginPage *plugin_page)
00503 {
00504         GncPluginPageAccountTree *page;
00505         GncPluginPageAccountTreePrivate *priv;
00506 
00507         ENTER("page %p", plugin_page);
00508         page = GNC_PLUGIN_PAGE_ACCOUNT_TREE (plugin_page);
00509         priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
00510 
00511         gnc_gconf_general_remove_cb(KEY_SUMMARYBAR_POSITION,
00512                 gnc_plugin_page_account_tree_summarybar_position_changed,
00513                 page);
00514 
00515         if (priv->widget) {
00516           g_object_unref(G_OBJECT(priv->widget));
00517           priv->widget = NULL;
00518         }
00519 
00520         if (priv->component_id) {
00521           gnc_unregister_gui_component(priv->component_id);
00522           priv->component_id = 0;
00523         }
00524 
00525         LEAVE("widget destroyed");
00526 }
00527 
00537 static void
00538 gnc_plugin_page_account_tree_save_page (GncPluginPage *plugin_page,
00539                                         GKeyFile *key_file,
00540                                         const gchar *group_name)
00541 {
00542         GncPluginPageAccountTree *account_page;
00543         GncPluginPageAccountTreePrivate *priv;
00544         
00545         g_return_if_fail (GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE(plugin_page));
00546         g_return_if_fail (key_file != NULL);
00547         g_return_if_fail (group_name != NULL);
00548 
00549         ENTER("page %p, key_file %p, group_name %s", plugin_page, key_file,
00550               group_name);
00551 
00552         account_page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(plugin_page);
00553         priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(account_page);
00554 
00555         gnc_tree_view_account_save(GNC_TREE_VIEW_ACCOUNT(priv->tree_view), 
00556                                    &priv->fd, key_file, group_name);
00557         LEAVE(" ");
00558 }
00559 
00560 
00561 
00571 static GncPluginPage *
00572 gnc_plugin_page_account_tree_recreate_page (GtkWidget *window,
00573                                             GKeyFile *key_file,
00574                                             const gchar *group_name)
00575 {
00576         GncPluginPageAccountTree *account_page;
00577         GncPluginPageAccountTreePrivate *priv;
00578         GncPluginPage *page;
00579         
00580         g_return_val_if_fail(key_file, NULL);
00581         g_return_val_if_fail(group_name, NULL);
00582         ENTER("key_file %p, group_name %s", key_file, group_name);
00583 
00584         /* Create the new page. */
00585         page = gnc_plugin_page_account_tree_new();
00586         account_page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(page);
00587         priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(account_page);
00588 
00589         /* Install it now so we can then manipulate the created widget */
00590         gnc_main_window_open_page(GNC_MAIN_WINDOW(window), page);
00591 
00592         gnc_tree_view_account_restore(GNC_TREE_VIEW_ACCOUNT(priv->tree_view), 
00593                                       &priv->fd, key_file, group_name);
00594         LEAVE(" ");
00595         return page;
00596 }
00597 
00598 
00599 /* Callbacks */
00600 
00601 static void
00602 gnc_plugin_page_account_tree_summarybar_position_changed(GConfEntry *entry,
00603                                                          gpointer user_data)
00604 {
00605         GncPluginPage *plugin_page;
00606         GncPluginPageAccountTree *page;
00607         GncPluginPageAccountTreePrivate *priv;
00608         GtkPositionType position = GTK_POS_BOTTOM;
00609         gchar *conf_string;
00610         
00611         g_return_if_fail(user_data != NULL);
00612         
00613         plugin_page = GNC_PLUGIN_PAGE(user_data);
00614         page = GNC_PLUGIN_PAGE_ACCOUNT_TREE (user_data);
00615         priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
00616         
00617         conf_string = gnc_gconf_get_string (GCONF_GENERAL,
00618                                             KEY_SUMMARYBAR_POSITION, NULL);
00619         if (conf_string) {
00620                 position = gnc_enum_from_nick (GTK_TYPE_POSITION_TYPE,
00621                                                conf_string, GTK_POS_BOTTOM);
00622                 g_free (conf_string);
00623         }
00624 
00625         gtk_box_reorder_child(GTK_BOX(priv->widget),
00626                               plugin_page->summarybar,
00627                               (position == GTK_POS_TOP ? 0 : -1) );
00628 }
00629 
00637 static gboolean
00638 gnc_plugin_page_account_tree_button_press_cb (GtkWidget *widget,
00639                                               GdkEventButton *event,
00640                                               GncPluginPage *page)
00641 {
00642   gboolean result;
00643 
00644   g_return_val_if_fail(GNC_IS_PLUGIN_PAGE(page), FALSE);
00645 
00646   ENTER("widget %p, event %p, page %p", widget, event, page);
00647   result = gnc_main_window_button_press_cb(widget, event, page);
00648   LEAVE(" ");
00649 
00650   /* Always return FALSE.  This will let the tree view callback run as
00651    * well which will select the item under the cursor.  By the time
00652    * the user sees the menu both callbacks will have run and the menu
00653    * actions will operate on the just-selected account. */
00654   return FALSE;
00655 }
00656 
00657 static void
00658 gppat_open_account_common (GncPluginPageAccountTree *page,
00659                            Account *account,
00660                            gboolean include_subs)
00661 {
00662         GncPluginPageAccountTreePrivate *priv;
00663         GtkWidget *window;
00664         GncPluginPage *new_page;
00665 
00666         if (account == NULL)
00667           return;
00668 
00669         priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
00670         window = GNC_PLUGIN_PAGE (page)->window;
00671         new_page = gnc_plugin_page_register_new (account, include_subs);
00672         gnc_main_window_open_page (GNC_MAIN_WINDOW(window), new_page);
00673 }
00674 
00675 static void
00676 gnc_plugin_page_account_tree_double_click_cb (GtkTreeView        *treeview,
00677                                               GtkTreePath        *path,
00678                                               GtkTreeViewColumn  *col,
00679                                               GncPluginPageAccountTree *page)
00680 {
00681         Account *account;
00682 
00683         g_return_if_fail (GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE (page));
00684         account = gnc_tree_view_account_get_account_from_path (GNC_TREE_VIEW_ACCOUNT(treeview), path);
00685         gppat_open_account_common (page, account, FALSE);
00686 }
00687 
00688 static void
00689 gnc_plugin_page_account_tree_selection_changed_cb (GtkTreeSelection *selection,
00690                                                    GncPluginPageAccountTree *page)
00691 {
00692         GtkActionGroup *action_group;
00693         GtkAction *action;
00694         GtkTreeView *view;
00695         Account *account = NULL;
00696         gboolean sensitive;
00697         gboolean subaccounts;
00698 
00699         g_return_if_fail(GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE(page));
00700 
00701         if (!selection) {
00702                 sensitive = FALSE;
00703                 subaccounts = FALSE;
00704         } else {
00705                 g_return_if_fail(GTK_IS_TREE_SELECTION(selection));
00706                 view = gtk_tree_selection_get_tree_view (selection);
00707                 account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(view));
00708                 sensitive = (account != NULL);
00709 
00710                 subaccounts = account && (gnc_account_n_children(account) != 0);
00711                 /* Check here for placeholder accounts, etc. */
00712         }
00713 
00714         action_group = gnc_plugin_page_get_action_group(GNC_PLUGIN_PAGE(page));
00715         gnc_plugin_update_actions (action_group, actions_requiring_account,
00716                                    "sensitive", sensitive);
00717         g_signal_emit (page, plugin_page_signals[ACCOUNT_SELECTED], 0, account);
00718 
00719         action = gtk_action_group_get_action (action_group, "EditRenumberSubaccountsAction");
00720         g_object_set (G_OBJECT(action), "sensitive",
00721                       sensitive && subaccounts, NULL);
00722 
00723         gnc_plugin_update_actions (action_group, actions_requiring_account,
00724                                    "sensitive", sensitive);
00725 }
00726         
00727 
00728 /* Command callbacks */
00729 static void
00730 gnc_plugin_page_account_tree_cmd_new_account (GtkAction *action, GncPluginPageAccountTree *page)
00731 {
00732         Account *account = gnc_plugin_page_account_tree_get_current_account (page);
00733 
00734         gnc_ui_new_account_window (gnc_get_current_book(), account);
00735 }
00736 
00737 static void
00738 gnc_plugin_page_account_tree_cmd_file_new_hierarchy (GtkAction *action, GncPluginPageAccountTree *page)
00739 {
00740         gnc_ui_hierarchy_druid(FALSE);
00741 }
00742 
00743 static void
00744 gnc_plugin_page_account_tree_cmd_open_account (GtkAction *action,
00745                                                GncPluginPageAccountTree *page)
00746 {
00747         Account *account;
00748 
00749         g_return_if_fail (GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE (page));
00750         account = gnc_plugin_page_account_tree_get_current_account (page);
00751         gppat_open_account_common (page, account, FALSE);
00752 }
00753 
00754 static void
00755 gnc_plugin_page_account_tree_cmd_open_subaccounts (GtkAction *action,
00756                                                    GncPluginPageAccountTree *page)
00757 {
00758         Account *account;
00759 
00760         g_return_if_fail (GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE (page));
00761         account = gnc_plugin_page_account_tree_get_current_account (page);
00762         gppat_open_account_common (page, account, TRUE);
00763 }
00764 
00765 static void
00766 gnc_plugin_page_account_tree_cmd_edit_account (GtkAction *action, GncPluginPageAccountTree *page)
00767 {
00768         Account *account;
00769 
00770         ENTER("action %p, page %p", action, page);
00771 
00772         account = gnc_plugin_page_account_tree_get_current_account (page);
00773         g_return_if_fail (account != NULL);
00774 
00775         gnc_ui_edit_account_window (account);
00776         LEAVE(" ");
00777 }
00778 
00779 /********************************************************************
00780  * delete_account_helper
00781  * See if this account has any splits present.  Set the user data
00782  * and return the same value to stop walking the account tree if
00783  * appropriate.
00784  ********************************************************************/
00785 typedef struct _delete_helper
00786 {
00787         gboolean has_splits;
00788         gboolean has_ro_splits;
00789 } delete_helper_t;
00790 
00791 static gpointer
00792 delete_account_helper (Account * account, gpointer data)
00793 {
00794         delete_helper_t *helper_res = data;
00795         GList *splits;
00796 
00797         splits = xaccAccountGetSplitList (account);
00798         if (splits) {
00799                 helper_res->has_splits = TRUE;
00800                 while (splits) {
00801                         Split *s = splits->data;
00802                         Transaction *txn = xaccSplitGetParent (s);
00803                         if (xaccTransGetReadOnly (txn)) {
00804                                 helper_res->has_ro_splits = TRUE;
00805                                 break;
00806                         }
00807                         splits = splits->next;
00808                 }
00809         }
00810 
00811         return GINT_TO_POINTER (helper_res->has_splits || helper_res->has_ro_splits);
00812 }
00813 
00814 /***
00815  *** The OK button of a Delete Account dialog is insensitive if
00816  *** and only if a sensitive account selector contains no accounts.
00817  ***/
00818 static void
00819 set_ok_sensitivity(GtkWidget *dialog)
00820 {
00821   GtkWidget *button;
00822   gpointer dmas, tmas;
00823   gint dmas_cnt, tmas_cnt;
00824   gboolean sensitive;
00825 
00826   dmas = g_object_get_data(G_OBJECT(dialog), "dmas");
00827   tmas = g_object_get_data(G_OBJECT(dialog), "tmas");
00828   dmas_cnt = gnc_account_sel_get_num_account(GNC_ACCOUNT_SEL(dmas));
00829   tmas_cnt = gnc_account_sel_get_num_account(GNC_ACCOUNT_SEL(tmas));
00830 
00831   sensitive = (((NULL == dmas) ||
00832                 (!GTK_WIDGET_IS_SENSITIVE(GTK_WIDGET(dmas)) || dmas_cnt)) &&
00833                ((NULL == tmas) ||
00834                 (!GTK_WIDGET_IS_SENSITIVE(GTK_WIDGET(tmas)) || tmas_cnt)));
00835 
00836   button = gnc_glade_lookup_widget(dialog, "deletebutton");
00837   gtk_widget_set_sensitive(button, sensitive);
00838 }
00839 
00840 static void
00841 gppat_populate_gas_list(GtkWidget *dialog,
00842                         GNCAccountSel *gas,
00843                         gboolean exclude_subaccounts)
00844 {
00845   Account *account;
00846   GList *filter;
00847 
00848   g_return_if_fail(GTK_IS_DIALOG(dialog));
00849   if (gas == NULL)
00850     return;
00851   account = g_object_get_data(G_OBJECT(dialog), DELETE_DIALOG_ACCOUNT);
00852   filter = g_object_get_data(G_OBJECT(dialog), DELETE_DIALOG_FILTER);
00853 
00854   /* Setting the account type filter triggers GNCAccountSel population. */
00855   gnc_account_sel_set_acct_filters (gas, filter);
00856 
00857   /* Accounts to be deleted must be removed. */
00858   gnc_account_sel_purge_account( gas, account, exclude_subaccounts);
00859 
00860   /* The sensitivity of the OK button needs to be reevaluated. */
00861   set_ok_sensitivity(GTK_WIDGET(dialog));
00862 }
00863 
00864 void
00865 gppat_populate_tmas_list(GtkToggleButton *damrb,
00866                          gpointer tmas)
00867 {
00868   GtkWidget *dialog;
00869 
00870   /* Cannot move transactions to subaccounts if they are to be deleted. */
00871   dialog = gnc_glade_lookup_widget(GTK_WIDGET(damrb), "Delete Account");
00872   gppat_populate_gas_list(dialog, tmas, !gtk_toggle_button_get_active(damrb));
00873 }
00874 
00875 void
00876 gppat_set_insensitive_iff_rb_active(GtkToggleButton *b, GtkWidget *widget)
00877 {
00878   gtk_widget_set_sensitive(widget, !gtk_toggle_button_get_active(b));
00879   set_ok_sensitivity(gtk_widget_get_toplevel(widget));
00880 }
00881 
00882 static void
00883 gnc_plugin_page_account_tree_cmd_delete_account (GtkAction *action, GncPluginPageAccountTree *page)
00884 {
00885   Account *account = gnc_plugin_page_account_tree_get_current_account (page);
00886   gchar *acct_name;
00887   GList *splits;
00888   delete_helper_t delete_res = { FALSE, FALSE };
00889   GtkWidget *widget;
00890   GtkWidget *window;
00891   GtkWidget *dialog = NULL;
00892   GNCAccountSel *damas = NULL; /* descendant account move account selector */
00893   GNCAccountSel *dtmas = NULL; /* descendant transaction move account selector */
00894   GNCAccountSel *tmas = NULL; /* transaction move account selector */
00895   gint response;
00896   Account *ta = NULL; /* transaction adopter */
00897   Account *daa = NULL; /* descendant account adopter */
00898   Account *dta = NULL; /* descendant transaction adopter */
00899 
00900   if (NULL == account)
00901     return;
00902 
00903   window = gnc_plugin_page_get_window(GNC_PLUGIN_PAGE(page));
00904   acct_name = xaccAccountGetFullName(account);
00905   if (!acct_name) {
00906     acct_name = g_strdup (_("(no name)"));
00907   }
00908 
00909   splits = xaccAccountGetSplitList(account);
00910 
00911   /*
00912    * If the account has transactions or child accounts then conduct a
00913    * dialog to allow the user to specify what should be done with them.
00914    */
00915   if ((NULL != splits) || (gnc_account_n_children(account) > 0)) {
00916     GList *filter;
00917     GladeXML *xml;
00918     GtkWidget *label;
00919     gchar *message;
00920 
00921     xml = gnc_glade_xml_new ("account.glade", "Delete Account");
00922     dialog = glade_xml_get_widget (xml, "Delete Account");
00923     gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(window));
00924     glade_xml_signal_autoconnect_full(xml, gnc_glade_autoconnect_full_func, dialog);
00925 
00926     label = glade_xml_get_widget (xml, "header");
00927     message = g_strdup_printf(_("Deleting account %s"), acct_name);
00928     gtk_label_set_text(GTK_LABEL(label), message);
00929     g_free(message);
00930 
00931     /*
00932      * Reparent only to accounts of the same
00933      * type as the one being deleted.
00934      */
00935     filter = g_list_prepend(NULL, (gpointer)xaccAccountGetType(account));
00936     g_object_set_data(G_OBJECT(dialog), DELETE_DIALOG_FILTER, filter);
00937     g_object_set_data(G_OBJECT(dialog), DELETE_DIALOG_ACCOUNT, account);
00938 
00939     /*
00940      * Adjust the dialog based on whether the account has
00941      * transactions.
00942      */
00943     if (splits) {
00944       delete_helper_t delete_res2 = { FALSE, FALSE };
00945 
00946       tmas = GNC_ACCOUNT_SEL(glade_xml_get_widget (xml, "tmas"));
00947       gppat_populate_gas_list(dialog, tmas, FALSE);
00948 
00949       delete_account_helper(account, &delete_res2);
00950       if (delete_res2.has_ro_splits) {
00951         gtk_widget_destroy(glade_xml_get_widget (xml, "trans_rw"));
00952         widget = glade_xml_get_widget (xml, "tdrb");
00953         gtk_widget_set_sensitive(widget, FALSE);
00954       } else {
00955         gtk_widget_destroy(glade_xml_get_widget (xml, "trans_ro"));
00956       }
00957     } else {
00958       gtk_widget_destroy(glade_xml_get_widget (xml, "transactions"));
00959     }
00960 
00961     /*
00962      * Adjust the dialog based on whether the account has children.
00963      */
00964     if (gnc_account_n_children(account) > 0) {
00965       /*
00966        * Check for RO txns in descendants
00967        */
00968       gnc_account_foreach_descendant_until(account, delete_account_helper,
00969                               &delete_res);
00970       if (delete_res.has_ro_splits) {
00971         gtk_widget_destroy(glade_xml_get_widget (xml, "sa_trans_rw"));
00972         widget = glade_xml_get_widget (xml, "dtdrb");
00973         gtk_widget_set_sensitive(widget, FALSE);
00974       } else if (delete_res.has_splits) {
00975         gtk_widget_destroy(glade_xml_get_widget (xml, "sa_trans_ro"));
00976       } else {
00977         gtk_widget_destroy(glade_xml_get_widget (xml, "subaccount_trans"));
00978       }
00979       damas = GNC_ACCOUNT_SEL(glade_xml_get_widget (xml, "damas"));
00980       gppat_populate_gas_list(dialog, damas, TRUE);
00981       dtmas = GNC_ACCOUNT_SEL(glade_xml_get_widget (xml, "dtmas"));
00982       gppat_populate_gas_list(dialog, dtmas, TRUE);
00983     } else {
00984       gtk_widget_destroy(glade_xml_get_widget (xml, "subaccounts"));
00985       gtk_widget_destroy(glade_xml_get_widget (xml, "subaccount_trans"));
00986     }
00987 
00988     /* default to cancel */
00989     gtk_dialog_set_default_response (GTK_DIALOG(dialog), GTK_RESPONSE_CANCEL);
00990 
00991     /*
00992      * Note that one effect of the modal dialog is preventing
00993      * the account selectors from being repopulated.
00994      */ 
00995     gtk_widget_show_all(dialog);
00996     response = gtk_dialog_run(GTK_DIALOG(dialog));
00997     if (GTK_RESPONSE_ACCEPT != response) {
00998       /* Account deletion is cancelled, so clean up and return. */
00999       gtk_widget_destroy(dialog);
01000       g_list_free(filter);
01001       g_free(acct_name);
01002       return;
01003     }
01004     if (tmas && GTK_WIDGET_IS_SENSITIVE(tmas))
01005       ta = gnc_account_sel_get_account(tmas);
01006     if (damas && GTK_WIDGET_IS_SENSITIVE(damas))
01007       daa = gnc_account_sel_get_account(damas);
01008     if (dtmas && GTK_WIDGET_IS_SENSITIVE(dtmas))
01009       dta = gnc_account_sel_get_account(dtmas);
01010     gtk_widget_destroy(dialog);
01011     g_list_free(filter);
01012   } /* (NULL != splits) || (NULL != children) */
01013 
01014   /*
01015    * Present a message to the user which specifies what will be
01016    * deleted and what will be reparented, then ask for verification.
01017    */
01018   {
01019     const char *format = _("The account %s will be deleted.");
01020     char *lines[8];
01021     char *message;
01022     char *name;
01023     int i = 0;
01024 
01025     lines[0] = g_strdup_printf(format, acct_name);
01026     if (splits) {
01027       if (ta) {
01028         name = xaccAccountGetFullName(ta);
01029         format = _("All transactions in this account will be moved to "
01030                    "the account %s.");
01031         lines[++i] = g_strdup_printf(format, name);
01032       } else if (splits) {
01033         format = _("All transactions in this account will be deleted.");
01034         lines[++i] = g_strdup_printf("%s", format);
01035       }
01036     }
01037     if (gnc_account_n_children(account) > 0) {
01038       if (daa) {
01039         name = xaccAccountGetFullName(daa);
01040         format = _("All of its sub-accounts will be moved to "
01041                    "the account %s.");
01042         lines[++i] = g_strdup_printf(format, name);
01043       } else {
01044         format = _("All of its subaccounts will be deleted.");
01045         lines[++i] = g_strdup_printf("%s", format);
01046         if (dta) {
01047           name = xaccAccountGetFullName(dta);
01048           format = _("All sub-account transactions will be moved to "
01049                      "the account %s.");
01050           lines[++i] = g_strdup_printf(format, name);
01051         } else if (delete_res.has_splits) {
01052           format = _("All sub-account transactions will be deleted.");
01053           lines[++i] = g_strdup_printf("%s", format);
01054         }
01055       }
01056     }
01057     lines[++i] = _("Are you sure you want to do this?");
01058     lines[i] = NULL;
01059     i--; /* Don't try to free the constant question. */
01060     message = g_strjoinv(" ", lines);
01061     while (i--) {
01062         g_free(lines[i]);
01063     }
01064 
01065     dialog =  gtk_message_dialog_new(GTK_WINDOW(window),
01066                                      GTK_DIALOG_DESTROY_WITH_PARENT,
01067                                      GTK_MESSAGE_QUESTION,
01068                                      GTK_BUTTONS_NONE,
01069                                      "%s", message);
01070     g_free(message);
01071     gtk_dialog_add_buttons(GTK_DIALOG(dialog),
01072                              GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
01073                              GTK_STOCK_DELETE, GTK_RESPONSE_ACCEPT,
01074                              (gchar *)NULL);
01075     gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_CANCEL);
01076     response = gtk_dialog_run(GTK_DIALOG(dialog));
01077     gtk_widget_destroy(dialog);
01078 
01079     if (GTK_RESPONSE_ACCEPT == response) {
01080       gnc_set_busy_cursor(NULL, TRUE);
01081       gnc_suspend_gui_refresh ();
01082       xaccAccountBeginEdit (account);
01083       if (NULL != daa) {
01084         GList *acct_list, *ptr;
01085 
01086         xaccAccountBeginEdit (daa);
01087         acct_list = gnc_account_get_children(account);
01088         for (ptr = acct_list; ptr; ptr = g_list_next(ptr))
01089           gnc_account_append_child (daa, ptr->data);
01090         g_list_free(acct_list);
01091         xaccAccountCommitEdit (daa);
01092       } else if (NULL != dta) {
01093         /* Move the splits of its subaccounts, if any. */
01094         gnc_account_foreach_descendant(account,
01095                                        (AccountCb)xaccAccountMoveAllSplits,
01096                                        dta);
01097       }
01098       if (NULL != ta) {
01099         /* Move the splits of the account to be deleted. */
01100         xaccAccountMoveAllSplits (account, ta);
01101       }
01102       /*
01103        * Finally, delete the account, any subaccounts it may still
01104        * have, and any splits it or its subaccounts may still have.
01105        */
01106       xaccAccountDestroy (account);
01107       gnc_resume_gui_refresh ();
01108       gnc_unset_busy_cursor(NULL);
01109     }
01110   }
01111   g_free(acct_name);
01112 }
01113 
01114 static void
01115 gnc_plugin_page_account_tree_cmd_renumber_accounts (GtkAction *action,
01116                                                     GncPluginPageAccountTree *page)
01117 {
01118   Account *account;
01119   GtkWidget *window;
01120 
01121   window = gnc_plugin_page_get_window(GNC_PLUGIN_PAGE(page));
01122   account = gnc_plugin_page_account_tree_get_current_account(page);
01123   if (!window || !account)
01124     return;
01125 
01126   gnc_account_renumber_create_dialog(window, account);
01127 }
01128 
01129 /*********************/
01130 
01131 static void
01132 gnc_plugin_page_account_tree_cmd_view_filter_by (GtkAction *action,
01133                                                  GncPluginPageAccountTree *page)
01134 {
01135   GncPluginPageAccountTreePrivate *priv;
01136 
01137   g_return_if_fail(GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE(page));
01138   ENTER("(action %p, page %p)", action, page);
01139 
01140   priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
01141   account_filter_dialog_create(&priv->fd, GNC_PLUGIN_PAGE(page));
01142   LEAVE(" ");
01143 }
01144 
01145 static void
01146 gnc_plugin_page_account_tree_cmd_reconcile (GtkAction *action,
01147                                             GncPluginPageAccountTree *page)
01148 {
01149         GtkWidget *window;
01150         Account *account;
01151         RecnWindow *recnData;
01152 
01153         account = gnc_plugin_page_account_tree_get_current_account (page);
01154         g_return_if_fail (account != NULL);
01155 
01156         window = GNC_PLUGIN_PAGE (page)->window;
01157         recnData = recnWindow (window, account);
01158         gnc_ui_reconcile_window_raise (recnData);
01159 }
01160 
01161 static void
01162 gnc_plugin_page_account_tree_cmd_transfer (GtkAction *action,
01163                                            GncPluginPageAccountTree *page)
01164 {
01165         GtkWidget *window;
01166         Account *account;
01167 
01168         account = gnc_plugin_page_account_tree_get_current_account (page);
01169         window = GNC_PLUGIN_PAGE (page)->window;
01170         gnc_xfer_dialog (window, account);
01171 }
01172 
01173 static void
01174 gnc_plugin_page_account_tree_cmd_stock_split (GtkAction *action,
01175                                               GncPluginPageAccountTree *page)
01176 {
01177         GtkWidget *window;
01178         Account *account;
01179 
01180         account = gnc_plugin_page_account_tree_get_current_account (page);
01181         window = GNC_PLUGIN_PAGE (page)->window;
01182         gnc_stock_split_dialog (window, account);
01183 }
01184 
01185 static void
01186 gnc_plugin_page_account_tree_cmd_lots (GtkAction *action,
01187                                        GncPluginPageAccountTree *page)
01188 {
01189         Account *account;
01190 
01191         account = gnc_plugin_page_account_tree_get_current_account (page);
01192         gnc_lot_viewer_dialog (account);
01193 }
01194 
01195 static void
01196 gnc_plugin_page_account_tree_cmd_scrub (GtkAction *action, GncPluginPageAccountTree *page)
01197 {
01198         Account *account = gnc_plugin_page_account_tree_get_current_account (page);
01199 
01200         g_return_if_fail (account != NULL);
01201 
01202         gnc_suspend_gui_refresh ();
01203 
01204         xaccAccountScrubOrphans (account);
01205         xaccAccountScrubImbalance (account);
01206 
01207         // XXX: Lots are disabled
01208         if (g_getenv("GNC_AUTO_SCRUB_LOTS") != NULL)
01209             xaccAccountScrubLots(account);
01210 
01211         gnc_resume_gui_refresh ();
01212 }
01213 
01214 static void
01215 gnc_plugin_page_account_tree_cmd_scrub_sub (GtkAction *action, GncPluginPageAccountTree *page)
01216 {
01217         Account *account = gnc_plugin_page_account_tree_get_current_account (page);
01218 
01219         g_return_if_fail (account != NULL);
01220 
01221         gnc_suspend_gui_refresh ();
01222 
01223         xaccAccountTreeScrubOrphans (account);
01224