[gcalctool] Make the currency code OO



commit 1e2b5410bb26d041c0fb7fb31f442e643f1ffc55
Author: Robert Ancell <robert ancell canonical com>
Date:   Thu Jan 27 12:02:21 2011 +1000

    Make the currency code OO

 src/Makefile.am        |    4 +
 src/currency-manager.c |  571 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/currency-manager.h |   37 +++
 src/currency.c         |  463 +++------------------------------------
 src/currency.h         |  102 +++------
 src/math-buttons.c     |    1 -
 src/math-converter.c   |    1 -
 src/math-equation.c    |   14 +-
 src/unit-category.c    |    1 -
 src/unit-manager.c     |   11 +-
 src/unit.c             |    4 +-
 11 files changed, 690 insertions(+), 519 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index e653455..f0f79ef 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -11,6 +11,8 @@ INCLUDES = \
 gcalctool_SOURCES = \
 	currency.c \
 	currency.h \
+	currency-manager.c \
+	currency-manager.h \
 	gcalctool.c \
 	math-buttons.c \
 	math-buttons.h \
@@ -63,6 +65,8 @@ gcalccmd_SOURCES = \
 	gcalccmd.c \
 	currency.c \
 	currency.h \
+	currency-manager.c \
+	currency-manager.h \
 	mp.c \
 	mp-convert.c \
 	mp-binary.c \
