diff --git a/invest-applet/data/prefs-dialog.ui b/invest-applet/data/prefs-dialog.ui
index db12c24..0beee9a 100644
--- a/invest-applet/data/prefs-dialog.ui
+++ b/invest-applet/data/prefs-dialog.ui
@@ -58,6 +58,7 @@
                 <child>
                   <object class="GtkAlignment" id="alignment16">
                     <property name="visible">True</property>
+                    <property name="bottom_padding">18</property>
                     <property name="left_padding">18</property>
                     <child>
                       <object class="GtkVBox" id="vbox156">
@@ -140,6 +141,40 @@
                     <property name="position">2</property>
                   </packing>
                 </child>
+                <child>
+                  <object class="GtkLabel" id="currencylabel">
+                    <property name="visible">True</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">Currency</property>
+                    <property name="use_underline">True</property>
+                    <property name="justify">center</property>
+                    <attributes>
+                      <attribute name="weight" value="bold"/>
+                    </attributes>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkAlignment" id="alignment1">
+                    <property name="visible">True</property>
+                    <property name="left_padding">18</property>
+                    <child>
+                      <object class="GtkEntry" id="currency">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="invisible_char">&#x25CF;</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">4</property>
+                  </packing>
+                </child>
               </object>
               <packing>
                 <property name="padding">6</property>
diff --git a/invest-applet/invest/Makefile.am b/invest-applet/invest/Makefile.am
index 308149c..ede7a61 100644
--- a/invest-applet/invest/Makefile.am
+++ b/invest-applet/invest/Makefile.am
@@ -11,6 +11,7 @@ invest_PYTHON = \
 	about.py \
 	applet.py \
 	chart.py \
+	currencies.py \
 	widgets.py \
 	quotes.py \
 	networkmanager.py \
diff --git a/invest-applet/invest/__init__.py b/invest-applet/invest/__init__.py
index 63cc9dd..a02bd33 100644
--- a/invest-applet/invest/__init__.py
+++ b/invest-applet/invest/__init__.py
@@ -67,8 +67,8 @@ GCONF_DIR = "/apps/invest"
 # Preload gconf directories
 #GCONF_CLIENT.add_dir(GCONF_DIR, gconf.CLIENT_PRELOAD_RECURSIVE)
 
-# tests whether the given stocks are in the old format
-def old_stock_format(stocks):
+# tests whether the given stocks are in the old labelless format
+def labelless_stock_format(stocks):
 	if len(stocks) == 0:
 		return False
 
@@ -79,8 +79,8 @@ def old_stock_format(stocks):
 	# there is no list, so it is already the new stock file format
 	return False
 
-# converts the given stocks from the old format into the new one
-def update_stock_format(stocks):
+# converts the given stocks from the labelless format into the one with labels
+def update_to_labeled_stock_format(stocks):
 	new = {}
 
 	for k, l in stocks.items():
@@ -89,15 +89,43 @@ def update_stock_format(stocks):
 
 	return new
 
+# tests whether the given stocks are in the format without exchange information
+def exchangeless_stock_format(stocks):
+	if len(stocks) == 0:
+		return False
+
+	# take the first element of the dict and check if its value is a list
+	for symbol, data in stocks.items():
+		purchases = stocks[symbol]["purchases"]
+		if len(purchases) > 0:
+			purchase = purchases[0]
+			if not purchase.has_key("exchange"):
+				return True
+
+	return False
+
+# converts the given stocks into format with exchange information
+def update_to_exchange_stock_format(stocks):
+	for symbol, data in stocks.items():
+		purchases = data["purchases"]
+		for purchase in purchases:
+			purchase["exchange"] = 0
+
+	return stocks
+
 STOCKS_FILE = join(USER_INVEST_DIR, "stocks.pickle")
 
 try:
 	STOCKS = cPickle.load(file(STOCKS_FILE))
 
-	# if the stocks file is in the old stocks format,
-	# then we need to convert it into the new format
-	if old_stock_format(STOCKS):
-		STOCKS = update_stock_format(STOCKS);
+	# if the stocks file is in the stocks format without labels,
+	# then we need to convert it into the new labeled format
+	if labelless_stock_format(STOCKS):
+		STOCKS = update_to_labeled_stock_format(STOCKS);
+
+	# if the stocks file does not contain exchange rates, add them
+	if exchangeless_stock_format(STOCKS):
+		STOCKS = update_to_exchange_stock_format(STOCKS);
 except Exception, msg:
 	error("Could not load the stocks from %s: %s" % (STOCKS_FILE, msg) )
 	STOCKS = {}
@@ -120,6 +148,12 @@ except Exception, msg:
 #	},
 #}
 
