~registry/gcalctool/trunk

« back to all changes in this revision

Viewing changes to src/currency-manager.c

  • Committer: Robert Ancell
  • Date: 2012-10-14 03:31:40 UTC
  • Revision ID: git-v1:12ba2c81b0a81bb3ac776d1034a3c41b3173196a
Port to Vala

https://bugzilla.gnome.org/show_bug.cgi?id=640685

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2008-2011 Robert Ancell.
3
 
 *
4
 
 * This program is free software: you can redistribute it and/or modify it under
5
 
 * the terms of the GNU General Public License as published by the Free Software
6
 
 * Foundation, either version 2 of the License, or (at your option) any later
7
 
 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
8
 
 * license.
9
 
 */
10
 
 
11
 
#include <time.h>
12
 
 
13
 
#include <glib.h>
14
 
#include <glib/gstdio.h>
15
 
#include <gio/gio.h>
16
 
#include <libxml/tree.h>
17
 
#include <libxml/xpath.h>
18
 
#include <libxml/xpathInternals.h>
19
 
#include <glib/gi18n.h>
20
 
 
21
 
#include "currency-manager.h"
22
 
#include "mp.h"
23
 
 
24
 
typedef struct {
25
 
    char *short_name;
26
 
    char *symbol;
27
 
    char *long_name;
28
 
} CurrencyInfo;
29
 
static const CurrencyInfo currency_info[] = {
30
 
    {"AED", "إ.د",  N_("UAE Dirham")},
31
 
    {"AUD", "$",    N_("Australian Dollar")},
32
 
    {"BGN", "лв",   N_("Bulgarian Lev")},
33
 
    {"BHD", ".ب.د", N_("Bahraini Dinar")},
34
 
    {"BND", "$",    N_("Brunei Dollar")},
35
 
    {"BRL", "R$",   N_("Brazilian Real")},
36
 
    {"BWP", "P",    N_("Botswana Pula")},
37
 
    {"CAD", "$",    N_("Canadian Dollar")},
38
 
    {"CFA", "Fr",   N_("CFA Franc")},
39
 
    {"CHF", "Fr",   N_("Swiss Franc")},
40
 
    {"CLP", "$",    N_("Chilean Peso")},
41
 
    {"CNY", "元",   N_("Chinese Yuan")},
42
 
    {"COP", "$",    N_("Colombian Peso")},
43
 
    {"CZK", "Kč",   N_("Czech Koruna")},
44
 
    {"DKK", "kr",   N_("Danish Krone")},
45
 
    {"DZD", "ج.د",  N_("Algerian Dinar")},
46
 
    {"EEK", "KR",   N_("Estonian Kroon")},
47
 
    {"EUR", "€",    N_("Euro")},
48
 
    {"GBP", "£",    N_("Pound Sterling")},
49
 
    {"HKD", "$",    N_("Hong Kong Dollar")},
50
 
    {"HRK", "kn",   N_("Croatian Kuna")},
51
 
    {"HUF", "Ft",   N_("Hungarian Forint")},
52
 
    {"IDR", "Rp",   N_("Indonesian Rupiah")},
53
 
    {"ILS", "₪",    N_("Israeli New Shekel")},
54
 
    {"INR", "₹",    N_("Indian Rupee")},
55
 
    {"IRR", "﷼",    N_("Iranian Rial")},
56
 
    {"ISK", "kr",   N_("Icelandic Krona")},
57
 
    {"JPY", "¥",    N_("Japanese Yen")},
58
 
    {"KRW", "₩",    N_("South Korean Won")},
59
 
    {"KWD", "ك.د",  N_("Kuwaiti Dinar")},
60
 
    {"KZT", "₸",    N_("Kazakhstani Tenge")},
61
 
    {"LKR", "Rs",   N_("Sri Lankan Rupee")},
62
 
    {"LTL", "Lt",   N_("Lithuanian Litas")},
63
 
    {"LVL", "Ls",   N_("Latvian Lats")},
64
 
    {"LYD", "د.ل",  N_("Libyan Dinar")},
65
 
    {"MUR", "Rs",   N_("Mauritian Rupee")},
66
 
    {"MXN", "$",    N_("Mexican Peso")},
67
 
    {"MYR", "RM",   N_("Malaysian Ringgit")},
68
 
    {"NOK", "kr",   N_("Norwegian Krone")},
69
 
    {"NPR", "Rs",   N_("Nepalese Rupee")},
70
 
    {"NZD", "$",    N_("New Zealand Dollar")},
71
 
    {"OMR", "ع.ر.", N_("Omani Rial")},
72
 
    {"PEN", "S/.",  N_("Peruvian Nuevo Sol")},
73
 
    {"PHP", "₱",    N_("Philippine Peso")},
74
 
    {"PKR", "Rs",   N_("Pakistani Rupee")},
75
 
    {"PLN", "zł",   N_("Polish Zloty")},
76
 
    {"QAR", "ق.ر",  N_("Qatari Riyal")},
77
 
    {"RON", "L",    N_("New Romanian Leu")},
78
 
    {"RUB", "руб.", N_("Russian Rouble")},
79
 
    {"SAR", "س.ر",  N_("Saudi Riyal")},
80
 
    {"SEK", "kr",   N_("Swedish Krona")},
81
 
    {"SGD", "$",    N_("Singapore Dollar")},
82
 
    {"THB", "฿",    N_("Thai Baht")},
83
 
    {"TND", "ت.د",  N_("Tunisian Dinar")},
84
 
    {"TRY", "TL",   N_("New Turkish Lira")},
85
 
    {"TTD", "$",    N_("T&T Dollar (TTD)")},
86
 
    {"USD", "$",    N_("US Dollar")},
87
 
    {"UYU", "$",    N_("Uruguayan Peso")},
88
 
    {"VEF", "Bs F", N_("Venezuelan Bolívar")},
89
 
    {"ZAR", "R",    N_("South African Rand")},
90
 
    {NULL, NULL}
91
 
};
92
 
 
93
 