diff --git a/src/currency-manager.c b/src/currency-manager.c
new file mode 100644
index 0000000..ea43ef1
--- /dev/null
+++ b/src/currency-manager.c
@@ -0,0 +1,571 @@
+#include <time.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <gio/gio.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <glib/gi18n.h>
+
+#include "currency-manager.h"
+#include "mp.h"
+
+typedef struct {
+    char *short_name;
+    char *symbol;
+    char *long_name;
+} CurrencyInfo;
+static const CurrencyInfo currency_info[] = {
+    {"AED", "إ.د",  N_("United Arab Emirates dirham")},
+    {"AUD", "$",    N_("Australian dollar")},
+    {"BGN", "лв",   N_("Bulgarian lev")},
+    {"BHD", ".ب.د", N_("Bahraini dinar")},
+    {"BND", "$",    N_("Brunei dollar")},
+    {"BRL", "R$",   N_("Brazilian real")},
+    {"BWP", "P",    N_("Botswana pula")},
+    {"CAD", "$",    N_("Canadian dollar")},
+    {"CHF", "Fr",   N_("Swiss franc")},
+    {"CLP", "$",    N_("Chilean peso")},
+    {"CNY", "å??",   N_("Chinese yuan renminbi")},
+    {"COP", "$",    N_("Colombian peso")},
+    {"CZK", "KÄ?",   N_("Czech koruna")},
+    {"DKK", "kr",   N_("Danish krone")},
+    {"DZD", "ج.د",  N_("Algerian dinar")},
+    {"EEK", "KR",   N_("Estonian kroon")},
+    {"EUR", "â?¬",    N_("Euro")},
+    {"GBP", "£",    N_("Pound sterling")},
+    {"HKD", "$",    N_("Hong Kong dollar")},
+    {"HRK", "kn",   N_("Croatian kuna")},
+    {"HUF", "Ft",   N_("Hungarian forint")},
+    {"IDR", "Rp",   N_("Indonesian rupiah")},
+    {"ILS", "â?ª",    N_("Israeli new shekel")},
+    {"INR", "â?¹",    N_("Indian rupee")},
+    {"IRR", "ï·¼",    N_("Iranian rial")},
+    {"ISK", "kr",   N_("Icelandic krona")},
+    {"JPY", "Â¥",    N_("Japanese yen")},
+    {"KRW", "â?©",    N_("South Korean won")},
+    {"KWD", "Ù?.د",  N_("Kuwaiti dinar")},
+    {"KZT", "â?¸",    N_("Kazakhstani tenge")},
+    {"LKR", "Rs",   N_("Sri Lankan rupee")},
+    {"LTL", "Lt",   N_("Lithuanian litas")},
+    {"LVL", "Ls",   N_("Latvian lats")},
+    {"LYD", "د.Ù?",  N_("Libyan dinar")},
+    {"MUR", "Rs",   N_("Mauritian rupee")},
+    {"MXN", "$",    N_("Mexican peso")},
+    {"MYR", "RM",   N_("Malaysian ringgit")},
+    {"NOK", "kr",   N_("Norwegian krone")},
+    {"NPR", "Rs",   N_("Nepalese rupee")},
+    {"NZD", "$",    N_("New Zealand dollar")},
+    {"OMR", "ع.ر.", N_("Omani rial")},
+    {"PEN", "S/.",  N_("Peruvian nuevo sol")},
+    {"PHP", "â?±",    N_("Philippine peso")},
+    {"PKR", "Rs",   N_("Pakistani rupee")},
+    {"PLN", "zÅ?",   N_("Polish zloty")},
+    {"QAR", "Ù?.ر",  N_("Qatari riyal")},
+    {"RON", "L",    N_("New Romanian leu")},
+    {"RUB", "Ñ?Ñ?б.", N_("Russian rouble")},
+    {"SAR", "س.ر",  N_("Saudi riyal")},
+    {"SEK", "kr",   N_("Swedish krona")},
+    {"SGD", "$",    N_("Singapore dollar")},
+    {"THB", "฿",    N_("Thai baht")},
+    {"TND", "ت.د",  N_("Tunisian dinar")},
+    {"TRY", "TL",   N_("New Turkish lira")},
+    {"TTD", "$",    N_("Trinidad and Tobago dollar")},
+    {"USD", "$",    N_("US dollar")},
+    {"UYU", "$",    N_("Uruguayan peso")},
+    {"VEF", "Bs F", N_("Venezuelan bolívar")},
+    {"ZAR", "R",    N_("South African rand")},
+    {NULL, NULL}
+};
+
+static gboolean downloading_imf_rates = FALSE, downloading_ecb_rates = FALSE;
+static gboolean loaded_rates = FALSE;
+
+struct CurrencyManagerPrivate
+{
+    GList *currencies;
+};
+
+G_DEFINE_TYPE (CurrencyManager, currency_manager, G_TYPE_OBJECT);
+
+
+static CurrencyManager *default_currency_manager = NULL;
+
+
+CurrencyManager *
+currency_manager_get_default(void)
+{
+    int i;
+
+    if (default_currency_manager)
+        return default_currency_manager;
+
+    default_currency_manager = g_object_new(currency_manager_get_type(), NULL);
+
+    for (i = 0; currency_info[i].short_name; i++) {
+        Currency *c = currency_new(currency_info[i].short_name, currency_info[i].long_name, currency_info[i].symbol);
+        default_currency_manager->priv->currencies = g_list_append(default_currency_manager->priv->currencies, c);
+    }
+
+    return default_currency_manager;
+}
+
+
+const GList *
+currency_manager_get_currencies(CurrencyManager *manager)
+{
+     return manager->priv->currencies;
+}
+
+
+Currency *
+currency_manager_get_currency(CurrencyManager *manager, const gchar *name)
+{
+    GList *link;
+    for (link = manager->priv->currencies; link; link = link->next) {
+        Currency *c = link->data;
+        const MPNumber *value;
+
+        value = currency_get_value(c);
+
+        if (!strcmp(name, currency_get_name(c))) {
+            if (mp_is_negative(value) ||
+                mp_is_zero(value)) {
+                return NULL;
+            }
+            else
+                return c;
+        }
+    }
+    return NULL;
+}
+
+
+static char *
+get_imf_rate_filepath()
+{
+    return g_build_filename(g_get_user_cache_dir (),
+                            "gcalctool",
+                            "rms_five.xls",
+                            NULL);
+}
+
+
+static char *
+get_ecb_rate_filepath()
+{
+    return g_build_filename(g_get_user_cache_dir (),
+                            "gcalctool",
+                            "eurofxref-daily.xml",
+                            NULL);
+}
+
+
+static Currency *
+add_currency(CurrencyManager *manager, const gchar *short_name)
+{
+    GList *iter;
+    Currency *c;
+
+    for (iter = manager->priv->currencies; iter; iter = iter->next) {
+        c = iter->data;
+        if (strcmp(short_name, currency_get_name(c)) == 0)
+            return c;
+    }
+
+    g_warning("Currency %s is not in the currency table", short_name);
+    c = currency_new(short_name, short_name, short_name);
+    manager->priv->currencies = g_list_append(manager->priv->currencies, c);
+
+    return c;
+}
+
+
+/* A file needs to be redownloaded if it doesn't exist, or is too old.
+ * When an error occur, it probably won't hurt to try to download again.
+ */
+static gboolean
+file_needs_update(gchar *filename, double max_age)
+{
+    struct stat buf;
+
+    if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR))
+        return TRUE;
+
+    if (g_stat(filename, &buf) == -1)
+        return TRUE;
+
+    if (difftime(time(NULL), buf.st_mtime) > max_age)
+        return TRUE;
+
+    return FALSE;
+}
+
+
+static void
+download_imf_cb(GObject *object, GAsyncResult *result, gpointer user_data)
+{
+    GError *error = NULL;
+
+    if (g_file_copy_finish(G_FILE(object), result, &error))
+        g_debug("IMF rates updated");
+    else
+        g_warning("Couldn't download IMF currency rate file: %s", error->message);
+    g_clear_error(&error);
+    downloading_imf_rates = FALSE;
+}
+
+
+static void
+download_ecb_cb(GObject *object, GAsyncResult *result, gpointer user_data)
+{
+    GError *error = NULL;
+
+    if (g_file_copy_finish(G_FILE(object), result, &error))
+        g_debug("ECB rates updated");
+    else
+        g_warning("Couldn't download ECB currency rate file: %s", error->message);
+    g_clear_error(&error);
+    downloading_ecb_rates = FALSE;
+}
+
+
+static void
+download_file(gchar *uri, gchar *filename, GAsyncReadyCallback callback)
+{
+    gchar *directory;
+    GFile *source, *dest;
+
+    directory = g_path_get_dirname(filename);
+    g_mkdir_with_parents(directory, 0755);
+    g_free(directory);
+
+    source = g_file_new_for_uri(uri);
+    dest = g_file_new_for_path(filename);
+
+    g_file_copy_async(source, dest, G_FILE_COPY_OVERWRITE, G_PRIORITY_DEFAULT, NULL, NULL, NULL, callback, NULL);
+    g_object_unref(source);
+    g_object_unref(dest); 
+}
+
+
+static void
+load_imf_rates(CurrencyManager *manager)
+{
+    gchar *filename;
+    gchar *data, **lines;
+    gsize length;
+    GError *error = NULL;
+    int i;
+    gboolean result, in_data = FALSE;
+    struct 
+    {
+        const gchar *name, *symbol;
+    } name_map[] = 
+    {
+        {"Euro",                "EUR"},
+        {"Japanese Yen",        "JPY"},
+        {"U.K. Pound Sterling", "GBP"},
+        {"U.S. Dollar",         "USD"},
+        {"Algerian Dinar",      "DZD"},
+        {"Australian Dollar",   "AUD"},
+        {"Bahrain Dinar",       "BHD"},
+        {"Botswana Pula",       "BWP"},
+        {"Brazilian Real",      "BRL"},
+        {"Brunei Dollar",       "BND"},
+        {"Canadian Dollar",     "CAD"},
+        {"Chilean Peso",        "CLP"},
+        {"Chinese Yuan",        "CNY"},
+        {"Colombian Peso",      "COP"},
+        {"Czech Koruna",        "CZK"},
+        {"Danish Krone",        "DKK"},
+        {"Hungarian Forint",    "HUF"},
+        {"Icelandic Krona",     "ISK"},
+        {"Indian Rupee",        "INR"},
+        {"Indonesian Rupiah",   "IDR"},
+        {"Iranian Rial",        "IRR"},
+        {"Israeli New Sheqel",  "ILS"},
+        {"Kazakhstani Tenge",   "KZT"},
+        {"Korean Won",          "KRW"},
+        {"Kuwaiti Dinar",       "KWD"},
+        {"Libyan Dinar",        "LYD"},
+        {"Malaysian Ringgit",   "MYR"},
+        {"Mauritian Rupee",     "MUR"},
+        {"Mexican Peso",        "MXN"},
+        {"Nepalese Rupee",      "NPR"},
+        {"New Zealand Dollar",  "NZD"},
+        {"Norwegian Krone",     "NOK"},
+        {"Rial Omani",          "OMR"},
+        {"Pakistani Rupee",     "PKR"},
+        {"Nuevo Sol",           "PEN"},
+        {"Philippine Peso",     "PHP"},
+        {"Polish Zloty",        "PLN"},
+        {"Qatar Riyal",         "QAR"},
+        {"Russian Ruble",       "RUB"},
+        {"Saudi Arabian Riyal", "SAR"},
+        {"Singapore Dollar",    "SGD"},
+        {"South African Rand",  "ZAR"},
+        {"Sri Lanka Rupee",     "LKR"},
+        {"Swedish Krona",       "SEK"},
+        {"Swiss Franc",         "CHF"},
+        {"Thai Baht",           "THB"},
+        {"Trinidad And Tobago Dollar", "TTD"},
+        {"Tunisian Dinar",      "TND"},
+        {"U.A.E. Dirham",       "AED"},
+        {"Peso Uruguayo",       "UYU"},
+        {"Bolivar Fuerte",      "VEF"},
+        {NULL, NULL}
+    };
+
+    filename = get_imf_rate_filepath();
+    result = g_file_get_contents(filename, &data, &length, &error);
+    g_free(filename);
+    if (!result)
+    {
+        g_warning("Failed to read exchange rates: %s", error->message);
+        g_clear_error(&error);
+        return;
+    }
+
+    lines = g_strsplit(data, "\n", 0);
+    g_free(data);
+
+    for (i = 0; lines[i]; i++) {
+        gchar *line, **tokens;
+
+        line = g_strchug(lines[i]);
+      
+        /* Start after first blank line, stop on next */
+        if (line[0] == '\0') {
+            if (!in_data) {
+               in_data = TRUE;
+               continue;
+            }
+            else
+               break;
+        }
+        if (!in_data)
+            continue;
+
+        tokens = g_strsplit(line, "\t", 0);
+        if (strcmp(tokens[0], "Currency") != 0) {
+            gint value_index, name_index;
+
+            for (value_index = 1; tokens[value_index]; value_index++) {
+                gchar *value = g_strchug (tokens[value_index]);
+                if (value[0] != '\0')
+                    break;
+            }
+            if (tokens[value_index]) {
+                for (name_index = 0; name_map[name_index].name; name_index++) {
+                    if (strcmp(name_map[name_index].name, tokens[0]) == 0)
+                        break;
+                }
+                if (name_map[name_index].name) {
+                    Currency *c = currency_manager_get_currency(manager, name_map[name_index].symbol);
+                    MPNumber value;
+
+                    if (!c) {
+                        g_debug ("Using IMF rate of %s for %s", tokens[value_index], name_map[name_index].symbol);
+                        c = add_currency(manager, name_map[name_index].symbol);
+                    }
+                    mp_set_from_string(tokens[value_index], 10, &value);
+                    currency_set_value(c, &value);
+                }
+                else
+                    g_warning("Unknown currency '%s'", tokens[0]);
+            }
+        }
+        g_strfreev(tokens);
+    }
+    g_strfreev(lines);
+}
+
+
+static void
+set_ecb_rate(CurrencyManager *manager, xmlNodePtr node, Currency *eur_rate)
+{
+    xmlAttrPtr attribute;
+    gchar *name = NULL, *value = NULL;
+
+    for (attribute = node->properties; attribute; attribute = attribute->next) {
+        if (strcmp((char *)attribute->name, "currency") == 0) {
+            if (name)
+                xmlFree(name);
+            name = (gchar *)xmlNodeGetContent((xmlNodePtr)attribute);
+        } else if (strcmp ((char *)attribute->name, "rate") == 0) {
+            if (value)
+                xmlFree(value);
+            value = (gchar *)xmlNodeGetContent((xmlNodePtr)attribute);
+        }
+    }
+
+    /* Use data if value and no rate currently defined */
+    if (name && value && !currency_manager_get_currency(manager, name)) {
+        Currency *c;
+        MPNumber r, v;
+
+        g_debug ("Using ECB rate of %s for %s", value, name);
+        c = add_currency(manager, name);
+        mp_set_from_string(value, 10, &r);
+        mp_set_from_mp(currency_get_value(eur_rate), &v);
+        mp_divide(&v, &r, &v);
+        currency_set_value(c, &v);
+    }
+
+    if (name)
+        xmlFree(name);
+    if (value)
+        xmlFree(value);
+}
+
+
+static void
+set_ecb_fixed_rate(CurrencyManager *manager, const gchar *name, const gchar *value, Currency *eur_rate)
+{
+    Currency *c;
+    MPNumber r, v;
+
+    g_debug ("Using ECB fixed rate of %s for %s", value, name);
+    c = add_currency(manager, name);
+    mp_set_from_string(value, 10, &r);
+    mp_set_from_mp(currency_get_value(eur_rate), &v);
+    mp_divide(&v, &r, &v);
+    currency_set_value(c, &v);
+}
+
+
+static void
+load_ecb_rates(CurrencyManager *manager)
+{
+    Currency *eur_rate;
+    char *filename = get_ecb_rate_filepath();
+    xmlDocPtr document;
+    xmlXPathContextPtr xpath_ctx;
+    xmlXPathObjectPtr xpath_obj;
+    int i, len;
+
+    /* Scale rates to the EUR value */
+    eur_rate = currency_manager_get_currency(manager, "EUR");
+    if (!eur_rate) {
+        g_warning("Cannot use ECB rates as don't have EUR rate");
+        return;
+    }
+
+    /* Set some fixed rates */
+    set_ecb_fixed_rate(manager, "EEK", "15.6466", eur_rate);
+
+    xmlInitParser();
+    document = xmlReadFile(filename, NULL, 0);
+    g_free (filename);
+    if (document == NULL) {
+        g_error("Couldn't parse ECB rate file %s", filename);
+        return;
+    }
+
+    xpath_ctx = xmlXPathNewContext(document);
+    if (xpath_ctx == NULL) {
+        xmlFreeDoc(document);
+        g_error("Couldn't create XPath context");
+        return;
+    }
+
+    xmlXPathRegisterNs(xpath_ctx,
+                       BAD_CAST("xref"),
+                       BAD_CAST("http://www.ecb.int/vocabulary/2002-08-01/eurofxref";));
+    xpath_obj = xmlXPathEvalExpression(BAD_CAST("//xref:Cube[ currency][@rate]"),
+                                       xpath_ctx);
+    if (xpath_obj == NULL) {
+        xmlXPathFreeContext(xpath_ctx);
+        xmlFreeDoc(document);
+        fprintf(stderr, "Couldn't create XPath object\n");
+        return;
+    }
+    len = (xpath_obj->nodesetval) ? xpath_obj->nodesetval->nodeNr : 0;
+    for (i = 0; i < len; i++) {
+        if (xpath_obj->nodesetval->nodeTab[i]->type == XML_ELEMENT_NODE)
+            set_ecb_rate(manager, xpath_obj->nodesetval->nodeTab[i], eur_rate);
+
+        /* Avoid accessing removed elements */
+        if (xpath_obj->nodesetval->nodeTab[i]->type != XML_NAMESPACE_DECL)
+            xpath_obj->nodesetval->nodeTab[i] = NULL;
+    }
+
+    xmlXPathFreeObject(xpath_obj);
+    xmlXPathFreeContext(xpath_ctx);
+    xmlFreeDoc(document);
+    xmlCleanupParser();
+}
+
+
+static void
+load_rates(CurrencyManager *manager)
+{
+    int i;
+
+    /* Use the IMF provided values and top up with currencies tracked by the ECB and not the IMF */
+    load_imf_rates(manager);
+    load_ecb_rates(manager);
+
+    for (i = 0; currency_info[i].short_name; i++) {
+       GList *link;
+       for (link = manager->priv->currencies; link; link = link->next) {
+           Currency *c = link->data;
+           if (strcmp(currency_get_name(c), currency_info[i].short_name) == 0)
+              break;
+       }
+       if (!link)
+           g_warning("Currency %s is not provided by IMF or ECB", currency_info[i].short_name);
+    }
+
+    g_debug("Rates loaded");
+    loaded_rates = TRUE;  
+}
+
+
+const MPNumber *
+currency_manager_get_value(CurrencyManager *manager, const gchar *currency)
+{
+    gchar *path;
+    Currency *c;
+
+    /* Update rates if necessary */
+    path = get_imf_rate_filepath();
+    if (!downloading_imf_rates && file_needs_update(path, 60 * 60 * 24 * 7)) {
+        downloading_imf_rates = TRUE;
+        g_debug("Downloading rates from the IMF...");
+        download_file("http://www.imf.org/external/np/fin/data/rms_five.aspx?tsvflag=Y";, path, download_imf_cb);
+    }
+    g_free(path);
+    path = get_ecb_rate_filepath();
+    if (!downloading_ecb_rates && file_needs_update(path, 60 * 60 * 24 * 7)) {
+        downloading_ecb_rates = TRUE;
+        g_debug("Downloading rates from the ECB...");
+        download_file("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml";, path, download_ecb_cb);
+    }
+    g_free(path);
+
+    if (downloading_imf_rates || downloading_ecb_rates)
+        return NULL;
+
+    if (!loaded_rates)
+        load_rates(manager);
+  
+    c = currency_manager_get_currency(manager, currency);
+    return currency_get_value(c);
+}
+
+
+static void
+currency_manager_class_init(CurrencyManagerClass *klass)
+{
+    g_type_class_add_private(klass, sizeof(CurrencyManagerPrivate));
+}
+
+
+static void
+currency_manager_init(CurrencyManager *manager)
+{
+    manager->priv = G_TYPE_INSTANCE_GET_PRIVATE(manager, currency_manager_get_type(), CurrencyManagerPrivate);
+}
diff --git a/src/currency-manager.h b/src/currency-manager.h
new file mode 100644
index 0000000..6d3a887
--- /dev/null
+++ b/src/currency-manager.h
@@ -0,0 +1,37 @@
+#ifndef CURRENCY_MANAGER_H
+#define CURRENCY_MANAGER_H
+
+#include "currency.h"
+#include "mp.h"
+ 
+G_BEGIN_DECLS
+
+#define CURRENCY_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), currency_manager_get_type(), CurrencyManager))
+
+typedef struct CurrencyManagerPrivate CurrencyManagerPrivate;
+
+typedef struct
+{
+    GObject parent_instance;
+    CurrencyManagerPrivate *priv;
+} CurrencyManager;
+
+typedef struct
+{
+    GObjectClass parent_class;
+    // FIXME: Should indicate when rates are updated to UI
+} CurrencyManagerClass;
+
+GType currency_manager_get_type(void);
+
+CurrencyManager *currency_manager_get_default(void);
+
+const GList *currency_manager_get_currencies(CurrencyManager *manager);
+
+Currency *currency_manager_get_currency(CurrencyManager *manager, const gchar *name);
+
+const MPNumber *currency_manager_get_value(CurrencyManager *manager, const gchar *currency);
+
+G_END_DECLS
+
+#endif /* CURRENCY_MANAGER_H */
diff --git a/src/currency.c b/src/currency.c
index 883a002..481a2eb 100644
--- a/src/currency.c
+++ b/src/currency.c
@@ -1,466 +1,77 @@
-#include <time.h>
-
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <gio/gio.h>
-#include <libxml/tree.h>
-#include <libxml/xpath.h>
-#include <libxml/xpathInternals.h>
+#include <string.h>
+#include <stdarg.h>
 
 #include "currency.h"
