You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gnucash/src/gnome/druid-hierarchy.c

944 lines
24 KiB

/********************************************************************\
* druid-hierarchy.c -- account hierarchy creation functionality *
* Copyright (C) 2001 Gnumatic, Inc. *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
* Boston, MA 02111-1307, USA gnu@gnu.org *
\********************************************************************/
#include "config.h"
#include <gnome.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "Group.h"
#include "dialog-new-user.h"
#include "dialog-utils.h"
#include "druid-hierarchy.h"
#include "druid-utils.h"
#include "gnc-amount-edit.h"
#include "gnc-commodity-edit.h"
#include "gnc-general-select.h"
#include "gnc-component-manager.h"
#include "../gnome-utils/gnc-dir.h"
#include "gnc-gui-query.h"
#include "gnc-ui-util.h"
#include "io-example-account.h"
#include "top-level.h"
static GtkWidget *hierarchy_window = NULL;
static AccountGroup *our_final_group = NULL;
static void on_balance_changed (GNCAmountEdit *gae);
static GtkWidget*
hierarchy_get_widget (const char *name)
{
if (!hierarchy_window) return NULL;
return gnc_glade_lookup_widget (hierarchy_window, name);
}
static GtkCTree *
hierarchy_get_final_account_tree (void)
{
return GTK_CTREE (hierarchy_get_widget ("final_account_ctree"));
}
static void
delete_hierarchy_window (void)
{
if (!hierarchy_window) return;
gtk_widget_destroy (hierarchy_window);
hierarchy_window = NULL;
}
static void
destroy_hash_helper (gpointer key, gpointer value, gpointer user_data)
{
char *fullname = key;
gnc_numeric *balance = value;
g_free (fullname);
g_free (balance);
}
static GNCAmountEdit *
get_balance_editor (void)
{
if (!hierarchy_window) return NULL;
return gtk_object_get_data (GTK_OBJECT (hierarchy_window), "balance_editor");
}
static GtkCList*
get_account_types_clist (void)
{
return GTK_CLIST(hierarchy_get_widget ("account_types_clist"));
}
static GNCGeneralSelect *
get_commodity_editor(void)
{
GtkWidget *tmp_wid = gtk_object_get_data (GTK_OBJECT (hierarchy_window),
"commod_editor");
if(!tmp_wid)
{
GNCGeneralSelect *cur_editor;
cur_editor =
GNC_GENERAL_SELECT (gnc_general_select_new(gnc_commodity_edit_get_string,
gnc_commodity_edit_new_select));
gtk_widget_show (GTK_WIDGET(cur_editor));
gnc_general_select_set_selected (cur_editor,
gnc_locale_default_currency());
gtk_object_set_data(GTK_OBJECT(hierarchy_window),
"commod_editor", cur_editor);
return cur_editor;
}
else
{
return GNC_GENERAL_SELECT(tmp_wid);
}
}
static void
gnc_hierarchy_destroy_cb (GtkObject *obj, gpointer user_data)
{
GHashTable *hash;
hash = gtk_object_get_data (obj, "balance_hash");
if (hash)
{
g_hash_table_foreach (hash, destroy_hash_helper, NULL);
g_hash_table_destroy (hash);
gtk_object_set_data (obj, "balance_hash", NULL);
}
}
static void
block_amount_changed (void)
{
GNCAmountEdit *balance_edit;
balance_edit = get_balance_editor ();
if (!balance_edit) return;
gtk_signal_handler_block_by_func
(GTK_OBJECT (balance_edit),
GTK_SIGNAL_FUNC(on_balance_changed), NULL);
}
static void
unblock_amount_changed (void)
{
GNCAmountEdit *balance_edit;
balance_edit = get_balance_editor ();
if (!balance_edit) return;
gtk_signal_handler_unblock_by_func
(GTK_OBJECT (balance_edit),
GTK_SIGNAL_FUNC(on_balance_changed), NULL);
}
static gnc_numeric
get_final_balance (Account *account)
{
GHashTable *hash;
gnc_numeric *balance;
char *fullname;
if (!account || !hierarchy_window) return gnc_numeric_zero ();
hash = gtk_object_get_data (GTK_OBJECT (hierarchy_window), "balance_hash");
if (!hash) return gnc_numeric_zero ();
fullname = xaccAccountGetFullName (account, ':');
balance = g_hash_table_lookup (hash, fullname);
g_free (fullname);
if (balance)
return *balance;
return gnc_numeric_zero ();
}
static void
set_final_balance (Account *account, gnc_numeric in_balance)
{
GHashTable *hash;
gnc_numeric *balance;
char *fullname;
if (!account || !hierarchy_window) return;
hash = gtk_object_get_data (GTK_OBJECT (hierarchy_window), "balance_hash");
if (!hash) return;
fullname = xaccAccountGetFullName (account, ':');
balance = g_hash_table_lookup (hash, fullname);
if (balance)
{
*balance = in_balance;
g_free (fullname);
}
else
{
balance = g_new (gnc_numeric, 1);
*balance = in_balance;
g_hash_table_insert (hash, fullname, balance);
}
}
static void
update_account_balance (GtkCTree *ctree, GtkCTreeNode *node)
{
Account *account;
GNCAmountEdit *balance_edit;
gboolean result;
balance_edit = get_balance_editor ();
account = gtk_ctree_node_get_row_data (ctree, node);
if (!account)
return;
block_amount_changed ();
result = gnc_amount_edit_evaluate (balance_edit);
unblock_amount_changed ();
if (result)
{
gnc_numeric balance;
GNCPrintAmountInfo print_info;
const char *string;
balance = gnc_amount_edit_get_amount (balance_edit);
print_info = gnc_account_print_info (account, FALSE);
string = xaccPrintAmount (balance, print_info);
if (gnc_numeric_zero_p (balance))
string = "";
gtk_ctree_node_set_text (ctree, GTK_CTREE_NODE (node), 2, string);
if (gnc_reverse_balance (account))
balance = gnc_numeric_neg (balance);
set_final_balance (account, balance);
}
}
static void
on_balance_changed (GNCAmountEdit *gae)
{
GtkCTree *ctree;
GtkCTreeNode *node;
if (!GTK_WIDGET_SENSITIVE (GTK_WIDGET (gae)))
return;
ctree = hierarchy_get_final_account_tree ();
if (!ctree)
return;
node = gtk_ctree_node_nth (ctree, GTK_CLIST(ctree)->focus_row);
if (!node)
return;
update_account_balance (ctree, node);
}
static void
on_choose_currency_prepare (GnomeDruidPage *gnomedruidpage,
gpointer arg1,
gpointer user_data)
{
if(!GPOINTER_TO_INT (gtk_object_get_data
(GTK_OBJECT(hierarchy_window), "commod_added")))
{
gtk_object_set_data (GTK_OBJECT(hierarchy_window),
"commod_added", GINT_TO_POINTER (1));
gtk_box_pack_start(GTK_BOX(gnc_glade_lookup_widget
(hierarchy_window, "currency_chooser_vbox")),
GTK_WIDGET(get_commodity_editor()), FALSE, FALSE, 0);
}
}
static gchar*
gnc_get_ea_locale_dir(const char *top_dir)
{
static gchar *default_locale = "C";
gchar *ret;
gchar *locale;
struct stat buf;
locale = g_strdup(setlocale(LC_MESSAGES, NULL));
ret = g_strdup_printf("%s/%s", top_dir, locale);
if(stat(ret, &buf) != 0 && (strlen (locale) > 2))
{
g_free (ret);
locale[2] = '\0';
ret = g_strdup_printf("%s/%s", top_dir, locale);
}
if(stat(ret, &buf) != 0)
{
g_free (ret);
ret = g_strdup_printf("%s/%s", top_dir, default_locale);
}
g_free(locale);
return ret;
}
static void
add_each_gea_to_clist (gpointer data, gpointer user_data)
{
GncExampleAccount *gea = (GncExampleAccount*)data;
GtkCList *clist = GTK_CLIST (user_data);
gchar *rowdata[2];
int row = 0;
rowdata[0] = gea->title;
rowdata[1] = gea->short_description;
row = gtk_clist_insert(clist, row, rowdata);
gtk_clist_set_row_data(clist, row, gea);
}
static void
on_choose_account_types_prepare (GnomeDruidPage *gnomedruidpage,
gpointer arg1,
gpointer user_data)
{
gpointer added_ptr;
added_ptr = gtk_object_get_data (GTK_OBJECT(hierarchy_window),
"account_list_added");
if (!GPOINTER_TO_INT(added_ptr))
{
GSList *list;
GtkCList *clist;
gchar *locale_dir = gnc_get_ea_locale_dir (GNC_ACCOUNTS_DIR);
gnc_suspend_gui_refresh ();
list = gnc_load_example_account_list (gnc_get_current_session (),
locale_dir);
gnc_resume_gui_refresh ();
clist = get_account_types_clist ();
gtk_clist_freeze (clist);
g_slist_foreach (list, add_each_gea_to_clist, (gpointer)clist);
gtk_clist_set_sort_column (clist, 0);
gtk_clist_sort (clist);
gtk_clist_thaw (clist);
g_slist_free (list);
g_free (locale_dir);
gtk_object_set_data (GTK_OBJECT(hierarchy_window),
"account_list_added",
GINT_TO_POINTER(1));
}
}
static gpointer
add_to_tree_account (Account* toadd, gpointer data)
{
GtkWidget *item;
GtkTree *tree = GTK_TREE (data);
if (!toadd)
return NULL;
item = gtk_tree_item_new_with_label (xaccAccountGetName(toadd));
gtk_tree_insert (tree, item, 0);
gtk_widget_show (item);
if (xaccGroupGetNumSubAccounts (xaccAccountGetChildren (toadd)) > 0)
{
GtkWidget *subtree = gtk_tree_new ();
gtk_tree_item_set_subtree (GTK_TREE_ITEM(item), subtree);
gtk_tree_item_expand (GTK_TREE_ITEM(item));
xaccGroupForEachAccount (xaccAccountGetChildren(toadd),
add_to_tree_account, subtree, FALSE);
}
return NULL;
}
static void
add_to_tree (GtkTree *tree, AccountGroup *grp)
{
xaccGroupForEachAccount(grp, add_to_tree_account, tree, FALSE);
}
static void
on_account_types_list_select_row (GtkCList *clist,
gint row,
gint column,
GdkEvent *event,
gpointer user_data)
{
GtkLabel *datext = GTK_LABEL (hierarchy_get_widget
("account_types_description_entry"));
GtkTree *datree = GTK_TREE (hierarchy_get_widget ("account_type_tree"));
GncExampleAccount *gea = gtk_clist_get_row_data (clist, row);
if(gea->long_description != NULL)
gtk_label_set_text (datext, gea->long_description);
gtk_tree_clear_items (datree, 0, g_list_length (datree->children));
add_to_tree (datree, gea->group);
}
static void
on_account_types_list_unselect_row (GtkCList *clist,
gint row,
gint column,
GdkEvent *event,
gpointer user_data)
{
GtkLabel *datext = GTK_LABEL (hierarchy_get_widget
("account_types_description_entry"));
GtkTree *datree = GTK_TREE (hierarchy_get_widget ("account_type_tree"));
gtk_label_set_text (datext, "");
gtk_tree_clear_items (datree, 0, g_list_length (datree->children));
}
static void
select_all_clicked (GtkButton *button,
gpointer user_data)
{
gtk_clist_select_all (get_account_types_clist ());
}
static void
clear_all_clicked (GtkButton *button,
gpointer user_data)
{
gtk_clist_unselect_all (get_account_types_clist ());
}
typedef struct FinalInsertData_struct
{
GtkCTree *tree;
GtkCTreeNode *node;
GtkCTreeNode *sibling;
} FinalInsertData;
static gchar**
generate_account_titles (Account *act)
{
gchar **ret;
ret = g_new (gchar *, 3);
ret[0] = (gchar*)xaccAccountGetName(act);
ret[1] = (gchar*)xaccAccountGetTypeStr(xaccAccountGetType(act));
{
gnc_numeric balance;
const char *string;
balance = get_final_balance (act);
if (gnc_numeric_zero_p (balance))
string = "";
else
{
GNCPrintAmountInfo print_info;
print_info = gnc_account_print_info (act, FALSE);
string = xaccPrintAmount (balance, print_info);
}
ret[2] = (gchar*)string;
}
return ret;
}
static void
free_account_titles (gchar **tofree)
{
g_free (tofree);
}
static gpointer
add_to_ctree_final_account (Account* toadd, gpointer data)
{
FinalInsertData *topdata = (FinalInsertData*)data;
GtkCTreeNode *node;
gchar **titles;
titles = generate_account_titles (toadd);
node = gtk_ctree_insert_node (topdata->tree, topdata->node,
topdata->sibling,
titles, 0,
NULL, NULL, NULL, NULL,
FALSE, TRUE);
free_account_titles (titles);
gtk_ctree_node_set_row_data (topdata->tree, node, toadd);
if (xaccGroupGetNumAccounts (xaccAccountGetChildren (toadd)) > 0)
{
FinalInsertData nextdata;
nextdata.tree = topdata->tree;
nextdata.node = node;
nextdata.sibling = NULL;
xaccGroupForEachAccount (xaccAccountGetChildren(toadd),
add_to_ctree_final_account, &nextdata, FALSE);
}
topdata->sibling = node;
return NULL;
}
static void
insert_final_accounts (GtkCTree *tree, AccountGroup *group)
{
FinalInsertData data;
data.tree = tree;
data.node = NULL;
data.sibling = NULL;
xaccGroupForEachAccount(group, add_to_ctree_final_account, &data, FALSE);
}
static void
delete_our_final_group (void)
{
if (our_final_group != NULL)
{
xaccFreeAccountGroup (our_final_group);
our_final_group = NULL;
}
}
static Account*
clone_account (const Account* from, gnc_commodity *com)
{
Account *ret;
ret = xaccCloneAccountSimple (from, gnc_get_current_session ());
xaccAccountSetCommodity (ret, com);
return ret;
}
struct add_group_data_struct
{
AccountGroup *to;
Account *parent;
gnc_commodity *com;
};
static gpointer
add_groups_for_each (Account *toadd, gpointer data)
{
struct add_group_data_struct *dadata = data;
Account *foundact;
foundact = xaccGetAccountFromName (dadata->to, xaccAccountGetName(toadd));
if (!foundact)
{
foundact = clone_account (toadd, dadata->com);
if (dadata->to)
xaccGroupInsertAccount (dadata->to, foundact);
else if (dadata->parent)
xaccAccountInsertSubAccount (dadata->parent, foundact);
else
{
g_warning ("add_groups_for_each: no valid parent");
}
}
{
AccountGroup *addgrp = xaccAccountGetChildren (toadd);
if (xaccGroupGetNumAccounts(addgrp) > 0)
{
struct add_group_data_struct downdata;
downdata.to = xaccAccountGetChildren(foundact);
downdata.parent = foundact;
downdata.com = dadata->com;
xaccGroupForEachAccount (addgrp, add_groups_for_each,
&downdata, FALSE);
}
}
return NULL;
}
static void
add_groups_to_with_random_guids (AccountGroup *into, AccountGroup *from,
gnc_commodity *com)
{
struct add_group_data_struct data;
data.to = into;
data.parent = NULL;
data.com = com;
xaccGroupForEachAccount (from, add_groups_for_each, &data, FALSE);
}
static AccountGroup *
hierarchy_merge_groups (GSList *dalist)
{
GSList *mark;
gnc_commodity *com;
AccountGroup *ret = xaccMallocAccountGroup (gnc_get_current_session ());
com = gnc_general_select_get_selected (get_commodity_editor ());
for (mark = dalist; mark; mark = mark->next)
{
GncExampleAccount *xea = mark->data;
add_groups_to_with_random_guids (ret, xea->group, com);
}
return ret;
}
static void
on_final_account_prepare (GnomeDruidPage *gnomedruidpage,
gpointer arg1,
gpointer user_data)
{
GtkCList *clist;
GtkWidget *ctree;
GSList *actlist;
GList *dalist;
clist = get_account_types_clist ();
ctree = GTK_WIDGET (hierarchy_get_final_account_tree ());
gtk_clist_clear (GTK_CLIST(ctree));
actlist = NULL;
for (dalist = clist->selection; dalist; dalist = dalist->next)
{
int row = GPOINTER_TO_INT(dalist->data);
actlist = g_slist_append (actlist, gtk_clist_get_row_data(clist, row));
}
gnc_suspend_gui_refresh ();
delete_our_final_group ();
our_final_group = hierarchy_merge_groups (actlist);
gnc_resume_gui_refresh ();
insert_final_accounts (GTK_CTREE(ctree), our_final_group);
gnc_clist_columns_autosize (GTK_CLIST(ctree));
{
GNCAmountEdit *balance_edit;
GtkWidget *entry;
block_amount_changed ();
balance_edit = get_balance_editor ();
gnc_amount_edit_set_amount (balance_edit, gnc_numeric_zero ());
entry = gnc_amount_edit_gtk_entry (balance_edit);
gtk_entry_set_text (GTK_ENTRY (entry), "");
unblock_amount_changed ();
gtk_widget_set_sensitive (GTK_WIDGET (balance_edit), FALSE);
}
}
static void
on_final_account_tree_select_row (GtkCTree *ctree,
GList *node,
gint column,
gpointer user_data)
{
Account *account;
GNCAmountEdit *balance_edit;
GNCPrintAmountInfo print_info;
gnc_numeric balance;
balance_edit = get_balance_editor ();
account = gtk_ctree_node_get_row_data (ctree, GTK_CTREE_NODE (node));
if (!account || xaccAccountGetType (account) == EQUITY)
{
GtkWidget *entry;
entry = gnc_amount_edit_gtk_entry (balance_edit);
gtk_entry_set_text (GTK_ENTRY (entry), "");
gtk_widget_set_sensitive (GTK_WIDGET (balance_edit), FALSE);
return;
}
gtk_widget_set_sensitive (GTK_WIDGET (balance_edit), TRUE);
balance = get_final_balance (account);
if (gnc_reverse_balance (account))
balance = gnc_numeric_neg (balance);
print_info = gnc_account_print_info (account, FALSE);
gnc_amount_edit_set_print_info (balance_edit, print_info);
gnc_amount_edit_set_fraction (balance_edit,
xaccAccountGetCommoditySCU (account));
block_amount_changed ();
gnc_amount_edit_set_amount (balance_edit, balance);
if (gnc_numeric_zero_p (balance))
{
GtkWidget *entry;
entry = gnc_amount_edit_gtk_entry (balance_edit);
gtk_entry_set_text (GTK_ENTRY (entry), "");
}
unblock_amount_changed ();
}
static void
on_final_account_tree_unselect_row (GtkCTree *ctree,
GList *node,
gint column,
gpointer user_data)
{
update_account_balance (ctree, GTK_CTREE_NODE (node));
{
GNCAmountEdit *balance_edit;
GtkWidget *entry;
balance_edit = get_balance_editor ();
entry = gnc_amount_edit_gtk_entry (balance_edit);
gtk_entry_set_text (GTK_ENTRY (entry), "");
gtk_widget_set_sensitive (GTK_WIDGET (balance_edit), FALSE);
}
}
static gboolean
on_final_account_next (GnomeDruidPage *gnomedruidpage,
gpointer arg1,
gpointer user_data)
{
GNCAmountEdit *balance_edit;
balance_edit = get_balance_editor ();
if (!gnc_amount_edit_evaluate (balance_edit))
{
GtkWidget *top;
const char *message = _("You must enter a valid balance.");
top = gtk_widget_get_toplevel (GTK_WIDGET (gnomedruidpage));
gnc_error_dialog_parented (GTK_WINDOW(top), message);
return TRUE;
}
return FALSE;
}
static void
cancel_everything_out(void)
{
delete_our_final_group ();
delete_hierarchy_window ();
gncp_new_user_finish ();
}
static void
on_cancel (GnomeDruid *gnomedruid,
gpointer user_data)
{
cancel_everything_out ();
}
static gpointer
starting_balance_helper (Account *account, gpointer data)
{
gnc_numeric balance;
balance = get_final_balance (account);
if (!gnc_numeric_zero_p (balance))
gnc_account_create_opening_balance (account, balance, time (NULL),
gnc_get_current_session ());
return NULL;
}
static void
on_finish (GnomeDruidPage *gnomedruidpage,
gpointer arg1,
gpointer user_data)
{
gnc_suspend_gui_refresh ();
if (our_final_group)
xaccGroupForEachAccount (our_final_group, starting_balance_helper,
NULL, TRUE);
delete_hierarchy_window ();
gncp_new_user_finish ();
gnc_set_first_startup (FALSE);
if (our_final_group)
xaccGroupConcatGroup (gnc_get_current_group (), our_final_group);
gnc_resume_gui_refresh ();
}
static GtkWidget *
gnc_create_hierarchy_druid (void)
{
GtkWidget *balance_edit;
GtkWidget *dialog;
GtkWidget *druid;
GtkWidget *clist;
GtkWidget *box;
GHashTable *hash;
GladeXML *xml;
xml = gnc_glade_xml_new ("account.glade", "Hierarchy Druid");
glade_xml_signal_connect
(xml, "on_choose_currency_prepare",
GTK_SIGNAL_FUNC (on_choose_currency_prepare));
glade_xml_signal_connect
(xml, "on_choose_account_types_prepare",
GTK_SIGNAL_FUNC (on_choose_account_types_prepare));
glade_xml_signal_connect
(xml, "on_account_types_list_select_row",
GTK_SIGNAL_FUNC (on_account_types_list_select_row));
glade_xml_signal_connect
(xml, "on_account_types_list_unselect_row",
GTK_SIGNAL_FUNC (on_account_types_list_unselect_row));
glade_xml_signal_connect
(xml, "on_final_account_prepare",
GTK_SIGNAL_FUNC (on_final_account_prepare));
glade_xml_signal_connect
(xml, "on_final_account_tree_select_row",
GTK_SIGNAL_FUNC (on_final_account_tree_select_row));
glade_xml_signal_connect
(xml, "on_final_account_tree_unselect_row",
GTK_SIGNAL_FUNC (on_final_account_tree_unselect_row));
glade_xml_signal_connect
(xml, "on_final_account_next",
GTK_SIGNAL_FUNC (on_final_account_next));
glade_xml_signal_connect
(xml, "select_all_clicked", GTK_SIGNAL_FUNC (select_all_clicked));
glade_xml_signal_connect
(xml, "clear_all_clicked", GTK_SIGNAL_FUNC (clear_all_clicked));
glade_xml_signal_connect (xml, "on_finish", GTK_SIGNAL_FUNC (on_finish));
glade_xml_signal_connect (xml, "on_cancel", GTK_SIGNAL_FUNC (on_cancel));
dialog = glade_xml_get_widget (xml, "Hierarchy Druid");
druid = glade_xml_get_widget (xml, "hierarchy_druid");
gnc_druid_set_colors (GNOME_DRUID (druid));
balance_edit = gnc_amount_edit_new ();
gnc_amount_edit_set_evaluate_on_enter (GNC_AMOUNT_EDIT (balance_edit), TRUE);
gtk_widget_show (balance_edit);
gtk_signal_connect (GTK_OBJECT (balance_edit), "amount_changed",
GTK_SIGNAL_FUNC(on_balance_changed), NULL);
clist = glade_xml_get_widget (xml, "account_types_clist");
gtk_clist_column_titles_passive (GTK_CLIST (clist));
box = glade_xml_get_widget (xml, "start_balance_box");
gtk_box_pack_start (GTK_BOX (box), balance_edit, TRUE, TRUE, 0);
gtk_object_set_data (GTK_OBJECT(dialog), "balance_editor", balance_edit);
hash = g_hash_table_new (g_str_hash, g_str_equal);
gtk_object_set_data (GTK_OBJECT(dialog), "balance_hash", hash);
gtk_signal_connect (GTK_OBJECT(dialog), "destroy",
GTK_SIGNAL_FUNC(gnc_hierarchy_destroy_cb), NULL);
return dialog;
}
void
gnc_ui_hierarchy_druid (void)
{
if (hierarchy_window) return;
hierarchy_window = gnc_create_hierarchy_druid ();
return;
}