static gboolean downloading_imf_rates = FALSE, downloading_ecb_rates = FALSE;
94
 
static gboolean loaded_rates = FALSE;
95
 
static gboolean load_rates(CurrencyManager *manager);
96
 
 
97
 
struct CurrencyManagerPrivate
98
 
{
99
 
    GList *currencies;
100
 
};
101
 
 
102
 
G_DEFINE_TYPE (CurrencyManager, currency_manager, G_TYPE_OBJECT);
103
 
 
104
 
 
105
 
enum {
106
 
    UPDATED,
107
 
    LAST_SIGNAL
108
 
};
109
 
static guint signals[LAST_SIGNAL] = { 0, };
110
 
 
111
 
static CurrencyManager *default_currency_manager = NULL;
112
 
 
113
 
 
114
 
CurrencyManager *
115
 
currency_manager_get_default(void)
116
 
{
117
 
    int i;
118
 
 
119
 
    if (default_currency_manager)
120
 
        return default_currency_manager;
121
 
 
122
 
    default_currency_manager = g_object_new(currency_manager_get_type(), NULL);
123
 
 
124
 
    for (i = 0; currency_info[i].short_name; i++) {
125
 
        Currency *c = currency_new(currency_info[i].short_name,
126
 
                                   _(currency_info[i].long_name),
127
 
                                   currency_info[i].symbol);
128
 
        default_currency_manager->priv->currencies = g_list_append(default_currency_manager->priv->currencies, c);
129
 
    }
130
 
 
131
 
    return default_currency_manager;
132
 
}
133
 
 
134
 
 
135
 
GList *
136
 
currency_manager_get_currencies(CurrencyManager *manager)
137
 
{
138
 
    g_return_val_if_fail(manager != NULL, NULL);
139
 
    return manager->priv->currencies;
140
 
}
141
 
 
142
 
 
143
 
Currency *
144
 
currency_manager_get_currency(CurrencyManager *manager, const gchar *name)
145
 