-#include "mp.h"
-
-typedef struct {
-    char *short_name;
-    MPNumber value;
-    const CurrencyInfo *info;
-} Currency;
-
-static GList *currencies = NULL;
-
-static gboolean downloading_imf_rates = FALSE, downloading_ecb_rates = FALSE;
-static gboolean loaded_rates = FALSE;
+#include "mp-serializer.h"
+#include "currency-manager.h" // FIXME: Move out of here
 
-static char *
-get_imf_rate_filepath()
+struct CurrencyPrivate
 {
-    return g_build_filename(g_get_user_cache_dir (),
-                            "gcalctool",
-                            "rms_five.xls",
-                            NULL);
-}
-
+    gchar *name;
+    gchar *display_name;
+    gchar *symbol;
+    MPNumber value;
+};
 
-static char *
-get_ecb_rate_filepath()
-{
-    return g_build_filename(g_get_user_cache_dir (),
-                            "gcalctool",
-                            "eurofxref-daily.xml",
-                            NULL);
-}
+G_DEFINE_TYPE (Currency, currency, G_TYPE_OBJECT);
 
 
-static Currency *
-add_currency(const gchar *short_name)
+Currency *
+currency_new(const gchar *name, const gchar *display_name, const gchar *symbol)
 {
-    Currency *c;
-    int i;
-
-    c = g_malloc0(sizeof(Currency));
-    c->short_name = g_strdup(short_name);
-    for (i = 0; currency_info[i].short_name; i++) {
-        if (strcmp(c->short_name, currency_info[i].short_name) == 0) {
-            c->info = &currency_info[i];
-            break;
-        }
-    }
-    if (!c->info)
-        g_warning("Currency %s is not in the currency table", c->short_name);
+    Currency *currency = g_object_new(currency_get_type(), NULL);
 
-    currencies = g_list_append(currencies, c);
+    currency->priv->name = g_strdup(name);
+    currency->priv->display_name = g_strdup(display_name);
+    currency->priv->symbol = g_strdup(symbol);
 
-    return c;
+    return currency;
 }
 
 