+CONFIG_FILE = join(USER_INVEST_DIR, "config.pickle")
+try:
+	CONFIG = cPickle.load(file(CONFIG_FILE))
+except Exception, msg:
+	CONFIG = {}       # default configuration
+
 client = gconf.client_get_default()
 
 # borrowed from Ross Burton
diff --git a/invest-applet/invest/currencies.py b/invest-applet/invest/currencies.py
new file mode 100644
index 0000000..0eaa075
--- /dev/null
+++ b/invest-applet/invest/currencies.py
@@ -0,0 +1,145 @@
+class Currencies:
+	currencies = {
+		"BZD" : "Belize Dollar",
+		"NLG" : "Dutch Guilder",
+		"SLL" : "Sierra Leone Leone",
+		"FRF" : "French Franc",
+		"NGN" : "Nigerian Naira",
+		"CRC" : "Costa Rican Colon",
+		"LAK" : "Laos Kip",
+		"CLP" : "Chilean Peso",
+		"DZD" : "Algerian Dinar",
+		"SZL" : "Swaziland Lilangeni",
+		"MUR" : "Mauritius Rupee",
+		"WST" : "Western Samoa Tala",
+		"MMK" : "Myanmar Kyat",
+		"IDR" : "Indonesian Rupiah",
+		"GTQ" : "Guatemala Quetzal",
+		"CAD" : "Canadian Dollar",
+		"AWG" : "Aruban Florin",
+		"TTD" : "Trinidad Dollar",
+		"PKR" : "Pakistani Rupee",
+		"XCD" : "East Caribbean Dollar",
+		"VUV" : "Vanuatu Vatu",
+		"XOF" : "CFA Franc (BCEAO)",
+		"ROL" : "Romanian Leu",
+		"KMF" : "Comoros Franc",
+		"SIT" : "Slovenian Tolar",
+		"VEB" : "Venezuelan Bolivar",
+		"ANG" : "Netherlands Antilles Guilder",
+		"MNT" : "Mongolian Tugrik",
+		"LBP" : "Lebanese Pound",
+		"KES" : "Kenyan Shilling",
+		"BTN" : "Bhutan Ngultrum",
+		"GBP" : "British Pound",
+		"SEK" : "Swedish Krona",
+		"ZMK" : "Zambia Kwacha",
+		"SKK" : "Slovak Koruna",
+		"DKK" : "Danish Krone",
+		"AFA" : "Afganistan Afghani",
+		"CYP" : "Cypriot Pound",
+		"SCR" : "Seychelles Rupee",
+		"FJD" : "Fiji Dollar",
+		"SRG" : "Surinam Guilder",
+		"SHP" : "St. Helena Pound",
+		"ALL" : "Albanian Lek",
+		"TOP" : "Tonga Isl Pa'anga",
+		"UGX" : "Ugandan Shilling",
+		"OMR" : "Oman Rial",
+		"DJF" : "Djibouti Franc",
+		"BND" : "Brunei Dollar",
+		"TND" : "Tunisian Dinar",
+		"PTE" : "Portuguese Escudo",
+		"IEP" : "Irish Punt",
+		"SBD" : "Salomon Islands Dollar",
+		"GNF" : "Guinea Franc",
+		"BOB" : "Bolivian Boliviano",
+		"CVE" : "Cape Verde Escudo",
+		"ARS" : "Argentinian Peso",
+		"GMD" : "Gambia Dalasi",
+		"ZWD" : "Zimbabwean Dollar",
+		"MWK" : "Malawi Kwacha",
+		"BDT" : "Bangladesh Taka",
+		"GRD" : "Greek Drachma",
+		"KWD" : "Kuwaiti Dinar",
+		"EUR" : "Euro",
+		"TRL" : "Turkish Lira",
+		"CHF" : "Swiss Franc",
+		"DOP" : "Dominican Peso",
+		"PEN" : "Peruvian Sol",
+		"SVC" : "El Salvador Colon",
+		"SGD" : "Singapore Dollar",
+		"TWD" : "Taiwan New Dollar",
+		"USD" : "US Dollar",
+		"BGN" : "Bulgarian Lev",
+		"MAD" : "Moroccan Dirham",
+		"SAR" : "Saudi Arabian Riyal",
+		"AUD" : "Australian Dollar",
+		"KYD" : "Cayman Islands Dollar",
+		"GHC" : "Ghanaian Cedi",
+		"KRW" : "South Korean Won",
+		"GIP" : "Gibraltar Pound",
+		"NAD" : "Namibian Dollar",
+		"CZK" : "Czech Koruna",
+		"JMD" : "Jamaican Dollar",
+		"MXN" : "Mexican Peso",
+		"BWP" : "Botswana Pula",
+		"GYD" : "Guyana Dollar",
+		"EGP" : "Egyptian Pound",
+		"THB" : "Thai Baht",
+		"AED" : "United Arab Emirates Dirham",
+		"JPY" : "Japanese Yen",
+		"JOD" : "Jordanian Dinar",
+		"HRK" : "Croatian Kuna",
+		"ZAR" : "South African Rand",
+		"CUP" : "Cuban Peso",
+		"BBD" : "Barbados Dollar",
+		"PGK" : "Papua New Guinea Kina",
+		"LKR" : "Sri Lanka Rupee",
+		"BEF" : "Belgian Franc",
+		"PLN" : "Polish Zloty",
+		"MYR" : "Malaysian Ringgit",
+		"FIM" : "Finnish Markka",
+		"CNY" : "Renmimbi Yuan",
+		"SDD" : "Sudanese Dinar",
+		"LVL" : "Latvian Lats",
+		"ITL" : "Italian Lira",
+		"INR" : "Indian Rupee",
+		"NIO" : "Nicaraguan Cordoba",
+		"PHP" : "Philippines Peso",
+		"HNL" : "Honduras Lempira",
+		"HKD" : "Hong Kong Dollar",
+		"NZD" : "New Zealand Dollar",
+		"BRL" : "Brazilian Real",
+		"MTL" : "Maltese Pound",
+		"ATS" : "Austrian Schilling",
+		"EEK" : "Estonian Kroon",
+		"NOK" : "Norwegian Krone",
+		"ISK" : "Iceland Krona",
+		"ILS" : "Israeli Shekel",
+		"LSL" : "Lesotho Loti",
+		"HUF" : "Hungarian Forint",
+		"ESP" : "Spanish Peseta",
+		"UAH" : "Ukraine Hryvnia",
+		"RUB" : "Russian Ruble",
+		"BMD" : "Bermuda Dollar",
+		"MVR" : "Maldives Rufiyan",
+		"QAR" : "Qatari Rial",
+		"VND" : "Vietnam Dong",
+		"MRO" : "Mauritania Ouguiya",
+		"MZM" : "Mozambique Metical",
+		"NPR" : "Nepal Rupee",
+		"COP" : "Colombian Peso",
+		"TZS" : "Tanzanian Shilling",
+		"MGF" : "Malagasy Franc",
+		"KHR" : "Cambodian Riel",
+		"SYP" : "Syria Pound",
+		"HTG" : "Haitian Gourde",
+		"DEM" : "German Mark",
+		"BHD" : "Bahraini Dinar",
+		"XAF" : "CFA Franc(BEAC)",
+		"STD" : "Sao Tome & Principe Dobra",
+		"LTL" : "Lithuanian Litas",
+		"ETB" : "Ethiopian Birr",
+		"XPF" : "CFP Franc",
+}
diff --git a/invest-applet/invest/preferences.py b/invest-applet/invest/preferences.py
index 65d83dc..9401590 100644
--- a/invest-applet/invest/preferences.py
+++ b/invest-applet/invest/preferences.py
@@ -2,6 +2,7 @@ from gettext import gettext as _
 from os.path import join
 import gtk, gobject, gconf
 import invest