{
146
 
    g_return_val_if_fail(manager != NULL, NULL);
147
 
    g_return_val_if_fail(name != NULL, NULL);
148
 
 
149
 
    GList *link;
150
 
    for (link = manager->priv->currencies; link; link = link->next) {
151
 
        Currency *c = link->data;
152
 
        const MPNumber *value;
153
 
 
154
 
        value = currency_get_value(c);
155
 
 
156
 
        if (!strcmp(name, currency_get_name(c))) {
157
 
            if (mp_is_negative(value) ||
158
 
                mp_is_zero(value)) {
159
 
                return NULL;
160
 
            }
161
 
            else
162
 
                return c;
163
 
        }
164
 
    }
165
 
    return NULL;
166
 
}
167
 
 
168
 
 
169
 
static char *
170
 
get_imf_rate_filepath()
171
 
{
172
 
    return g_build_filename(g_get_user_cache_dir (),
173
 
                            "gcalctool",
174
 
                            "rms_five.xls",
175
 
                            NULL);
176
 
}
177
 
 
178
 
 
179
 
static char *
180
 
get_ecb_rate_filepath()
181
 
{
182
 
    return g_build_filename(g_get_user_cache_dir (),
183
 
                            "gcalctool",
184
 
                            "eurofxref-daily.xml",
185
 
                            NULL);
186
 
}
187
 
 
188
 
 
189
 
static Currency *
190
 
add_currency(CurrencyManager *manager, const gchar *short_name)
191
 
{
192
 
    GList *iter;
193
 
    Currency *c;
194
 
 
195
 
    for (iter = manager->priv->currencies; iter; iter = iter->next) {
196
 
        c = iter->data;
197
 
        if (strcmp(short_name, currency_get_name(c)) == 0)
198
 
            return c;
199
 
    }
200
 
 
201
 
    g_warning("Currency %s is not in the currency table", short_name);
202
 
    c = currency_new(short_name, short_name, short_name);
203
 
    manager->priv->currencies = g_list_append(manager->priv->currencies, c);
204
 
 
205
 
    return c;
206
 
}
207
 
 
208
 
 
209
 
/* A file needs to be redownloaded if it doesn't exist, or is too old.
210
 
 * When an error occur, it probably won't hurt to try to download again.
211
 
 */
212
 
static gboolean
213
 
file_needs_update(gchar *filename, double max_age)
214
 
{
215
 
    struct stat buf;
216
 
 
217
 
    if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR))
218
 
        return TRUE;
219
 
 
220
 
    if (g_stat(filename, &buf) == -1)
221
 
        return TRUE;
222
 
 
223
 
    if (difftime(time(NULL), buf.st_mtime) > max_age)
224
 
        return TRUE;
225
 
 
226
 
    return FALSE;
227
 
}
228
 
 
229
 
 
230
 
static void
231
 
download_imf_cb(GObject *object, GAsyncResult *result, gpointer user_data)
232
 
{
233
 
    CurrencyManager *manager = user_data;
234
 
    GError *error = NULL;
235
 
 
236
 
    if (g_file_copy_finish(G_FILE(object), result, &error))
237
 
        g_debug("IMF rates updated");
238
 
    else
239
 
        g_warning("Couldn't download IMF currency rate file: %s", error->message);
240
 
    g_clear_error(&error);
241
 
    downloading_imf_rates = FALSE;
242
 
    load_rates(manager);
243
 
}
244
 
 
245
 
 
246
 
static void
247
 
download_ecb_cb(GObject *object, GAsyncResult *result, gpointer user_data)
248
 
{
249
 
    CurrencyManager *manager = user_data;
250
 
    GError *error = NULL;
251
 
 
252
 
    if (g_file_copy_finish(G_FILE(object), result, &error))
253
 
        g_debug("ECB rates updated");
254
 
    else
255
 
        g_warning("Couldn't download ECB currency rate file: %s", error->message);
256
 
    g_clear_error(&error);
257
 
    downloading_ecb_rates = FALSE;
258
 
    load_rates(manager);
259
 
}
260
 
 
261
 
 
262
 
static void
263
 
download_file(CurrencyManager *manager, gchar *uri, gchar *filename, GAsyncReadyCallback callback)
264
 