-static Currency *
-get_currency(const gchar *short_name)
+const gchar *
+currency_get_name(Currency *currency)
 {
-    GList *link;
-    for (link = currencies; link; link = link->next) {
-        Currency *c = link->data;
-        if (!strcmp(short_name, c->short_name)) {
-            if (mp_is_negative(&c->value) ||
-                mp_is_zero(&c->value)) {
-                return NULL;
-            }
-            else
-                return c;
-        }
-    }
-    return NULL;
+    return currency->priv->name;
 }
 
 
-/* A file needs to be redownloaded if it doesn't exist, or is too old.
- * When an error occur, it probably won't hurt to try to download again.
- */
-static gboolean
-file_needs_update(gchar *filename, double max_age)
+const gchar *
+currency_get_display_name(Currency *currency)
 {
-    struct stat buf;
-
-    if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR))
-        return TRUE;
-
-    if (g_stat(filename, &buf) == -1)
-        return TRUE;
-
-    if (difftime(time(NULL), buf.st_mtime) > max_age)
-        return TRUE;
-
-    return FALSE;
+    return currency->priv->display_name;
 }
 
-
-static void
-download_imf_cb(GObject *object, GAsyncResult *result, gpointer user_data)
+const gchar *
+currency_get_symbol(Currency *currency)
 {
-    GError *error = NULL;
-
-    if (g_file_copy_finish(G_FILE(object), result, &error))
-        g_debug("IMF rates updated");
-    else
-        g_warning("Couldn't download IMF currency rate file: %s", error->message);
-    g_clear_error(&error);
-    downloading_imf_rates = FALSE;
+    return currency->priv->symbol;
 }
 
 