+import currencies
 from gettext import gettext as _
 
 import cPickle
@@ -13,59 +14,60 @@ class PrefsDialog:
 
 		self.dialog = self.ui.get_object("preferences")
 		self.treeview = self.ui.get_object("stocks")
+		self.currency = self.ui.get_object("currency")
+		self.currency_code = None
+		self.currencies = currencies.Currencies.currencies
 
 		self.ui.get_object("add").connect('clicked', self.on_add_stock)
 		self.ui.get_object("add").connect('activate', self.on_add_stock)
 		self.ui.get_object("remove").connect('clicked', self.on_remove_stock)
 		self.ui.get_object("remove").connect('activate', self.on_remove_stock)
 		self.treeview.connect('key-press-event', self.on_tree_keypress)
+		self.currency.connect('key-press-event', self.on_entry_keypress)
+		self.currency.connect('activate', self.on_activate_entry)
+		self.currency.connect('focus-out-event', self.on_focus_out_entry)
 
-		self.typs = (str, str, float, float, float)
-		self.names = (_("Symbol"), _("Label"), _("Amount"), _("Price"), _("Commission"))
+		self.typs = (str, str, float, float, float, float)
+		self.names = (_("Symbol"), _("Label"), _("Amount"), _("Price"), _("Commission"), _("Currency Rate"))
 		store = gtk.ListStore(*self.typs)
 		store.set_sort_column_id(0, gtk.SORT_ASCENDING)
 		self.treeview.set_model(store)
 		self.model = store
 