{
265
 
    gchar *directory;
266
 
    GFile *source, *dest;
267
 
 
268
 
    directory = g_path_get_dirname(filename);
269
 
    g_mkdir_with_parents(directory, 0755);
270
 
    g_free(directory);
271
 
 
272
 
    source = g_file_new_for_uri(uri);
273
 
    dest = g_file_new_for_path(filename);
274
 
 
275
 
    g_file_copy_async(source, dest, G_FILE_COPY_OVERWRITE, G_PRIORITY_DEFAULT, NULL, NULL, NULL, callback, manager);
276
 
    g_object_unref(source);
277
 
    g_object_unref(dest); 
278
 
}
279
 
 
280
 
 
281
 
static void
282
 
load_imf_rates(CurrencyManager *manager)
283
 
{
284
 
    gchar *filename;
285
 
    gchar *data, **lines;
286
 
    gsize length;
287
 
    GError *error = NULL;
288
 
    int i;
289
 
    gboolean result, in_data = FALSE;
290
 
    struct 
291
 
    {
292
 
        const gchar *name, *symbol;
293
 
    } name_map[] = 
294
 
    {
295
 
        {"Euro",                "EUR"},
296
 
        {"Japanese Yen",        "JPY"},
297
 
        {"U.K. Pound Sterling", "GBP"},
298
 
        {"U.S. Dollar",         "USD"},
299
 
        {"Algerian Dinar",      "DZD"},
300
 
        {"Australian Dollar",   "AUD"},
301
 
        {"Bahrain Dinar",       "BHD"},
302
 
        {"Botswana Pula",       "BWP"},
303
 
        {"Brazilian Real",      "BRL"},
304
 
        {"Brunei Dollar",       "BND"},
305
 
        {"Canadian Dollar",     "CAD"},
306
 
        {"Chilean Peso",        "CLP"},
307
 
        {"Chinese Yuan",        "CNY"},
308
 
        {"Colombian Peso",      "COP"},
309
 
        {"Czech Koruna",        "CZK"},
310
 
        {"Danish Krone",        "DKK"},
311
 
        {"Hungarian Forint",    "HUF"},
312
 
        {"Icelandic Krona",     "ISK"},
313
 
        {"Indian Rupee",        "INR"},
314
 
        {"Indonesian Rupiah",   "IDR"},
315
 
        {"Iranian Rial",        "IRR"},
316
 
        {"Israeli New Sheqel",  "ILS"},
317
 
        {"Kazakhstani Tenge",   "KZT"},
318
 
        {"Korean Won",          "KRW"},
319
 
        {"Kuwaiti Dinar",       "KWD"},
320
 
        {"Libyan Dinar",        "LYD"},
321
 
        {"Malaysian Ringgit",   "MYR"},
322
 
        {"Mauritian Rupee",     "MUR"},
323
 
        {"Mexican Peso",        "MXN"},
324
 
        {"Nepalese Rupee",      "NPR"},
325
 
        {"New Zealand Dollar",  "NZD"},
326
 
        {"Norwegian Krone",     "NOK"},
327
 
        {"Rial Omani",          "OMR"},
328
 
        {"Pakistani Rupee",     "PKR"},
329
 
        {"Nuevo Sol",           "PEN"},
330
 
        {"Philippine Peso",     "PHP"},
331
 
        {"Polish Zloty",        "PLN"},
332
 
        {"Qatar Riyal",         "QAR"},
333
 
        {"Russian Ruble",       "RUB"},
334
 
        {"Saudi Arabian Riyal", "SAR"},
335
 
        {"Singapore Dollar",    "SGD"},
336
 
        {"South African Rand",  "ZAR"},
337
 
        {"Sri Lanka Rupee",     "LKR"},
338
 
        {"Swedish Krona",       "SEK"},
339
 
        {"Swiss Franc",         "CHF"},
340
 
        {"Thai Baht",           "THB"},
341
 
        {"Trinidad And Tobago Dollar", "TTD"},
342
 
        {"Tunisian Dinar",      "TND"},
343
 
        {"U.A.E. Dirham",       "AED"},
344
 
        {"Peso Uruguayo",       "UYU"},
345
 
        {"Bolivar Fuerte",      "VEF"},
346
 
        {NULL, NULL}
347
 
    };
348
 
 
349
 
    filename = get_imf_rate_filepath();
350
 
    result = g_file_get_contents(filename, &data, &length, &error);
351
 
    g_free(filename);
352
 
    if (!result)
353
 
    {
354
 
        g_warning("Failed to read exchange rates: %s", error->message);
355
 
        g_clear_error(&error);
356
 
        return;
357
 
    }
358
 
 
359
 
    lines = g_strsplit(data, "\n", 0);
360
 
    g_free(data);
361
 
 
362
 
    for (i = 0; lines[i]; i++) {
363
 
        gchar *line, **tokens;
364
 
 
365
 
        line = g_strchug(lines[i]);
366
 
      
367
 
        /* Start after first blank line, stop on next */
368
 
        if (line[0] == '\0') {
369
 
            if (!in_data) {
370
 
               in_data = TRUE;
371
 
               continue;
372
 
            }
373
 
            else
374
 
               break;
375
 
        }
376
 
        if (!in_data)
377
 
            continue;
378
 
 
379
 
        tokens = g_strsplit(line, "\t", 0);
380
 
        if (strcmp(tokens[0], "Currency") != 0) {
381
 
            gint value_index, name_index;
382
 
 
383
 
            for (value_index = 1; tokens[value_index]; value_index++) {
384
 
                gchar *value = g_strchug (tokens[value_index]);
385
 
                if (value[0] != '\0')
386
 
                    break;
387
 
            }
388
 
            if (tokens[value_index]) {
389
 
                for (name_index = 0; name_map[name_index].name; name_index++) {
390
 
                    if (strcmp(name_map[name_index].name, tokens[0]) == 0)
391
 
                        break;
392
 
                }
393
 
                if (name_map[name_index].name) {
394
 
                    Currency *c = currency_manager_get_currency(manager, name_map[name_index].symbol);
395
 
                    MPNumber value;
396
 
 
397
 
                    if (!c) {
398
 
                        g_debug ("Using IMF rate of %s for %s", tokens[value_index], name_map[name_index].symbol);
399
 
                        c = add_currency(manager, name_map[name_index].symbol);
400
 
                    }
401
 
                    mp_set_from_string(tokens[value_index], 10, &value);
402
 
                    mp_reciprocal(&value, &value);
403
 
                    currency_set_value(c, &value);
404
 
                }
405
 
                else
406
 
                    g_warning("Unknown currency '%s'", tokens[0]);
407
 
            }
408
 
        }
409
 
        g_strfreev(tokens);
410
 
    }
411
 
    g_strfreev(lines);
412
 
}
413
 
 
414
 
 
415
 