-static void
-download_ecb_cb(GObject *object, GAsyncResult *result, gpointer user_data)
+void
+currency_set_value(Currency *currency, MPNumber *value)
 {
-    GError *error = NULL;
-
-    if (g_file_copy_finish(G_FILE(object), result, &error))
-        g_debug("ECB rates updated");
-    else
-        g_warning("Couldn't download ECB currency rate file: %s", error->message);
-    g_clear_error(&error);
-    downloading_ecb_rates = FALSE;
+    mp_set_from_mp (value, &currency->priv->value);
 }
 
 
-static void
-download_file(gchar *uri, gchar *filename, GAsyncReadyCallback callback)
+const MPNumber *
+currency_get_value(Currency *currency)
 {
-    gchar *directory;
-    GFile *source, *dest;
-
-    directory = g_path_get_dirname(filename);
-    g_mkdir_with_parents(directory, 0755);
-    g_free(directory);
-
-    source = g_file_new_for_uri(uri);
-    dest = g_file_new_for_path(filename);
-
-    g_file_copy_async(source, dest, G_FILE_COPY_OVERWRITE, G_PRIORITY_DEFAULT, NULL, NULL, NULL, callback, NULL);
-    g_object_unref(source);
-    g_object_unref(dest); 
+    return &currency->priv->value;
 }
 
 
 static void
-load_imf_rates()
+currency_class_init(CurrencyClass *klass)
 {
-    gchar *filename;
-    gchar *data, **lines;
-    gsize length;
-    GError *error = NULL;
-    int i;
-    gboolean result, in_data = FALSE;
-    struct 
-    {
-        const gchar *name, *symbol;
-    } name_map[] = 
-    {
-        {"Euro",                "EUR"},
-        {"Japanese Yen",        "JPY"},
-        {"U.K. Pound Sterling", "GBP"},
-        {"U.S. Dollar",         "USD"},
-        {"Algerian Dinar",      "DZD"},
-        {"Australian Dollar",   "AUD"},
-        {"Bahrain Dinar",       "BHD"},
-        {"Botswana Pula",       "BWP"},
-        {"Brazilian Real",      "BRL"},
-        {"Brunei Dollar",       "BND"},
-        {"Canadian Dollar",     "CAD"},
-        {"Chilean Peso",        "CLP"},
-        {"Chinese Yuan",        "CNY"},
-        {"Colombian Peso",      "COP"},
-        {"Czech Koruna",        "CZK"},
-        {"Danish Krone",        "DKK"},
-        {"Hungarian Forint",    "HUF"},
-        {"Icelandic Krona",     "ISK"},
-        {"Indian Rupee",        "INR"},
-        {"Indonesian Rupiah",   "IDR"},
-        {"Iranian Rial",        "IRR"},
-        {"Israeli New Sheqel",  "ILS"},
-        {"Kazakhstani Tenge",   "KZT"},
-        {"Korean Won",          "KRW"},
-        {"Kuwaiti Dinar",       "KWD"},
-        {"Libyan Dinar",        "LYD"},
-        {"Malaysian Ringgit",   "MYR"},
-        {"Mauritian Rupee",     "MUR"},
-        {"Mexican Peso",        "MXN"},
-        {"Nepalese Rupee",      "NPR"},
-        {"New Zealand Dollar",  "NZD"},
-        {"Norwegian Krone",     "NOK"},
-        {"Rial Omani",          "OMR"},
-        {"Pakistani Rupee",     "PKR"},
-        {"Nuevo Sol",           "PEN"},
-        {"Philippine Peso",     "PHP"},
-        {"Polish Zloty",        "PLN"},
-        {"Qatar Riyal",         "QAR"},
-        {"Russian Ruble",       "RUB"},
-        {"Saudi Arabian Riyal", "SAR"},
-        {"Singapore Dollar",    "SGD"},
-        {"South African Rand",  "ZAR"},
-        {"Sri Lanka Rupee",     "LKR"},
-        {"Swedish Krona",       "SEK"},
-        {"Swiss Franc",         "CHF"},
-        {"Thai Baht",           "THB"},
-        {"Trinidad And Tobago Dollar", "TTD"},
-        {"Tunisian Dinar",      "TND"},
-        {"U.A.E. Dirham",       "AED"},
-        {"Peso Uruguayo",       "UYU"},
-        {"Bolivar Fuerte",      "VEF"},
-        {NULL, NULL}
-    };
-
-    filename = get_imf_rate_filepath();
-    result = g_file_get_contents(filename, &data, &length, &error);
-    g_free(filename);
-    if (!result)
-    {
-        g_warning("Failed to read exchange rates: %s", error->message);
-        g_clear_error(&error);
-        return;
-    }
-
-    lines = g_strsplit(data, "\n", 0);
-    g_free(data);
-
-    for (i = 0; lines[i]; i++) {
-        gchar *line, **tokens;
-
-        line = g_strchug(lines[i]);
-      
-        /* Start after first blank line, stop on next */
-        if (line[0] == '\0') {
-            if (!in_data) {
-               in_data = TRUE;
-               continue;
-            }
-            else
-               break;
-        }
-        if (!in_data)
-            continue;
-
-        tokens = g_strsplit(line, "\t", 0);
-        if (strcmp(tokens[0], "Currency") != 0) {
-            gint value_index, name_index;
-
-            for (value_index = 1; tokens[value_index]; value_index++) {
-                gchar *value = g_strchug (tokens[value_index]);
-                if (value[0] != '\0')
-                    break;
-            }
-            if (tokens[value_index]) {
-                for (name_index = 0; name_map[name_index].name; name_index++) {
-                    if (strcmp(name_map[name_index].name, tokens[0]) == 0)
-                        break;
-                }
-                if (name_map[name_index].name) {
-                    Currency *c = get_currency(name_map[name_index].symbol);
-                    if (!c) {
-                        g_debug ("Using IMF rate of %s for %s", tokens[value_index], name_map[name_index].symbol);
-                        c = add_currency(name_map[name_index].symbol);
-                    }
-                    mp_set_from_string(tokens[value_index], 10, &c->value);
-                }
-                else
-                    g_warning("Unknown currency '%s'", tokens[0]);
-            }
-        }
-        g_strfreev(tokens);
-    }
-    g_strfreev(lines);
+    g_type_class_add_private(klass, sizeof(CurrencyPrivate));
 }
 
 
 static void