-		def on_cell_edited(cell, path, new_text, col, typ):
-			try:
-				if col == 0:    # stock symbols must be uppercase
-					new_text = str.upper(new_text)
-				store[path][col] = typ(new_text)
-			except:
-				pass
-
-		def get_cell_data(column, cell, model, iter, data):
-			typ, col = data
-			if typ == int:
-				cell.set_property('text', "%d" % typ(model[iter][col]))
-			elif typ == float:
-				cell.set_property('text', "%.2f" % typ(model[iter][col]))
-			else:
-				cell.set_property('text', typ(model[iter][col]))
-
-		def create_cell (view, column, name, typ):
-			cell_description = gtk.CellRendererText ()
-			cell_description.set_property("editable", True)
-			cell_description.connect("edited", on_cell_edited, column, typ)
-			column_description = gtk.TreeViewColumn (name, cell_description)
-			if typ == str:
-				column_description.set_attributes (cell_description, text=column)
-				column_description.set_sort_column_id(column)
-			if typ == float:
-				column_description.set_cell_data_func(cell_description, get_cell_data, (float, column))
-			view.append_column(column_description)
+		completion = gtk.EntryCompletion()
+		self.currency.set_completion(completion)
+		liststore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
+		completion.set_model(liststore)
+		completion.set_text_column(0)
+		for code, label in self.currencies.items():
+			liststore.append([self.format_currency(label, code), code])
 
+		completion.set_match_func(self.match_func, 0)
+		completion.connect("match-selected", self.on_completion_selection, 1)
+
+		if invest.CONFIG.has_key("currency"):
+			code = invest.CONFIG["currency"];
+			if self.currencies.has_key(code):
+				self.currency_code = code;
+				currency = self.format_currency(self.currencies[self.currency_code], self.currency_code)
+				self.currency.set_text(currency)
 
 		for n in xrange (0, 5):
-			create_cell (self.treeview, n, self.names[n], self.typs[n])		
+			self.create_cell (self.treeview, n, self.names[n], self.typs[n])
+		if self.currency_code != None:
+			self.add_exchange_column()
+
 		stock_items = invest.STOCKS.items ()
 		stock_items.sort ()
 		for key, data in stock_items:
 			label = data["label"]
 			purchases = data["purchases"]
 			for purchase in purchases:
-				store.append([key, label, purchase["amount"], purchase["bought"], purchase["comission"]])
+				if purchase.has_key("exchange"):
+					exchange =  purchase["exchange"]
+				else:
+					exchange = 0.0
+				store.append([key, label, purchase["amount"], purchase["bought"], purchase["comission"], exchange])
 
 		try:
 			pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(join(invest.ART_DATA_DIR, "invest-16.png"), -1,-1)
@@ -76,6 +78,42 @@ class PrefsDialog:
 
 		self.sync_ui()
 
+	def on_cell_edited(self, cell, path, new_text, col, typ):
+		try:
+			if col == 0:    # stock symbols must be uppercase
+				new_text = str.upper(new_text)
+			self.model[path][col] = typ(new_text)
+		except:
+			pass
+
+	def get_cell_data(self, column, cell, model, iter, data):
+		typ, col = data
+		if typ == int:
+			cell.set_property('text', "%d" % typ(model[iter][col]))
+		elif typ == float:
+			cell.set_property('text', "%.2f" % typ(model[iter][col]))
+		else:
+			cell.set_property('text', typ(model[iter][col]))
+
+	def create_cell (self, view, column, name, typ):
+		cell_description = gtk.CellRendererText ()
+		cell_description.set_property("editable", True)
+		cell_description.connect("edited", self.on_cell_edited, column, typ)
+		column_description = gtk.TreeViewColumn (name, cell_description)
+		if typ == str:
+			column_description.set_attributes (cell_description, text=column)
+			column_description.set_sort_column_id(column)
+		if typ == float:
+			column_description.set_cell_data_func(cell_description, self.get_cell_data, (float, column))
+		view.append_column(column_description)
+
+	def add_exchange_column(self):
+		self.create_cell (self.treeview, 5, self.names[5], self.typs[5])
+
+	def remove_exchange_column(self):
+		column = self.treeview.get_column(5)
+		self.treeview.remove_column(column)
+
 	def show_run_hide(self, explanation = ""):
 		expl = self.ui.get_object("explanation")
 		expl.set_markup(explanation)
@@ -98,6 +136,7 @@ class PrefsDialog:
 				"amount": float(model[iter][2]),
 				"bought": float(model[iter][3]),
 				"comission": float(model[iter][4]),
+				"exchange": float(model[iter][5])
 			})
 		self.model.foreach(save_symbol)
 		try:
@@ -106,12 +145,20 @@ class PrefsDialog:
 		except Exception, msg:
 			invest.error('Could not save stocks file: %s' % msg)
 
