GnuCash 2.4.99
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 "assistant-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-icons.h"
00056 #include "gnc-plugin-account-tree.h"
00057 #include "gnc-session.h"
00058 #include "gnc-split-reg.h"
00059 #include "gnc-tree-view-account.h"
00060 #include "gnc-tree-model-account-types.h"
00061 #include "gnc-ui.h"
00062 #include "gnc-ui-util.h"
00063 #include "dialog-lot-viewer.h"
00064 #include "window-reconcile.h"
00065 #include "window-autoclear.h"
00066 #include "window-main-summarybar.h"
00067 #include "dialog-object-references.h"
00068 
00069 /* This static indicates the debugging module that this .o belongs to.  */
00070 static QofLogModule log_module = GNC_MOD_GUI;
00071 
00072 #define PLUGIN_PAGE_ACCT_TREE_CM_CLASS "plugin-page-acct-tree"
00073 #define GCONF_SECTION "window/pages/account_tree"
00074 
00075 #define DELETE_DIALOG_FILTER       "filter"
00076 #define DELETE_DIALOG_ACCOUNT      "account"
00077 #define DELETE_DIALOG_TRANS_MAS    "trans_mas"
00078 #define DELETE_DIALOG_SA_MAS       "sa_mas"
00079 #define DELETE_DIALOG_SA_TRANS_MAS "sa_trans_mas"
00080 #define DELETE_DIALOG_OK_BUTTON    "deletebutton"
00081 
00082 enum
00083 {
00084     ACCOUNT_SELECTED,
00085     LAST_SIGNAL
00086 };
00087 
00088 typedef struct GncPluginPageAccountTreePrivate
00089 {
00090     GtkWidget   *widget;
00091     GtkTreeView *tree_view;
00092     gint         component_id;
00093     AccountFilterDialog fd;
00094 } GncPluginPageAccountTreePrivate;
00095 
00096 #define GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(o)  \
00097    (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_PLUGIN_PAGE_ACCOUNT_TREE, GncPluginPageAccountTreePrivate))
00098 
00099 static GObjectClass *parent_class = NULL;
00100 
00101 /************************************************************
00102  *                        Prototypes                        *
00103  ************************************************************/
00104 /* Plugin Actions */
00105 static void gnc_plugin_page_account_tree_class_init (GncPluginPageAccountTreeClass *klass);
00106 static void gnc_plugin_page_account_tree_init (GncPluginPageAccountTree *plugin_page);
00107 static void gnc_plugin_page_account_tree_finalize (GObject *object);
00108 static void gnc_plugin_page_account_tree_selected (GObject *object, gpointer user_data);
00109 
00110 static GtkWidget *gnc_plugin_page_account_tree_create_widget (GncPluginPage *plugin_page);
00111 static void gnc_plugin_page_account_tree_destroy_widget (GncPluginPage *plugin_page);
00112 static void gnc_plugin_page_account_tree_save_page (GncPluginPage *plugin_page, GKeyFile *file, const gchar *group);
00113 static GncPluginPage *gnc_plugin_page_account_tree_recreate_page (GtkWidget *window, GKeyFile *file, const gchar *group);
00114 
00115 /* Callbacks */
00116 static void gnc_plugin_page_account_tree_summarybar_position_changed(GConfEntry *entry,
00117         gpointer user_data);
00118 static gboolean gnc_plugin_page_account_tree_button_press_cb (GtkWidget *widget,
00119         GdkEventButton *event,
00120         GncPluginPage *page);
00121 static void gnc_plugin_page_account_tree_double_click_cb (GtkTreeView        *treeview,
00122         GtkTreePath        *path,
00123         GtkTreeViewColumn  *col,
00124         GncPluginPageAccountTree *page);
00125 
00126 static void gnc_plugin_page_account_tree_selection_changed_cb (GtkTreeSelection *selection,
00127         GncPluginPageAccountTree *page);
00128 void gppat_populate_trans_mas_list(GtkToggleButton *sa_mrb, GtkWidget *dialog);
00129 void gppat_set_insensitive_iff_rb_active(GtkWidget *widget, GtkToggleButton *b);
00130 
00131 /* Command callbacks */
00132 static void gnc_plugin_page_account_tree_cmd_new_account (GtkAction *action, GncPluginPageAccountTree *plugin_page);
00133 static void gnc_plugin_page_account_tree_cmd_file_new_hierarchy (GtkAction *action, GncPluginPageAccountTree *plugin_page);
00134 static void gnc_plugin_page_account_tree_cmd_open_account (GtkAction *action, GncPluginPageAccountTree *page);
00135 static void gnc_plugin_page_account_tree_cmd_open_subaccounts (GtkAction *action, GncPluginPageAccountTree *page);
00136 static void gnc_plugin_page_account_tree_cmd_edit_account (GtkAction *action, GncPluginPageAccountTree *page);
00137 static void gnc_plugin_page_account_tree_cmd_delete_account (GtkAction *action, GncPluginPageAccountTree *page);
00138 static void gnc_plugin_page_account_tree_cmd_renumber_accounts (GtkAction *action, GncPluginPageAccountTree *page);
00139 static void gnc_plugin_page_account_tree_cmd_view_filter_by (GtkAction *action, GncPluginPageAccountTree *plugin_page);
00140 static void gnc_plugin_page_account_tree_cmd_reconcile (GtkAction *action, GncPluginPageAccountTree *page);
00141 static void gnc_plugin_page_account_tree_cmd_autoclear (GtkAction *action, GncPluginPageAccountTree *page);
00142 static void gnc_plugin_page_account_tree_cmd_transfer (GtkAction *action, GncPluginPageAccountTree *page);
00143 static void gnc_plugin_page_account_tree_cmd_stock_split (GtkAction *action, GncPluginPageAccountTree *page);
00144 static void gnc_plugin_page_account_tree_cmd_lots (GtkAction *action, GncPluginPageAccountTree *page);
00145 static void gnc_plugin_page_account_tree_cmd_scrub (GtkAction *action, GncPluginPageAccountTree *page);
00146 static void gnc_plugin_page_account_tree_cmd_scrub_sub (GtkAction *action, GncPluginPageAccountTree *page);
00147 static void gnc_plugin_page_account_tree_cmd_scrub_all (GtkAction *action, GncPluginPageAccountTree *page);
00148 
00149 
00150 static guint plugin_page_signals[LAST_SIGNAL] = { 0 };
00151 
00152 
00153 static GtkActionEntry gnc_plugin_page_account_tree_actions [] =
00154 {
00155     /* Toplevel */
00156     { "FakeToplevel", NULL, "", NULL, NULL, NULL },
00157 
00158     /* File menu */
00159     {
00160         "FileNewAccountAction", GNC_STOCK_NEW_ACCOUNT, N_("New _Account..."), NULL,
00161         N_("Create a new Account"),
00162         G_CALLBACK (gnc_plugin_page_account_tree_cmd_new_account)
00163     },
00164     {
00165         "FileAddAccountHierarchyAssistantAction", GNC_STOCK_NEW_ACCOUNT, N_("New Account _Hierarchy..."), NULL,
00166         N_("Extend the current book by merging with new account type categories"),
00167         G_CALLBACK (gnc_plugin_page_account_tree_cmd_file_new_hierarchy)
00168     },
00169     {
00170         "FileOpenAccountAction", GNC_STOCK_OPEN_ACCOUNT, N_("Open _Account"), NULL,
00171         N_("Open the selected account"),
00172         G_CALLBACK (gnc_plugin_page_account_tree_cmd_open_account)
00173     },
00174     {
00175         "FileOpenSubaccountsAction", GNC_STOCK_OPEN_ACCOUNT, N_("Open _Subaccounts"), NULL,
00176         N_("Open the selected account and all its subaccounts"),
00177         G_CALLBACK (gnc_plugin_page_account_tree_cmd_open_subaccounts)
00178     },
00179 
00180     /* Edit menu */
00181     {
00182         "EditEditAccountAction", GNC_STOCK_EDIT_ACCOUNT, N_("Edit _Account"), "<control>e",
00183         N_("Edit the selected account"),
00184         G_CALLBACK (gnc_plugin_page_account_tree_cmd_edit_account)
00185     },
00186     {
00187         "EditDeleteAccountAction", GNC_STOCK_DELETE_ACCOUNT, N_("_Delete Account..."), "Delete",
00188         N_("Delete selected account"),
00189         G_CALLBACK (gnc_plugin_page_account_tree_cmd_delete_account)
00190     },
00191     {
00192         "EditRenumberSubaccountsAction", NULL, N_("_Renumber Subaccounts..."), NULL,
00193         N_("Renumber the children of the selected account"),
00194         G_CALLBACK (gnc_plugin_page_account_tree_cmd_renumber_accounts)
00195     },
00196 
00197     /* View menu */
00198     {
00199         "ViewFilterByAction", NULL, N_("_Filter By..."), NULL, NULL,
00200         G_CALLBACK (gnc_plugin_page_account_tree_cmd_view_filter_by)
00201     },
00202 
00203     /* Actions menu */
00204     {
00205         "ActionsReconcileAction", NULL, N_("_Reconcile..."), NULL,
00206         N_("Reconcile the selected account"),
00207         G_CALLBACK (gnc_plugin_page_account_tree_cmd_reconcile)
00208     },
00209     {
00210         "ActionsAutoClearAction", NULL, N_("_Auto-clear..."), NULL,
00211         N_("Automatically clear individual transactions, given a cleared amount"),
00212         G_CALLBACK (gnc_plugin_page_account_tree_cmd_autoclear)
00213     },
00214     {
00215         "ActionsTransferAction", NULL, N_("_Transfer..."), "<control>t",
00216         N_("Transfer funds from one account to another"),
00217         G_CALLBACK (gnc_plugin_page_account_tree_cmd_transfer)
00218     },
00219     {
00220         "ActionsStockSplitAction", NULL, N_("Stoc_k Split..."), NULL,
00221         N_("Record a stock split or a stock merger"),
00222         G_CALLBACK (gnc_plugin_page_account_tree_cmd_stock_split)
00223     },
00224     {
00225         "ActionsLotsAction", NULL, N_("View _Lots..."), NULL,
00226         N_("Bring up the lot viewer/editor window"),
00227         G_CALLBACK (gnc_plugin_page_account_tree_cmd_lots)
00228     },
00229     {
00230         "ScrubAction", NULL, N_("Check & Repair A_ccount"), NULL,
00231         N_("Check for and repair unbalanced transactions and orphan splits " "in this account"),
00232         G_CALLBACK (gnc_plugin_page_account_tree_cmd_scrub)
00233     },
00234     {
00235         "ScrubSubAction", NULL, N_("Check & Repair Su_baccounts"), NULL,
00236         N_("Check for and repair unbalanced transactions and orphan splits "
00237         "in this account and its subaccounts"),
00238         G_CALLBACK (gnc_plugin_page_account_tree_cmd_scrub_sub)
00239     },
00240     {
00241         "ScrubAllAction", NULL, N_("Check & Repair A_ll"), NULL,
00242         N_("Check for and repair unbalanced transactions and orphan splits " "in all accounts"),
00243         G_CALLBACK (gnc_plugin_page_account_tree_cmd_scrub_all)
00244     },
00245 };
00247 static guint gnc_plugin_page_account_tree_n_actions = G_N_ELEMENTS (gnc_plugin_page_account_tree_actions);
00248 
00249 
00252 static const gchar *actions_requiring_account_rw[] =
00253 {
00254     "EditEditAccountAction",
00255     "EditDeleteAccountAction",
00256     "ActionsReconcileAction",
00257     "ActionsAutoClearAction",
00258     NULL
00259 };
00260 
00263 static const gchar *actions_requiring_account_always[] =
00264 {
00265     "FileOpenAccountAction",
00266     "FileOpenSubaccountsAction",
00267     "ActionsLotsAction",
00268     NULL
00269 };
00270 
00271 /* This is the list of actions which are switched inactive in a read-only book. */
00272 static const gchar* readonly_inactive_actions[] =
00273 {
00274     "FileNewAccountAction",
00275     "FileAddAccountHierarchyAssistantAction",
00276     "EditEditAccountAction",
00277     "EditDeleteAccountAction",
00278     "EditRenumberSubaccountsAction",
00279     "ActionsTransferAction",
00280     "ActionsReconcileAction",
00281     "ActionsAutoClearAction",
00282     "ActionsStockSplitAction",
00283     "ScrubAction",
00284     "ScrubSubAction",
00285     "ScrubAllAction",
00286     NULL
00287 };
00288 
00290 static action_toolbar_labels toolbar_labels[] =
00291 {
00292     { "FileOpenAccountAction",      N_("Open") },
00293     { "EditEditAccountAction",      N_("Edit") },
00294     { "FileNewAccountAction",               N_("New") },
00295     { "EditDeleteAccountAction",            N_("Delete") },
00296     { NULL, NULL },
00297 };
00298 
00299 
00300 GType
00301 gnc_plugin_page_account_tree_get_type (void)
00302 {
00303     static GType gnc_plugin_page_account_tree_type = 0;
00304 
00305     if (gnc_plugin_page_account_tree_type == 0)
00306     {
00307         static const GTypeInfo our_info =
00308         {
00309             sizeof (GncPluginPageAccountTreeClass),
00310             NULL,
00311             NULL,
00312             (GClassInitFunc) gnc_plugin_page_account_tree_class_init,
00313             NULL,
00314             NULL,
00315             sizeof (GncPluginPageAccountTree),
00316             0,
00317             (GInstanceInitFunc) gnc_plugin_page_account_tree_init
00318         };
00319 
00320         gnc_plugin_page_account_tree_type = g_type_register_static (GNC_TYPE_PLUGIN_PAGE,
00321                                             GNC_PLUGIN_PAGE_ACCOUNT_TREE_NAME,
00322                                             &our_info, 0);
00323     }
00324 
00325     return gnc_plugin_page_account_tree_type;
00326 }
00327 
00328 GncPluginPage *
00329 gnc_plugin_page_account_tree_new (void)
00330 {
00331     GncPluginPageAccountTree *plugin_page;
00332 
00333     ENTER(" ");
00334     plugin_page = g_object_new (GNC_TYPE_PLUGIN_PAGE_ACCOUNT_TREE,
00335                                 NULL);
00336 
00337     LEAVE("new account tree page %p", plugin_page);
00338     return GNC_PLUGIN_PAGE (plugin_page);
00339 }
00340 
00341 static void
00342 gnc_plugin_page_account_tree_class_init (GncPluginPageAccountTreeClass *klass)
00343 {
00344     GObjectClass *object_class = G_OBJECT_CLASS (klass);
00345     GncPluginPageClass *gnc_plugin_class = GNC_PLUGIN_PAGE_CLASS(klass);
00346 
00347     parent_class = g_type_class_peek_parent (klass);
00348 
00349     object_class->finalize = gnc_plugin_page_account_tree_finalize;
00350 
00351     gnc_plugin_class->tab_icon        = GNC_STOCK_ACCOUNT;
00352     gnc_plugin_class->plugin_name     = GNC_PLUGIN_PAGE_ACCOUNT_TREE_NAME;
00353     gnc_plugin_class->create_widget   = gnc_plugin_page_account_tree_create_widget;
00354     gnc_plugin_class->destroy_widget  = gnc_plugin_page_account_tree_destroy_widget;
00355     gnc_plugin_class->save_page       = gnc_plugin_page_account_tree_save_page;
00356     gnc_plugin_class->recreate_page   = gnc_plugin_page_account_tree_recreate_page;
00357 
00358     g_type_class_add_private(klass, sizeof(GncPluginPageAccountTreePrivate));
00359 
00360     plugin_page_signals[ACCOUNT_SELECTED] =
00361         g_signal_new ("account_selected",
00362                       G_OBJECT_CLASS_TYPE (object_class),
00363                       G_SIGNAL_RUN_FIRST,
00364                       G_STRUCT_OFFSET (GncPluginPageAccountTreeClass, account_selected),
00365                       NULL, NULL,
00366                       g_cclosure_marshal_VOID__POINTER,
00367                       G_TYPE_NONE, 1,
00368                       G_TYPE_POINTER);
00369 }
00370 
00371 static void
00372 gnc_plugin_page_account_tree_init (GncPluginPageAccountTree *plugin_page)
00373 {
00374     GtkActionGroup *action_group;
00375     GncPluginPageAccountTreePrivate *priv;
00376     GncPluginPage *parent;
00377     const GList *page_list;
00378 
00379     ENTER("page %p", plugin_page);
00380     priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(plugin_page);
00381 
00382     /* Init parent declared variables */
00383     parent = GNC_PLUGIN_PAGE(plugin_page);
00384     g_object_set(G_OBJECT(plugin_page),
00385                  "page-name",      _("Accounts"),
00386                  "page-uri",       "default:",
00387                  "ui-description", "gnc-plugin-page-account-tree-ui.xml",
00388                  NULL);
00389     g_signal_connect (G_OBJECT (plugin_page), "selected",
00390                       G_CALLBACK (gnc_plugin_page_account_tree_selected), plugin_page);
00391 
00392     /* change me when the system supports multiple books */
00393     gnc_plugin_page_add_book(parent, gnc_get_current_book());
00394 
00395     /* Is this the first accounts page? */
00396     page_list =
00397         gnc_gobject_tracking_get_list(GNC_PLUGIN_PAGE_ACCOUNT_TREE_NAME);
00398     if (plugin_page == page_list->data)
00399     {
00400         g_object_set_data(G_OBJECT(plugin_page), PLUGIN_PAGE_IMMUTABLE,
00401                           GINT_TO_POINTER(1));
00402     }
00403 
00404     /* Create menu and toolbar information */
00405     action_group =
00406         gnc_plugin_page_create_action_group(parent,
00407                                             "GncPluginPageAccountTreeActions");
00408     gtk_action_group_add_actions(action_group,
00409                                  gnc_plugin_page_account_tree_actions,
00410                                  gnc_plugin_page_account_tree_n_actions,
00411                                  plugin_page);
00412     gnc_plugin_init_short_names (action_group, toolbar_labels);
00413 
00414     /* Visible types */
00415     priv->fd.visible_types = -1; /* Start with all types */
00416     priv->fd.show_hidden = FALSE;
00417     priv->fd.show_zero_total = TRUE;
00418 
00419     LEAVE("page %p, priv %p, action group %p",
00420           plugin_page, priv, action_group);
00421 }
00422 
00423 static void
00424 gnc_plugin_page_account_tree_finalize (GObject *object)
00425 {
00426     GncPluginPageAccountTree *page;
00427     GncPluginPageAccountTreePrivate *priv;
00428 
00429     ENTER("object %p", object);
00430     page = GNC_PLUGIN_PAGE_ACCOUNT_TREE (object);
00431     g_return_if_fail (GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE (page));
00432     priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
00433     g_return_if_fail (priv != NULL);
00434 
00435     G_OBJECT_CLASS (parent_class)->finalize (object);
00436     LEAVE(" ");
00437 }
00438 
00439 Account *
00440 gnc_plugin_page_account_tree_get_current_account (GncPluginPageAccountTree *page)
00441 {
00442     GncPluginPageAccountTreePrivate *priv;
00443     Account *account;
00444 
00445     priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
00446     ENTER("page %p (tree view %p)", page, priv->tree_view);
00447     account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(priv->tree_view));
00448     if (account == NULL)
00449     {
00450         LEAVE("no account");
00451         return NULL;
00452     }
00453 
00454     LEAVE("account %p", account);
00455     return account;
00456 }
00457 
00458 
00459 /* Virtual Functions */
00460 
00461 static void
00462 gnc_plugin_page_account_refresh_cb (GHashTable *changes, gpointer user_data)
00463 {
00464     GncPluginPageAccountTree *page = user_data;
00465     GncPluginPageAccountTreePrivate *priv;
00466 
00467     g_return_if_fail(GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE(page));
00468 
00469     /* We're only looking for forced updates here. */
00470     if (changes)
00471         return;
00472 
00473     priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
00474     gtk_widget_queue_draw(priv->widget);
00475 }
00476 
00477 static void
00478 gnc_plugin_page_account_tree_close_cb (gpointer user_data)
00479 {
00480     GncPluginPage *plugin_page;
00481     GncPluginPageAccountTree *page;
00482 
00483     plugin_page = GNC_PLUGIN_PAGE(user_data);
00484     page = GNC_PLUGIN_PAGE_ACCOUNT_TREE (plugin_page);
00485     gnc_main_window_close_page(plugin_page);
00486 }
00487 
00488 static GtkWidget *
00489 gnc_plugin_page_account_tree_create_widget (GncPluginPage *plugin_page)
00490 {
00491     GncPluginPageAccountTree *page;
00492     GncPluginPageAccountTreePrivate *priv;
00493     GtkTreeSelection *selection;
00494     GtkTreeView *tree_view;
00495     GtkWidget *scrolled_window;
00496     GtkTreeViewColumn *col;
00497 
00498     ENTER("page %p", plugin_page);
00499     page = GNC_PLUGIN_PAGE_ACCOUNT_TREE (plugin_page);
00500     priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
00501     if (priv->widget != NULL)
00502     {
00503         LEAVE("widget = %p", priv->widget);
00504         return priv->widget;
00505     }
00506 
00507     priv->widget = gtk_vbox_new (FALSE, 0);
00508     gtk_widget_show (priv->widget);
00509 
00510     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
00511     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
00512                                     GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
00513     gtk_widget_show (scrolled_window);
00514     gtk_box_pack_start (GTK_BOX (priv->widget), scrolled_window,
00515                         TRUE, TRUE, 0);
00516 
00517     tree_view = gnc_tree_view_account_new(FALSE);
00518     col = gnc_tree_view_find_column_by_name(
00519               GNC_TREE_VIEW(tree_view), "description");
00520     g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1));
00521     col = gnc_tree_view_find_column_by_name(
00522               GNC_TREE_VIEW(tree_view), "total");
00523     g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1));
00524     gnc_tree_view_configure_columns(GNC_TREE_VIEW(tree_view));
00525     g_object_set(G_OBJECT(tree_view),
00526                  "gconf-section", GCONF_SECTION,
00527                  "show-column-menu", TRUE,
00528                  NULL);
00529 
00530     /* No name handler; then the user can't click on the name of the
00531        account to open its register. */
00532     gnc_tree_view_account_set_code_edited(GNC_TREE_VIEW_ACCOUNT(tree_view),
00533                                           gnc_tree_view_account_code_edited_cb);
00534     gnc_tree_view_account_set_description_edited(GNC_TREE_VIEW_ACCOUNT(tree_view),
00535             gnc_tree_view_account_description_edited_cb);
00536     gnc_tree_view_account_set_notes_edited(GNC_TREE_VIEW_ACCOUNT(tree_view),
00537                                            gnc_tree_view_account_notes_edited_cb);
00538 
00539     priv->tree_view = tree_view;
00540     selection = gtk_tree_view_get_selection(tree_view);
00541     g_signal_connect (G_OBJECT (selection), "changed",
00542                       G_CALLBACK (gnc_plugin_page_account_tree_selection_changed_cb), page);
00543     g_signal_connect (G_OBJECT (tree_view), "button-press-event",
00544                       G_CALLBACK (gnc_plugin_page_account_tree_button_press_cb), page);
00545     g_signal_connect (G_OBJECT (tree_view), "row-activated",
00546                       G_CALLBACK (gnc_plugin_page_account_tree_double_click_cb), page);
00547 
00548     gtk_tree_view_set_headers_visible(tree_view, TRUE);
00549     gnc_plugin_page_account_tree_selection_changed_cb (NULL, page);
00550     gtk_widget_show (GTK_WIDGET (tree_view));
00551     gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET(tree_view));
00552 
00553     priv->fd.tree_view = GNC_TREE_VIEW_ACCOUNT(priv->tree_view);
00554     gnc_tree_view_account_set_filter (
00555         GNC_TREE_VIEW_ACCOUNT(tree_view),
00556         gnc_plugin_page_account_tree_filter_accounts, &priv->fd, NULL);
00557 
00558     priv->component_id =
00559         gnc_register_gui_component(PLUGIN_PAGE_ACCT_TREE_CM_CLASS,
00560                                    gnc_plugin_page_account_refresh_cb,
00561                                    gnc_plugin_page_account_tree_close_cb,
00562                                    page);
00563     gnc_gui_component_set_session (priv->component_id,
00564                                    gnc_get_current_session());
00565 
00566     plugin_page->summarybar = gnc_main_window_summary_new();
00567     gtk_box_pack_start (GTK_BOX (priv->widget), plugin_page->summarybar,
00568                         FALSE, FALSE, 0);
00569     gtk_widget_show(plugin_page->summarybar);
00570     gnc_plugin_page_account_tree_summarybar_position_changed(NULL, page);
00571     gnc_gconf_general_register_cb(KEY_SUMMARYBAR_POSITION,
00572                                   gnc_plugin_page_account_tree_summarybar_position_changed,
00573                                   page);
00574 
00575     LEAVE("widget = %p", priv->widget);
00576     return priv->widget;
00577 }
00578 
00579 static void
00580 gnc_plugin_page_account_tree_destroy_widget (GncPluginPage *plugin_page)
00581 {
00582     GncPluginPageAccountTree *page;
00583     GncPluginPageAccountTreePrivate *priv;
00584 
00585     ENTER("page %p", plugin_page);
00586     page = GNC_PLUGIN_PAGE_ACCOUNT_TREE (plugin_page);
00587     priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
00588 
00589     gnc_gconf_general_remove_cb(KEY_SUMMARYBAR_POSITION,
00590                                 gnc_plugin_page_account_tree_summarybar_position_changed,
00591                                 page);
00592 
00593     if (priv->widget)
00594     {
00595         g_object_unref(G_OBJECT(priv->widget));
00596         priv->widget = NULL;
00597     }
00598 
00599     if (priv->component_id)
00600     {
00601         gnc_unregister_gui_component(priv->component_id);
00602         priv->component_id = 0;
00603     }
00604 
00605     LEAVE("widget destroyed");
00606 }
00607 
00608 static void update_inactive_actions(GncPluginPage *plugin_page)
00609 {
00610     GtkActionGroup *action_group;
00611     gboolean is_sensitive = !qof_book_is_readonly(gnc_get_current_book());
00612 
00613     // We are readonly - so we have to switch particular actions to inactive.
00614     g_return_if_fail(plugin_page);
00615     g_return_if_fail(GNC_IS_PLUGIN_PAGE(plugin_page));
00616 
00617     /* Get the action group */
00618     action_group = gnc_plugin_page_get_action_group(plugin_page);
00619     g_return_if_fail(GTK_IS_ACTION_GROUP (action_group));
00620 
00621     /* Set the action's sensitivity */
00622     gnc_plugin_update_actions (action_group, readonly_inactive_actions,
00623                                "sensitive", is_sensitive);
00624 }
00625 
00630 static void gnc_plugin_page_account_tree_selected (GObject *object, gpointer user_data)
00631 {
00632     GncPluginPage *plugin_page = GNC_PLUGIN_PAGE (object);
00633     g_return_if_fail (GNC_IS_PLUGIN_PAGE (plugin_page));
00634     update_inactive_actions(plugin_page);
00635 }
00636 
00646 static void
00647 gnc_plugin_page_account_tree_save_page (GncPluginPage *plugin_page,
00648                                         GKeyFile *key_file,
00649                                         const gchar *group_name)
00650 {
00651     GncPluginPageAccountTree *account_page;
00652     GncPluginPageAccountTreePrivate *priv;
00653 
00654     g_return_if_fail (GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE(plugin_page));
00655     g_return_if_fail (key_file != NULL);
00656     g_return_if_fail (group_name != NULL);
00657 
00658     ENTER("page %p, key_file %p, group_name %s", plugin_page, key_file,
00659           group_name);
00660 
00661     account_page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(plugin_page);
00662     priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(account_page);
00663 
00664     gnc_tree_view_account_save(GNC_TREE_VIEW_ACCOUNT(priv->tree_view),
00665                                &priv->fd, key_file, group_name);
00666     LEAVE(" ");
00667 }
00668 
00669 
00670 
00680 static GncPluginPage *
00681 gnc_plugin_page_account_tree_recreate_page (GtkWidget *window,
00682         GKeyFile *key_file,
00683         const gchar *group_name)
00684 {
00685     GncPluginPageAccountTree *account_page;
00686     GncPluginPageAccountTreePrivate *priv;
00687     GncPluginPage *page;
00688 
00689     g_return_val_if_fail(key_file, NULL);
00690     g_return_val_if_fail(group_name, NULL);
00691     ENTER("key_file %p, group_name %s", key_file, group_name);
00692 
00693     /* Create the new page. */
00694     page = gnc_plugin_page_account_tree_new();
00695     account_page = GNC_PLUGIN_PAGE_ACCOUNT_TREE(page);
00696     priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(account_page);
00697 
00698     /* Install it now so we can then manipulate the created widget */
00699     gnc_main_window_open_page(GNC_MAIN_WINDOW(window), page);
00700 
00701     gnc_tree_view_account_restore(GNC_TREE_VIEW_ACCOUNT(priv->tree_view),
00702                                   &priv->fd, key_file, group_name);
00703     LEAVE(" ");
00704     return page;
00705 }
00706 
00707 
00708 /* Callbacks */
00709 
00710 static void
00711 gnc_plugin_page_account_tree_summarybar_position_changed(GConfEntry *entry,
00712         gpointer user_data)
00713 {
00714     GncPluginPage *plugin_page;
00715     GncPluginPageAccountTree *page;
00716     GncPluginPageAccountTreePrivate *priv;
00717     GtkPositionType position = GTK_POS_BOTTOM;
00718     gchar *conf_string;
00719 
00720     g_return_if_fail(user_data != NULL);
00721 
00722     plugin_page = GNC_PLUGIN_PAGE(user_data);
00723     page = GNC_PLUGIN_PAGE_ACCOUNT_TREE (user_data);
00724     priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
00725 
00726     conf_string = gnc_gconf_get_string (GCONF_GENERAL,
00727                                         KEY_SUMMARYBAR_POSITION, NULL);
00728     if (conf_string)
00729     {
00730         position = gnc_enum_from_nick (GTK_TYPE_POSITION_TYPE,
00731                                        conf_string, GTK_POS_BOTTOM);
00732         g_free (conf_string);
00733     }
00734 
00735     gtk_box_reorder_child(GTK_BOX(priv->widget),
00736                           plugin_page->summarybar,
00737                           (position == GTK_POS_TOP ? 0 : -1) );
00738 }
00739 
00747 static gboolean
00748 gnc_plugin_page_account_tree_button_press_cb (GtkWidget *widget,
00749         GdkEventButton *event,
00750         GncPluginPage *page)
00751 {
00752     gboolean result;
00753 
00754     g_return_val_if_fail(GNC_IS_PLUGIN_PAGE(page), FALSE);
00755 
00756     ENTER("widget %p, event %p, page %p", widget, event, page);
00757     result = gnc_main_window_button_press_cb(widget, event, page);
00758     LEAVE(" ");
00759 
00760     /* Always return FALSE.  This will let the tree view callback run as
00761      * well which will select the item under the cursor.  By the time
00762      * the user sees the menu both callbacks will have run and the menu
00763      * actions will operate on the just-selected account. */
00764     return FALSE;
00765 }
00766 
00767 static void
00768 gppat_open_account_common (GncPluginPageAccountTree *page,
00769                            Account *account,
00770                            gboolean include_subs)
00771 {
00772     GncPluginPageAccountTreePrivate *priv;
00773     GtkWidget *window;
00774     GncPluginPage *new_page;
00775 
00776     if (account == NULL)
00777         return;
00778 
00779     priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
00780     window = GNC_PLUGIN_PAGE (page)->window;
00781     new_page = gnc_plugin_page_register_new (account, include_subs);
00782     gnc_main_window_open_page (GNC_MAIN_WINDOW(window), new_page);
00783 }
00784 
00785 static void
00786 gnc_plugin_page_account_tree_double_click_cb (GtkTreeView        *treeview,
00787         GtkTreePath        *path,
00788         GtkTreeViewColumn  *col,
00789         GncPluginPageAccountTree *page)
00790 {
00791     Account *account;
00792 
00793     g_return_if_fail (GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE (page));
00794     account = gnc_tree_view_account_get_account_from_path (GNC_TREE_VIEW_ACCOUNT(treeview), path);
00795     gppat_open_account_common (page, account, FALSE);
00796 }
00797 
00798 static void
00799 gnc_plugin_page_account_tree_selection_changed_cb (GtkTreeSelection *selection,
00800         GncPluginPageAccountTree *page)
00801 {
00802     GtkActionGroup *action_group;
00803     GtkAction *action;
00804     GtkTreeView *view;
00805     Account *account = NULL;
00806     gboolean sensitive;
00807     gboolean subaccounts;
00808     gboolean is_readwrite = !qof_book_is_readonly(gnc_get_current_book());
00809 
00810     g_return_if_fail(GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE(page));
00811 
00812     if (!selection)
00813     {
00814         sensitive = FALSE;
00815         subaccounts = FALSE;
00816     }
00817     else
00818     {
00819         g_return_if_fail(GTK_IS_TREE_SELECTION(selection));
00820         view = gtk_tree_selection_get_tree_view (selection);
00821         account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(view));
00822         sensitive = (account != NULL);
00823 
00824         subaccounts = account && (gnc_account_n_children(account) != 0);
00825         /* Check here for placeholder accounts, etc. */
00826     }
00827 
00828     action_group = gnc_plugin_page_get_action_group(GNC_PLUGIN_PAGE(page));
00829     gnc_plugin_update_actions (action_group, actions_requiring_account_rw,
00830                                "sensitive", is_readwrite && sensitive);
00831     gnc_plugin_update_actions (action_group, actions_requiring_account_always,
00832                                "sensitive", sensitive);
00833     g_signal_emit (page, plugin_page_signals[ACCOUNT_SELECTED], 0, account);
00834 
00835     action = gtk_action_group_get_action (action_group, "EditRenumberSubaccountsAction");
00836     g_object_set (G_OBJECT(action), "sensitive",
00837                   is_readwrite && sensitive && subaccounts, NULL);
00838 
00839     gnc_plugin_update_actions (action_group, actions_requiring_account_rw,
00840                                "sensitive", is_readwrite && sensitive);
00841     gnc_plugin_update_actions (action_group, actions_requiring_account_always,
00842                                "sensitive", sensitive);
00843 }
00844 
00845 
00846 /* Command callbacks */
00847 static void
00848 gnc_plugin_page_account_tree_cmd_new_account (GtkAction *action, GncPluginPageAccountTree *page)
00849 {
00850     Account *account = gnc_plugin_page_account_tree_get_current_account (page);
00851 
00852     gnc_ui_new_account_window (gnc_get_current_book(), account);
00853 }
00854 
00855 static void
00856 gnc_plugin_page_account_tree_cmd_file_new_hierarchy (GtkAction *action, GncPluginPageAccountTree *page)
00857 {
00858     gnc_ui_hierarchy_assistant(FALSE);
00859 }
00860 
00861 static void
00862 gnc_plugin_page_account_tree_cmd_open_account (GtkAction *action,
00863         GncPluginPageAccountTree *page)
00864 {
00865     Account *account;
00866 
00867     g_return_if_fail (GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE (page));
00868     account = gnc_plugin_page_account_tree_get_current_account (page);
00869     gppat_open_account_common (page, account, FALSE);
00870 }
00871 
00872 static void
00873 gnc_plugin_page_account_tree_cmd_open_subaccounts (GtkAction *action,
00874         GncPluginPageAccountTree *page)
00875 {
00876     Account *account;
00877 
00878     g_return_if_fail (GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE (page));
00879     account = gnc_plugin_page_account_tree_get_current_account (page);
00880     gppat_open_account_common (page, account, TRUE);
00881 }
00882 
00883 static void
00884 gnc_plugin_page_account_tree_cmd_edit_account (GtkAction *action, GncPluginPageAccountTree *page)
00885 {
00886     Account *account;
00887 
00888     ENTER("action %p, page %p", action, page);
00889 
00890     account = gnc_plugin_page_account_tree_get_current_account (page);
00891     g_return_if_fail (account != NULL);
00892 
00893     gnc_ui_edit_account_window (account);
00894     LEAVE(" ");
00895 }
00896 
00897 /********************************************************************
00898  * delete_account_helper
00899  * See if this account has any splits present.  Set the user data
00900  * and return the same value to stop walking the account tree if
00901  * appropriate.
00902  ********************************************************************/
00903 typedef struct _delete_helper
00904 {
00905     gboolean has_splits;
00906     gboolean has_ro_splits;
00907 } delete_helper_t;
00908 
00909 static gpointer
00910 delete_account_helper (Account * account, gpointer data)
00911 {
00912     delete_helper_t *helper_res = data;
00913     GList *splits;
00914 
00915     splits = xaccAccountGetSplitList (account);
00916     if (splits)
00917     {
00918         helper_res->has_splits = TRUE;
00919         while (splits)
00920         {
00921             Split *s = splits->data;
00922             Transaction *txn = xaccSplitGetParent (s);
00923             if (xaccTransGetReadOnly (txn))
00924             {
00925                 helper_res->has_ro_splits = TRUE;
00926                 break;
00927             }
00928             splits = splits->next;
00929         }
00930     }
00931 
00932     return GINT_TO_POINTER (helper_res->has_splits || helper_res->has_ro_splits);
00933 }
00934 
00935 /***
00936  *** The OK button of a Delete Account dialog is insensitive if
00937  *** and only if a sensitive account selector contains no accounts.
00938  ***/
00939 static void
00940 set_ok_sensitivity(GtkWidget *dialog)
00941 {
00942     GtkWidget *button;
00943     GtkWidget *sa_mas, *trans_mas;
00944     gint sa_mas_cnt, trans_mas_cnt;
00945     gboolean sensitive;
00946 
00947     sa_mas = g_object_get_data(G_OBJECT(dialog), DELETE_DIALOG_SA_MAS);
00948     trans_mas = g_object_get_data(G_OBJECT(dialog), DELETE_DIALOG_TRANS_MAS);
00949     sa_mas_cnt = gnc_account_sel_get_num_account(GNC_ACCOUNT_SEL(sa_mas));
00950     trans_mas_cnt = gnc_account_sel_get_num_account(GNC_ACCOUNT_SEL(trans_mas));
00951 
00952     sensitive = (((NULL == sa_mas) ||
00953                   (!GTK_WIDGET_IS_SENSITIVE(sa_mas) || sa_mas_cnt)) &&
00954                  ((NULL == trans_mas) ||
00955                   (!GTK_WIDGET_IS_SENSITIVE(trans_mas) || trans_mas_cnt)));
00956 
00957     button = g_object_get_data(G_OBJECT(dialog), DELETE_DIALOG_OK_BUTTON);
00958     gtk_widget_set_sensitive(button, sensitive);
00959 }
00960 
00961 static void
00962 gppat_populate_gas_list(GtkWidget *dialog,
00963                         GNCAccountSel *gas,
00964                         gboolean exclude_subaccounts)
00965 {
00966     Account *account;
00967     GList *filter;
00968 
00969     g_return_if_fail(GTK_IS_DIALOG(dialog));
00970     if (gas == NULL)
00971         return;
00972     account = g_object_get_data(G_OBJECT(dialog), DELETE_DIALOG_ACCOUNT);
00973     filter = g_object_get_data(G_OBJECT(dialog), DELETE_DIALOG_FILTER);
00974 
00975     /* Setting the account type filter triggers GNCAccountSel population. */
00976     gnc_account_sel_set_acct_filters (gas, filter, NULL);
00977 
00978     /* Accounts to be deleted must be removed. */
00979     gnc_account_sel_purge_account( gas, account, exclude_subaccounts);
00980 
00981     /* The sensitivity of the OK button needs to be reevaluated. */
00982     set_ok_sensitivity(dialog);
00983 }
00984 
00985 void
00986 gppat_populate_trans_mas_list(GtkToggleButton *sa_mrb,
00987                               GtkWidget *dialog)
00988 {
00989     GtkWidget *trans_mas;
00990 
00991     g_return_if_fail(GTK_IS_DIALOG(dialog));
00992 
00993     /* Cannot move transactions to subaccounts if they are to be deleted. */
00994     trans_mas = g_object_get_data(G_OBJECT(dialog), DELETE_DIALOG_TRANS_MAS);
00995     gppat_populate_gas_list(dialog, GNC_ACCOUNT_SEL(trans_mas), !gtk_toggle_button_get_active(sa_mrb));
00996 }
00997 
00998 /* Note that the emitting object (the toggle button) and the signal data
00999  * are swapped in below callback function. This is a gtkbuilder feature:
01000  * it swaps if you explicitly set an object for a signal handler in the
01001  * gtkbuilder xml file.
01002  */
01003 void
01004 gppat_set_insensitive_iff_rb_active(GtkWidget *widget, GtkToggleButton *b)
01005 {
01006     gtk_widget_set_sensitive(widget, !gtk_toggle_button_get_active(b));
01007     set_ok_sensitivity(gtk_widget_get_toplevel(widget));
01008 }
01009 
01010 static void
01011 gnc_plugin_page_account_tree_cmd_delete_account (GtkAction *action, GncPluginPageAccountTree *page)
01012 {
01013     Account *account = gnc_plugin_page_account_tree_get_current_account (page);
01014     gchar *acct_name;
01015     delete_helper_t delete_res = { FALSE, FALSE };
01016     GtkWidget *window;
01017     GtkWidget *trans_mas = NULL; /* transaction move to account selector */
01018     GtkWidget *sa_mas = NULL;    /* subaccount move to account selector */
01019     GtkWidget *sa_trans_mas = NULL; /* subaccount's transaction move to account selector */
01020     Account *ta = NULL; /* transaction adopter */
01021     Account *saa = NULL; /* subaccount adopter */
01022     Account *sta = NULL; /* subaccount transaction adopter */
01023     GList *splits;
01024     GList* list;
01025     gint response;
01026 
01027     if (NULL == account)
01028         return;
01029 
01030     /* If the account has objects referring to it, show the list - the account can't be deleted until these
01031        references are dealt with. */
01032     list = qof_instance_get_referring_object_list(QOF_INSTANCE(account));
01033     if (list != NULL)
01034     {
01035 #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"
01036 
01037         gnc_ui_object_references_show( _(EXPLANATION), list);
01038         g_list_free(list);
01039         return;
01040     }
01041 
01042     window = gnc_plugin_page_get_window(GNC_PLUGIN_PAGE(page));
01043     acct_name = gnc_account_get_full_name(account);
01044     if (!acct_name)
01045     {
01046         acct_name = g_strdup (_("(no name)"));
01047     }
01048 
01049     splits = xaccAccountGetSplitList(account);
01050 
01051     /*
01052      * If the account has transactions or child accounts then conduct a
01053      * dialog to allow the user to specify what should be done with them.
01054      */
01055     if ((NULL != splits) || (gnc_account_n_children(account) > 0))
01056     {
01057         GList *filter = NULL;
01058         GtkBuilder *builder = NULL;
01059         GtkWidget *dialog = NULL;
01060         GtkWidget *box = NULL;
01061         GtkWidget *widget = NULL;
01062         gchar *title = NULL;
01063 
01064         builder = gtk_builder_new();
01065         gnc_builder_add_from_file (builder, "dialog-account.glade", "Delete Account");
01066 
01067         dialog = GTK_WIDGET(gtk_builder_get_object (builder, "Delete Account"));
01068         gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(window));
01069 
01070         widget = GTK_WIDGET(gtk_builder_get_object (builder, "header"));
01071         title = g_strdup_printf(_("Deleting account %s"), acct_name);
01072         gtk_label_set_text(GTK_LABEL(widget), title);
01073         g_free(title);
01074 
01075         widget = GTK_WIDGET(gtk_builder_get_object (builder, DELETE_DIALOG_OK_BUTTON));
01076         g_object_set_data(G_OBJECT(dialog), DELETE_DIALOG_OK_BUTTON, widget);
01077 
01078         /*
01079          * Reparent only to accounts of the same
01080          * type as the one being deleted.
01081          */
01082         filter = g_list_prepend(NULL, (gpointer)xaccAccountGetType(account));
01083         g_object_set_data(G_OBJECT(dialog), DELETE_DIALOG_FILTER, filter);
01084         g_object_set_data(G_OBJECT(dialog), DELETE_DIALOG_ACCOUNT, account);
01085 
01086         /*
01087          * Adjust the dialog based on whether the account has
01088          * transactions.
01089          */
01090         if (splits)
01091         {
01092             delete_helper_t delete_res2 = { FALSE, FALSE };
01093 
01094             trans_mas = gnc_account_sel_new();
01095             box = GTK_WIDGET(gtk_builder_get_object (builder, "trans_mas_hbox"));
01096             gtk_box_pack_start (GTK_BOX(box), trans_mas, TRUE, TRUE, 0);
01097             g_object_set_data(G_OBJECT(dialog), DELETE_DIALOG_TRANS_MAS, trans_mas);
01098             gppat_populate_gas_list(dialog, GNC_ACCOUNT_SEL(trans_mas), FALSE);
01099 
01100             delete_account_helper(account, &delete_res2);
01101             if (delete_res2.has_ro_splits)
01102             {
01103                 gtk_widget_destroy(GTK_WIDGET(gtk_builder_get_object (builder, "trans_rw")));
01104                 widget = GTK_WIDGET(gtk_builder_get_object (builder, "trans_drb"));
01105                 gtk_widget_set_sensitive(widget, FALSE);
01106             }
01107             else
01108             {
01109                 gtk_widget_destroy(GTK_WIDGET(gtk_builder_get_object (builder, "trans_ro")));
01110             }
01111         }
01112         else
01113         {
01114             gtk_widget_destroy(GTK_WIDGET(gtk_builder_get_object (builder, "transactions")));
01115         }
01116 
01117         /*
01118          * Adjust the dialog based on whether the account has children.
01119          */
01120         if (gnc_account_n_children(account) > 0)
01121         {
01122             /*
01123              * Check for RO txns in descendants
01124              */
01125             gnc_account_foreach_descendant_until(account, delete_account_helper,
01126                                                  &delete_res);
01127             if (delete_res.has_ro_splits)
01128             {
01129                 gtk_widget_destroy(GTK_WIDGET(gtk_builder_get_object (builder, "sa_trans_rw")));
01130                 widget = GTK_WIDGET(gtk_builder_get_object (builder, "sa_trans_drb"));
01131                 gtk_widget_set_sensitive(widget, FALSE);
01132             }
01133             else if (delete_res.has_splits)
01134             {
01135                 gtk_widget_destroy(GTK_WIDGET(gtk_builder_get_object (builder, "sa_trans_ro")));
01136             }
01137             else
01138             {
01139                 gtk_widget_destroy(GTK_WIDGET(gtk_builder_get_object (builder, "subaccount_trans")));
01140             }
01141 
01142             sa_mas = gnc_account_sel_new();
01143             box = GTK_WIDGET(gtk_builder_get_object (builder, "sa_mas_hbox"));
01144             gtk_box_pack_start (GTK_BOX(box), sa_mas, TRUE, TRUE, 0);
01145             g_object_set_data(G_OBJECT(dialog), DELETE_DIALOG_SA_MAS, sa_mas);
01146             gppat_populate_gas_list(dialog, GNC_ACCOUNT_SEL(sa_mas), TRUE);
01147 
01148             sa_trans_mas = gnc_account_sel_new();
01149             box = GTK_WIDGET(gtk_builder_get_object (builder, "sa_trans_mas_hbox"));
01150             gtk_box_pack_start (GTK_BOX(box), sa_trans_mas, TRUE, TRUE, 0);
01151             g_object_set_data(G_OBJECT(dialog), DELETE_DIALOG_SA_TRANS_MAS, sa_trans_mas);
01152             gppat_populate_gas_list(dialog, GNC_ACCOUNT_SEL(sa_trans_mas), TRUE);
01153         }
01154         else
01155         {
01156             gtk_widget_destroy(GTK_WIDGET(gtk_builder_get_object (builder, "subaccounts")));
01157             gtk_widget_destroy(GTK_WIDGET(gtk_builder_get_object (builder, "subaccount_trans")));
01158         }
01159 
01160         /* default to cancel */
01161         gtk_dialog_set_default_response (GTK_DIALOG(dialog), GTK_RESPONSE_CANCEL);
01162 
01163         gtk_builder_connect_signals(builder, dialog);
01164         g_object_unref(G_OBJECT(builder));
01165 
01166         /*
01167          * Note that one effect of the modal dialog is preventing
01168          * the account selectors from being repopulated.
01169          */
01170         gtk_widget_show_all(dialog);
01171         response = gtk_dialog_run(GTK_DIALOG(dialog));
01172         if (GTK_RESPONSE_ACCEPT != response)
01173         {
01174             /* Account deletion is cancelled, so clean up and return. */
01175             gtk_widget_destroy(dialog);
01176             g_list_free(filter);
01177             g_free(acct_name);
01178             return;
01179         }
01180         if (trans_mas && GTK_WIDGET_IS_SENSITIVE(trans_mas))
01181             ta = gnc_account_sel_get_account(GNC_ACCOUNT_SEL(trans_mas));
01182         if (sa_mas && GTK_WIDGET_IS_SENSITIVE(sa_mas))
01183             saa = gnc_account_sel_get_account(GNC_ACCOUNT_SEL(sa_mas));
01184         if (sa_trans_mas && GTK_WIDGET_IS_SENSITIVE(sa_trans_mas))
01185             sta = gnc_account_sel_get_account(GNC_ACCOUNT_SEL(sa_trans_mas));
01186         gtk_widget_destroy(dialog);
01187         g_list_free(filter);
01188     } /* (NULL != splits) || (NULL != children) */
01189 
01190     /*
01191      * Present a message to the user which specifies what will be
01192      * deleted and what will be reparented, then ask for verification.
01193      */
01194     {
01195         const char *format = _("The account %s will be deleted.");
01196         char *lines[8];
01197         char *message;
01198         char *name;
01199         int i = 0;
01200         GtkWidget *dialog;
01201 
01202         lines[0] = g_strdup_printf(format, acct_name);
01203         if (splits)
01204         {
01205             if (ta)
01206             {
01207                 name = gnc_account_get_full_name(ta);
01208                 format = _("All transactions in this account will be moved to "
01209                            "the account %s.");
01210                 lines[++i] = g_strdup_printf(format, name);
01211             }
01212             else if (splits)
01213             {
01214                 format = _("All transactions in this account will be deleted.");
01215                 lines[++i] = g_strdup_printf("%s", format);
01216             }
01217         }
01218         if (gnc_account_n_children(account) > 0)
01219         {
01220             if (saa)
01221             {
01222                 name = gnc_account_get_full_name(saa);
01223                 format = _("All of its sub-accounts will be moved to "
01224                            "the account %s.");
01225                 lines[++i] = g_strdup_printf(format, name);
01226             }
01227             else
01228             {
01229                 format = _("All of its subaccounts will be deleted.");
01230                 lines[++i] = g_strdup_printf("%s", format);
01231                 if (sta)
01232                 {
01233                     name = gnc_account_get_full_name(sta);
01234                     format = _("All sub-account transactions will be moved to "
01235                                "the account %s.");
01236                     lines[++i] = g_strdup_printf(format, name);
01237                 }
01238                 else if (delete_res.has_splits)
01239                 {
01240                     format = _("All sub-account transactions will be deleted.");
01241                     lines[++i] = g_strdup_printf("%s", format);
01242                 }
01243             }
01244         }
01245         lines[++i] = _("Are you sure you want to do this?");
01246         lines[i] = NULL;
01247         i--; /* Don't try to free the constant question. */
01248         message = g_strjoinv(" ", lines);
01249         while (i--)
01250         {
01251             g_free(lines[i]);
01252         }
01253 
01254         dialog =  gtk_message_dialog_new(GTK_WINDOW(window),
01255                                          GTK_DIALOG_DESTROY_WITH_PARENT,
01256                                          GTK_MESSAGE_QUESTION,
01257                                          GTK_BUTTONS_NONE,
01258                                          "%s", message);
01259         g_free(message);
01260         gtk_dialog_add_buttons(GTK_DIALOG(dialog),
01261                                GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
01262                                GTK_STOCK_DELETE, GTK_RESPONSE_ACCEPT,
01263                                (gchar *)NULL);
01264         gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_CANCEL);
01265         response = gtk_dialog_run(GTK_DIALOG(dialog));
01266         gtk_widget_destroy(dialog);
01267 
01268         if (GTK_RESPONSE_ACCEPT == response)
01269         {
01270             gnc_set_busy_cursor(NULL, TRUE);
01271             gnc_suspend_gui_refresh ();
01272             xaccAccountBeginEdit (account);
01273             if (NULL != saa)
01274             {
01275                 GList *acct_list, *ptr;
01276 
01277                 xaccAccountBeginEdit (saa);
01278                 acct_list = gnc_account_get_children(account);
01279                 for (ptr = acct_list; ptr; ptr = g_list_next(ptr))
01280                     gnc_account_append_child (saa, ptr->data);
01281                 g_list_free(acct_list);
01282                 xaccAccountCommitEdit (saa);
01283             }
01284             else if (NULL != sta)
01285             {
01286                 /* Move the splits of its subaccounts, if any. */
01287                 gnc_account_foreach_descendant(account,
01288                                                (AccountCb)xaccAccountMoveAllSplits,
01289                                                sta);
01290             }
01291             if (NULL != ta)
01292             {
01293                 /* Move the splits of the account to be deleted. */
01294                 xaccAccountMoveAllSplits (account, ta);
01295             }
01296             /*
01297              * Finally, delete the account, any subaccounts it may still
01298              * have, and any splits it or its subaccounts may still have.
01299              */
01300             xaccAccountDestroy (account);
01301             gnc_resume_gui_refresh ();
01302             gnc_unset_busy_cursor(NULL);
01303         }
01304     }
01305     g_free(acct_name);
01306 }
01307 
01308 static void
01309 gnc_plugin_page_account_tree_cmd_renumber_accounts (GtkAction *action,
01310         GncPluginPageAccountTree *page)
01311 {
01312     Account *account;
01313     GtkWidget *window;
01314 
01315     window = gnc_plugin_page_get_window(GNC_PLUGIN_PAGE(page));
01316     account = gnc_plugin_page_account_tree_get_current_account(page);
01317     if (!window || !account)
01318         return;
01319 
01320     gnc_account_renumber_create_dialog(window, account);
01321 }
01322 
01323 /*********************/
01324 
01325 static void
01326 gnc_plugin_page_account_tree_cmd_view_filter_by (GtkAction *action,
01327         GncPluginPageAccountTree *page)
01328 {
01329     GncPluginPageAccountTreePrivate *priv;
01330 
01331     g_return_if_fail(GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE(page));
01332     ENTER("(action %p, page %p)", action, page);
01333 
01334     priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
01335     account_filter_dialog_create(&priv->fd, GNC_PLUGIN_PAGE(page));
01336     LEAVE(" ");
01337 }
01338 
01339 static void
01340 gnc_plugin_page_account_tree_cmd_reconcile (GtkAction *action,
01341         GncPluginPageAccountTree *page)
01342 {
01343     GtkWidget *window;
01344     Account *account;
01345     RecnWindow *recnData;
01346 
01347     account = gnc_plugin_page_account_tree_get_current_account (page);
01348     g_return_if_fail (account != NULL);
01349 
01350     window = GNC_PLUGIN_PAGE (page)->window;
01351     recnData = recnWindow (window, account);
01352     gnc_ui_reconcile_window_raise (recnData);
01353 }
01354 
01355 static void
01356 gnc_plugin_page_account_tree_cmd_autoclear (GtkAction *action,
01357         GncPluginPageAccountTree *page)
01358 {
01359     GtkWidget *window;
01360     Account *account;
01361     AutoClearWindow *autoClearData;
01362 
01363     account = gnc_plugin_page_account_tree_get_current_account (page);
01364     g_return_if_fail (account != NULL);
01365 
01366     window = GNC_PLUGIN_PAGE (page)->window;
01367     autoClearData = autoClearWindow (window, account);
01368     gnc_ui_autoclear_window_raise (autoClearData);
01369 }
01370 
01371 static void
01372 gnc_plugin_page_account_tree_cmd_transfer (GtkAction *action,
01373         GncPluginPageAccountTree *page)
01374 {
01375     GtkWidget *window;
01376     Account *account;
01377 
01378     account = gnc_plugin_page_account_tree_get_current_account (page);
01379     window = GNC_PLUGIN_PAGE (page)->window;
01380     gnc_xfer_dialog (window, account);
01381 }
01382 
01383 static void
01384 gnc_plugin_page_account_tree_cmd_stock_split (GtkAction *action,
01385         GncPluginPageAccountTree *page)
01386 {
01387     GtkWidget *window;
01388     Account *account;
01389 
01390     account = gnc_plugin_page_account_tree_get_current_account (page);
01391     window = GNC_PLUGIN_PAGE (page)->window;
01392     gnc_stock_split_dialog (window, account);
01393 }
01394 
01395 static void
01396 gnc_plugin_page_account_tree_cmd_lots (GtkAction *action,
01397                                        GncPluginPageAccountTree *page)
01398 {
01399     Account *account;
01400 
01401     account = gnc_plugin_page_account_tree_get_current_account (page);
01402     gnc_lot_viewer_dialog (account);
01403 }
01404 
01405 static void
01406 gnc_plugin_page_account_tree_cmd_scrub (GtkAction *action, GncPluginPageAccountTree *page)
01407 {
01408     Account *account = gnc_plugin_page_account_tree_get_current_account (page);
01409 
01410     g_return_if_fail (account != NULL);
01411 
01412     gnc_suspend_gui_refresh ();
01413 
01414     xaccAccountScrubOrphans (account);
01415     xaccAccountScrubImbalance (account);
01416 
01417     // XXX: Lots are disabled
01418     if (g_getenv("GNC_AUTO_SCRUB_LOTS") != NULL)
01419         xaccAccountScrubLots(account);
01420 
01421     gnc_resume_gui_refresh ();
01422 }
01423 
01424 static void
01425 gnc_plugin_page_account_tree_cmd_scrub_sub (GtkAction *action, GncPluginPageAccountTree *page)
01426 {
01427     Account *account = gnc_plugin_page_account_tree_get_current_account (page);
01428 
01429     g_return_if_fail (account != NULL);
01430 
01431     gnc_suspend_gui_refresh ();
01432 
01433     xaccAccountTreeScrubOrphans (account);
01434     xaccAccountTreeScrubImbalance (account);
01435 
01436     // XXX: Lots are disabled
01437     if (g_getenv("GNC_AUTO_SCRUB_LOTS") != NULL)
01438         xaccAccountTreeScrubLots(account);
01439 
01440     gnc_resume_gui_refresh ();
01441 }
01442 
01443 static void
01444 gnc_plugin_page_account_tree_cmd_scrub_all (GtkAction *action, GncPluginPageAccountTree *page)
01445 {
01446     Account *root = gnc_get_current_root_account ();
01447 
01448     gnc_suspend_gui_refresh ();
01449 
01450     xaccAccountTreeScrubOrphans (root);
01451     xaccAccountTreeScrubImbalance (root);
01452     // XXX: Lots are disabled
01453     if (g_getenv("GNC_AUTO_SCRUB_LOTS") != NULL)
01454         xaccAccountTreeScrubLots(root);
01455 
01456     gnc_resume_gui_refresh ();
01457 }
01458 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines