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/import-export/binary-import/druid-commodity.c

512 lines
17 KiB

/********************************************************************
* druid-commodity.c -- fancy importer for old Gnucash files *
* (GnuCash) *
* Copyright (C) 2000 Bill Gribble <grib@billgribble.com> *
* *
* 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 *
********************************************************************/
#define _GNU_SOURCE
#include "config.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <glib.h>
#include "Scrub.h"
#include "dialog-commodity.h"
#include "dialog-utils.h"
#include "druid-commodity.h"
#include "druid-utils.h"
#include "gnc-commodity.h"
#include "gnc-engine-util.h"
#include "gnc-engine.h"
#include "gnc-file.h"
#include "gnc-gui-query.h"
#include "gnc-pricedb-p.h"
#include "gnc-ui-util.h"
#include "gnc-ui.h"
/* This static indicates the debugging module that this .o belongs to. */
static short module = MOD_GUI;
struct _commoditydruid {
GtkWidget * window;
GtkWidget * druid;
GtkWidget * intro_page;
GtkWidget * finish_page;
GHashTable * new_map;
GHashTable * old_map;
GList * pages;
int is_modal;
};
struct _commoditydruidpage {
GtkWidget * page;
char * old_name;
GtkWidget * new_type_combo;
GtkWidget * new_name_entry;
GtkWidget * new_mnemonic_entry;
};
typedef struct _commoditydruidpage CommodityDruidPage;
static CommodityDruidPage * make_commodity_druid_page(gnc_commodity * comm);
static GdkColor std_bg_color = { 0, 39835, 49087, 40092 };
static GdkColor std_logo_bg_color = { 0, 65535, 65535, 65535 };
static GdkColor std_title_color = { 0, 65535, 65535, 65535 };
static int gnc_ui_commodity_druid_comm_check_cb(GnomeDruidPage * page,
gpointer druid,
gpointer user_data);
static gboolean gnc_ui_commodity_druid_cancel_cb(GnomeDruidPage * page,
gpointer druid,
gpointer user_data);
static void gnc_ui_commodity_druid_finish_cb(GnomeDruidPage * page,
gpointer druid,
gpointer user_data);
void
gnc_import_legacy_commodities(const char * filename)
{
CommodityDruid * d;
if (!gnc_commodity_table_has_namespace (gnc_get_current_commodities (),
GNC_COMMODITY_NS_LEGACY))
return;
d = gnc_ui_commodity_druid_create(filename);
d->is_modal = TRUE;
gtk_window_set_modal(GTK_WINDOW(d->window), TRUE);
gtk_main();
}
static gboolean
window_delete_cb(GtkWidget *widget,
GdkEvent *event,
gpointer user_data)
{
CommodityDruid *cd = user_data;
/* unload the current file (can't have out-of-date commodities) */
gnc_file_quit ();
gnc_ui_commodity_druid_destroy (cd);
/* Don't delete the window, we'll handle things ourselves. */
return TRUE;
}
/********************************************************************
* gnc_ui_commodity_druid_create()
********************************************************************/
CommodityDruid *
gnc_ui_commodity_druid_create(const char * filename)
{
CommodityDruid * d = g_new0(CommodityDruid, 1);
GtkObject * dobj;
GList * orphans, * l;
gnc_commodity * lost;
gnc_commodity * found;
CommodityDruidPage * new_page;
GnomeDruidPage * back_page;
GladeXML * xml;
xml = gnc_glade_xml_new ("binary-import.glade",
"New Commodity Format Druid");
d->window = glade_xml_get_widget (xml, "New Commodity Format Druid");
dobj = GTK_OBJECT(d->window);
gtk_signal_connect (dobj, "delete_event",
GTK_SIGNAL_FUNC (window_delete_cb), d);
d->druid = glade_xml_get_widget (xml, "commodity_druid");
d->intro_page = glade_xml_get_widget (xml, "start_page");
d->finish_page = glade_xml_get_widget (xml, "finish_page");
back_page = GNOME_DRUID_PAGE(d->intro_page);
d->is_modal = FALSE;
glade_xml_signal_connect_data
(xml, "gnc_ui_commodity_druid_cancel_cb",
GTK_SIGNAL_FUNC (gnc_ui_commodity_druid_cancel_cb), d);
glade_xml_signal_connect_data
(xml, "gnc_ui_commodity_druid_finish_cb",
GTK_SIGNAL_FUNC (gnc_ui_commodity_druid_finish_cb), d);
d->new_map = g_hash_table_new(g_str_hash, g_str_equal);
d->old_map = g_hash_table_new(g_str_hash, g_str_equal);
orphans =
gnc_commodity_table_get_commodities(gnc_get_current_commodities(),
GNC_COMMODITY_NS_LEGACY);
/* make a new list with the (saved) old mnemonic and the
* new currency. */
for(l=orphans; l; l=l->next) {
lost = (gnc_commodity *)l->data;
/* if the mnemonic is an ISO-4217 currency, use that as
* the default */
found = gnc_commodity_table_lookup(gnc_get_current_commodities(),
GNC_COMMODITY_NS_ISO,
gnc_commodity_get_mnemonic(lost));
/* otherwise, guess that it's a NASDAQ security. */
if(!found) {
found = gnc_commodity_new(gnc_commodity_get_mnemonic(lost),
GNC_COMMODITY_NS_NASDAQ,
gnc_commodity_get_mnemonic(lost),
NULL, 100000);
}
g_hash_table_insert(d->new_map, (gpointer)gnc_commodity_get_mnemonic(lost),
(gpointer)found);
g_hash_table_insert(d->old_map, (gpointer)gnc_commodity_get_mnemonic(lost),
(gpointer)lost);
/* create a new page in the wizard for the commodity */
new_page = make_commodity_druid_page(found);
/* set up next/back signal handlers */
gtk_signal_connect(GTK_OBJECT (new_page->page), "next",
GTK_SIGNAL_FUNC(gnc_ui_commodity_druid_comm_check_cb),
d);
gtk_signal_connect(GTK_OBJECT(new_page->page), "cancel",
GTK_SIGNAL_FUNC(gnc_ui_commodity_druid_cancel_cb),
d);
d->pages = g_list_append(d->pages, new_page);
gnome_druid_insert_page(GNOME_DRUID(d->druid),
back_page,
GNOME_DRUID_PAGE(new_page->page));
back_page = GNOME_DRUID_PAGE(new_page->page);
}
gnc_druid_set_colors (GNOME_DRUID (d->druid));
gtk_widget_show_all(d->window);
g_list_free(orphans);
return d;
}
/********************************************************************
* make_commodity_druid_page : build a single commodity xlator
* page. This really should be done in glade, but I can't figure out
* how to make it work.
********************************************************************/
static CommodityDruidPage *
make_commodity_druid_page(gnc_commodity * comm)
{
CommodityDruidPage * retval = g_new0(CommodityDruidPage, 1);
GtkWidget * alignment;
GtkWidget * top_vbox;
GtkWidget * info_label;
GtkWidget * next_label;
GtkWidget * temp;
char * title = NULL;
GnomeDruidPageStandard * page;
/* make the page widget */
retval->page = gnome_druid_page_standard_new_with_vals("", NULL);
gtk_object_set_data(GTK_OBJECT(retval->page), "page_struct", retval);
page = GNOME_DRUID_PAGE_STANDARD(retval->page);
/* save the old commodity name */
retval->old_name = g_strdup(gnc_commodity_get_mnemonic(comm));
title = g_strdup_printf("Enter information about \"%s\"",
retval->old_name ? retval->old_name : "");
gnome_druid_page_standard_set_bg_color(page, & std_bg_color);
gnome_druid_page_standard_set_logo_bg_color(page, & std_logo_bg_color);
gnome_druid_page_standard_set_title_color(page, & std_title_color);
gnome_druid_page_standard_set_title(page, title);
g_free(title);
alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
gtk_box_pack_start(GTK_BOX(page->vbox), alignment, FALSE, FALSE, 0);
top_vbox = gtk_vbox_new(FALSE, 3);
gtk_container_add(GTK_CONTAINER(alignment), top_vbox);
info_label =
gtk_label_new(_("Pick the type of the currency or security. For "
"national currencies, \nuse \"CURRENCY\". "
"Enter a new type in the box if the ones in the\n"
"pick list are inappropriate."));
gtk_label_set_justify (GTK_LABEL(info_label), GTK_JUSTIFY_LEFT);
gtk_box_pack_start(GTK_BOX(top_vbox), info_label, TRUE, TRUE, 0);
temp = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(top_vbox), temp, FALSE, FALSE, 0);
retval->new_type_combo = gtk_combo_new();
gtk_box_pack_start(GTK_BOX(temp), retval->new_type_combo, TRUE, TRUE, 0);
gnc_ui_update_namespace_picker(retval->new_type_combo,
gnc_commodity_get_namespace(comm),
TRUE, TRUE);
temp = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(top_vbox), temp, FALSE, FALSE, 5);
info_label =
gtk_label_new(_("Enter a descriptive name for the currency or stock, "
"such as \n\"US Dollar\" or \"Red Hat Stock\""));
gtk_label_set_justify (GTK_LABEL(info_label), GTK_JUSTIFY_LEFT);
gtk_box_pack_start(GTK_BOX(top_vbox), info_label, TRUE, TRUE, 0);
temp = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(top_vbox), temp, FALSE, FALSE, 0);
retval->new_name_entry = gtk_entry_new();
gtk_box_pack_start(GTK_BOX(temp), retval->new_name_entry,
TRUE, TRUE, 0);
gtk_entry_set_text(GTK_ENTRY(retval->new_name_entry),
gnc_commodity_get_fullname(comm));
temp = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(top_vbox), temp, FALSE, FALSE, 5);
info_label =
gtk_label_new(_("Enter the ticker symbol (such as \"RHAT\"), "
"national currency symbol \n(such as \"USD\"), or "
"other unique abbreviation for the name."));
gtk_label_set_justify (GTK_LABEL(info_label), GTK_JUSTIFY_LEFT);
gtk_box_pack_start(GTK_BOX(top_vbox), info_label, TRUE, TRUE, 0);
temp = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(top_vbox), temp, FALSE, FALSE, 0);
retval->new_mnemonic_entry = gtk_entry_new();
gtk_box_pack_start(GTK_BOX(temp), retval->new_mnemonic_entry,
TRUE, TRUE, 0);
gtk_entry_set_text(GTK_ENTRY(retval->new_mnemonic_entry),
gnc_commodity_get_mnemonic(comm));
temp = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(top_vbox), temp, FALSE, FALSE, 5);
next_label = gtk_label_new(_("Click \"Next\" to accept the information "
"and move \nto the next currency or stock."));
gtk_label_set_justify (GTK_LABEL(next_label), GTK_JUSTIFY_LEFT);
gtk_box_pack_start(GTK_BOX(top_vbox), next_label, TRUE, TRUE, 0);
return retval;
}
/********************************************************************
* gnc_ui_commodity_druid_destroy()
********************************************************************/
void
gnc_ui_commodity_druid_destroy(CommodityDruid * cd)
{
GList * p;
CommodityDruidPage * cdp;
/* remove the old commodities no matter how we exit */
gnc_commodity_table_delete_namespace(gnc_get_current_commodities(),
GNC_COMMODITY_NS_LEGACY);
for(p=cd->pages; p; p=p->next) {
cdp = (CommodityDruidPage *)p->data;
g_free(cdp->old_name);
g_free(cdp);
}
g_list_free(cd->pages);
g_hash_table_destroy(cd->new_map);
g_hash_table_destroy(cd->old_map);
gtk_widget_destroy(GTK_WIDGET(cd->window));
if(cd->is_modal) {
gtk_main_quit();
}
g_free (cd);
}
/********************************************************************
* callbacks
********************************************************************/
static gboolean
gnc_ui_commodity_druid_cancel_cb(GnomeDruidPage * page, gpointer druid,
gpointer user_data)
{
CommodityDruid * cd = user_data;
/* destroy the dialog */
gnc_ui_commodity_druid_destroy(cd);
/* unload the current file (can't have out-of-date commodities) */
gnc_file_quit ();
gnc_file_new ();
return TRUE;
}
static gboolean
gnc_ui_commodity_druid_comm_check_cb(GnomeDruidPage * page, gpointer druid,
gpointer user_data)
{
CommodityDruid * cd = user_data;
CommodityDruidPage * dpage =
(CommodityDruidPage *)gtk_object_get_data(GTK_OBJECT(page),
"page_struct");
const char * new_type;
char * new_name;
char * new_mnemonic;
gnc_commodity * new_comm;
new_type = gnc_ui_namespace_picker_ns (dpage->new_type_combo);
new_name = gtk_entry_get_text(GTK_ENTRY(dpage->new_name_entry));
new_mnemonic = gtk_entry_get_text(GTK_ENTRY(dpage->new_mnemonic_entry));
if((strlen(new_type) == 0) ||
(strlen(new_name) == 0) ||
(strlen(new_mnemonic) == 0)) {
gnc_warning_dialog_parented(cd->window,
_("You must put values for the type, name,\n"
"and abbreviation of the currency/stock."));
return TRUE;
}
if (gnc_commodity_namespace_is_iso (new_type) &&
!gnc_commodity_table_lookup (gnc_get_current_commodities (),
new_type, new_mnemonic))
{
gnc_warning_dialog_parented(cd->window,
_("You must enter an existing national "
"currency or enter a different type."));
return TRUE;
}
new_comm = g_hash_table_lookup(cd->new_map, dpage->old_name);
g_assert(new_comm);
/* fill in the commodity structure info */
gnc_commodity_set_fullname(new_comm, new_name);
gnc_commodity_set_namespace(new_comm, new_type);
gnc_commodity_set_mnemonic(new_comm, new_mnemonic);
return FALSE;
}
static void
finish_helper(gpointer key, gpointer value, gpointer data)
{
CommodityDruid * cd = data;
gnc_commodity * comm = value;
gnc_commodity * old_comm = g_hash_table_lookup(cd->old_map, key);
GList * accts;
GList * node;
GNCBook * book = gnc_get_current_book ();
if(!book)
{
PERR("finish_helper - no current book.");
return;
}
/* key is the old mnemonic, value is a pointer to the gnc_commodity
* structure. */
comm = gnc_commodity_table_insert(gnc_get_current_commodities(), comm);
/* s/old commodity/new commodity/g in the pricedb */
gnc_pricedb_substitute_commodity(gnc_book_get_pricedb(book),
old_comm,
comm);
/* now replace all the accounts using old_comm with new_comm */
accts = xaccGroupGetSubAccounts(gnc_get_current_group ());
for(node = accts; node; node = node->next)
{
Account *account = node->data;
xaccAccountBeginEdit(account);
if (gnc_commodity_equiv (DxaccAccountGetCurrency(account),
old_comm))
DxaccAccountSetCurrency (account, comm);
if (gnc_commodity_equiv (DxaccAccountGetSecurity(account),
old_comm))
DxaccAccountSetSecurity(account, comm);
if (gnc_commodity_equiv (xaccAccountGetCommodity(account), old_comm))
xaccAccountSetCommodity(account, comm);
xaccAccountCommitEdit(account);
}
g_list_free (accts);
}
static void
gnc_ui_commodity_druid_finish_cb(GnomeDruidPage * page, gpointer druid,
gpointer user_data)
{
CommodityDruid * cd = user_data;
/* add the new commodities to the engine's namespace map and
* replace the account commodity pointers */
g_hash_table_foreach(cd->new_map, &finish_helper, (gpointer)cd);
/* Fix account and transaction commodities */
xaccGroupScrubCommodities (gnc_get_current_group ());
/* Fix split amount/value */
xaccGroupScrubSplits (gnc_get_current_group ());
/* destroy the dialog */
gnc_ui_commodity_druid_destroy(cd);
}