+		invest.CONFIG = {}
+		if self.currency_code != None and len(self.currency_code) == 3:
+			invest.CONFIG['currency'] = self.currency_code
+		try:
+			cPickle.dump(invest.CONFIG, file(invest.CONFIG_FILE, 'w'))
+			invest.debug('Configuration written to file')
+		except Exception, msg:
+			invest.debug('Could not save configuration file: %s' % msg)
 
 	def sync_ui(self):
 		pass
 
 	def on_add_stock(self, w):
-		iter = self.model.append(["GOOG", "Google Inc.", 0, 0, 0])
+		iter = self.model.append(["GOOG", "Google Inc.", 0, 0, 0, 0])
 		path = self.model.get_path(iter)
 		self.treeview.set_cursor(path, self.treeview.get_column(0), True)
 
@@ -126,5 +173,97 @@ class PrefsDialog:
 
 		return False
 
+	def format_currency(self, label, code):
+		if code == None:
+			return label
+		return label + " (" + code + ")"
+
+	def on_entry_keypress(self, w, event):
+		# enter key was pressed
+		if event.keyval == 65293:
+			self.match_currency()
+		return False
+
+	# entry was activated (Enter)
+	def on_activate_entry(self, entry):
+		self.match_currency()
+
+	# entry left focus
+	def on_focus_out_entry(self, w, event):
+		self.match_currency()
+		return False
+
+	# tries to find a currency for the text in the currency entry
+	def match_currency(self):
+		# get the text
+		text = self.currency.get_text().upper()
+
+		# if there is none, finish
+		if len(text) == 0:
+			self.currency_code = None
+			self.pick_currency(None)
+			return
+
+		# if it is a currency code, take that one
+		if len(text) == 3:
+			# try to find the string as code
+			if self.currencies.has_key(text):
+				self.pick_currency(text)
+				return
+		else:
+			# try to find the code for the string
+			for code, label in self.currencies.items():
+				# if the entry equals to the full label,
+				# or the entry equals to the label+code concat
+				if label.upper() == text or self.format_currency(label.upper(), code) == text:
+					# then we take that code
+					self.pick_currency(code)
+					return
+
+		# the entry is not valid, reuse the old one
+		self.pick_currency(self.currency_code)
+
+	# pick this currency, stores it and sets the entry text
+	def pick_currency(self, code):
+		if code == None:
+			label = ""
+			if len(self.treeview.get_columns()) == 6:
+				self.remove_exchange_column()
+		else:
+			label = self.currencies[code]
+			if len(self.treeview.get_columns()) == 5:
+				self.add_exchange_column()
+		self.currency.set_text(self.format_currency(label, code))
+		self.currency_code = code
+
+	# finds matches by testing candidate strings to have tokens starting with the entered text's tokens
+	def match_func(self, completion, key, iter, column):
+		keys = key.split()
+		model = completion.get_model()
+		text = model.get_value(iter, column).lower()
+		tokens = text.split()
+
+		# each key must have a match
+		for key in keys:
+			found_key = False
+			# check any token of the completions start with the key
+			for token in tokens:
+				# remove the ( from the currency code
+				if token.startswith("("):
+					token = token[1:]
+				if token.startswith(key):
+					found_key = True
+					break
+			# this key does not have a match, this is not a completion
+			if not found_key:
+				return False
+		# all keys matched, this is a completion
+		return True
+
+	# stores the selected currency code
+	def on_completion_selection(self, completion, model, iter, column):
+		self.pick_currency(model.get_value(iter, column))
+
+
 def show_preferences(applet, explanation = ""):
 	PrefsDialog(applet).show_run_hide(explanation)
diff --git a/invest-applet/invest/quotes.py b/invest-applet/invest/quotes.py
index 3f1a096..c96ed4a 100644
--- a/invest-applet/invest/quotes.py
+++ b/invest-applet/invest/quotes.py
@@ -11,10 +11,10 @@ import invest, invest.about, invest.chart
 CHUNK_SIZE = 512*1024 # 512 kB
 AUTOREFRESH_TIMEOUT = 15*60*1000 # 15 minutes
 
-QUOTES_URL="http://finance.yahoo.com/d/quotes.csv?s=%(s)s&f=sl1d1t1c1ohgv&e=.csv"
+QUOTES_URL="http://finance.yahoo.com/d/quotes.csv?s=%(s)s&f=snc4l1d1t1c1ohgv&e=.csv"
 