static void
416
 
set_ecb_rate(CurrencyManager *manager, xmlNodePtr node, Currency *eur_rate)
417
 
{
418
 
    xmlAttrPtr attribute;
419
 
    gchar *name = NULL, *value = NULL;
420
 
 
421
 
    for (attribute = node->properties; attribute; attribute = attribute->next) {
422
 
        if (strcmp((char *)attribute->name, "currency") == 0) {
423
 
            if (name)
424
 
                xmlFree(name);
425
 
            name = (gchar *)xmlNodeGetContent((xmlNodePtr)attribute);
426
 
        } else if (strcmp ((char *)attribute->name, "rate") == 0) {
427
 
            if (value)
428
 
                xmlFree(value);
429
 
            value = (gchar *)xmlNodeGetContent((xmlNodePtr)attribute);
430
 
        }
431
 
    }
432
 
 
433
 
    /* Use data if value and no rate currently defined */
434
 
    if (name && value && !currency_manager_get_currency(manager, name)) {
435
 
        Currency *c;
436
 
        MPNumber r, v;
437
 
 
438
 
        g_debug ("Using ECB rate of %s for %s", value, name);
439
 
        c = add_currency(manager, name);
440
 
        mp_set_from_string(value, 10, &r);
441
 
        mp_set_from_mp(currency_get_value(eur_rate), &v);
442
 
        mp_multiply(&v, &r, &v);
443
 
        currency_set_value(c, &v);
444
 
    }
445
 
 
446
 
    if (name)
447
 
        xmlFree(name);
448
 
    if (value)
449
 
        xmlFree(value);
450
 
}
451
 
 
452
 
 
453
 