-set_ecb_rate(xmlNodePtr node, Currency *eur_rate)
+currency_init(Currency *currency)
 {
-    xmlAttrPtr attribute;
-    gchar *name = NULL, *value = NULL;
-
-    for (attribute = node->properties; attribute; attribute = attribute->next) {
-        if (strcmp((char *)attribute->name, "currency") == 0) {
-            if (name)
-                xmlFree(name);
-            name = (gchar *)xmlNodeGetContent((xmlNodePtr)attribute);
-        } else if (strcmp ((char *)attribute->name, "rate") == 0) {
-            if (value)
-                xmlFree(value);
-            value = (gchar *)xmlNodeGetContent((xmlNodePtr)attribute);
-        }
-    }
-
-    /* Use data if value and no rate currently defined */
-    if (name && value && !get_currency(name)) {
-        Currency *c;
-        MPNumber r;
-
-        g_debug ("Using ECB rate of %s for %s", value, name);
-        c = add_currency(name);
-        mp_set_from_string(value, 10, &r);
-        mp_set_from_mp(&eur_rate->value, &c->value);
-        mp_divide(&c->value, &r, &c->value);
-    }
-
-    if (name)
-        xmlFree(name);
-    if (value)
-        xmlFree(value);
-}
-
-
-static void
-set_ecb_fixed_rate(const gchar *name, const gchar *value, Currency *eur_rate)
-{
-    Currency *c;
-    MPNumber r;
-
-    g_debug ("Using ECB fixed rate of %s for %s", value, name);
-    c = add_currency(name);
-    mp_set_from_string(value, 10, &r);
-    mp_set_from_mp(&eur_rate->value, &c->value);
-    mp_divide(&c->value, &r, &c->value);
-}
-
-
-static void
-load_ecb_rates()
-{
-    Currency *eur_rate;
-    char *filename = get_ecb_rate_filepath();
-    xmlDocPtr document;
-    xmlXPathContextPtr xpath_ctx;
-    xmlXPathObjectPtr xpath_obj;
-    int i, len;
-
-    /* Scale rates to the EUR value */
-    eur_rate = get_currency("EUR");
-    if (!eur_rate) {
-        g_warning("Cannot use ECB rates as don't have EUR rate");
-        return;
-    }
-
-    /* Set some fixed rates */
-    set_ecb_fixed_rate("EEK", "15.6466", eur_rate);
-
-    xmlInitParser();
-    document = xmlReadFile(filename, NULL, 0);
-    g_free (filename);
-    if (document == NULL) {
-        g_error("Couldn't parse ECB rate file %s", filename);
-        return;
-    }
-
-    xpath_ctx = xmlXPathNewContext(document);
-    if (xpath_ctx == NULL) {
-        xmlFreeDoc(document);
-        g_error("Couldn't create XPath context");
-        return;
-    }
-
-    xmlXPathRegisterNs(xpath_ctx,
-                       BAD_CAST("xref"),
-                       BAD_CAST("http://www.ecb.int/vocabulary/2002-08-01/eurofxref";));
-    xpath_obj = xmlXPathEvalExpression(BAD_CAST("//xref:Cube[ currency][@rate]"),
-                                       xpath_ctx);
-    if (xpath_obj == NULL) {
-        xmlXPathFreeContext(xpath_ctx);
-        xmlFreeDoc(document);
-        fprintf(stderr, "Couldn't create XPath object\n");
-        return;
-    }
-    len = (xpath_obj->nodesetval) ? xpath_obj->nodesetval->nodeNr : 0;
-    for (i = 0; i < len; i++) {
-        if (xpath_obj->nodesetval->nodeTab[i]->type == XML_ELEMENT_NODE)
-            set_ecb_rate(xpath_obj->nodesetval->nodeTab[i], eur_rate);
-
-        /* Avoid accessing removed elements */
-        if (xpath_obj->nodesetval->nodeTab[i]->type != XML_NAMESPACE_DECL)
-            xpath_obj->nodesetval->nodeTab[i] = NULL;
-    }
-
-    xmlXPathFreeObject(xpath_obj);
-    xmlXPathFreeContext(xpath_ctx);
-    xmlFreeDoc(document);
-    xmlCleanupParser();
-}
-
-
-static void
-load_rates()
-{
-    int i;
-
-    /* Use the IMF provided values and top up with currencies tracked by the ECB and not the IMF */
-    load_imf_rates();
-    load_ecb_rates();
-
-    for (i = 0; currency_info[i].short_name; i++) {
-       GList *link;
-       for (link = currencies; link; link = link->next) {
-           Currency *c = link->data;
-           if (c->info == &currency_info[i])
-              break;
-       }
-       if (!link)
-           g_warning("Currency %s is not provided by IMF or ECB", currency_info[i].short_name);
-    }
-
-    g_debug("Rates loaded");
-    loaded_rates = TRUE;  
-}
-
-
-const CurrencyInfo *
-currency_get_info(const gchar *name)
-{
-    int i = 0;
-    while (currency_info[i].short_name && strcmp(name, currency_info[i].short_name) != 0)
-        i++;
-    if (currency_info[i].short_name)
-        return &currency_info[i];
-    else
-        return NULL;
-}
-
-
-MPNumber *
-currency_get_value(const gchar *currency)
-{
-    gchar *path;
-    Currency *info;
-
-    /* Update rates if necessary */
-    path = get_imf_rate_filepath();
-    if (!downloading_imf_rates && file_needs_update(path, 60 * 60 * 24 * 7)) {
-        downloading_imf_rates = TRUE;
-        g_debug("Downloading rates from the IMF...");
-        download_file("http://www.imf.org/external/np/fin/data/rms_five.aspx?tsvflag=Y";, path, download_imf_cb);
-    }
-    g_free(path);
-    path = get_ecb_rate_filepath();
-    if (!downloading_ecb_rates && file_needs_update(path, 60 * 60 * 24 * 7)) {
-        downloading_ecb_rates = TRUE;
-        g_debug("Downloading rates from the ECB...");
-        download_file("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml";, path, download_ecb_cb);
-    }
-    g_free(path);
-
-    if (downloading_imf_rates || downloading_ecb_rates)
-        return NULL;
-
-    if (!loaded_rates)
-        load_rates();
-  
-    info = get_currency(currency);
-    return &info->value;
+    currency->priv = G_TYPE_INSTANCE_GET_PRIVATE(currency, currency_get_type(), CurrencyPrivate);
 }