-# Sample (25/4/2008): UCG.MI,"4,86",09:37:00,2008/04/25,"0,07","4,82","4,87","4,82",11192336
-QUOTES_CSV_FIELDS=["ticker", ("trade", float), "time", "date", ("variation", float), ("open", float)]
+# Sample (09/2/2010): "UCG.MI","UNICREDIT","EUR","UCG.MI",1.9410,"2/9/2010","6:10am",+0.0210,1.9080,1.9810,1.8920,166691232
+QUOTES_CSV_FIELDS=["ticker", "label", "currency", ("trade", float), "date", "time", ("variation", float), ("open", float), ("high", float), ("low", float), ("volume", int)]
 
 # based on http://www.johnstowers.co.nz/blog/index.php/2007/03/12/threading-and-pygtk/
 class _IdleObject(gobject.GObject):
@@ -48,6 +48,7 @@ class QuotesRetriever(Thread, _IdleObject):
 		self.tickers = tickers
 		self.retrieved = False
 		self.data = []
+		self.currencies = []
 
 	def run(self):
 		quotes_url = QUOTES_URL % {"s": self.tickers}
@@ -67,9 +68,9 @@ class QuoteUpdater(gtk.ListStore):
 	last_updated = None
 	quotes_valid = False
 	timeout_id = None
-	SYMBOL, LABEL, TICKER_ONLY, BALANCE, BALANCE_PCT, VALUE, VARIATION_PCT, PB = range(8)
+	SYMBOL, LABEL, CURRENCY, TICKER_ONLY, BALANCE, BALANCE_PCT, VALUE, VARIATION_PCT, PB = range(9)
 	def __init__ (self, change_icon_callback, set_tooltip_callback):
-		gtk.ListStore.__init__ (self, gobject.TYPE_STRING, gobject.TYPE_STRING, bool, float, float, float, float, gtk.gdk.Pixbuf)
+		gtk.ListStore.__init__ (self, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, bool, float, float, float, float, gtk.gdk.Pixbuf)
 		self.set_update_interval(AUTOREFRESH_TIMEOUT)
 		self.change_icon_callback = change_icon_callback
 		self.set_tooltip_callback = set_tooltip_callback
@@ -125,16 +126,30 @@ class QuoteUpdater(gtk.ListStore):
 			self.populate(self.parse_yahoo_csv(csv.reader(retriever.data)))
 			self.updated = True
 			self.last_updated = datetime.datetime.now()
-			tooltip = []
-			if self.simple_quotes_count > 0:
-				# Translators: This is share-market jargon. It is the percentage change in the price of a stock. The %% gets changed to a single percent sign and the %+.2f gets replaced with the value of the change.
-				tooltip.append(_('Quotes average change %%: %+.2f%%') % self.avg_simple_quotes_change)
-			if self.positions_count > 0:
-				# Translators: This is share-market jargon. It refers to the total difference between the current price and purchase price for all the shares put together. i.e. How much money would be earned if they were sold right now.
-				tooltip.append(_('Positions balance: %+.2f') % self.positions_balance)
-			tooltip.append(_('Updated at %s') % self.last_updated.strftime("%H:%M"))
-			self.set_tooltip_callback('\n'.join(tooltip))
+			self.update_tooltip()
 
+	def on_currency_retriever_completed(self, retriever):
+		if retriever.retrieved == False:
+			invest.error("Failed to retrieve currency rates!")
+		else:
+			self.convert_currencies(self.parse_yahoo_csv(csv.reader(retriever.data)))
+		self.update_tooltip()
+
+	def update_tooltip(self):
+		tooltip = []
+		if self.simple_quotes_count > 0:
+			# Translators: This is share-market jargon. It is the percentage change in the price of a stock. The %% gets changed to a single percent sign and the %+.2f gets replaced with the value of the change.
+			tooltip.append(_('Quotes average change %%: %+.2f%%') % self.avg_simple_quotes_change)
+		for currency, stats in self.statistics.items():
+			# get the statsitics
+			balance = stats["balance"]
+			paid = stats["paid"]
+			change = balance / paid * 100
+
+			# Translators: This is share-market jargon. It refers to the total difference between the current price and purchase price for all the shares put together. i.e. How much money would be earned if they were sold right now.
+			tooltip.append(_('Positions balance: %+.2f %s (%+.2f%%)') % (balance, currency, change))
+		tooltip.append(_('Updated at %s') % self.last_updated.strftime("%H:%M"))
+		self.set_tooltip_callback('\n'.join(tooltip))
 
 
 	def parse_yahoo_csv(self, csvreader):
@@ -159,20 +174,54 @@ class QuoteUpdater(gtk.ListStore):
 				result[fields[0]]['variation_pct'] = 0
 		return result
 