static void
454
 
set_ecb_fixed_rate(CurrencyManager *manager, const gchar *name, const gchar *value, Currency *eur_rate)
455
 
{
456
 
    Currency *c;
457
 
    MPNumber r, v;
458
 
 
459
 
    g_debug ("Using ECB fixed rate of %s for %s", value, name);
460
 
    c = add_currency(manager, name);
461
 
    mp_set_from_string(value, 10, &r);
462
 
    mp_set_from_mp(currency_get_value(eur_rate), &v);
463
 
    mp_divide(&v, &r, &v);
464
 
    currency_set_value(c, &v);
465
 
}
466
 
 
467
 
 
468
 
static void
469
 
load_ecb_rates(CurrencyManager *manager)
470
 
{
471
 
    Currency *eur_rate;
472
 
    char *filename;
473
 
    xmlDocPtr document;
474
 
    xmlXPathContextPtr xpath_ctx;
475
 
    xmlXPathObjectPtr xpath_obj;
476
 
    int i, len;
477
 
 
478
 
    /* Scale rates to the EUR value */
479
 
    eur_rate = currency_manager_get_currency(manager, "EUR");
480
 
    if (!eur_rate) {
481
 
        g_warning("Cannot use ECB rates as don't have EUR rate");
482
 
        return;
483
 
    }
484
 
 
485
 
    /* Set some fixed rates */
486
 
    set_ecb_fixed_rate(manager, "EEK", "0.06391", eur_rate);
487
 
    set_ecb_fixed_rate(manager, "CFA", "0.152449", eur_rate);
488
 
 
489
 
    xmlInitParser();
490
 
    filename = get_ecb_rate_filepath();
491
 
    document = xmlReadFile(filename, NULL, 0);
492
 
    if (!document)
493
 
        g_warning("Couldn't parse ECB rate file %s", filename);
494
 
    g_free (filename);
495
 
    if (!document)    
496
 
        return;
497
 
 
498
 
    xpath_ctx = xmlXPathNewContext(document);
499
 
    if (xpath_ctx == NULL) {
500
 
        xmlFreeDoc(document);
501
 
        g_warning("Couldn't create XPath context");
502
 
        return;
503
 
    }
504
 
 
505
 
    xmlXPathRegisterNs(xpath_ctx,
506
 
                       BAD_CAST("xref"),
507
 
                       BAD_CAST("http://www.ecb.int/vocabulary/2002-08-01/eurofxref"));
508
 
    xpath_obj = xmlXPathEvalExpression(BAD_CAST("//xref:Cube[@currency][@rate]"),
509
 
                                       xpath_ctx);
510
 
    if (xpath_obj == NULL) {
511
 
        xmlXPathFreeContext(xpath_ctx);
512
 
        xmlFreeDoc(document);
513
 
        g_warning("Couldn't create XPath object");
514
 
        return;
515
 
    }
516
 
    len = (xpath_obj->nodesetval) ? xpath_obj->nodesetval->nodeNr : 0;
517
 
    for (i = 0; i < len; i++) {
518
 
        if (xpath_obj->nodesetval->nodeTab[i]->type == XML_ELEMENT_NODE)
519
 
            set_ecb_rate(manager, xpath_obj->nodesetval->nodeTab[i], eur_rate);
520
 
 
521
 
        /* Avoid accessing removed elements */
522
 
        if (xpath_obj->nodesetval->nodeTab[i]->type != XML_NAMESPACE_DECL)
523
 
            xpath_obj->nodesetval->nodeTab[i] = NULL;
524
 
    }
525
 
 
526
 
    xmlXPathFreeObject(xpath_obj);
527
 
    xmlXPathFreeContext(xpath_ctx);
528
 
    xmlFreeDoc(document);
529
 
    xmlCleanupParser();
530
 
}
531
 
 
532
 
 
533
 