diff --git a/src/currency.h b/src/currency.h
index ea45751..f7f761b 100644
--- a/src/currency.h
+++ b/src/currency.h
@@ -1,82 +1,40 @@
 #ifndef CURRENCY_H
 #define CURRENCY_H
 
-#include <glib/gi18n.h>
-
+#include <glib-object.h>
 #include "mp.h"
 
-typedef struct {
-    char *short_name;
-    char *symbol;
-    char *long_name;
-} CurrencyInfo;
-static const CurrencyInfo currency_info[] = {
-    {"AED", "إ.د",  N_("United Arab Emirates dirham")},
-    {"AUD", "$",    N_("Australian dollar")},
-    {"BGN", "лв",   N_("Bulgarian lev")},
-    {"BHD", ".ب.د", N_("Bahraini dinar")},
-    {"BND", "$",    N_("Brunei dollar")},
-    {"BRL", "R$",   N_("Brazilian real")},
-    {"BWP", "P",    N_("Botswana pula")},
-    {"CAD", "$",    N_("Canadian dollar")},
-    {"CHF", "Fr",   N_("Swiss franc")},
-    {"CLP", "$",    N_("Chilean peso")},
-    {"CNY", "å??",   N_("Chinese yuan renminbi")},
-    {"COP", "$",    N_("Colombian peso")},
-    {"CZK", "KÄ?",   N_("Czech koruna")},
-    {"DKK", "kr",   N_("Danish krone")},
-    {"DZD", "ج.د",  N_("Algerian dinar")},
-    {"EEK", "KR",   N_("Estonian kroon")},
-    {"EUR", "â?¬",    N_("Euro")},
-    {"GBP", "£",    N_("Pound sterling")},
-    {"HKD", "$",    N_("Hong Kong dollar")},
-    {"HRK", "kn",   N_("Croatian kuna")},
-    {"HUF", "Ft",   N_("Hungarian forint")},
-    {"IDR", "Rp",   N_("Indonesian rupiah")},
-    {"ILS", "â?ª",    N_("Israeli new shekel")},
-    {"INR", "â?¹",    N_("Indian rupee")},
-    {"IRR", "ï·¼",    N_("Iranian rial")},
-    {"ISK", "kr",   N_("Icelandic krona")},
-    {"JPY", "Â¥",    N_("Japanese yen")},
-    {"KRW", "â?©",    N_("South Korean won")},
-    {"KWD", "Ù?.د",  N_("Kuwaiti dinar")},
-    {"KZT", "â?¸",    N_("Kazakhstani tenge")},
-    {"LKR", "Rs",   N_("Sri Lankan rupee")},
-    {"LTL", "Lt",   N_("Lithuanian litas")},
-    {"LVL", "Ls",   N_("Latvian lats")},
-    {"LYD", "د.Ù?",  N_("Libyan dinar")},
-    {"MUR", "Rs",   N_("Mauritian rupee")},
-    {"MXN", "$",    N_("Mexican peso")},
-    {"MYR", "RM",   N_("Malaysian ringgit")},
-    {"NOK", "kr",   N_("Norwegian krone")},
-    {"NPR", "Rs",   N_("Nepalese rupee")},
-    {"NZD", "$",    N_("New Zealand dollar")},
-    {"OMR", "ع.ر.", N_("Omani rial")},
-    {"PEN", "S/.",  N_("Peruvian nuevo sol")},
-    {"PHP", "â?±",    N_("Philippine peso")},
-    {"PKR", "Rs",   N_("Pakistani rupee")},
-    {"PLN", "zÅ?",   N_("Polish zloty")},
-    {"QAR", "Ù?.ر",  N_("Qatari riyal")},
-    {"RON", "L",    N_("New Romanian leu")},
-    {"RUB", "Ñ?Ñ?б.", N_("Russian rouble")},
-    {"SAR", "س.ر",  N_("Saudi riyal")},
-    {"SEK", "kr",   N_("Swedish krona")},
-    {"SGD", "$",    N_("Singapore dollar")},
-    {"THB", "฿",    N_("Thai baht")},
-    {"TND", "ت.د",  N_("Tunisian dinar")},
-    {"TRY", "TL",   N_("New Turkish lira")},
-    {"TTD", "$",    N_("Trinidad and Tobago dollar")},
-    {"USD", "$",    N_("US dollar")},
-    {"UYU", "$",    N_("Uruguayan peso")},
-    {"VEF", "Bs F", N_("Venezuelan bolívar")},
-    {"ZAR", "R",    N_("South African rand")},
-    {NULL, NULL}
-};
+G_BEGIN_DECLS
+
+#define CURRENCY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), currency_get_type(), Currency))
+
+typedef struct CurrencyPrivate CurrencyPrivate;
+
+typedef struct
+{
+    GObject parent_instance;
+    CurrencyPrivate *priv;
+} Currency;
+
+typedef struct
+{
+    GObjectClass parent_class;
+} CurrencyClass;
+
+GType currency_get_type(void);
+
+Currency *currency_new(const gchar *name, const gchar *display_name, const gchar *symbol);
+
+const gchar *currency_get_name(Currency *currency);
+
+const gchar *currency_get_display_name(Currency *currency);
+
+const gchar *currency_get_symbol(Currency *currency);
 