+	# Computes the balance of the given purchases using a certain current value
+	# and optionally a current exchange rate.
+	def balance(self, purchases, value, currentrate=None):
+		current = 0
+		paid = 0
+
+		for purchase in purchases:
+			if purchase["amount"] != 0:
+				buyrate = purchase["exchange"]
+				# if the buy rate is invalid, use 1.0
+				if buyrate <= 0:
+					buyrate = 1.0
+
+				# if no current rate is given, ignore buy rate
+				if currentrate == None:
+					buyrate = 1.0
+					rate = 1.0
+				else:
+					# otherwise, take use buy rate and current rate to compute the balance
+					rate = currentrate
+
+				# current value is the current rate * amount * value
+				current += rate * purchase["amount"] * value
+				# paid is buy rate * ( amount * price + commission )
+				paid += buyrate * (purchase["amount"] * purchase["bought"] + purchase["comission"])
+
+		balance = current - paid
+		if paid != 0:
+			change = 100*balance/paid
+		else:
+			change = 100 # Not technically correct, but it will look more intuitive than the real result of infinity.
+
+		return (balance, change)
+
 	def populate(self, quotes):
 		if (len(quotes) == 0):
 			return
 
 		self.clear()
-		
+		self.currencies = []
+
 		try:
 			quote_items = quotes.items ()
 			quote_items.sort ()
 
 			simple_quotes_change = 0
 			self.simple_quotes_count = 0
-			self.positions_balance = 0
-			self.positions_count = 0
+			self.statistics = {}
 
 			for ticker, val in quote_items:
 				pb = None
@@ -180,7 +229,26 @@ class QuoteUpdater(gtk.ListStore):
 				# get the label of this stock for later reuse
 				label = invest.STOCKS[ticker]["label"]
 				if len(label) == 0:
-					label = ticker
+					if len(val["label"]) != 0:
+						label = val["label"]
+					else:
+						label = ticker
+
+				# make sure the currency field is upper case
+				val["currency"] = val["currency"].upper();
+
+				# the currency of currency conversion rates like EURUSD=X is wrong in csv
+				# this can be fixed easily by reusing the latter currency in the symbol
+				if len(ticker) == 8 and ticker.endswith("=X"):
+					val["currency"] = ticker[3:6]
+
+				# indices should not have a currency, though yahoo says so
+				if ticker.startswith("^"):
+					val["currency"] = ""
+
+				# if this is a currency not yet seen and different from the target currency, memorize it
+				if val["currency"] not in self.currencies and len(val["currency"]) > 0:
+					self.currencies.append(val["currency"])
 
 				# Check whether the symbol is a simple quote, or a portfolio value
 				is_simple_quote = True
@@ -191,19 +259,12 @@ class QuoteUpdater(gtk.ListStore):
 
 				if is_simple_quote:
 					self.simple_quotes_count += 1
-					row = self.insert(0, [ticker, label, True, 0, 0, val["trade"], val["variation_pct"], pb])
+					row = self.insert(0, [ticker, label, val["currency"], True, 0, 0, val["trade"], val["variation_pct"], pb])
 					simple_quotes_change += val['variation_pct']
 				else:
-					self.positions_count += 1
-					current = sum([purchase["amount"]*val["trade"] for purchase in invest.STOCKS[ticker]["purchases"] if purchase["amount"] != 0])
-					paid = sum([purchase["amount"]*purchase["bought"] + purchase["comission"] for purchase in invest.STOCKS[ticker]["purchases"] if purchase["amount"] != 0])
-					balance = current - paid
-					if paid != 0:
-						change = 100*balance/paid
-					else:
-						change = 100 # Not technically correct, but it will look more intuitive than the real result of infinity.
-					row = self.insert(0, [ticker, label, False, balance, change, val["trade"], val["variation_pct"], pb])
-					self.positions_balance += balance
+					(balance, change) = self.balance(invest.STOCKS[ticker]["purchases"], val["trade"])
+					row = self.insert(0, [ticker, label, val["currency"], False, balance, change, val["trade"], val["variation_pct"], pb])
+					self.add_balance_change(balance, change, val["currency"])
 
 				if len(ticker.split('.')) == 2:
 					url = 'http://ichart.europe.yahoo.com/h?s=%s' % ticker
@@ -239,6 +300,82 @@ class QuoteUpdater(gtk.ListStore):
 			invest.debug(quotes)
 			self.quotes_valid = False
 