static gboolean
534
 
load_rates(CurrencyManager *manager)
535
 
{
536
 
    int i;
537
 
 
538
 
    /* Already loaded */
539
 
    if (loaded_rates)
540
 
        return TRUE;
541
 
 
542
 
    /* In process */
543
 
    if (downloading_imf_rates || downloading_ecb_rates)
544
 
        return FALSE;
545
 
 
546
 
    /* Use the IMF provided values and top up with currencies tracked by the ECB and not the IMF */
547
 
    load_imf_rates(manager);
548
 
    load_ecb_rates(manager);
549
 
 
550
 
    for (i = 0; currency_info[i].short_name; i++) {
551
 
       GList *link;
552
 
       for (link = manager->priv->currencies; link; link = link->next) {
553
 
           Currency *c = link->data;
554
 
           if (strcmp(currency_get_name(c), currency_info[i].short_name) == 0)
555
 
              break;
556
 
       }
557
 
       if (!link)
558
 
           g_warning("Currency %s is not provided by IMF or ECB", currency_info[i].short_name);
559
 
    }
560
 
 
561
 
    g_debug("Rates loaded");
562
 
    loaded_rates = TRUE;
563
 
 
564
 
    g_signal_emit(manager, signals[UPDATED], 0);
565
 
  
566
 
    return TRUE;
567
 
}
568
 
 
569
 
 
570
 
const MPNumber *
571
 
currency_manager_get_value(CurrencyManager *manager, const gchar *currency)
572
 
{
573
 
    gchar *path;
574
 
    Currency *c;
575
 
 
576
 
    g_return_val_if_fail(manager != NULL, NULL);
577
 
    g_return_val_if_fail(currency != NULL, NULL);
578
 
 
579
 
    /* Update rates if necessary */
580
 
    path = get_imf_rate_filepath();
581
 
    if (!downloading_imf_rates && file_needs_update(path, 60 * 60 * 24 * 7)) {
582
 
        downloading_imf_rates = TRUE;
583
 
        g_debug("Downloading rates from the IMF...");
584
 
        download_file(manager, "http://www.imf.org/external/np/fin/data/rms_five.aspx?tsvflag=Y", path, download_imf_cb);
585
 
    }
586
 
    g_free(path);
587
 
    path = get_ecb_rate_filepath();
588
 
    if (!downloading_ecb_rates && file_needs_update(path, 60 * 60 * 24 * 7)) {
589
 
        downloading_ecb_rates = TRUE;
590
 
        g_debug("Downloading rates from the ECB...");
591
 
        download_file(manager, "http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml", path, download_ecb_cb);
592
 
    }
593
 
    g_free(path);
594
 
 
595
 
    if (!load_rates(manager))
596
 
        return NULL;
597
 
 
598
 
    c = currency_manager_get_currency(manager, currency);
599
 
    if (c)
600
 
        return currency_get_value(c);
601
 
    else
602
 
        return NULL;
603
 
}
604
 
 
605
 
 
606
 
static void
607
 
currency_manager_class_init(CurrencyManagerClass *klass)
608
 
{
609
 
    g_type_class_add_private(klass, sizeof(CurrencyManagerPrivate));
610
 
 
611
 
    signals[UPDATED] =
612
 
        g_signal_new("updated",
613
 
                     G_TYPE_FROM_CLASS (klass),
614
 
                     G_SIGNAL_RUN_LAST,
615
 
                     G_STRUCT_OFFSET (CurrencyManagerClass, updated),
616
 
                     NULL, NULL,
617
 
                     g_cclosure_marshal_VOID__VOID,
618
 
                     G_TYPE_NONE, 0);
619
 
}
620
 
 
621
 
 
622
 
static void
623
 
currency_manager_init(CurrencyManager *manager)
624
 
{
625
 
    manager->priv = G_TYPE_INSTANCE_GET_PRIVATE(manager, currency_manager_get_type(), CurrencyManagerPrivate);
626
 
}