-// FIXME: Should indicate when rates are updated to UI
+void currency_set_value(Currency *currency, MPNumber *value);
 
-const CurrencyInfo *currency_get_info(const gchar *name);
+const MPNumber *currency_get_value(Currency *currency);
 
-MPNumber *currency_get_value(const gchar *currency);
+G_END_DECLS
 
 #endif /* CURRENCY_H */
diff --git a/src/math-buttons.c b/src/math-buttons.c
index 87eded8..4295ff2 100644
--- a/src/math-buttons.c
+++ b/src/math-buttons.c
@@ -22,7 +22,6 @@
 #include "math-converter.h"
 #include "math-variable-popup.h"
 #include "financial.h"
-#include "currency.h"
 #include "mp-serializer.h"
 
 enum {
diff --git a/src/math-converter.c b/src/math-converter.c
index e2279a7..c5021f0 100644
--- a/src/math-converter.c
+++ b/src/math-converter.c
@@ -20,7 +20,6 @@
 
 #include "math-converter.h"
 #include "unit-manager.h"
-#include "currency.h"
 
 enum {
     CHANGED,
diff --git a/src/math-equation.c b/src/math-equation.c
index c76b774..082a3c1 100644
--- a/src/math-equation.c
+++ b/src/math-equation.c
@@ -24,13 +24,13 @@
 #include <math.h>
 #include <errno.h>
 #include <glib.h>
+#include <glib/gi18n.h>
 
 #include "math-equation.h"
 
 #include "mp.h"
 #include "mp-equation.h"
 #include "mp-serializer.h"
-#include "currency.h"
 #include "math-enums.h"
 
 
@@ -648,10 +648,6 @@ math_equation_get_angle_units(MathEquation *equation)
 void
 math_equation_set_source_currency(MathEquation *equation, const gchar *currency)
 {
-    // FIXME: Pick based on locale  
-    if (!currency || currency[0] == '\0')
-        currency = currency_info[0].short_name;
-
     if (strcmp(equation->priv->source_currency, currency) == 0)
         return;
     g_free(equation->priv->source_currency);
@@ -670,10 +666,6 @@ math_equation_get_source_currency(MathEquation *equation)
 void
 math_equation_set_target_currency(MathEquation *equation, const gchar *currency)
 {
-    // FIXME: Pick based on locale  
-    if (!currency || currency[0] == '\0')
-        currency = currency_info[0].short_name;
-
     if (strcmp(equation->priv->target_currency, currency) == 0)
         return;
     g_free(equation->priv->target_currency);
@@ -1859,8 +1851,8 @@ math_equation_init(MathEquation *equation)
     equation->priv->word_size = 32;
     equation->priv->angle_units = MP_DEGREES;
     // FIXME: Pick based on locale
-    equation->priv->source_currency = g_strdup(currency_info[0].short_name);
-    equation->priv->target_currency = g_strdup(currency_info[0].short_name);
+    equation->priv->source_currency = g_strdup("");
+    equation->priv->target_currency = g_strdup("");
     equation->priv->source_units = g_strdup("");
     equation->priv->target_units = g_strdup("");
     equation->priv->serializer = mp_serializer_new(MP_DISPLAY_FORMAT_AUTOMATIC, 10, 9);
diff --git a/src/unit-category.c b/src/unit-category.c
index 81edd70..aae9e98 100644
--- a/src/unit-category.c
+++ b/src/unit-category.c
@@ -1,7 +1,6 @@
 #include <string.h>
 
 #include "unit-category.h"
-#include "currency.h" // FIXME: TEMP
 
 struct UnitCategoryPrivate
 {
diff --git a/src/unit-manager.c b/src/unit-manager.c
index b77c99b..4d5e032 100644
--- a/src/unit-manager.c
+++ b/src/unit-manager.c
@@ -2,7 +2,7 @@
 #include <glib/gi18n.h> // FIXME: Move out of here
 
 #include "unit-manager.h"
-#include "currency.h" // FIXME: Move out of here
+#include "currency-manager.h" // FIXME: Move out of here
 
 struct UnitManagerPrivate
 {
@@ -35,7 +35,7 @@ unit_manager_get_default(void)
 {
     UnitCategory *category;
     MPNumber t;
-    int i;
+    const GList *iter;
 
     if (default_unit_manager)
         return default_unit_manager;
@@ -105,13 +105,14 @@ unit_manager_get_default(void)
     //unit_category_add_unit(category, unit_new("kelvin", _("Kelvin"), "%s days", get_value("86400", &t), "days", "day", NULL));
 
     category = unit_manager_add_category(default_unit_manager, "currency", _("Currency"));
-    for (i = 0; currency_info[i].short_name != NULL; i++)
+    for (iter = currency_manager_get_currencies(currency_manager_get_default()); iter; iter = iter->next)
     {
+        Currency *currency = iter->data;
         gchar *format;
         Unit *unit;
 
-        format = g_strdup_printf("%s%%s", currency_info[i].symbol);
-        unit = unit_new(currency_info[i].short_name, currency_info[i].short_name, format, NULL, currency_info[i].short_name, NULL);
+        format = g_strdup_printf("%s%%s", currency_get_symbol(currency));
+        unit = unit_new(currency_get_name(currency), currency_get_name(currency), format, NULL, currency_get_name(currency), NULL);
         g_free(format);
 
         unit_category_add_unit(category, unit);
diff --git a/src/unit.c b/src/unit.c
index 3a53d74..762b572 100644
--- a/src/unit.c
+++ b/src/unit.c
@@ -3,7 +3,7 @@
 
 #include "unit.h"
 #include "mp-serializer.h"
-#include "currency.h" // FIXME: Move out of here
+#include "currency-manager.h" // FIXME: Move out of here
 
 struct UnitPrivate
 {
@@ -92,7 +92,7 @@ unit_get_value(Unit *unit)
     if (unit->priv->has_value)
         return &unit->priv->value;
     else
-        return currency_get_value(unit->priv->name); // FIXME: Hack to make currency work
+        return currency_manager_get_value(currency_manager_get_default(), unit->priv->name); // FIXME: Hack to make currency work
 }
 
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]