+		# start retrieving currency conversion rates
+		if invest.CONFIG.has_key("currency"):
+			target_currency = invest.CONFIG["currency"]
+			symbols = []
+
+			invest.debug("These currencies occur: %s" % self.currencies)
+			for currency in self.currencies:
+				if currency == target_currency:
+					continue
+
+				invest.debug("%s will be converted to %s" % ( currency, target_currency ))
+				symbol = currency + target_currency + "=X"
+				symbols.append(symbol)
+
+			if len(symbols) > 0:
+				tickers = '+'.join(symbols)
+				quotes_retriever = QuotesRetriever(tickers)
+				quotes_retriever.connect("completed", self.on_currency_retriever_completed)
+				quotes_retriever.start()
+
+	def convert_currencies(self, quotes):
+		# if there is no target currency, this method should never have been called
+		if not invest.CONFIG.has_key("currency"):
+			return
+
+		# reset the overall balance
+		self.statistics = {}
+
+		# collect the rates for the currencies
+		rates = {}
+		for symbol, data in quotes.items():
+			currency = symbol[0:3]
+			rate = data["trade"]
+			rates[currency] = rate
+
+		# convert all non target currencies
+		target_currency = invest.CONFIG["currency"]
+		iter = self.get_iter_first()
+		while iter != None:
+			currency = self.get_value(iter, self.CURRENCY)
+			symbol = self.get_value(iter, self.SYMBOL)
+			# ignore stocks that are currency conversions
+			# and only convert stocks that are not in the target currency
+			# and if we have a conversion rate
+			if not ( len(symbol) == 8 and symbol[6:8] == "=X" ) and \
+			   currency != target_currency and rates.has_key(currency):
+				# first convert the balance, it needs the original value
+				if not self.get_value(iter, self.TICKER_ONLY):
+					ticker = self.get_value(iter, self.SYMBOL)
+					value = self.get_value(iter, self.VALUE)
+					(balance, change) = self.balance(invest.STOCKS[ticker]["purchases"], value, rates[currency])
+					self.set(iter, self.BALANCE, balance)
+					self.set(iter, self.BALANCE_PCT, change)
+					self.add_balance_change(balance, change, target_currency)
+
+				# now, convert the value
+				value = self.get_value(iter, self.VALUE)
+				value *= rates[currency]
+				self.set(iter, self.VALUE, value)
+				self.set(iter, self.CURRENCY, target_currency)
+
+			else:
+				# consider non-converted stocks here
+				balance = self.get_value(iter, self.BALANCE)
+				change  = self.get_value(iter, self.BALANCE_PCT)
+				self.add_balance_change(balance, change, currency)
+
+			iter = self.iter_next(iter)
+
+	def add_balance_change(self, balance, change, currency):
+		if self.statistics.has_key(currency):
+			self.statistics[currency]["balance"] += balance
+			self.statistics[currency]["paid"] += balance/change*100
+		else:
+			self.statistics[currency] = { "balance" : balance, "paid" : balance/change*100 }
+
 	def set_pb_callback(self, retriever, row):
 		self.set_value(row, self.PB, retriever.image.get_pixbuf())
 
diff --git a/invest-applet/invest/widgets.py b/invest-applet/invest/widgets.py
index ef1017b..851823f 100644
--- a/invest-applet/invest/widgets.py
+++ b/invest-applet/invest/widgets.py
@@ -57,6 +57,8 @@ class InvestWidget(gtk.TreeView):
 		for i, col_name in enumerate(col_names):
 			if i < 3:
 				cell = gtk.CellRendererText()
+				if i > 0:
+					cell.set_property("xalign", 1.0)
 				column = gtk.TreeViewColumn (col_name, cell)
 				if i == 0:
 					column.set_sort_column_id(quotes_updater.LABEL)
@@ -72,6 +74,7 @@ class InvestWidget(gtk.TreeView):
 				# add the last two column only if we have any positions
 				if simple_quotes_only == False:
 					cell = gtk.CellRendererText()
+					cell.set_property("xalign", 1.0)
 					column = gtk.TreeViewColumn (col_name, cell)
 					if i == 4:
 						column.set_sort_column_id(quotes_updater.BALANCE)
@@ -90,7 +93,7 @@ class InvestWidget(gtk.TreeView):
 		cell.set_property('text', model[iter][model.LABEL])
 
 	def _getcelldata_value(self, column, cell, model, iter):
-		cell.set_property('text', "%.5g" % model[iter][model.VALUE])
+		cell.set_property('text', "%.5g %s" % ( model[iter][model.VALUE], model[iter][model.CURRENCY] ))
 
 	def _getcelldata_variation(self, column, cell, model, iter):
 		color = GREEN
@@ -108,8 +111,8 @@ class InvestWidget(gtk.TreeView):
 			cell.set_property('text', '')
 		else:
 					cell.set_property('markup',
-			"<span foreground='%s'>%+.2f</span>" %
-			(color, model[iter][model.BALANCE]))
+			"<span foreground='%s'>%+.2f %s</span>" %
+			(color, model[iter][model.BALANCE], model[iter][model.CURRENCY]))
 
 	def _getcelldata_balancepct(self, column, cell, model, iter):
 		is_ticker_only = model[iter][model.TICKER_ONLY]
